如何提升Langchain ConversationalRetrievalQAChain的源文档相关性
解决方案:限制ConversationalRetrievalQAChain返回无关源文档
核心问题
已实现returnSourceDocuments=true的ConversationalRetrievalQAChain,针对VectorStore数据库的特定问题能返回匹配的源文档,但处理"地球是圆的吗""你今天好吗"这类通用问题时,会返回无关文档——向量存储始终返回文档,即便内容不匹配。
LangChain框架内的缓解方案
1. 为检索设置相似度阈值
多数向量存储(包括Qdrant)支持通过相似度阈值过滤结果,仅返回与查询相似度超过阈值的文档。修改检索器创建逻辑,添加similarity_threshold参数:
private async createRetrieverFromDriver(): Promise<VectorStoreRetriever<QdrantVectorStore>> { return this.driver.asRetriever({ k: qdrantConfig.noResults ?? 5, searchKwargs: { similarity_threshold: 0.7 // 可根据实际数据调整,建议0.6-0.8区间测试 } }) }
阈值需结合你的嵌入模型和数据集调整,过高可能漏检相关文档,过低则仍会返回无关内容。
2. 使用MultiQueryRetriever优化检索查询
通过LLM生成多个与原问题相关的查询,再综合多个查询的检索结果,提升匹配准确性,减少无关文档的出现概率:
import { MultiQueryRetriever } from "langchain/retrievers/multi_query"; private async createRetrieverFromDriver(): Promise<VectorStoreRetriever<QdrantVectorStore>> { const baseRetriever = this.driver.asRetriever(qdrantConfig.noResults ?? 5); return MultiQueryRetriever.fromLLM({ llm: this.chat, retriever: baseRetriever, // 可选:自定义生成查询的提示词 // prompt: yourCustomPrompt }); }
该工具会自动生成多个变体查询,扩大检索覆盖面的同时过滤低相关结果。
3. 添加LLM驱动的文档相关性过滤
在检索到文档后,用LLM判断每个文档是否与当前问题相关,过滤掉无关内容。可以自定义一个链来处理这一步:
// 示例:创建文档过滤链 private async createDocumentFilterChain(): Promise<LLMChain> { const filterPrompt = new PromptTemplate({ inputVariables: ["question", "document"], template: `判断以下文档是否与问题相关: 问题:{question} 文档内容:{document} 仅回答"相关"或"无关"。` }); return new LLMChain({ llm: this.chat, prompt: filterPrompt }); } // 在初始化或检索后调用过滤逻辑 async retrieveRelevantDocuments(question: string): Promise<Document[]> { const rawDocs = await this.retriever.getRelevantDocuments(question); const filterChain = await this.createDocumentFilterChain(); const relevantDocs = []; for (const doc of rawDocs) { const result = await filterChain.call({ question, document: doc.pageContent }); if (result.text.trim() === "相关") { relevantDocs.push(doc); } } return relevantDocs; }
之后可以将过滤后的文档传入ConversationalRetrievalQAChain,替换原有的retriever逻辑。
4. 调整检索返回数量
减少默认返回的文档数量(比如从5降到2-3),降低无关文档被返回的概率:
private async createRetrieverFromDriver(): Promise<VectorStoreRetriever<QdrantVectorStore>> { return this.driver.asRetriever(qdrantConfig.noResults ?? 2); // 减少返回数量 }
是否需要手动评估文档相关性?
如果上述内置工具能满足需求,无需开发手动评估流程。若业务对相关性要求极高,可考虑:
- 手动标注一批"问题-文档"相关性数据,训练轻量的文本分类模型
- 将模型集成到LangChain的检索流程中,作为过滤环节
但优先尝试LangChain内置的阈值过滤、MultiQueryRetriever等方案,这些工具已能解决大部分通用问题导致的无关文档返回问题。
内容的提问来源于stack exchange,提问作者Jakub Skurčák
相关产品推荐
相关产品推荐

