大模型幻觉怎么治?引用溯源兜底实操

先把结论甩前面:想让大模型别瞎编,靠 prompt 写「请不要编造」基本没用,得逼它每句话都挂知识库的引用来源,查不到就老老实实说不知道------这套组合拳我跑了两周,幻觉肉眼可见地降了。下面是我自己踩过坑后总结的步骤。

事情起因挺糟心的。上个月我给一个内部客服场景做问答机器人,测试同事问了句「我们 7 天无理由退货的运费谁出」,模型答得那叫一个流畅,条款编号、责任划分、甚至「依据《消费者权益保护法》第 X 条」都给我编出来了。我一查知识库,根本没这条。那一刻说实话我有点冒汗------要是这话发给真实用户,售后得炸。

so,问题不是模型笨,是它太想讨好你,宁可编也不肯空着手回来。治法分三步走。

第一步:怎么强制它带引用

核心就一句话,把「答案」和「证据」绑死,没证据不许出答案。

  1. 改造检索环节,给每个知识块打 ID。 我把知识库切片的时候,每个 chunk 存进向量库时都带上 doc_id + chunk_id + 原文片段。检索回来的不是一坨纯文本,是带编号的结构化片段。

  2. system prompt 里把输出格式钉死。 不是泛泛要求「请引用」,而是给死格式:

    你只能依据【参考资料】回答。
    每个结论后面必须紧跟来源标记 [来源:chunk_id]。
    没有任何参考资料支撑的句子,禁止输出。

  3. 检索结果按编号喂进去。

    【参考资料】
    [1] (chunk_0312) 退货运费由消费者承担,除非商品存在质量问题...
    [2] (chunk_0455) 质量问题退货,运费由商家承担...

这样模型答「质量问题退货运费商家出 来源:chunk_0455」,你一眼能核对。我测下来,带强制引用格式后,那种张口就来的法条编号基本消失了------因为它发现资料里压根没有,凑不出 [来源]

|---------------|----------|-------|
| 做法 | 幻觉表现 | 可核查性 |
| 裸 prompt 问答 | 高,爱编条款 | 几乎为零 |
| 让它「尽量引用」 | 中,引用还是假的 | 看运气 |
| 格式钉死+chunk_id | 明显下降 | 能逐句对照 |

第二步:查不到怎么办

这步才是真正的兜底,也是最容易被忽略的。光要求引用不够,得给模型一条「体面的退路」,否则它为了凑引用会去硬蹭最沾边的那个 chunk,照样错。

  1. 设相似度阈值,低于线直接判为「无依据」。 我用的余弦相似度,卡在 0.78(这个值跟你的 embedding 模型强相关,别照抄,自己 grid 一下)。检索回来 top 片段都低于阈值,直接不把资料喂给模型,后端就返回固定话术「这个我没查到」。

  2. prompt 里显式授权它说不知道。 很多人忘了这条。你得明明白白写:「若参考资料不足以回答,请回复『根据现有资料无法确认』,不要猜测。」给了这句,模型才敢空手而归。

  3. 做一道事后校验。 答案生成后,我再跑一遍轻量检查:把回答里每个 [来源:xxx] 抠出来,验证这个 chunk_id 真在本次检索结果里、且原文确实支撑该句。对不上的,拦截重答或降级成「无法确认」。这步拦下来过好几次模型自己编 chunk_id 的骚操作......对,它连引用编号都能编,离谱。

搭这套验证我没写多少代码。智能体那部分是在一个零代码就能配知识库的平台上拖出来的,挂个现成大模型、把切好片的私有文档传上去、相似度阈值和兜底话术在界面上配,一个下午搞定了第一版。当然第一版很干,纯能跑,话术生硬得像机器人念稿,后面又手动调了好几轮 prompt 才像个人话。它也只干「检索+约束输出」这种杂活,真正的业务判断还得我自己定规则,别指望它替你思考。

结论

折腾下来我的体会是:大模型的幻觉治不了根,但能「关进笼子」。这个笼子就两根栏杆------答案必须挂可核查的来源 ,够不着就允许它说不知道。把这两条做扎实,模型从「自信地胡说」变成「诚实地有限」,对生产环境来说,后者安全太多了。

代价当然有:相似度阈值卡严了,一些其实能答的也被挡成「无法确认」,召回率掉了点;事后校验也多一道延迟。这是我愿意付的------客服场景里,答错一次的成本远高于答「不知道」一次。

(模型/API 我直接调的讯飞星辰 MaaS,现成大模型拿来就用,知识库 RAG 也在上面配的,没自己部署算力)

你们治幻觉是靠引用溯源,还是另有招?阈值都卡在多少?评论区聊聊,我那 0.78 调得到底对不对我自己也没底。