You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Langchain.js的ConversationalRetrievalQAChain中实现相似度阈值回退至无向量库上下文LLM

在Langchain.js中实现ConversationalRetrievalQAChain的阈值回退逻辑

默认的ConversationalRetrievalQAChain无法直接实现相似度阈值判断,需要手动拆解检索、上下文构建和LLM调用流程,自定义逻辑实现回退。以下是具体实现步骤和代码:

核心思路

  1. 直接调用向量存储的similaritySearchWithScore方法,获取带相似度分数的检索结果
  2. 设置阈值过滤有效文档,无有效文档时跳过上下文注入
  3. 结合对话内存,动态构建提示词并调用LLM
  4. 手动维护对话内存的更新

具体实现代码

1. 自定义带阈值过滤的检索函数

// 自定义相似度阈值(根据业务场景调整)
const SIMILARITY_THRESHOLD = 0.7;

/**
 * 检索符合相似度阈值的文档
 * @param {string} query 用户提问
 * @param {object} filters 检索过滤器(可选)
 * @returns {Document[]} 符合条件的文档列表
 */
async function retrieveRelevantDocs(query, filters) {
  // 调用向量存储的带分数检索方法
  const docsWithScores = filters 
    ? await vectorStore.similaritySearchWithScore(query, 1, filters)
    : await vectorStore.similaritySearchWithScore(query, 1);
  
  // 过滤掉分数低于阈值的文档,只保留内容
  const validDocs = docsWithScores
    .filter(([_, score]) => score >= SIMILARITY_THRESHOLD)
    .map(([doc]) => doc);
  
  return validDocs;
}

2. 构建动态查询处理逻辑

结合对话内存和LLM,根据检索结果决定是否注入上下文:

async function processUserQuery(query, filters) {
  // 从内存中加载对话历史
  const memoryVars = await memory.loadMemoryVariables({});
  const chatHistory = memoryVars.history || "";

  // 获取符合阈值的相关文档
  const validDocs = await retrieveRelevantDocs(query, filters);

  let prompt;
  if (validDocs.length > 0) {
    // 有有效文档,构建带上下文的提示词
    const context = validDocs.map(doc => doc.pageContent).join("\n\n");
    prompt = `根据以下上下文和对话历史回答问题:

上下文:
${context}

对话历史:
${chatHistory}

当前问题:${query}`;
  } else {
    // 无有效文档,直接使用对话历史和当前提问
    prompt = `根据对话历史回答问题:

对话历史:
${chatHistory}

当前问题:${query}`;
  }

  // 调用LLM生成回答
  const response = await model.call(prompt);
  
  // 更新对话内存
  await memory.saveContext({ input: query }, { output: response });
  
  return response;
}

3. 使用PromptTemplate优化提示词(可选)

如果需要更规范的提示词管理,可以用Langchain的PromptTemplate:

import { PromptTemplate } from "langchain/prompts";

// 定义带上下文的提示模板
const withContextPrompt = new PromptTemplate({
  template: `根据以下上下文和对话历史回答问题:

上下文:
{context}

对话历史:
{chatHistory}

当前问题:{question}`,
  inputVariables: ["context", "chatHistory", "question"]
});

// 定义无上下文的提示模板
const withoutContextPrompt = new PromptTemplate({
  template: `根据对话历史回答问题:

对话历史:
{chatHistory}

当前问题:{question}`,
  inputVariables: ["chatHistory", "question"]
});

async function processUserQuery(query, filters) {
  const memoryVars = await memory.loadMemoryVariables({});
  const chatHistory = memoryVars.history || "";
  const validDocs = await retrieveRelevantDocs(query, filters);

  let response;
  if (validDocs.length > 0) {
    const context = validDocs.map(doc => doc.pageContent).join("\n\n");
    const formattedPrompt = await withContextPrompt.format({
      context,
      chatHistory,
      question: query
    });
    response = await model.call(formattedPrompt);
  } else {
    const formattedPrompt = await withoutContextPrompt.format({
      chatHistory,
      question: query
    });
    response = await model.call(formattedPrompt);
  }

  await memory.saveContext({ input: query }, { output: response });
  return response;
}

替代方案:自定义Chain(进阶)

如果希望保留Langchain的Chain结构,可以通过BaseChain自定义实现阈值判断逻辑,但手动实现的方式更直观灵活,适合快速落地需求。

内容的提问来源于stack exchange,提问作者Zainul Abideen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 09:53:18