☰
10_生成端的最后一道闸_引用编号校验与两道拒答
2026/10/9 7:54:54 网站建设 项目流程

生成端的最后一道闸:引用编号、校验,和两道拒答

很多人把 RAG 的成败全押在"检索得准不准"上。但检索做得再好,最后一步没约束住,就是白做——模型可以无视检索结果,自己编一段通顺但错误的话出来。这篇讲我在生成端加的三道约束。

一、引用:既要编号,又要校验

给模型加提示词约束只是第一层:

1. 每个结论后标注来源编号,如 [1][2] 2. 只使用提供的文档,不得夹带文档之外的知识 3. 若文档不足以回答,直接输出 NO_ANSWER

但只有这三句是不够的。编号只是让"根据文档所述"变得可验证;校验才是让编号不是装饰。

没有校验时,"带引用"就是纯粹的装饰——模型完全可以编一个[3]出来,而[3]在原文里根本不存在。所以我加了一个extract_cited步骤:把答案里出现的所有[n]抽出来,逐个比对检索回来的文档,看这个编号是不是真被引用了、对应内容是不是真在那个文档里。

引用校验是唯一能被自动化发现的幻觉信号。模型编一段假话你很难自动判断,但模型编一个不存在的[3]是可以被代码抓住的。

实测:瞎标率 0/29。这不是说模型不会幻觉了,是说"乱编引用"这一种幻觉被堵住了——剩下的幻觉要靠 LLM-as-judge 去抓,那是下一周的事。

二、两道拒答闸门,是被数据逼出来的

"答不上来就拒答"是 RAG 的基本功。但拿什么判断"该拒答",我一开始想当然用了向量相似度,结果被实测数据打脸:

组向量相似度 p50
命中组(有答案)0.775
未命中组(没答案)0.749

几乎一样。因为 API 文档语料高度同质化,一个域外问题和域内问题,向量分都落在 0.75 上下,余弦根本区分不了"像不像"和"能不能回答"。

所以我把拒答拆成了两道闸门:

  • 闸门①(检索侧,阈值 0.40):只挡"跑题"的。域外问题向量分落在 0.236~0.397,全拦下,而且这一步成本是 0——不用调 LLM;
  • 闸门②(生成侧):兜住"域内但答非所问"的——域内问题向量分不低,但文档里其实没有答案,交给模型自己输出 NO_ANSWER。

两道都要有,不是设计癖好,是被数据逼出来的。余弦这道闸只能挡明显的域外问题,挡不住"看着相关但答案不在文档里"的,后者只能靠模型。

三、为什么拒答阈值用向量余弦,而不是融合分

既然有了混合检索,为什么不用融合分(RRF)做阈值?因为融合分是1/(60+名次)的累加,取值范围只有0.016~0.033——这么窄的区间根本选不出有意义的阈值,而且换个 k 值全部失效。

向量余弦是 0~1,语义直观:“低于 0.40 就不答”,谁都听得懂、也好调。

四、三道闸实测的拒答率

50 条 golden set + 18 条拒答集,三种模式的拒答率:

模式abstain_rate
纯向量0.16
纯 BM250.28
混合0.20

拒答率不是越高越好,也不是越低越好——它是准确拒答的比例。纯 BM25 拒答率最高(0.28),但这不代表它最好,因为拒答率要跟"该拒的有没有拒、不该拒的有没有误拒"一起看。这正是评测要回答的问题,下一篇讲。

小结

结论数字 / 事实
引用要编号 + 校验编号可验证,校验是唯一自动幻觉信号,瞎标率 0/29
两道拒答闸门余弦挡域外(成本 0)+ 模型兜域内
余弦分不了"像不像"和"能不能答"命中 0.775 vs 未命中 0.749,几乎一样
拒答阈值用余弦不用融合分融合分 0.016~0.033 太窄
闸门①阈值0.40,域外问题 0.236~0.397 全拦

上一篇:混合检索为什么用 RRF。下一篇:给 RAG 建 baseline。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询