资讯动态

FACTS Grounding评测实战:长上下文下如何检测大模型幻觉与引用准确率

发布时间:2026/10/22 3:10:05 来源:尧图企业网站定制
1. 先看懂 FACTS Grounding 到底在测什么1.1 从短上下文到长上下文幻觉的隐蔽性完全不同如果你正在做长文本问答八成绕不开一个词事实接地Grounding。我最近集中跑了一轮 FACTS Grounding 评测目标很明确把模型扔进 32k token 的长上下文里只允许它依据给定材料回答再看它引用得到不到位、每一句话有没有落到源头上。这轮实测我尽量覆盖了能拿到的开源和闭源大模型接口踩了不少坑也有些结果跟主流印象完全不一样。短上下文场景里幻觉其实很容易抓。给定一段 500 token 的材料模型只要稍微偷懒把预训练知识当成上下文内容说出来你一眼就能发现问题。可一旦把上下文拉到 32k事情完全变了。这就好比原来你在桌上找一张纸条现在你要在一个档案室里翻资料相关证据可能分散在前 1/4 处和后 3/4 处中间还夹杂着大量无关叙述。模型如果只会“看开头几段然后凭常识补全”在这种评测里马上现形。更麻烦的是长文档里经常出现“相似但不对”的信息两个项目名称接近、两处日期只差一天、同一个人在不同章节有完全不同的职务描述。模型很容易把A段的事实挪到B段头上或者把两个事实都写出来但互相矛盾。这种幻觉不是整段胡编而是“看起来合理、细节经不起核对”的局部错乱。FACTS Grounding 这类评测恰恰就是冲着这个痛点来的把模型的回答拆到句子级逐个检查有没有引用、引用是否正确、陈述是否被支持。这套评估适合谁我自己是长期在做 RAG 和 Agent 工作流的所以特别需要这种过程级的评测。如果你也在做企业知识库问答、尽调报告摘要、产品手册客服助手、合规审计问答那 FACTS Grounding 的评估方式会非常贴近你的真实需求。它不关心回答是否文采飞扬只关心每句话是不是“从给定材料里长出来的”。这比单一“正确率”有用得多。1.2 FACTS Grounding 不是传统 RAG 评测的简单升级传统 RAG 评测通常只看两件事一是检索出来的文档片段是否包含答案二是生成结果和标准答案的相似度。前者衡量“有没有把正确内容找出来”后者衡量“结果像不像”但它们都漏掉了一个关键中间环节模型到底有没有在生成时真正使用检索到的片段。我遇到过很多次这种情况检索器把关键段落找出来了模型的答案看起来也对但人工去翻原文发现模型引用的是一段压根不相关的内容或者是它自己脑补出来的“正确说法”。传统评测在这个环节会打高分因为答案内容本身和标准答案是接近的。可到了实际业务里用户要求的是“每个结论都能追溯到原文”这种模型就会出问题因为你没法判断哪个回答是真正可信的。FACTS Grounding 把重点从“检索”挪到了“生成后的忠实度验证”。它不再默认“检索到了就等于模型会用”而是强制模型在回答中明确给出支撑来源。判定器再去对照来源和陈述判断这句话到底是“有依据”“无依据”还是“自相矛盾”。这个过程实际上是把 RAG 里最容易被跳过的信任链条重新拉了出来。用生活类比的话传统评测像是“有没有把正确的一本书递给你”FACTS Grounding 则是“要求你当着考官的面从书里找到原文然后用自己的话复述并且每一步都要能指给考官看”。后者显然更接近真实业务里“可核查”的要求。1.3 这种评测最适合啃的硬骨头场景我自己的经验里FACTS Grounding 最适合的场景有一个共同点回答可以不够简洁但必须有据可查。尤其在金融、法律、医疗这类领域一个数字错了可能影响决策一个“看似合理但出处不对”的说法可能引发合规风险。举个例子某企业内部知识库有几十份产品技术手册客服人员需要回答客户关于“某个功能在哪个版本开始支持”的问题。普通评测可能只看模型答没答出“V2.3 开始支持”但实际业务里你可能还要知道这个结论来自哪份手册的哪一节。如果模型说“V2.3 开始支持”但引用的手册里只有 V2.2那这就是一个事实接地错误哪怕最终答案碰巧和标准答案一致。FACTS Grounding 的另一类典型场景是“多文档交叉验证”。比如你给模型 32k 上下文里面有供应商A的报价单也有供应商B的报价单还有一份汇总报告。模型被问到“哪家供应商的总报价更低”时需要在多个文档之间做比较而不是只从一份文档里抄结论。这个过程一旦出现“只参考了一份文档忽略另一份中的额外费用”判定器就会通过无依据或矛盾标记出来。所以如果你做的是通用闲聊、创意写作这种追求发散性的产品我反而不推荐用这套基准因为它的判定标准非常严格甚至会惩罚模型为了流畅而做的同义改写。只要改写后意思与原文档不一致在 FACTS Grounding 里就是一条事实错误。但如果你要的是“每一步都可审计”的答案这可能是目前最值得花时间跑的一套流程。2. 整体设计拆解从“回答得好”到“回答得有据”2.1 一句话评估逻辑生成、引用、判定我跑通一套最小的 FACTS Grounding 流程只需要四步给模型一段或几段长上下文总长度控制在 32k 左右提出具体问题让模型生成带证据引用的回答把回答按句子拆成断言再把每个断言和它引用的原文片段一起送给判定器判定器输出 SUPPORTED、NOT_SUPPORTED、CONTRADICTED 三选一最后聚合指标。这四步里面最容易理解错的是“引用”这个设计。它不是一个单纯要求模型“装模作样标注出处”的形式而是判定器做事实判断的第一步。模型如果输出里没有引用或者引用的片段编号根本不存在判定器会直接判成无依据。你可能想问为什么不直接让判定器读完整上下文去判断那样更省事。但实际操作中让判定器从头到尾读 32k token 再综合判断会导致两个问题一是成本高二是判定器本身也会出现长上下文幻觉它可能只记住首尾部分。所以更稳的做法是把回答拆成句子每个句子单独带上它与原文的局部证据缩小判定范围。这就像人工复核时你不会让人从头读完整个档案室而是把相关的那几页抽出来对照检查。我实际体会到这种“断言级判定”还有一个额外好处它可以定位模型到底在哪一步开始偏离原文。一个句子被判定为无依据你能很清楚地看到是“引用了无关段落”还是“引用内容不足以推出结论”这对于后续调 prompt 或做模型微调都非常有价值。2.2 指标到底在惩罚什么标准答案拆成关键点模型回答拆成断言剩下的事情就交给指标。我习惯同时看四个数事实精确率支持句数 / 总句数惩罚的是模型“多说多错”。事实召回率支持句数 / 标准答案中应覆盖的关键句数惩罚的是“漏说”。引用准确率正确引用片段数 / 总引用片段数惩罚的是“乱挂引用”。综合得分通常用 F1即 2 × 精确率 × 召回率 / (精确率 召回率)。指标计算口径主要惩罚行为事实精确率支持句数 ÷ 总句数幻觉、过度延伸、脑补细节事实召回率覆盖关键点 ÷ 标准关键点漏掉核心信息、答非所问引用准确率正确引用数 ÷ 总引用数引用来源张冠李戴、伪相关引用举个我实测里的例子。某个回答被拆成 10 个句子其中 8 句被判定为支持标准答案里有 7 个关键点模型只覆盖了 5 个引用的 12 处片段里有 9 处真正支撑了对应句子。那么事实精确率就是 0.8事实召回率是 0.714F1 算下来大约是 0.755引用准确率是 0.75。如果没有拆分到这种粒度只看一个“回答正确率”很可能会给出一个虚高的分数。我特别推荐把“引用准确率”单独列出来看因为这是传统评测最容易漏掉的维度。有的模型确实能做到每句话都从上下文里找依据但它找的依据和结论之间是弱相关。比如原文提到“某项目周期是18个月”模型却引用这句话来支撑“某项目成本超支了”这就是典型的引用正确但推理不接地。FACTS Grounding 判定器在训练或调试时会特别留意这种“伪相关”但它不会替你解决你只能在 prompt 设计和人工抽查时不断强化。2.3 为什么偏偏把上下文拉到 32k 量级你可能见过不少评测只做 2k 或 4k 上下文那个太容易过了。4k 上下文大致就是几页文档模型只需在一个比较窄的范围内找答案很多长距离依赖根本没有被测试出来。真正在业务里要处理的材料动辄就是几十页产品手册、一整份市场调研报告、多个部门的预算汇总表这些场景折算成 token 基本都要到 20k 以上。32k 这个量级大致对应一份 50 页左右的技术方案或者一个包含了主文档、附件、历史修订记录的资料包。这个规模能暴露出模型的“长程查找能力”一个关键数字出现在前 1/4另一个关键条件出现在后 3/4中间夹着大量无关描述。模型如果只会“抓开头几段然后凭常识补全”分数会非常难看。我也试过把上下文拉到 64k 甚至 128k但那更多是“能不能读进去”的测试而不是“能不能用好”的测试。64k 以上调用成本陡增延迟也高而且当判定器需要复核引用时候选证据范围太大容易出现噪声。对我这种要跑多模型横向对比的场景来说32k 是在“能暴露问题”和“跑得动”之间比较好的平衡点。如果你做的是具体业务也可以根据自己的材料长度调整但首轮评测我建议还是固定 32k方便和其他模型、其他测试对比。2.4 判定器也是 LLM怎么避免“自己人查自己人”这是很多第一次接触 FACTS Grounding 的人都会纠结的问题既然判定器也是模型它凭什么说生成模型错了如果两个模型串通或者都偏严分数还能信吗我的经验是判定环节要尽量把“综合判断”变成“局部比对”而不是让判定器做开放题。具体来说把回答里的每个断言单独抽出来只让它读这个断言所引用的候选片段然后做三分类支持、无依据、矛盾。这样判定器的任务范围很小更像一个“校对员”而不是“阅卷老师”。但这也意味着你选择的判定器必须足够强。我在跑的时候做过对比弱模型当判定器时会把“无法判定”大量标成“支持”导致框架分数虚高。后来我做了三个改进第一个是给判定器明确的指令要求它“只判断引用内容能否推出断言不要输出解释”第二个是同一批断言跑 3 次取多数票作为最终结果第三个是每隔 50 条做一次人工抽查校正判定器的一致性。这三个改动让排名稳定了很多。我为了保证公平会对所有模型用同一套判定器。但要注意判定器对某些模型的文风可能更友好比如对“长句多、口语化”的回答容易误判。所以在看过一轮结果后我建议把分数异常的样本拉出来做一次人工复核不要急着下结论。3. 完整跑一轮 32k 上下文实测3.1 最小但完整的评测流程整个流程不复杂但每一步都藏了不少细节。我按实际执行顺序拆开讲。第一步准备文档集。把你要测的长文本转成纯文本清洗掉表格里多余的分页符、页眉页脚然后切成带编号的 chunk。chunk 大小我建议控制在 512 到 1024 token 之间切得太小容易把完整语义切断切得太大又会让后续判定器的候选范围变大。如果文档里有表格我建议把表格单独抽出来做一个 chunk因为混合文本切分时表格内容很容易被切得七零八落。第二步构造问题集和标准答案。这是整个评测里最依赖人工的一步。每组问题要配一个标准答案再把标准答案拆成“不可再分的事实点”。比如“某公司二季度营收为 3.2 亿元同比增长 8%”这句话要拆成两个点营收是 3.2 亿元同比增长 8%。只有这样拆模型漏掉一半时你才能准确定位。我第一轮偷懒直接用强模型生成标准答案结果发现它的表达过度抽象很多关键数字被吞掉了导致模型的召回率虚低。后来我老老实实做了 50 条人工标注之后的自动扩展才稍微靠谱一点。第三步构造生成提示词。这里要规定引用格式并明确“只根据资料回答”。具体模板我在下一节展示。第四步调用模型生成回答。温度设成 0关闭随机性。max tokens 设成 512 或 1024不需要让模型长篇大论。记录模型返回内容的同时记录 prompt 中的上下文 token 数方便后续分析“是不是真的塞满了 32k”。第五步调用判定器逐句判定。先把回答按句子拆分再把每个句子和其引用的 chunk 内容打包传给判定器。如果一个句子引用了多个 chunk就同时带多个 chunk 片段。为了控制成本可以一次请求里放多个断言但不要放太多否则判定器可能会把前面句子的判断结果带到后面。第六步汇总指标和排名。把每个模型的精确率、召回率、引用准确率、F1 汇总成一张表并记录每个模型在各问题类型上的单独得分。只有到这一步你才看得出来模型是真的理解长上下文还是靠局部信息硬凑。3.2 数据准备里最容易被低估的一件事我在一开始跑的时候以为文档和问题齐了就能直接测但很快发现最花时间的不是调用模型而是“标准答案关键点”的拆解。如果关键点拆得太粗模型漏掉细节你也看不出来拆得太细又会让召回率低到没有参考价值。后来我定了一个比较实用的规则关键点尽量是“一个陈述只包含一个可验证事实”比如数字、日期、人名、结论、限定条件各算一个点。拿一个实际业务问题来说“请总结这份技术方案中关于数据库迁移的步骤和风险。”标准答案可能会包含迁移分为三个阶段第一阶段是数据备份风险包括连接超时和字符集不一致整体预计耗时三天。这四个点必须拆开不能写成“迁移分为三阶段风险是连接超时等耗时三天”这样笼统的一句话。我还建议在数据准备阶段就把“关键点 id”和“证据 chunk id”关联起来。这样在评测结束后你可以直接追溯“模型漏掉了哪个关键点是从哪些 chunk 里可以找到答案的”。这一步做扎实了后面无论调 prompt 还是选模型都会省很多力气。3.3 生成提示词与引用格式如何设计我用的生成提示词大致是这个结构你可以直接抄去改以下是参考资料总长度约 32k token。请回答用户问题。每条陈述后必须用[来源:X]标注支撑它的段落编号。只能使用资料中的信息不要补充个人知识。如果资料没有提及请明确回答“资料未提及”。这里有个细节引用格式一定要简单、可解析。我建议直接用半角方括号加编号比如[来源:17]不要用“来源第17段”这种自然语言。后续解析时会方便很多。如果模型一句话引用了两个来源就让它连续标注[来源:17][来源:23]。我实际测试下来绝大部分模型都能遵守这个格式但偶尔会出现“引用了但编号不存在”的情况。遇到这种情况判定器会把该句直接判成 NOT_SUPPORTED这也是一种有效的惩罚机制。温度设置方面生成器设 0这是为了可复现。max tokens 设 512 是一个比较合适的值因为长文本问答的要点是“精确”而不是“长篇”。我从实测里发现当 max tokens 设得过高时模型容易在回答后半段开始反复引用同一段内容凑字数限制长度后它反而会更克制更少编造。3.4 判定器提示词设计经验判定器的提示词比生成器更重要。我踩过最大的坑就是早期判定器 prompt 里只写了“判断这个句子是否被引用支持”却没有给它引用原文结果它只能靠自己的知识硬猜导致支持率虚高。正确的判定 prompt 至少要包含四部分问题原文、待判定句子、引用段落原文、判定选项。我给一个模板参考以下是用户问题、模型回答中的单个句子以及它引用的原文片段。请判断该句子是否能被原文片段支持。选项SUPPORTED、NOT_SUPPORTED、CONTRADICTED。只输出一个选项。不要根据常识脑补不要参考材料之外的信息。同时我会特别强调一句“如果引用片段为空或引用编号不存在输出 NOT_SUPPORTED。”这能避免模型把缺引用的情况当成“支持”。试跑时我发现有的判定器在连续多次输出 SUPPORTED 之后会产生惯性即使后面出现了矛盾句也倾向继续给支持。所以我不让判定器一次处理过多句子。一个请求里最多放 5 到 8 个断言每句都带引用片段。如果同一个回答的句子很多我会分成几个请求而不是一把梭。3.5 多模型排行的实际结果示例这次实测我没有使用真实商业产品名而是把它们记成模型代号。原因是不少模型版本更新很快直接报名字容易误导读者。下面这张表是我在 32k 上下文、同一组 200 个问题下得到的一组代表性结果模型代号部署类型事实精确率事实召回率引用准确率32k 稳定性模型X闭源大型0.910.840.89较高模型Y开源中型0.850.760.82中等模型Z闭源较早版本0.780.720.75较低模型X的总分最高但它的回答往往更长精确率被拖到 0.91而不是更高。模型Y在长上下文场景里有个明显问题引用同一个来源的次数过多明显是在找不到其他证据时反复使用同一段内容。模型Z在上下文超过 24k token 后引用准确率开始明显下跌说明它对长上下文的后半段信息利用能力偏弱。这张表给我最大的提示是不能只看平均分。模型Z如果只用于 8k 以下短文本成绩可能和模型X差不了多少但一旦业务场景真的需要读完整份材料差距就出来了。所以在选型时更稳妥的做法是把它业务场景里最长的文档切成 32k 左右做验收而不是只跑短问答。3.6 排行榜不能只看总分只看总分会把很多关键行为差异掩盖掉。我建议至少按问题类型分层看信息抽取类、多跳推理类、矛盾检测类。信息抽取类主要测“能不能从长文本里找到明确的实体和数字”多跳推理类要求把分散在不同 chunk 的信息拼接起来矛盾检测类要求找出上下文里互相冲突的表述并给出准确判断。我实测中发现模型Z总分只比模型Y低 5 个百分点但它在矛盾检测类问题上的得分只有 0.5 左右远远低于模型Y的 0.73。如果一个业务场景是合规审查需要对材料中的前后矛盾做出判断那模型Z基本不能用哪怕它的平均分看起来还能接受。另一个被忽略的点是位置偏差。同一个问题如果相关内容被放在 32k 文档的开头和放在接近结尾的位置模型的分数可能会差很多。我专门做过一组测试把同一份材料翻序再把同样的问题跑一遍。稳定模型在两个顺序下的 F1 变化不超过 3 个百分点不稳定模型却可能相差 10 个百分点。如果你要选型建议把这一项也纳入考量。4. 常见问题与排查技巧4.1 引用没错但句子依然被判定无依据这是我在测评里遇到最多的情况。仔细看之后发现引用编号没错段落也对但模型写的句子比引用内容多了一层“推理”。比如原文说“某项目工期缩短了两个月”模型写“某项目工期缩短了两个月因此成本下降了 10%”。“因此成本下降了 10%”这部分在引用段落里根本没有。判定器不会替你脑补这个因果关系所以它会把这个句子判成无依据。处理方式有两个第一在生成提示词里直接要求“每个陈述尽量拆成单句不要把一个事实和它的推论写在同一句里”第二在判定阶段把句子拆成更细的“原子断言”。如果你发现这种现象很集中说明模型倾向于“过度推出结论”需要在应用层设计时限制它的最终输出比如只允许输出资料中明确出现的结论。4.2 判定器读 32k 上下文时把 token 打爆了怎么办如果你的判定器不支持很大的上下文或者一次传入 32k 导致请求超时解决办法是不要让判定器读完整上下文。它在判断某个句子时只需要读这个句子引用的 chunk以及相邻的一两个 chunk。如果出现“模型没有给引用”的情况那就要先做一次轻量检索用问题里的关键词从长文本里召回最相关的几个 chunk再让判定器在那几个 chunk 上判断。这一步可以明显降低成本也能加快速度。另一点要注意的是如果你的判定器是窄上下文模型它一次只能接受比如 4k token。这时你可以把引用 chunk 分成更小的片段或者使用两步判定先判断“引用是否相关”再判断“引用是否支持陈述”。我实际用下来两步判定虽然多一点请求数但稳定性更好。4.3 为什么模型在处理“判断类问题”时分数普遍偏低判断类问题的典型形式是“根据材料判断某供应商是否符合验收条件”这类问题需要模型把材料里所有相关条目都读一遍再确认没有反例才能给出“是”的结论。但在 32k 长上下文里模型很容易只看到前面几条符合条件就草率写下“符合”结果漏掉了藏在文档后面的一个例外条款。这种问题暴露的其实是模型的“否认能力”不足。解决方式是在评测问题集里增加反事实和反例问题比如“材料中是否提到某功能可以离线使用”即使材料里通篇都是在线使用场景模型也应该回答“未明确提及”而不是从自己的知识里推断“也许可以”。如果你的应用场景里大量存在这种否定判断就要格外关注这项指标而不是只看平均分。4.4 成本控制与并行评估的注意点FACTS Grounding 的 token 大头在判定器不在生成器。假设 200 个问题每个回答拆出 10 个句子就有 2000 次判定。如果每个判定请求都带 2k token 的引用片段总量相当可观。我的做法是先用 50 个问题跑通流程确认 prompt 没有明显问题再跑全量。批量请求是必须的但并发不要开太大。太多并发容易触发限流也可能让网络超时和失败重试变多反而拖慢整体进度。如果你需要多次运行最好把回答结果和引用片段缓存下来只重跑“判定器”环节这样可以节省一大半调用成本。还有一个省钱技巧同一个问题的多个断言可以合并到一个判定请求里。每个断言附带它自己的引用片段请求格式做成列表。这样能减少请求次数但注意不要超过判定器支持的上下文长度。如果合并后经常截断就分成两批。4.5 快速排查表现象可能原因处理建议引用格式正确但句子无依据句子包含引用之外的额外推理拆成原子断言或在生成 prompt 中限制推理性表达引用编号不存在模型幻觉或 chunk 编号解析错误在解析阶段对齐编号缺失编号判为 NOT_SUPPORTED判定器把所有句子都判成支持判定器 prompt 太宽松增加“未提及判为无依据”的硬性说明长上下文后段引用明显减少模型对后文记忆弱重新排列上下文顺序做位置偏差测试成本太高判定请求过多且每次都带长引用先做轻量候选检索再局部判定批量调用5. 我的经验和后续建议跑完这一轮我最深的感受是FACTS Grounding 最好用的地方是它把“模型有没有忠实于材料”变成了一个可回归、可对比的量化指标。以前我判断一个模型适不适合做长文本问答只能靠人工抽读几条回答主观性太强。现在同一组数据跑下来哪个模型在细节上更容易偏离原文哪个模型上下文一长就开始糊弄几乎一目了然。但我也要提醒三点。第一标准答案关键点不要因为模型强就迁就它的生成形式。有的模型写得精简恰好避开了你没标注的细节分数会虚高实际业务里你可能恰恰需要那个被省略的细节。第二判定器的人工校准不能省。我每隔 50 条人工抽查 10 条才发现了判定器在“同义改写”上过严的问题校正之后排名才比较可信。第三不要只看综合分。综合分可能被“简单抽取类问题”拉高而真正有业务风险的是低频率但高后果的“矛盾检测类问题”。后续可以把这个流程直接接进 CI每次改 prompt、换模型、更新知识库都自动跑一遍同一组 FACTS Grounding 回归集。你也可以做“上下文增长曲线”同一组问题分别给 8k、16k、32k 上下文看分数下降的斜率。这个曲线比单点分数更能说明长文本能力的变化。最后分享一个我在评估中踩得最深的坑早期我看到模型输出里的引用格式规规矩矩就以为事实一定正确结果人工复核才发现很多引用是伪相关的——段落标题相关内容根本不支持结论。后来我坚持把引用内容和断言一起送进判定器这个遮羞布才被扯下来。希望你在跑第一轮 FACTS Grounding 时就直接把这一步做好省得到后面推倒重来。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑