为什么模型不懂你的业务:记忆的边界
一个似曾相识的场景
你兴冲冲地把 Ollama 装好,拉下来一个 llama3.1 八十亿参数的开源模型,本地跑起来挺顺。然后你问它:我们公司请假流程是什么?它一本正经地回答:根据相关规定,员工请假应提前向人力资源部门提交书面申请,经主管审批后生效。
格式很漂亮,语气很专业,但内容和你公司半毛钱关系都没有。你们公司请假是在钉钉上提单,超过三天要部门总监批,销假还要回填单据,这些模型完全不知道。你接着把公司内部文档复制了一大段粘进对话框,它这次倒是答上来了;等你开一个新会话再问,它又回到那个万能的套话里去了。
这不是模型笨,也不是你装错了。这是这一章要讲清楚的核心问题:模型的记忆是有边界的,而这个边界恰恰把你的业务挡在外面。想搭私有知识库的开发者,第一件事不是研究怎么装向量数据库,而是先把这件事想透——到底哪些东西模型记得住,哪些记不住,记不住的那部分要靠什么补上来。
同样是问问题,差别很大。你问它翻译一段英文、写个正则、总结会议纪要,它处理得有模有样,因为这些知识在公开语料里铺天盖地,参数化记忆足够覆盖。你一旦问它你们公司的、你们部门的、你这个月刚制定的任何东西,它立刻原形毕露。判断一个需求要不要上私有知识库,就看一条:这个问题用搜索引擎能搜到标准答案吗?搜不到,模型也不知道。
模型的记忆只有两个来源
模型脑袋里的东西,来路只有两类。一类是训练阶段灌进去的,行话叫参数化记忆。你下载的那个四点几个 G 的模型文件,本质上就是几百亿个浮点数权重,训练语料里的知识被压缩在这些数字里。llama3.1 预训练用了约十五万亿 token 的公开语料,维基百科、开源代码、论坛帖子什么都有,唯独没有你们公司的请假制度。
另一类是对话时临时塞进去的,叫上下文记忆。就是你每次发消息时,程序自动带在前面的那段历史对话。模型在生成下一个词时能看见这段内容,所以表现得好像什么都记得。但这段空间有严格的大小限制,而且会话一关就彻底消失,连点渣都不剩。
参数化记忆里还有个有趣的现象,叫知识的涉猎面与确定性成反比。越主流、谈论越多的东西它记得越牢,唐朝哪一年灭亡、快速排序的平均复杂度,这种几乎不会错。但同一个模型你问它某个偏门产品的一款冷门型号的参数表,它就开始编得一本正经。公开语料的分布不均决定了模型的知识也呈金字塔形,而你的业务知识永远位于金字塔最底层那个最细的位置——全世界只有你们公司在乎。
理解这两条很重要,因为后面所有的技术选型都围着它们转。参数化记忆改不动,你不可能为了一个请假流程去重训一次模型,那算力和数据量都是小团队扛不住的。上下文记忆随用随弃,窗口有限,塞太满性能还会明显下降,稍后我们会动手验证这一点。
除了这两类,实际工程里还有第三种做法:外挂记忆。知识不放进模型,单独存在数据库里,每次提问时临时检索几条相关内容贴进提示。这也是整本书要讲的主线,先在脑子里占个位。
| 记忆类型 | 存储位置 | 容量 | 持久性 | 更新成本 |
|---|---|---|---|---|
| 参数化记忆 | 模型权重文件 | 理论上无上限 | 永久,除非重训 | 极高,需 GPU 集群 |
| 上下文记忆 | 推理时的显存 | 几千到几十万 token | 会话关闭即丢失 | 零成本,但占资源 |
| 外挂记忆(检索) | 向量数据库 | 取决于磁盘大小 | 永久,随用随改 | 极低,写库即可 |
上下文窗口不是真正的记忆
新手最容易踩的坑,就是把上下文窗口当成模型的记忆。你测了一下,模型支持八千 token 上下文,心想这够用了,把产品手册往提示里一贴,问吧。当时确实好使,对答如流,于是你判断系统已经懂你的业务了。这里有两个陷阱在等你,我们一个一个拆。
第一个是上下文里的内容存在衰减。窗口标称八千 token,不等于八千 token 内每个位置的内容都被同等对待。大量实验观察到,放在提示中后部、紧挨着问题的内容模型遵循得最好;放在最开头那一大段背景,反而容易被忽略。你贴了两万字的手册,真正被有效利用的可能就是头尾那一小截,中间全在陪跑。
第二个陷阱更现实,就是成本和速度。上下文越长,推理时要算的注意力矩阵越大,耗时近似按平方增长。每次提问都带两万字背景,在一张消费级显卡上可能要等十几秒才蹦出第一个字,显存稍不留神就爆掉。这在真实产品里完全没法用,没有用户愿意为一句话等十五秒。
不信可以自己验证。拉一个模型后跑这条命令,看看它声称的上下文长度。注意 llama3.1 这种新模型窗口动辄十二万 token,但小模型往往只有四千、八千,不同版本差别很大,别拿一个老模型的体感去套全部:
curl http://localhost:11434/api/show -d '{"name":"llama3.1"}' | python -c "import sys,json;d=json.load(sys.stdin);print(d['model_info']['llama.context_length'])"
返回的数字是上限,实际能用多少还得看显存脸色,差个两三成都算正常现象。接着做组对照实验:开一个全新会话问一个只有你知道的问题,比如你们公司国庆实际放几天假。它准会给你一个四平八稳的法定假日答案,因为参数里就没有你们公司的调休信息。然后把真实的放假通知贴进对话框再问,答得又准又稳。最见证奇迹的是第三步:关掉会话重新开,再问一遍原问题,正确答案荡然无存。你还可以用下面两行命令从接口层面确认,Ollama 服务端根本不帮你保存历史:
curl http://localhost:11434/api/generate -d '{"model":"llama3.1","prompt":"根据这份通知回答:今年国庆放几天?\n通知:因调休安排,今年国庆放假三天。"}'
curl http://localhost:11434/api/generate -d '{"model":"llama3.1","prompt":"今年国庆放几天?"}'
第二次请求一定答不出三天。谁带上下文谁负责传,传多少它看多少,模型只是个用完即走的计算器。
为什么你的数据进不了模型
既然参数化记忆这么可靠,把公司文档训进模型不就一劳永逸了?道理上没错,算一笔账你就冷静了。
先算经济账。哪怕用最省钱的 LoRA 微调方案,微调一个八十亿参数的小模型也要一张像样的显卡跑几十个小时,外加几万条高质量问答样本。样本从哪来?人工整理、标注、校对,这是最贵的人力成本。一家公司几百份制度文档,整理成合格的微调数据集,一个人闷头干一星期都未必利索,还不算反复调整格式的试错。
再算时效账。今天费劲训进去了,下周人事部改了请假制度,你全部白干。微调一次的代价如果只能保鲜一星期,没有哪个业务扛得住。模型最适合装的是那种八百年不变的知识,中文语法、代码常识、通用逻辑;越是变化频繁的东西,越不该往权重里塞,这是铁律。
最后是权限账,企业场景里这条最要命。知识库是要做访问控制的:财务报告只能财务看,客户名单只能销售看。把所有东西混进一个模型权重,它回答时可不懂什么权限系统,问什么吐什么。外挂数据库就没这问题,检索时只查当前用户有权看的那部分文档,权限逻辑留在业务层,清清楚楚。
| 方案 | 一次性成本 | 更新成本 | 时效性 | 权限控制 |
|---|---|---|---|---|
| 全量微调 | 高,显卡加人力 | 高,需要重训 | 差,更新慢 | 几乎无法实现 |
| LoRA 微调 | 中等 | 中等 | 一般 | 弱 |
| 提示里硬塞 | 零 | 零 | 好,但受窗口限制 | 由业务层控制 |
| 外挂知识库 | 低 | 极低 | 好,实时生效 | 容易实现 |
结论很清楚:对绝大多数私有知识库场景,微调是屠龙刀,外挂检索才是天天用的菜刀。屠龙刀偶尔抡一次可以,天天做饭还是菜刀实在。到这里,三条边界都摆在桌面上了:参数记忆改不动、上下文记忆留不住、微调成本划不来。三条边界合起来把一个明路逼了出来——知识外置,随用随取。
跨过边界的第一步:把记忆外置
想明白上面这些,出路自己就浮现了。模型不是记不住吗,那就别让它记。每次提问时,临时去公司的文档库里把相关的那几页翻出来,贴进提示里让它照着说。会话关了也无妨,文档库还在那儿,下次再问再翻一遍。这个思路就是检索增强生成,也就是后续几章要细讲的 RAG。模型只负责理解问题和组织语言,这是它擅长的;知识来自外部文档,这是你能控制的。各司其职,记忆的边界就绕过去了。
得提醒一句,外置记忆不是万能药。翻文档翻得准不准,直接决定回答质量。用户问年假怎么折算,你检索回来一堆差旅报销制度,模型再聪明也只能照着答或者瞎编。所以整条链路里真正值钱的是三件事:怎么把文档切碎、怎么找到对的那几片、怎么喂给模型。这些在 ol-0304 里有完整的拆解,包括切片大小的取舍和 top 5 片段这类具体参数为什么是那个数。
从工程角度看,外置记忆还顺带解决了三个衍生问题。一是可追溯,模型每句回答来自哪几段原文,你随时能点回去核对,这在合规场景是刚需。二是可审计,知识库改了什么、谁改的、什么时候生效,数据库日志写得清清楚楚,权重可给不了你这些。三是可灰度,一条新文档先放进去给部分用户用,效果好再全量铺开,model 里哪有这种开关。这些好处单独看都不大,合在一起就是知识库系统能不能上生产的分水岭。
如果你对链条里每一环的角色还没概念,可以先看 ol-0302 了解向量是怎么把文字变成可检索的数字的,再看 ol-0303 比较两个主流向量数据库的差别。这几篇连起来就是私有知识库的地基,而 ol-0305 会告诉你怎么用现成工具把地基搭成能跑的应用。记忆有边界不丢人,丢的是明明知道边界在哪还硬撞,撞完还怪模型不聪明。
常见问题
模型把我给的材料说对了,但一关窗口就忘,这正常吗
完全正常,这就是上下文记忆的定义。会话关闭后模型不保留任何状态,Ollama 默认也不把对话历史写进磁盘,下一次提问是从零开始。要让知识持久,只能走外挂记忆:把材料存进向量数据库,每次提问前检索相关片段拼进提示。模型本身永远是无状态的,别指望它偷偷帮你记着什么。
我把整份文档贴进提示也能答,为啥还要折腾 RAG
小文档当然可以硬贴,几百字的制度说明谁都能贴。但真实业务里文档是几十上百份、动辄几百万字的,八千 token 的窗口根本装不下;换长上下文模型又贵又慢,一张卡也未必顶得住。RAG 的价值在于每次只检索最相关的那几片,比如 top 5 片段、每片五百来字,两千多 token 就够,既省显存又快,点查点走。把硬贴当常态,等于每次开例会都把全公司档案柜搬进会议室,还只翻得了最上面那两层。
微调能让模型真正记住业务知识吗,值不值得做
能记住,但通常不值得。微调最擅长改变模型的行为习惯,比如固定文风、强制输出某种 JSON 格式,而不是注入三天两头变化的事实。变化频繁的业务知识配上 RAG,稳定的风格和格式交给系统模板,这套组合在成本和效果上都优于微调。真要微调,也建议先把 RAG 链路跑通再说,别一上来就梭哈显卡。
有没有什么知识值得专门微调进去
有,但很少。一类是纯输出习惯,比如你希望模型永远用某种固定结构回答、永远在结尾附一句免责声明、永远用 JSON 而不是大白话,这种用模板就能解决大部分,模板搞不定的才考虑微调。另一类是行业特有的术语体系,同样的词在你们行业有特殊含义,通用模型老理解歪,这类如果量大条目稳定,微调收益最高。至于今天改了明天还要改的业务规则,想都别想,那是给后续章节的检索方案准备的。
多个用户同时聊天,模型会不会串味
不会,前提是你别共享同一段对话历史。Ollama 的每次 generate 调用彼此独立,只要你的应用给每个用户维护各自的对话记录,就不会出现张三的问题带上李四的上下文。真正要小心的是相反的方向:多个用户共用同一个外挂知识库时,检索范围必须按用户权限过滤,否则张三一个提问就能搜出李四的内部资料。权限过滤慢一点不怕,漏了才是事故。
