你的机器人召回率92%,为什么还在编造数字?

这是每个做检索增强生成(RAG)的团队都踩过的坑。上线一周,财务用户投诉:机器人引用的数字在检索到的文档里根本不存在。你重跑评估——召回率还是92%。那个编造的数字,依然编造。

打开网易新闻 查看精彩图片

召回率@K(Recall@K)只回答一个问题:相关文档有没有进前K?它不告诉你模型有没有用那段文本,不告诉你答案是否有依据,不告诉你换个说法结果会不会变。这三件事它全沉默,而你的用户全看得见。

这篇笔记聊三个补位指标:忠实度、覆盖度、鲁棒性。文末附100行Python代码,一次跑完四项指标,零框架绑定,依赖只有OpenAI接口、NumPy和标准库。

召回率的盲区:检索之后发生了什么

召回率是检索指标。它把系统当搜索引擎,问的是"相关片段进前五了吗"。这确实该测,但该测的不止这个。

问题是检索之后的一切,它都看不见。

一个检索器召回率@5能到0.95,你的机器人照样能:

• 把"营收增长12%"说成"营收增长120%"

• 用文档A的数据回答文档B的问题

• 用户问"Q3表现如何",它答成"全年表现"

• 文档里有"可能上涨",它输出"确定上涨"

这些故障召回率全不反映,客服工单全反映。

下面三个指标填这个坑。它们不是新概念——TruLens的RAG三元组把"扎根性"和答案相关性放在上下文相关性旁边,Ragas的忠实度指标把答案拆成声明逐条核对。实际缺的是接线:一个统一跑四项的框架,让某项退化能跟别的指标出现在同一块看板。

指标一:忠实度——每个声明都要有出处

忠实度只问一件事:答案里的每个声明,能不能指到支持它的片段?能,得1分;一半能一半靠模型记忆,得0.5分;答案洋洋洒洒全是检索上下文里没出现的事实,得0分——你的机器人在带引用地幻觉。

标准实现两次调用大模型。第一次,把答案拆成原子声明;第二次,对每个声明做自然语言推理(NLI):上下文是否蕴含该声明、矛盾、还是无关?得分是"被蕴含"声明的比例。

Ragas叫这个Faithfulness。DeepEval叫FaithfulnessMetric,定位为生成端检查。TruLens叫Groundedness。区别在提示词措辞和聚合方式,形态一样。

上线阈值:评估集忠实度低于0.85算退化,低于0.75说明机器人在稳定编造。

今天就能跑的廉价版本,不拉框架:让评判模型列"答案里哪些事实声明不在检索上下文中"。列表为空则忠实,非空则标记幻觉。

指标二:覆盖度——该说的有没有漏

忠实度防编造,覆盖度防漏答。用户问三个问题,机器人只答两个,忠实度可能满分——它没说的自然没被验证为假。

覆盖度测量答案对问题的完整回应程度。实现方式:把问题拆成子查询或关键信息点,检查答案是否每个都提到。Ragas的AnswerRelevancy和DeepEval的ContextualRelevancy走这条路。

一个典型陷阱:用户问"对比A和B两款产品的价格和性能",机器人只讲价格。忠实度检查通过——提到的价格都有出处;覆盖度检查失败——性能部分完全缺失。

覆盖度低的问题比幻觉更隐蔽。用户不会立刻投诉"你漏了",只会觉得"这机器人不太聪明",然后默默流失。

上线阈值:覆盖度低于0.8需要审视提示词是否过度约束长度,或检索片段是否切断了关键上下文。

指标三:鲁棒性——换个问法答案变不变

鲁棒性测的是:问题改写后,答案是否一致且仍基于检索内容。

实现方式:用LLM生成语义等价的问题变体(主动改被动、加细节、换同义词、换语言),跑完整RAG链路,检查:答案是否矛盾?引用的片段是否漂移?忠实度和覆盖度是否崩盘?

这是生产环境的噩梦场景。用户不会按你的评估集提问。销售问"Q3营收",财务问"第三季度收入",老板问"上个季度我们赚了多少钱"——三个问题指向同一答案,你的机器人给的是同一个吗?

鲁棒性差的系统,客服会收到大量"我问过了,再问一遍答案不一样"的投诉。更隐蔽的是引用漂移:问题改写后,机器人换了一批检索片段,新片段支持新答案,表面自洽实则来源混乱。

上线阈值:鲁棒性测试通过率低于0.9,说明检索或生成对问题表述过度敏感,需要加固查询扩展或重排序策略。

四项指标一起跑:代码骨架

核心思路:一个数据类存单次RAG调用的全链路(问题、检索片段、答案),四个评分函数各自消费这个数据类,输出0-1分数。

数据结构设计:

• 问题原文

• 检索片段列表(含内容、来源、排名)

• 生成答案

• 可选:问题改写变体列表

召回率@K:检查黄金答案的片段是否在检索结果前K位。传统指标,保留用于监控检索器本身。

忠实度:LLM提取答案声明→逐条NLI验证→计算支持比例。

覆盖度:LLM提取问题的信息需求点→检查答案提及比例。

鲁棒性:生成N个问题改写→各跑一遍RAG→答案一致性检查(NLI互证)+ 片段重叠度。

关键设计:所有LLM调用走同一客户端,prompt模板外置可替换,评分结果结构化输出便于入库。没有框架魔法,就是明牌逻辑。

依赖控制:openai(或任意OpenAI兼容接口)、numpy、标准库。评估黄金集建议50-200条,覆盖高频问题类型和已知边界案例。

为什么现在就要加这三项

召回率92%的幻觉,和召回率70%的幻觉,对用户来说没有区别——都是不可信。区别在于前者让你误以为自己测过了,后者至少知道有问题。

忠实度、覆盖度、鲁棒性不是"更高级的指标",是召回率原本就该覆盖但没覆盖的维度。它们把评估从"检索器好不好"扩展到"整个系统能不能用"。

生产环境的诡异之处:这三项退化往往是渐进式的。某次模型升级、某次提示词优化、某次片段长度调整,不会动召回率,但会让忠实度从0.9滑到0.7。没有专项监控,这个滑坡会在客服工单里累积几周才被发现。

100行代码的.harness价值不在代码量,在强制四项同跑。回归测试时,任何一项抖动都暴露在同一视图,避免"召回率稳如狗,用户骂成狗"的盲区。

落地建议:从哪开始

已有RAG系统的团队,建议按这个顺序补指标:

第一周:加忠实度。幻觉是最痛的投诉类型,有出处检查至少能定位问题答案。

第二周:加覆盖度。复盘过去一个月的"答非所问"工单,把高频漏答模式做成测试用例。

第三周:加鲁棒性。从生产日志抽取用户问题的自然变体,或让运营同事用口语重述标准问题,跑批量对比。

黄金集构建原则:每条用例必须人工标注预期答案和关键声明,否则自动化评分无锚点。优先覆盖:数值类问题(易幻觉)、多条件问题(易漏答)、时间范围问题(易漂移)。

评分阈值不是圣经。0.85的忠实度在医疗场景可能太低,在闲聊场景可能过度。关键是建立自己数据的基线,监控相对变化而非绝对数值。

最后

RAG评估的陷阱,是用了搜索引擎的指标来测对话系统。召回率@K诞生于信息检索论文,它的假设是"列出相关文档即完成任务"。生成式AI打破了这个假设:文档列出来了,模型读没读、读对了没、记混了没、换个问法还认不认——这些才是用户实际体验。

忠实度、覆盖度、鲁棒性不是花哨的新概念,是召回率时代被搁置的老问题。现在补上,是因为生成模型让这些问题变得致命。一个带引用的幻觉,比一个赤裸裸的幻觉更难被用户识破,也更损害信任。

你的评估集里,有多少条用例同时跑了这四项?如果答案是"没统计过"或"只看了召回率",那个92%的数字,可能正在让你睡得太香。