Langchain-Chatchat 如何检测低质量答案?——置信度评分的实现与实践

在企业级 AI 应用日益深入的今天,一个看似简单的问题却常常让人头疼:“这个回答到底靠不靠谱?”

尤其是在金融、医疗、法务等高敏感领域,大语言模型(LLM)虽然能流畅作答,但偶尔也会“一本正经地胡说八道”——生成逻辑通顺却事实错误的内容。这种“幻觉”问题一旦出现在正式场景中,轻则误导决策,重则引发合规风险。

而像 Langchain-Chatchat 这类基于私有知识库的本地化问答系统,正是为解决这一痛点而生。它通过 RAG(检索增强生成)架构,将模型的回答锚定在用户上传的真实文档上,大幅降低虚构内容的概率。但即便如此,仍存在一种尴尬情况:检索结果勉强相关、上下文信息碎片化、模型“拼凑式”作答——这时候,怎么判断输出是否可信?

答案是:引入置信度评分机制

这并不是让模型自己说“我觉得我答得不错”,而是从外部构建一套可量化的评估体系,在答案生成后立即进行多维度打分,从而自动识别出那些“听起来像那么回事,实则站不住脚”的低质量响应。


这套机制的核心思想其实很朴素:可信的答案,通常建立在高质量的证据之上,并且表达清晰、依据充分。

Langchain-Chatchat 的置信度评分正是围绕这一点展开。它并不依赖对 LLM 的微调或额外训练,而是在现有流程中插入一个轻量级的后处理模块,综合分析检索阶段和生成阶段的关键信号,动态计算出一个介于 0 到 1 之间的数值——分数越高,说明系统越有把握这个答案是可靠的。

那具体是怎么做的呢?

整个流程始于一次普通的用户提问。比如员工问:“公司年假是怎么规定的?” 系统首先会把这个问题向量化,然后在本地向量数据库(如 FAISS 或 Chroma)中查找最相似的知识片段。假设我们有两个文本块:

  • “员工入职满一年后享有5天带薪年假,每工作满一年增加1天,最多不超过15天。”
  • “病假需提交医院证明,连续请假超过三天需部门主管审批。”

显然,第一个 chunk 更相关。系统会提取这些内容作为上下文,送入大模型生成最终回答,例如:“员工入职满一年后享有5天带薪年假。”

接下来就是关键一步——置信度评估

此时系统不会直接返回答案,而是启动评分逻辑,主要考察以下几个方面:

1. 检索相关性:问题和知识片段有多匹配?

这是最基础的一环。使用 Sentence-BERT 类似的嵌入模型,计算问题与每个检索到的文本块之间的余弦相似度。取最高值作为检索质量的代表。

如果最高相似度只有 0.4,说明问题和知识库中的任何内容都搭不上边,那后续再怎么生成也是无源之水。这类情况下,即使模型给出了看似合理的回答,也应该被打上“低可信”标签。

2. 关键词覆盖:问题里的关键词出现在上下文中了吗?

有时候语义相似度尚可,但关键信息缺失。比如用户问“差旅报销标准”,检索出的文本提到“费用审批流程”,虽然都属于财务制度范畴,但并未真正回答核心问题。

为此,可以做简单的关键词匹配,比如提取问题中的名词短语(“差旅”、“报销”、“标准”),检查它们是否出现在 top-k 的检索结果中。若多数未命中,则说明上下文支撑不足。

3. 答案是否含糊其辞?有没有“我不知道”之类的表达?

人类在不确定时会坦白承认;AI 也应如此。如果我们能在生成答案中检测到诸如“我不清楚”、“无法确定”、“没有相关信息”等表达,就应该果断降低置信度。

这看似简单,实则非常有效。很多低质量回答并不会直接拒绝,而是用模糊语言绕开问题,比如“一般来说……”、“可能涉及……”。因此除了显式否定词外,还可以加入一些启发式规则来捕捉这类软性回避。

4. 答案长度与冗余性:是不是太短或太泛?

过短的答案往往缺乏细节支撑。比如面对“项目立项流程是什么?”只回答“需要提交申请表”,显然不够完整。同样,过于笼统的回答如“请参考相关规定”也难以提供实际帮助。

设定一个最低字符阈值(如 10 字以上),并结合句式结构分析,有助于过滤掉这类敷衍式输出。

5. 多源一致性:不同文本块是否支持同一结论?

当系统检索出多个相关段落时,理想状态下它们应对同一事实给出一致描述。如果一个 chunk 说“年假5天”,另一个却写“年假7天”,这就出现了矛盾。

虽然目前大多数实现尚未完全自动化处理冲突推理,但可以通过统计高频术语、共现实体等方式初步判断一致性程度。未来结合 NLI(自然语言推理)模型,甚至能实现跨文档的事实校验。


把这些信号整合起来,就可以构建一个灵活的评分函数。以下是一个简化但实用的 Python 实现示例:

from sentence_transformers import util
import numpy as np

def calculate_confidence_score(query, retrieved_chunks, generated_answer, embedder, threshold=0.6):
    """
    计算问答系统的置信度评分

    参数:
        query: 用户原始问题
        retrieved_chunks: 检索返回的文本片段列表
        generated_answer: LLM生成的答案
        embedder: 预加载的SentenceTransformer模型
        threshold: 相似度判定阈值

    返回:
        confidence_score: 浮点数,范围[0,1]
    """

    # 1. 计算问题与最佳chunk的语义相似度
    query_emb = embedder.encode(query, convert_to_tensor=True)
    chunk_embs = embedder.encode(retrieved_chunks, convert_to_tensor=True)
    similarities = util.cos_sim(query_emb, chunk_embs)[0]
    max_similarity = float(similarities.max())

    # 2. 检查答案是否包含否定或不确定表述
    uncertainty_phrases = ["我不知道", "不清楚", "无法确定", "没有相关信息", "抱歉"]
    contains_uncertainty = any(phrase in generated_answer for phrase in uncertainty_phrases)

    # 3. 检查答案是否为空或过短
    is_too_short = len(generated_answer.strip()) < 10

    # 4. 综合评分逻辑
    base_score = max_similarity
    if contains_uncertainty or is_too_short:
        adjustment = -0.4
    else:
        adjustment = 0

    confidence_score = max(0.0, min(1.0, base_score + adjustment))

    return confidence_score

# 使用示例
if __name__ == "__main__":
    from sentence_transformers import SentenceTransformer

    model = SentenceTransformer('paraphrase-multilingual-MiniLM-L12-v2')

    query = "公司年假政策是如何规定的?"
    chunks = [
        "员工入职满一年后享有5天带薪年假,每工作满一年增加1天,最多不超过15天。",
        "病假需提交医院证明,连续请假超过三天需部门主管审批。"
    ]
    answer = "员工入职满一年后享有5天带薪年假。"

    score = calculate_confidence_score(query, chunks, answer, model)
    print(f"置信度评分: {score:.3f}")
    # 输出示例: 置信度评分: 0.872

这段代码虽然简洁,但已经涵盖了核心逻辑:以检索相似度为基础分,再根据答案中的“危险信号”进行扣减。你可以根据业务需求进一步扩展,比如加入关键词覆盖率权重、设置动态惩罚系数、甚至接入更复杂的 NLP 模型来做深层语义验证。

更重要的是,这个模块是非侵入式的。它不需要修改原有的 RAG 流程,也不依赖特定模型结构,只需在生成之后加一道“质检关”,就能显著提升输出稳定性。


在实际部署中,这套机制的价值尤为突出。

想象这样一个场景:某企业刚更新了差旅政策,旧文档还未下线。员工提问“2024年出差住宿标准是多少?”系统检索到了两条记录,一条写着“一线城市每日限额600元”,另一条则是“根据预算灵活调整”。此时模型可能会综合二者,回答“一般为600元左右”。

如果没有置信度机制,这条模棱两可的回答就会被原样返回。而有了评分系统,它可以识别出两份资料存在潜在冲突、且新政策未明确列出,于是将置信度压低至 0.5 以下,前端则提示:“当前信息可能存在冲突,请咨询行政部门确认。”

这种设计不仅避免了误导,还增强了用户对系统的信任感——他们知道,AI 不只是在“猜”,而是在“有依据的前提下作答”。


当然,我们也必须清醒认识到:置信度评分不是万能钥匙

它本质上是一种启发式判据,而非数学意义上的准确率预测。它的高分只能说明“系统认为这个答案有较强依据”,并不能保证绝对正确。尤其在知识库本身存在错误或矛盾时,模型可能“自信地犯错”。

因此,在关键业务场景中,建议采取分级策略:

  • 高置信(>0.8):直接展示答案,辅以绿色标识;
  • 中置信(0.6~0.8):显示答案同时标注“仅供参考”,提醒用户核实;
  • 低置信(<0.6):不返回具体内容,改为提示“暂未找到可靠信息”或转接人工服务。

同时,所有问答过程应保留日志,包括原始问题、检索结果、生成答案及各项得分明细,便于后期审计与模型优化。


回过头看,Langchain-Chatchat 的真正优势,不只是技术上的开源与本地化,更在于它提供了一种可解释、可控制、可迭代的 AI 应用范式。

置信度评分正是这一理念的具体体现:我们不再盲目接受模型输出,而是建立起一套透明的评估框架,让用户既能享受 AI 的效率,又能掌控其边界。

未来的智能系统,不应追求“全能”,而应追求“可知”——知道自己知道什么,也知道不知道什么。而这,或许才是通往“可信赖 AI”的真正路径。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐