我最近做了一个小实验,想验证一个很朴素但我觉得很重要的问题:
当我们给大模型做外部知识注入时,真的应该默认“能塞多少就塞多少”吗?
在很多 RAG 或知识增强系统里,一个很自然的直觉是:为了减少事实错误,最好把相关知识尽可能完整地放进上下文。这个直觉当然不荒谬,但它隐含了一个假设:更多上下文,通常意味着更好的答案。
我想测试的恰恰是这个假设的边界。因为在实际系统里,注入过多上下文至少会带来两类问题:一类是直接的 token 成本;另一类更微妙——真正重要的信息,可能会被冗余信息稀释掉。 在我的实验报告里,这个问题被明确表述为一个“selectivity problem”:外部知识不是只问“要不要注入”,而是要问“应该注入多少、注入哪些”。
这篇文章记录的是一个很早期、但我认为值得继续追下去的结果:在一个固定 benchmark 上,更严格的知识注入策略,确实表现出了比 full injection 更好的质量—成本方向。不过我先把结论说在前面:这还是一个feasibility-level 的信号,不是已经被充分证明的普适规律。
我想解决的不是“有没有知识”,而是“该注入多少知识”
我的实验场景是 investment QA。核心并不是设计一个新的语言模型架构,而是在固定 benchmark、固定评分规则、固定候选知识 universe 的前提下,比对不同知识注入策略的效果。原报告里把目标写得很清楚:不是做新模型,而是测试更严格的 injection policy 能否在固定评测条件下带来更好的 accuracy-cost balance。
换句话说,我研究的不是“LLM 需不需要外部知识”,而是另一个更工程化的问题:
如果模型本来就已经稳定知道一部分事实,那我是不是不应该再把这些事实反复塞进 prompt?
这是一个很小的问题,但我觉得它很值得做。因为它同时碰到了三个系统层面的核心变量:回答质量、上下文预算和运行成本。
我的核心假设:shared facts 可能会稀释真正有用的 facts
为了把这个问题说清楚,我先用 probe 去测试模型对候选事实的掌握状态。然后把候选 facts 分成三类:
shared:模型已经能稳定答对。
missing:模型通常答不出来。
conflict:模型倾向于答出非 gold 的错误事实。
基于这个划分,我比较了三种方法:
B_KG:把所有 eligible facts 全部注入。
PI_KG:只注入 probe 选出来的 facts,也就是 missing ∪ conflict。
PI:不做完整的 KG-style injection,只注入 probe-informed patch text。
这里最关键的一点是,B_KG 和 PI_KG 的差别非常干净。
在形式化定义里,B_KG 用的是整个 probe-qualified universe U,而 PI_KG 用的是 U \ shared,也就是去掉那些已经被判定为 shared 的 facts。报告里还特别强调了公平性约束:InjectSet(g) ⊆ U、zero unprobed usage、zero universe violations。这样做的目的,就是尽量把结果归因到“注入策略不同”,而不是归因到“数据集不一致”或“偷偷用了额外信息”。
我真正想验证的机制命题其实只有一句话:
对当前问题真正有增量的信息,不一定是“更多事实”,而更可能是“纠偏事实”。
如果 shared facts 本来就是模型稳定知道的内容,那它们带来的可能主要不是新增信息,而是新增长度。相反,真正值得留在上下文里的,可能是那些 missing 和 conflict 的部分。
实验是怎么做的
这次实验用的是一个固定的 200 题 investment QA benchmark。每道题有 issuer、as-of date、target fact 和 gold answer。题目分布在四个 fact family 上:executive 49 题、guidance 95 题、segment 43 题、event 13 题。候选事实一共 273 个,probe 总调用 819 次,也就是每个 fact 做 3 次 probe。gold answers 和 scoring rules 都在评测前冻结。
整个 pipeline 也尽量保持简单和固定:先构造 as-of boundary 下的 resolved state,再给 candidate facts 做 probe labeling,然后为每个方法构造 injection set,最后在同一模型、同一 prompt protocol 下生成答案,并用同一个 deterministic correctness rule 评分。控制条件包括:同一题集、同一 correctness rule、同一 fairness checks,以及没有 post-hoc relabeling。
我很在意这个实验设计的一个点:
它不是“换一堆东西然后看谁更强”,而是尽量把变量压缩到注入策略这一件事上。对个人研究项目来说,我觉得这比堆更多 fancy 组件更重要。
结果:更少注入,方向上更好
结果先直接给出来。
在 200 道题上:
PI_KG:170 / 200,85.0%
B_KG:163 / 200,81.5%
PI:145 / 200,72.5%
从 token 成本看:
PI_KG 总 tokens:1,210,181
B_KG 总 tokens:1,278,729
两者相比,PI_KG 少用了 68,548 tokens。
如果只看 headline,这个结果已经很有意思了。因为它不是“更准但更贵”,而是略更准,同时也更省。原报告里把这一点总结得很直接:质量和成本朝同一个方向移动,这会让结果的工程意义明显增强。
更细一点看 question-level paired outcomes,PI_KG only 的题有 23 道,B_KG only 的题有 16 道,另外 161 道是 tie。也就是说,改进并不是全局翻盘,而是集中在一小部分题上。报告里对这个现象的解释也比较克制:绝大多数问题没有变化,所以实际价值取决于这些“被改好的题”在真实下游场景里的频率和重要性。
这也是我很愿意保留的一个语气:
这不是大胜,这是一个方向性更好的 operating point。
为什么“少一点”反而可能更好
我觉得这次实验最有价值的地方,不只是那 3.5 个百分点,而是它给出了一个很具体的机制解释。
原报告里的表述是:PI_KG 本质上等于 B_KG 去掉那些被标记为 shared 的 facts。 既然 shared facts 已经是模型稳定知道的内容,那么删掉这些冗余事实后,真正有纠偏价值的 missing / conflict facts 就可能变得更显眼。报告把这个解释称为 reduced context dilution:减少冗余注入,可以提高 corrective facts 的显著性。
我非常喜欢这个解释,因为它不依赖一个夸张的新理论。它只是把一个常识变得更可操作:
不是知识越多越好,而是增量知识越纯越好。
如果这个机制在更多任务里成立,那很多知识增强系统的默认策略都值得重新想一遍。也许我们真正该优化的,不是“召回更多”,而是“过滤掉模型已经会的那部分”。
这个收益不是均匀发生的
另一个值得注意的现象是,收益在不同 fact type 上并不均匀。报告中的 fact-type analysis 明确指出,提升是conditional rather than uniform,而不是所有类别都平均受益。样本分布也不均衡:event 只有 13 个样本,所以几道题的翻转就会带来很大的可视波动。
这件事对我后续做框架很重要。它意味着以后如果我要把这个思路继续做下去,系统不应该只有一个统一的“selective injection 开关”,而更可能需要按 fact family 或任务类型做更细的策略。比如某些类别里,baseline knowledge 已经很强,那么额外注入的收益就会变小;另一些类别里,missing / conflict 更常见,那 selective injection 可能就更值得。
工程意义:它不只是“更聪明”,也可能“更划算”
如果只看学术式 accuracy,这个实验已经有点意思;但如果从系统角度看,它更有意思的地方在于质量和成本一起改善了。
报告里给出了一个很直白的 run-level 结论:PI_KG 相比 B_KG,accuracy 提升 3.5 个百分点,总 token 降低 5.36%;按“每个正确答案所消耗的 token”算,B_KG 约为 7,845,而 PI_KG 约为 7,119,下降约 9.26%。这意味着观察到的质量提升,并不是通过更高的 prompt expenditure 买来的。
当然,这里还有一个不能回避的问题:probe 自己也有成本。
报告对此处理得很透明:probe construction 一共 819 次调用,最终 profile 里没有保存每次调用的精确 token 用量,所以作者用 full-probe run 的平均值做了一个经验估计,约 582 tokens / call,对应大约 0.48M tokens 的一次性探测开销。报告也明确说了,这只是近似值,未来应该从 call-level logs 里重测。
我很认同这种写法。因为它没有为了让故事更好看就把 probe cost 藏起来,而是把它摊开说清楚:
如果同一领域会被反复使用,那么 probe overhead 是可以 amortize 的;如果模型更新很频繁、标签经常要重建,那优势就会被削弱。
为什么我还不把它叫作“结论”
虽然结果方向很好,但我现在不会把这件事写成“我证明了 selective injection 普遍优于 full injection”。
原因也很简单。
第一,统计强度还有限。continuity-corrected McNemar test 的 p 值是 0.337,Wilson 区间也重叠,所以更合适的说法是:这是一个 directional signal,不是稳定大效应的决定性证据。
第二,作用范围本来就被限定得很窄。报告明确写了,当前结论只对这个 benchmark、这个模型设置、这个评测协议成立。跨域、跨模型家族的泛化,还没有在这次实验里被验证。
第三,评测代理本身也有限。当前 correctness 用的是 substring-based rule,这在工程上很实用,但弱于更完整的 semantic adjudication。报告把这一点列为 measurement proxy 的威胁之一。除此之外,还有 label drift、coverage boundary、single benchmark slice 等风险。
所以,如果一定要用一句最准确的话来概括我现在的立场,那就是:
这不是最终证明,但它已经足够成为继续开发和继续验证的理由。
下一步:把一个实验,做成一个可复用的研究框架
我接下来更想做的,不是给这套想法起一个很大的理论名词,而是先把它做成一个最小可验证框架。
这个框架至少应该包含几层:
probe 模块:判断某个 fact 对模型来说是 shared、missing 还是 conflict。
labeling / universe 模块:保证不同方法比较时用的是同一套可审计 universe。
policy 模块:支持 full injection、selective injection、以及其他可能的策略。
evaluation / logging 模块:记录 accuracy、token、paired outcomes 和失败案例。
case analysis 模块:帮助我找出“为什么这道题在 selective policy 下变好了,另一道题却变差了”。
而验证方向也很明确。原报告自己已经把下一阶段列出来了:扩大 benchmark slice,跨更多时间窗口和 model families 做稳定性测试;把评测从 substring proxy 升级到更强的 semantic judgment 或 targeted human spot checks;补完整的端到端成本核算,把 probe overhead 和 amortization 放到 call-level logs 上重新量。
对我来说,这就是这个个人研究最有价值的地方:
它不是给了我一个“已经结束”的答案,而是给了我一个足够具体、足够可执行、也足够值得继续追的方向。
