发布声明:本文引用一份真实公开的岗位说明作为「人工沉淀文档」样本(已脱敏重写、全文无机构指纹),仅用于技术讨论,不构成招聘或培训推荐。
做agent工程的人迟早要撞上同一个问题:知识怎么进模型上下文。
手上有四种常见答案:每次手动把文档贴进prompt(动态注入)、让模型自己存进记忆、给模型建个库让它自己检索、或者干脆不载、指望模型本身会。站哪边?没人说得清。市面上讲记忆层的、讲RAG的、讲上下文压缩的文章各说各话,没人拿同一份文档、同一组问题、同一把尺子,把这几种做法并排量过一遍。
本文不转述任何一方的官方口径。原理部分只讲清一件事:三种进法差在哪一步。实验设计和踩过的坑我如实写出来,然后跑真实API调用,量出召回率、token成本两笔账,并标清哪些结论能外推、哪些不能。
一、原理:知识进上下文,三条进法各有各的lossy环节
大模型的知识分两处:参数里和上下文里。
参数里的知识是 pretraining 阶段把语料压进权重后留下的统计痕迹——有损、无法枚举、无法审计。关键后果是:它没在训练分布里出现过的东西,问不出来。
本文的样本就是个好例子。一份岗位说明里写着"模型不达标就从小样本微调、增量训练、换方案、与客户对齐约束处理"——这套处置框架既不通用也不是常识,模型在没有任何上下文时,只会给你"数据 / 模型 / 评估 / 工程 / 业务"五段式空话。这不叫幻觉,这叫知识压根不在它脑子里。
所以要拿到某份具体文档里的知识,唯一办法是把原文放进上下文。问题于是变成:放多少、怎么放、放什么形态。
1.1 上下文稀缺,成本随长度线性涨
token是计费单位,本文用统一估算口径:纯中文约1字符=0.5token,中英文混排约1.6字符=1token(近似值,不是真实tokenizer结果)。
这意味着每次都全量注入同一份文档,等于为同一份知识反复付费。N次问答就是N倍——一份2万token的制度文档就是40倍。而这正是"注入"这条路最先撞墙的地方。
1.2 三种进法的差别,本质是"压缩发生在哪一步"
三种做法都在"把知识塞进上下文",但它们做有损压缩的位置完全不同:
- 动态注入:不压缩。原文完整贴进prompt。信息零损失,代价是每次都付全量token,文档一长必然爆窗。
- 记忆层:压缩发生在写入端——先让模型把文档读一遍压成摘要,之后每次只带摘要走。有损,而且损失是隐形的:你不知道摘要漏了什么,直到某天它答不上来。
⚠️ 重要区分:本文C组是摘要式记忆模拟,不等同工业级结构化记忆框架(Hindsight / mem0等)。工业方案可用知识图谱、实体抽取降低损耗,但写入端有损压缩的底层逻辑不变,仅仅是损耗幅度不同。
- 文档检索:不预压缩,但只检索命中的少数分块。没有"摘要漏写"的损失,但检索本身就是另一道lossy环节:BM25认词不认义,检索歪了等于没给上下文——而且你同样不知道它歪了。
所以这三条路在不同环节上各有一处有损,不分谁更先进。谁能把那处损失压小谁赢。而"压得小"这件事,只能实测。
1.3 为什么裸上下文必须作为对照组
不做"不载知识直接问"这一组,你无法证明"载知识是必要的"——模型答不出来,你分不清是"该载没载"还是"载了但载歪了"。更关键的是**"载了但只载到错的部分"这种情况,只有在裸上下文旁边才显得出来**。它是基线,不是凑数的对照组。
重点提醒:A组Q1能拿到0.75高分,仅来自预训练自带的通用AI常识,岗位专属落地Know-How完全缺失。通用提问看不出缺陷,一旦进入场景落地类问题,直接崩盘,这也是Agent裸跑最容易被忽略的隐性坑。
二、实验设计:变量控制,和两处评分器踩的坑
四组唯一区别是"知识怎么进模型",其余全部相同——同一个模型(deepseek-ai/DeepSeek-V3,硅基流动端点)、同一份JD文本、同样两道题、同样temperature=0。
样本:一份公开可访问的科技企业岗位说明文档(AI/数据研发项目经理),约500token、经脱敏重写。选它而不选通用百科或标准评测集,是因为它同时含稳定权威知识(职责、门槛)和易变个性化经验(面试重点、风险处置),正好卡在"该用文档还是该用记忆"的争论主战场。
| 组 | 机制 | 实现 |
|---|---|---|
| A 裸上下文 | 不注入任何资料 | 直接提问 |
| B 动态注入 | 全文本完整注入prompt | 样本原样贴入system |
| C 记忆层 | 先写记忆→清空→新会话凭记忆答 | 压缩成摘要,新会话仅带摘要 |
| D 文档检索 | 本地BM25检索top-3注入 | 朴素按行分块,无向量无裁剪 |
两道题固定:Q1能力召回(“这个岗位面试最看重哪几项能力?给能力+理由”)、Q2场景处理(“若模型效果达不到预期,这个岗位应从什么视角处理”)。之所以要两题:Q1问"是什么"、Q2问"这份文档怎么处置",两题难度天然不同,只有Q2能区分"懂这个岗位"和"懂通用AI"。
打分用固化得分点逐点判定。Q1八项(全流程认知、数据研发专项、大模型概念、评估指标、风险落地处置、技术栈、案例沉淀、跨团队协调)、Q2五项(小样本微调、增量训练、方案替换、标注规范、客户对齐)。指标只报召回率=命中项/应命中总项——得分点是事先固定的清单,答案里多写的、编的那些不叫"命中",叫"幻觉"。
两处评分器踩的坑
坑一:精确字符串匹配,把命中全判成0。评分器第一版让模型返回"命中了哪些得分点",再用精确匹配过滤。问题是模型会把得分点换种说法返回——“AI/数据研发全流程认知"它写成"数据研发全流程把控能力”,精确匹配就miss了。结果B组明明双满分,判分却是0.00。任何LLM-judge的精确匹配都是自欺欺人。
坑二:改对之后,judge又太字面。改成"让模型逐点输出true/false"后,Q1正常了,Q2却集体归零。打印原始返回才发现:DeepSeek-V3在temperature=0下过于字面,只认完全相同的词。A/B/C三组的Q2答案用的是近义表述——“微调”“技术方案切换”“协商验收标准”“标注一致性报告”——被判false;只有D组恰好用了原词(“小样本微调/增量训练/方案替换”),才全true。加了近义词提示后,同一份C组Q1回答从0.62变0.75。
教训:评分器不是中立的测量工具,它本身是个需要校准的组件。你测的可能不是"知识架构的差异",而是"评分器对用词的偏好"。
三、实测:真实API调用跑一遍
3.1 对照总表
| 组 | Q1召回 | Q2召回 | 幻觉 | 注入Token(估) | 准备成本 |
|---|---|---|---|---|---|
| A 裸上下文 | 6/8 (0.75) | 0/5 (0.00) | 0 | 0 | 无 |
| B 动态注入 | 8/8 (1.00) | 5/5 (1.00) | 0 | ~498 | 中(写文档+切片段) |
| C 记忆层 | 6/8 (0.75) | 2/5 (0.40) | 0 | ~858(写498+读摘要360) | 中高(但自动化) |
| D 文档检索 | 1/8 (0.12) | 5/5 (1.00) | 0 | 48(Q1)/70(Q2) | 低(一次建库) |
「注入Token」指知识注入部分,不含问题本身的token,不是总输入token。表中召回为judge判分——A组Q2与C组Q2经人工按同口径复核疑似系统性漏判(分别约2/5、3/5),但无论哪种口径,A≪B、C<B的排序不变。
3.2 五条发现
① 动态注入是黄金基线,但依赖人把文档写好切好。Q1/Q2双满分,是四组里唯一满分的。代价是每次任务都要人工把文档喂进context,量大即爆窗。
② 记忆层在本实现下测得"摘要压缩损耗",但这不等于记忆系统的固有代价。C组先把JD压成长期记忆摘要再作答,Q1从8/8掉到6/8,Q2从5/5掉到2/5(judge口径;人工复核约3/5)——确定丢了「增量训练/技术方案替换」两项处置手法。
但本文的"记忆层"是让同一个模型做文字摘要的模拟,有损压缩是这个行为的固有属性,不是记忆系统的。真实记忆工具(云端原生记忆/结构化抽取/分条存储)可能保留更多细节,损耗幅度因工具而异。所以本文只能给出"摘要式记忆的损耗区间",不能断言"记忆碎片化被量化"。
③ 文档派呈极端非对称召回,主要由「查询-文档字面重叠度」决定。
- Q2查询词「模型/视角/处理」与JD「落地风险」行高重叠——那一行就含全部5个得分点,稳居检索第1名→满分。
- Q1查询词「能力/面试/看重」与各know-how行几乎零重叠——检索到的前三名是
# 岗位名称标题行和两条任职资格,know-how被系统性排挤,「全流程」行以第4名恰好落榜。
同一份文档、同一种算法、同一个模型,因查询表述不同,召回从12%跳到100%。生产环境必须上向量/重排补齐,否则"检索不到"会被误判成"文档里没有"。
④ 裸上下文能答"通用能力",答不了"岗位专属打法"——Q2才是主结论。Q1靠预训练拿到0.75,但那八项得分点里约半数(数据研发/评估指标/全流程)本就是通用AI知识,0.75属预期内、Q1区分度低。Q2近乎不命中才是关键(judge判0/5;人工按judge自带近义词口径复核约2/5——"尝试3种以上不同架构的模型对比"对应方案替换、"标注质量抽样审计"对应标注规范,属judge漏判)。
结论:人工沉淀的Know-How不在模型预训练分布里,不载入就取不到。
幻觉率四组均为0,但该指标本次无区分度:本次是封闭式文档问答场景,幻觉很难触发;幻觉高发场景集中在开放式创作、自由发挥、超长推理任务。A组Q1实际编造了多个虚构示例(“某CV模型在特定人群的识别偏差”“提升转化率2.5%”“GDPR合规”),judge仍判False——说明其幻觉判定对"举例性虚构"过宽。裸上下文的真实失败模式是既遗漏专属Know-How、又编造通用示例,不是"只漏不编"。
⑤ 记忆层有成本拐点:累计第4次使用起就比全量注入便宜。本实现每题都重写一次记忆,所以表中C组注入token偏高(≈858)。真实记忆层写入一次即可复用:写入≈498token,之后每次作答仅需读摘要≈360token,低于B组每次全量注入的498token。每复用一次省≈138token,累计第4次使用起,C的总成本就低于B。这是"记忆层适合多轮/重复问答"的量化依据。
3.3 检索层可以脱离LLM先验证(零成本,可复现)
BM25那一层不调任何模型就能先看明白,对调优很省事。我本地复现了两道题的top-3:
- Q1 top-3:
# 岗位名称…(15.78)→逻辑思维、时间管理、跨团队协调…(14.80)→有研发团队经历,具AI及数据化研发项目管理经验优先(11.08)。全流程know-how行排第4(9.08),恰好落榜。 - Q2 top-3:
落地风险:模型不达标…(小样本微调/增量训练/换方案/与客户对齐约束)(12.41)→## 岗位职责(5.72)→准备2–3个项目案例…(5.52)。
两点值得记:markdown标题行会作为"无实质信息分块"挤占top-3名额(Q2第2名就是一条标题);top-3注入文本的token估算(48/70)与实测完全对得上,说明这条链路可复现、可调优。
3.4 成本账
单次完整运行约18次主调用(8次生成 + 8次评分 + 2次记忆写入),DeepSeek-V3合计约¥0.1–0.5——比立项时预估的¥10–25低了两个数量级(原预估含重跑buffer)。这类对照实验真正的成本不在钱,而在设计。
四、工程选型汇总表(直接抄作业)
| 方案 | 核心优势 | 核心短板 | Token成本 | 维护成本 | 推荐适用场景 |
|---|---|---|---|---|---|
| 裸上下文 | 零准备、零token开销 | 仅能回答通用常识,专属业务知识完全缺失 | 无 | 无 | 通用闲聊、不涉及业务私有文档的简单问答 |
| 动态注入 | 信息零损失,召回最高,结果稳定可控 | 每次全量加载,长文档会触发上下文窗口溢出,重复问答token成本高 | 每次固定全量 | 中等(文档整理) | 一次性任务、文档短、对回答精度要求极高的场景 |
| 记忆层(摘要式) | 一次写入,多次复用,第4次起成本低于动态注入,自动沉淀经验 | 写入端存在摘要压缩损耗,细节丢失不可感知,不可审计 | 首次写入高,后续低 | 中高(记忆写入与质量管控) | 个人长期经验沉淀、高频重复问答、业务知识频繁迭代场景 |
| 文档检索(BM25基线) | 文档可审计、可追溯,原始文档不丢失 | 字面匹配,同义召回差,查询表述极大影响结果 | 单次查询极低 | 低(一次性建库) | 团队资产留存、需要审计追溯;生产环境需搭配向量+重排优化 |
五、边界与局限
- 结论性质:机制性结论,验证四类方案在能力/成本/场景上的差异存在,非工业级精确召回率,数值仅示趋势。
- 评分器自评偏差:打分与生成同为DeepSeek-V3,属自评。且judge对提示词高度敏感(0.62→0.75实证)。四组排序的跨评分器稳健性尚未验证——结论方向可信,具体数值不宜作定量引用。补救路径是标准的:换独立judge,算LLM Judge之间的一致性(Cohen’s kappa / Fleiss’ kappa),排序稳得住才算结论立得住。
- n=1,无方差估计:每组每题仅1次运行。
temperature=0≠输出确定(服务端批处理、MoE路由、浮点非结合性均引入波动),故小数点后两位不具统计意义。这也意味着"temperature=0保证可复现"是句不准确的话。 - 幻觉指标本次无区分度(见3.2④注),不代表模型无编造倾向。
- 主结论看Q2:Q1得分点偏通用,A组0.75属预期内。
- 未做长文档压力测试:样本仅约500token,全文本注入不可能爆窗,"注入"零沉淀成本的优势被样本长度掩盖。真实企业文档达万token量级时这条路不可行,届时结论需重测。这是本文最该补的一块。
- 记忆层是摘要模拟,非真实记忆工具(见发现②)。
- 不可与公开benchmark横向比:本文样本是"一份岗位说明",不是标准benchmark(benchmark本身有测试集泄漏、脱离实际两大通病),且只有一个模型、两道题、一个样本类型。本文数字只在本文实验内部有意义,不构成榜单结论;结论只在"人工沉淀Know-How类非标准化文档"这一类上成立。
- 未测:多文档堆叠、记忆冲突与遗忘。BM25同义改写漏召回已如实记录(Q1仅0.12)。
- 全程脱敏,样本经重写、无机构指纹。
六、横向:它和谁不一样
vs 纯文档RAG(向量检索):本文D组是最朴素的BM25基线,认词不认义。生产级RAG用嵌入向量+重排能把Q1那0.12拉上来——但代价是索引成本、embedding调用和一套新的调试面。我的结论是"BM25不足以当唯一方案",不是"RAG不行"。
vs 记忆层(本账号写过《Agent记忆层Hindsight》):记忆层通常是core/archive/recall三层抽象——core放常驻状态与偏好,archive归档历史,recall负责召回,解决跨会话的长期记忆沉淀;本文C组刻意把它压到最小(只做"写入→清空→新会话调记忆"),用来测**“摘要这一步到底损失多少”**。定位不同,不是替代。
vs 上下文压缩类方案(如context-mode那类"压缩+检索注入"):那类方案解决的是会话内细节连续性(compaction丢的细节能不能捞回来),和本文的C组同属"压缩有损"这一类问题,但作用点不同。理解了这个"压缩点在哪"的框架,再看任何一个新方案,基本能预判它会在哪一处有损。
verdict:按知识属性组合用,不是二选一——
权威要审计 → 文档派;
经验要自动 → 记忆层;
轮次要精准 → 动态注入;
三者递进用,莫把对立看。
七、小结
本文的实测结论压成一句:上下文有没有,决定下限;知识怎么进上下文,决定成本与可管控性。裸上下文答得了"是什么",答不了"这份文档该怎么处置";动态注入精准但不可规模化;记忆层把"人写文档"自动化、代价是压缩损耗和写入质量;文档派可审计可管控,但要补向量/重排才不漏召回。
原理不神秘(§1.2:三条路只是在不同环节做有损压缩),落地也便宜——单机Python、三个依赖、¥0.5以内跑完四组对照。真正难的是设计:变量怎么控、得分点怎么定、评分器怎么校。我最想留下的一句是:当你要评判一个"知识方案好不好"时,先问它把知识压缩在了哪一步——lossy在哪,风险就在哪。
续作计划:多文档堆叠、长文档压力测试、接真实记忆工具复测C组损耗、跨评分器交叉验证。
相关阅读:
- Agent记忆层Hindsight
- Agent长上下文别只会压缩:context-mode找回丢失的细节,减少幻觉