「有出处」这三个字现在被用得太松了。模型在答案末尾贴一排 [1][2][3],点开发现链接是真的,但那段原文里没有它引的那句话——这不是引用,是装饰。我的判断很直接:编号不该由模型生成,模型只该输出答案和它实际读过的 chunk ID,编号、链接、跳转位置由系统渲染。做不到这一步的,就别在 UI 上写「有出处」。
让模型自己编号,等于让它给自己发牌照
模型写 [3] 的时候,它是在做语言建模,不是在查表。它见过太多「带引用的文本长这样」,所以它能写出一段形式上完美、编号分布也合理的引用段落。编号对不对,和它写得像不像,是两件事。
这周 Caught in the Act 那篇讲的东西可以借过来看:模型的行为和它嘴上说的可以不一致,探针能在白盒里抓到它没说出口的部分。引用编号是同一个问题的小号版本——模型说「依据是第 3 条」,第 3 条到底是不是依据,得从外面验。它自报的证据,和它的行为,本来就该分开检查。
结构化返回的改造成本,卡在工具那一侧
反面意见我认同一半。这确实有成本,而且不在模型侧。模型侧好办:function calling 里加一个 citations: [chunk_id] 字段,prompt 里写清楚「只填你真正读过的 ID,没读过就留空」。
真正的坑在检索工具:你的 chunk 得有稳定 ID,得能按 ID 反查回原文位置(文件 + 行号,或者页号、时间戳),切片策略改了 ID 还不能漂。大部分团队的 RAG 现在停在「返回一段拼接好的文本」这个阶段,chunk 是临时的、没有身份的。要加 ID,等于回头补一遍索引层。
问题在这。这笔钱早晚要付,晚付更贵——等到出过一次事故再补,代价就不只是工时了。
一个土标准:点不到原文位置,就不算出处
我自己的验收方式很笨。随机抽答案里的每句结论,让它给出对应的原文位置,然后我手动点过去——不是我读,是看那句话在不在那儿。
三类结果:位置对、原文确实支持这句,过;位置对、原文只是同主题但不支持这个结论,打回;位置是编的,整条链路重做。第二类最常见,也最容易被放过,因为链接点得开,人一看就信了。
这周 Accurate but Not Humble 那篇讲的是同一件事的另一面:检索到的证据和模型原有判断冲突时,它会不会改口、会不会承认不确定。他们的观察不乐观。放到引用上就是——模型宁可给一个自洽的答案配一个像样的出处,也不愿意说「这条我没找到依据」。
所以 UI 上得留一个位置给「无出处」,而且要让它体面。否则模型永远倾向于编一个。
溯源不止是文本
OpenAI agent 在 Wikimedia 上的活动 那件事,讨论焦点是 agent 干了什么、谁授权的。这其实是行为层面的溯源,和文本引用是同一个需求:任何一句结论,都得能指回一个具体位置。文本那头是 chunk,行为那头是 log 行。两边都缺 ID,事后只能靠猜。
这周外部没什么新方法论。ArXiv 上还有几篇讲 agent 监控和轨迹干预的(比如 OnTrack),能当论据,不能当方案。方案还是老一套:让模型负责选,让系统负责渲染,让验收负责打假。
按我现在看,明年这时候还没做 chunk ID 的 RAG 团队会有一批在补课。也许我被打脸——那更好。