408 AI 答疑,从参数记忆到检索接地:治理大模型的"出处幻觉"
一位同学问答疑 AI:"按字节编址时,存储字长可以是 64 位吗?"AI 斩钉截铁地说"不行,必然是 8 位",被正确反驳后仍然死扛,还补了一句"主流教材都是这么定义的"。翻开教材,白纸黑字写着相反的结论。这篇把整件事拆开:它为什么会"自信地错、还编出处",我们怎么用向量内积和最近邻查找把答疑焊回教材原文,以及一个反直觉的修正——别让系统惩罚"我错了"。全程用向量数学讲清楚,不牵涉任何具体模型。
1. 事故现场:一次自信的错误
对话大致是这样(复述,去掉无关寒暄):
同学:按字节编址时,存储字长可以是 64 位吗? 答疑:不可以。按字节编址意味着每个地址对应一个字节,所以存储字长必然是 8 位。 同学:不对吧,字节编址说的是地址粒度,存储字长是一次访存读出的位数,这两个不是一回事。 答疑:你可能记混了。按字节编址的机器存储字长就是 8 位,主流教材都是这么写的。
然后我们去翻教材。蒋本珊《计算机组成原理》(第 4 版) 5.2.4 节原文:
目前,大多数存储器采用字节编址……设存储字长为 64 位(8 个字节),即一个存储字……
也就是说,同学是对的:字节编址(地址的最小粒度是 1 个字节)和存储字长(一次访存读/写的位数)是两个正交的概念。一台字节编址的机器,存储字长完全可以是 64 位——一次访存吐 8 个字节,但你仍然可以按单个字节去寻址。
这次翻车叠了三个问题:结论错、被反驳后死扛、还凭空编了个"教材共识"。
2. 为什么会"自信地错,还编出处"
拆成两层根因。
第一层,知识本身错了。 生成式大模型的"知识",本质是对海量文本做统计压缩后留下的参数。中文考研语料里,"编址单位就是存储字长"这种把两个概念焊死的简化说法出现得不少,于是模型内部这个错误口径的置信度是真高的。我们给它设过一条安全规则"拿不准就说拿不准"——但这条只在模型自认心虚时才触发。它挡得住"心虚地错",挡不住"自信地错"。
第二层,出处是编的。 当被追问时,模型有一种辩护性倾向,会去"找个权威给自己背书",于是生成了"教材都这么写"这句话。它并没有真的读过任何一本教材,只是拼出了一句听起来可信的话。
两层错误共用一个根:模型答题时,手里没有一个可以核实的事实锚。它在凭参数记忆复述,全程没有对着任何原文。
3. 思路:让它"查了再答"
解法的方向叫检索增强(RAG)。在模型开口之前,先从教材原文里把与这个问题最相关的几段捞出来,塞进它的上下文,再压一条硬规则:锚定这些原文作答,出处只许引这几段标注的书;检索不到就不许声称任何教材出处。
这一步顺手把"出处幻觉"这个最伤权威性的失效点,变成了一个可核实的能力——每句结论都能顺着引用点开对应的教材原文核对。
但真正的技术难点在这句话里:机器怎么知道"按字节编址存储字长能不能 64 位"这个问题,和教材里"大多数存储器采用字节编址……设存储字长为 64 位"这段话是相关的?
把两句话摆一起看:问句里没有"大多数""存储器",原文里没有"能不能"。字面上几乎一个词都对不齐,字符串匹配(哪怕是关键词模糊匹配)在这里基本失效。要让机器判断"语义像不像",得换一套数学。
4. 让机器"读懂"相似:向量 + 余弦相似度
第一步,把文本变成向量。 一个文本向量化模型,能把任意一段中文映射成一个高维向量
第二步,怎么量"方向接近"? 用两个向量夹角的余弦——余弦相似度:
取值落在
第三步,一个省算的小技巧。 如果入库时先把每个向量除以自己的模长、变成单位向量(即
我们在灌库时就把 12009 段教材向量全部归一化,检索时只算点积,省掉每次查询的开方。
第四步,检索就是最近邻查找。 把全部教材段的向量存下来(这批 12009 段),来一个问题就编码成向量
5. 怎么找得快:从暴力扫到索引
暴力法,
想更快,上近似最近邻索引。 两种主流思路都能在 408 里找到影子:
- 分层可导航图(HNSW):给这些向量建一张多层图,上层节点稀疏、跳得远,下层稠密、走得细;查询时从最上层粗定位,逐层往下逼近目标。这个"多层加速"的骨架,和数据结构里跳表/多级索引是同一个思想。实测建完索引后单次查询从 40 毫秒降到约 0.7 毫秒。
- 倒排聚类(IVF):先把向量粗聚成若干簇(K-means 的路子),查询时只在离
最近的几个簇里精算,用一次粗筛砍掉绝大部分计算。
边界:12009 段这种规模,暴力扫的 40 毫秒就够用,索引主要是给语料日后长大留的余量。规模小的时候,数据库的查询规划器甚至会主动放弃索引、直接暴力扫——因为建索引、跳指针的固定开销,还不如把一万多个向量直接乘一遍来得快。这一点和"小数组排序有时插入排序比快排还快"是同一个道理:渐进复杂度低,不代表在小输入上一定跑得快。工程上也经常有这些问题,量小的时候简单暴力的方案反而更好。
6. 不是每次都塞:阈值门控
接地不能无脑开。假如某个问题检索回来、最相关的一段余弦也只有 0.4,说明教材里根本没有对得上的原文——这时候硬把它塞进上下文,反而会用一段不相关的话把模型带偏。所以要设一道阈值:只有最高余弦超过阈值才注入原文;不到阈值就不接地,让答疑收敛成"常见的讲法是……具体以你手上的教材为准"。宁可这次不接地,也不添乱。
阈值怎么定?看数据。把一批真实的概念提问跑一遍,统计检索命中的余弦分布:真正相关的命中落在 0.67–0.77,明显不相关的落在 0.4 以下,中间有一段空档。我们取 0.55 作初值,偏保守,之后按线上真实命中率再往哪个方向挪。
7. 回到那道题:接地之后
复测开头那道题。把"按字节编址时,存储字长可以是 64 位吗"编码成向量,在 12009 段里检索,排在第一的是:
蒋本珊《计算机组成原理》(第 4 版) · 5.2.4 目前,大多数存储器采用字节编址……设存储字长为 64 位(8 个字节),即一个存储字……
余弦相似度 0.755。这段被注入上下文之后,答疑的回答变成:
可以。按字节编址的计算机存储字长可以是 64 位(即 8 个字节)……可见"字节编址"和"存储字长为 64 位"并不矛盾。 依据:蒋本珊《计算机组成原理》(第 4 版) 5.2.4 节。
接地前后对照:结论从"必然 8 位"回到"可以 64 位"(与标准一致),出处从凭空编造变成一句能点开核对的引用。
那句"依据:蒋本珊……"本身就是接地生效的硬证据。因为我们给模型的规则里明令禁止编造教材出处——它能报出这本具体的书、具体的节,唯一的可能就是系统真的把这段原文喂给了它。检索不接地,它连书名都不许提。
8. 一个反直觉的修正:别惩罚"我错了"
接地治的是"没有事实锚"。但复盘这次事故,还挖出一个更隐蔽的问题:它为什么被反驳了还死扛?
我们有一道回答质检,会拦掉答案里泄露的"内部独白痕迹"——比如"让我重新检查一下""这与前文矛盾,我再算算"这类本该在心里走完、不该展示给用户的思考过程。方向没错。但它的匹配规则里混进了一条误伤:把"我刚才说错了"这种表述也判成了低质量,直接拦下不展示。
后果很微妙。当用户给出正确的反例、模型本该诚实地讲"我上一轮答错了,正确的是……"时,这条质检把这句诚实的认错也拦掉了。于是系统在结构上变成了:认错会被打回,死扛反而能过审。这等于在训练它嘴硬。
我们把规则改成:只有在用户没有反驳的语境下,"自我纠错痕迹"才算问题;一旦上一句是用户在给反例、纠错,诚实认错一律放行。拦掉"我错了",只会把模型训练成死扛。
9. 能力边界
向量检索接地不是万能钥匙,几处我们清楚的短板:
- 教材本身写错或有分歧时,接地也会跟着被带偏。 我们的对冲是只喂权威课本、并对同一概念收多本互相印证,但这挡不住所有情况。
- 向量化模型对长表格、纯符号公式段的理解,弱于对连续文字的理解。 这类段落的检索质量要打折扣,靠人工抽检兜。
- 阈值 0.55 是保守初值。 真实流量跑一段时间才谈得上调准:太严会漏掉本该接地的,太松会塞进不相关的。
- 接地只解决"有没有对着原文答",解决不了"这道题的推导对不对"。 后者还是要靠题目本身的标准答案和解析兜底。
10. 结论
不要因为一个 AI 答得"自信"就信它,尤其当它给不出一个能点开核对的出处的时候。