如何在Stuff链型ConversationalRetrievalChain中获取源文档、分数及元数据?
解决方案
要在使用Stuff链的ConversationalRetrievalChain中获取source_documents、匹配分数及向量数据库原始元数据,无需依赖大模型返回,可通过以下步骤实现:
1. 开启链的源文档返回参数
ConversationalRetrievalChain默认仅返回问答内容,通过设置return_source_documents=True,可让链在返回结果中包含检索到的源文档数据。同时配置检索器(Retriever)以返回匹配分数:
from langchain.chains import ConversationalRetrievalChain from langchain.chat_models import ChatOpenAI # 初始化LLM和检索器 llm = ChatOpenAI(temperature=0) # 配置检索器返回匹配分数(以FAISS为例) retriever = your_vectorstore.as_retriever( search_type="similarity_score_threshold", search_kwargs={"k": 3, "score_threshold": 0.7} # 控制返回数量和分数阈值 ) # 创建Chain时开启源文档返回 qa_chain = ConversationalRetrievalChain.from_llm( llm=llm, retriever=retriever, return_source_documents=True, # 关键参数:启用源文档返回 return_generated_question=False # 可选:关闭自动生成问题功能 )
2. 提取并处理源文档、分数与元数据
调用链后,返回结果会包含answer和source_documents字段。source_documents是Document对象列表,每个对象包含:
page_content:文档内容片段metadata:向量数据库存储的原始元数据(含匹配分数score,需检索器配置支持)
在Chainlit中处理结果时,可直接提取这些数据用于展示或导出:
import chainlit as cl @cl.on_message async def handle_message(message: cl.Message): # 调用链获取结果 chat_history = cl.user_session.get("chat_history", []) result = await cl.make_async(qa_chain)( {"question": message.content, "chat_history": chat_history} ) # 提取源文档信息 source_docs = result["source_documents"] formatted_source_info = [] for idx, doc in enumerate(source_docs): # 获取匹配分数(检索器配置后会存在于metadata中) match_score = doc.metadata.get("score", "未获取") # 获取原始元数据(如文档路径、页码等) raw_metadata = {k: v for k, v in doc.metadata.items() if k != "score"} # 格式化展示内容 formatted_source_info.append( f"### 参考文档 {idx+1}\n" f"- 匹配分数: {match_score:.4f}\n" f"- 原始元数据: {raw_metadata}\n" f"- 内容片段: {doc.page_content[:250]}..." ) # 构建回复消息,合并问答内容与源文档信息 response = cl.Message(content=f"{result['answer']}\n\n" + "\n\n".join(formatted_source_info)) await response.send() # (可选)实现导出功能:将源数据转为JSON # import json # export_data = json.dumps([ # {"page_content": doc.page_content, "metadata": doc.metadata} # for doc in source_docs # ], indent=2) # 可通过Chainlit的`cl.File`组件提供下载
3. 避免大模型幻觉的优化思路
无需在提示词中要求大模型返回源文档信息,直接通过链的return_source_documents参数获取原始数据,由代码自行处理展示。这种方式既保证了源数据的准确性,又避免了大模型幻觉问题,同时保留Stuff链的使用。
内容的提问来源于stack exchange,提问作者Guilherme Giuliano Nicolau
相关产品推荐
相关产品推荐

