为什么需要 RAG
模型不可能知道你的文档,却会一本正经地编造答案。RAG 就是解法,而这个问题值得先弄懂,再看解法。
去问模型你公司的退款政策。它会回答。答案流畅、结构清晰,而且完全是编的。
三个彼此独立的局限共同导致了这次失败,而检索增强生成(RAG)三个都能解决。先花十分钟把问题搞清楚是值得的,否则那条管线就只是一张你记不住的图。
局限一 · 它从没见过你的数据
训练用的是公开文本。你的内部文档、代码库、客户记录、wiki,都不在里面。模型没有任何途径拿到这些信息。
局限二 · 知识是冻住的
训练在某一天结束了。在那之后的一切,对模型来说都不存在——而它也说不出这条线画在哪里,所以你别指望它主动告诉你哪里缺了东西。
即便是公开信息,近期的内容也拿不到。
局限三 · 不知道也要答
正是这一点,让前两条从麻烦变成了危险。
一个为看似合理的续写而优化的模型,在缺信息时不会拒绝。它会产出一份像政策的东西,用的是真政策的语气,带着真政策的自信。没有任何可见的标记,能让你分辨一个有据可依的答案和一个编造的答案。
知识的缺失加上流畅的编造,才是真正的问题。单独任何一样都还好办。
那为什么不直接微调?
直觉上的解法——拿你的文档去训练模型——在知识这件事上效果很差。
事实落不进去。 微调是把参数(parameter)往模式上调。教形式和风格,它很在行;教具体事实,就不可靠了,而一个没落进去的事实,产出的不是一个空白,而是一个自信的近似错误。
更新就得重训。 文档每改一次,就要再跑一轮训练。而文档每天都在改。
没有出处。 微调过的答案给不出来源,因为来源已经溶进权重里了。对大多数业务用途来说,「这是从哪来的」是一条硬要求。
权限控制没了。 一旦内容被训进去,模型会很乐意谈论提问用户无权查看的内容。
那为什么不干脆全都塞进去?
上下文窗口现在很大了。为什么不把整个语料库都发过去?
语料库比窗口大。 上下文再大,也装不下一个文档库。
每一次请求、每一个 token 都在计费。 一个问题发 10 万个 token,单次调用就很贵,量一大就离谱。
质量会下降。 注意力被摊薄,长上下文中部信息的利用也更不可靠。埋在一堆无关内容里的有用材料,用起来比单独放差。
延迟。 在一个巨大的 prompt 上做预填充(prefill),每次都很慢。
RAG 做了什么
把相关的部分检索出来,然后基于它作答。
- 把文档做成 embedding 索引一次
- 问题来了,找出在含义上离它最近的段落
- 把这些段落放进 prompt
- 让模型基于给出的文本作答
关键在这个转换。你不是让模型去回忆,而是让它去读。对给出的文本做阅读理解,是这些模型真正可靠的能力——比回忆可靠得多。
三个局限都有了着落:私有数据变得可用;更新是即时的,因为你重建索引而不是重训模型;出处有了,因为你知道自己发了哪些段落;权限控制也能在检索时落实。
它解决不了的问题
语料库里没有的,它答不了。 检索只能找到已经存在的东西。缺的信息还是缺。
检索质量决定整条系统的上限。 检索错了段落,模型就会基于错误的段落自信作答。大多数让人失望的 RAG 系统,问题出在检索而不是生成——见分块和重排序。
幻觉只是减少,没有消除。 基于资料作答帮助很大,但不能让编造变得不可能,尤其当检索到的段落只是部分相关时。
横跨多份文档的问题依然难。 「总结这一季度所有关于物流的投诉」不是一个「检索几段」能解决的问题。
行为上的事,还是该用微调。 RAG 提供知识;微调塑造形式、语气和任务特有的行为。两者解决的是不同问题,而且配合得很好。
要点回顾
- 三个局限叠在一起:你的数据从没进过训练,知识是冻住的,而模型不管怎样都会作答。
- 微调不适合装事实——落不进去、更新就要重训、没有出处、没有权限控制。
- 把一切塞进上下文又贵、又装不下、还会拉低质量。
- RAG 把回忆换成了阅读理解,而后者才是模型真正可靠的长处。
- 检索质量就是整条系统的天花板。
下一篇: RAG 是怎么一步步工作的