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

使用ConversationalRetrievalChain时,LLM无答案如何取消返回源文档?

解决ConversationalRetrievalChain无答案时不返回源文档的问题

核心思路

默认的ConversationalRetrievalChain只要设置return_source_documents=True,就会始终返回检索到的源文档,不管LLM最终是否能回答问题。要实现无答案时不返回源文档,需要在获取Chain输出后添加判断逻辑,识别LLM的无法回答回复,再动态移除源文档字段。

具体实现方法

方法1:结果后处理(简单直接)

调用Chain得到结果后,检查LLM的回答是否包含预设的无法回答关键词,若是则删除source_documents字段。

示例代码:

from langchain.chains import ConversationalRetrievalChain
from langchain.memory import ConversationBufferMemory

# 初始化配置好的Chain(带ConversationBufferMemory,return_source_documents=True)
chain = ConversationalRetrievalChain.from_llm(
    llm=your_llm_instance,
    retriever=your_retriever_instance,
    memory=ConversationBufferMemory(memory_key="chat_history", return_messages=True),
    return_source_documents=True
)

def get_answer_with_filtered_sources(query):
    result = chain({"question": query})
    # 根据LLM实际返回的无法回答话术调整关键词列表
    no_answer_triggers = ["I'm sorry, but I don't have access to", "无法回答该问题"]
    # 判断是否属于无法回答场景
    if any(trigger in result["answer"] for trigger in no_answer_triggers):
        result.pop("source_documents", None)
    return result

方法2:自定义Chain(优雅复用)

继承ConversationalRetrievalChain,重写_call方法,在内部完成判断和源文档过滤:

from langchain.chains.conversational_retrieval.base import ConversationalRetrievalChain

class FilteredConversationalRetrievalChain(ConversationalRetrievalChain):
    def _call(self, inputs):
        # 调用父类逻辑获取原始结果
        raw_result = super()._call(inputs)
        # 识别无法回答场景
        no_answer_triggers = ["I'm sorry, but I don't have access to", "无法回答该问题"]
        if any(trigger in raw_result["answer"] for trigger in no_answer_triggers):
            raw_result.pop("source_documents", None)
        return raw_result

# 用自定义Chain初始化
chain = FilteredConversationalRetrievalChain.from_llm(
    llm=your_llm_instance,
    retriever=your_retriever_instance,
    memory=ConversationBufferMemory(memory_key="chat_history", return_messages=True),
    return_source_documents=True
)

方法3:标准化LLM输出(精准识别)

通过提示词要求LLM在无法回答时返回标准化标记,再用输出解析器识别场景:

  1. 定义输出格式规范,要求LLM返回结构化结果
  2. 解析结果后判断是否需要保留源文档

示例代码:

from langchain.output_parsers import JsonOutputParser
from langchain.prompts import PromptTemplate
from pydantic import BaseModel, Field

# 定义结构化输出格式
class AnswerSchema(BaseModel):
    answer: str = Field(description="回答内容")
    can_answer: bool = Field(description="是否可回答该问题,无法回答时为false")

parser = JsonOutputParser(pydantic_object=AnswerSchema)

# 带格式要求的提示词
custom_prompt = PromptTemplate(
    template="根据提供的文档回答问题,无法回答时请将can_answer设为false。\n{format_instructions}\n问题:{question}\n文档:{context}",
    input_variables=["question", "context"],
    partial_variables={"format_instructions": parser.get_format_instructions()}
)

# 初始化Chain时使用自定义提示
chain = ConversationalRetrievalChain.from_llm(
    llm=your_llm_instance,
    retriever=your_retriever_instance,
    memory=ConversationBufferMemory(memory_key="chat_history", return_messages=True),
    return_source_documents=True,
    combine_docs_chain_kwargs={"prompt": custom_prompt}
)

def get_filtered_result(query):
    result = chain({"question": query})
    try:
        parsed_data = parser.parse(result["answer"])
        if not parsed_data.can_answer:
            result.pop("source_documents", None)
    except:
        # 解析失败时默认保留源文档,可根据需求调整逻辑
        pass
    return result

注意事项

  • 无法回答的触发关键词需要根据你的LLM实际返回话术调整,确保识别准确;
  • 标准化输出的方式可靠性更高,适合LLM回复风格不稳定的场景;
  • 自定义Chain的方式对现有代码侵入性小,适合需要多处复用的场景。

内容的提问来源于stack exchange,提问作者suramya verma

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 19:19:58