如何让LangChain的ConversationalRetrievalChain仅基于单文档嵌入对话
解决思路:让检索器只锁定目标文档
核心是给单个上传的文档做专属标记,然后让检索器只拉取带这个标记的内容,下面是两种可行方案:
方案一:用文档唯一标识过滤(推荐)
- 上传时给文档加专属标记:把当前会话的唯一ID(或自定义文档ID)塞进文档的metadata里,确保这个标记在整个索引里唯一。示例上传代码:
from langchain.schema import Document # content为读取的文档内容,session_id是当前会话的唯一标识(比如前端传入的会话ID) target_doc = Document( page_content=content, metadata={ "unique_doc_id": f"session_{session_id}_single_doc", "source": "用户上传的文件名.pdf" } ) self.vector_store.add_documents([target_doc])
- 检索时过滤目标文档:修改retriever初始化逻辑,用Azure搜索的OData过滤语法,只返回带专属标记的文档。替换原代码中的retriever部分:
# 生成和上传时一致的唯一标识 target_doc_id = f"session_{session_id}_single_doc" # 创建带过滤条件的检索器 retriever = self.vector_store.as_retriever( search_kwargs={ "filter": f"unique_doc_id eq '{target_doc_id}'" } ) # 后续链的初始化保持原有逻辑,传入这个带过滤的检索器即可 chain = ConversationalRetrievalChain( retriever=retriever, question_generator=question_generator, combine_docs_chain=doc_chain, return_source_documents=True )
方案二:用临时向量存储(适合单次会话用完即弃的场景)
如果不想和全局索引里的其他文档混在一起,每次上传文档时单独创建一个只包含该文档的向量存储实例:
# 新建临时Azure搜索索引(索引名用会话ID保证唯一) temp_vector_store = AzureCognitiveSearch( azure_search_endpoint="你的Azure搜索端点", azure_search_key="你的搜索密钥", index_name=f"temp_session_{session_id}_index" ) # 将单个上传文档添加到临时存储 temp_vector_store.add_documents([target_doc]) # 用临时存储创建检索器 retriever = temp_vector_store.as_retriever() # 后续链的初始化保持原有逻辑,传入这个临时检索器即可
注意:这种方式每次会话会生成新索引,用完记得删除临时索引,避免资源浪费。
内容的提问来源于stack exchange,提问作者Gaurav Mahapatro
相关产品推荐
相关产品推荐

