RAG:检索增强生成

7,044 字 · 预计阅读 20 分钟

2020 · Lewis 等 / Meta · 检索增强生成:先查资料再回答

模型答错,很多时候不是不会,是记错了,或者记的还是旧的。

RAG 让它回答前先查一遍资料:把外部文档当成一本随时能翻的书,查完再写。

原文:Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks

2020 年 5 月发布,NeurIPS 2020。作者是 Patrick Lewis 等,来自 Facebook AI Research(今天的 Meta AI)、伦敦大学学院和纽约大学。


一、知识被压在参数里

问模型「法国首都是哪」,它答「巴黎」。

这个知识不在任何文件里。训练时,它被压进了模型的参数。论文管这叫参数化记忆。

好处很直接:快。不用翻任何东西,一次计算就能答。

代价有四个,而且都不是调参能解决的:

  • 改不了。 训练截止之后发生的事,模型不知道。要更新,只能重新训练。
  • 说不清出处。 参数里没有「这段话来自维基百科的哪一行」这种信息。
  • 记混了也不自知。 冷门事实记错了,它照样答得很肯定。这就是幻觉。
  • 想多记,就得做大。 知识量和参数量绑在一起,模型越大,训练和推理越贵。

「压进参数」是什么意思?前面讲训练时说过:训练就是做一道道填空题,每做一道,把参数拧一点,让正确答案的概率变大。

「法国的首都是___」这类题做得多了,模型看到「法国首都」,就越来越倾向于接「巴黎」。

但这份知识没有存在某一个数字里。它散在几亿甚至几千亿个参数中,每个参数只沾一点点,同时还沾着成千上万条别的知识。

上面四个代价都从这里来。想改「巴黎」,没有一个单独的数字可以改;想问出处,参数里也没留下是哪道题教的;想多装知识,就得有更多参数。

顺便说一句,「训练和推理越贵」里的「推理」,指的是模型每回答一次要做的那一遍计算(英文 inference),不是「动脑想问题」。后面讲 ReAct 时说的「推理」,才是动脑想的那个意思。

论文开头讲的就是这件事:预训练模型存了很多知识,但访问和修改这些知识的手段很弱。

一个自然的想法是开卷考试。但开卷的难点不在「有书」,在「知道该翻哪一页」。翻错页,比不翻还糟。


二、先查,再写

RAG 是 Retrieval-Augmented Generation 的缩写,中文叫「检索增强生成」。

拆开看:Retrieval 是检索,Augmented 是增强,Generation 是生成。

连起来就是:先检索资料,再让模型带着资料生成答案。

一次问答分两步:

  1. 查:把问题交给检索器,从资料库里取回最相关的几段。论文取 5 段或 10 段。
  2. 写:把问题和这几段资料拼在一起,交给生成模型,让它写出答案。

根据问题取出相关段落,再参考这些资料组织出新的答案

论文里的配置很具体:检索器用 DPR,生成器用 BART-large,资料库是 2018 年 12 月的英文维基百科。整部维基切成 2100 万段,每段 100 个词。

切段是必须的。论文用的 BART 一次只能读一千个 token 上下,整本维基百科塞不进去。今天上下文窗口长了很多,但一次塞几百万字依然又慢又贵。资料一多,模型还容易漏看中间的部分。这个后面再说。

BART 是 Facebook(今天的 Meta)在 2019 年发布的模型,读一段话、再写一段话,摘要、问答都能干。large 是它的大号版本,后面讲成绩时会说到它约有 4 亿参数。DPR 是检索器,后面细讲。

2100 万段、每段 100 个词,加起来是 21 亿个词。一本书按 10 万词算,相当于两万多本书。

token 就是前面讲过的词块。就算一个词只算一个 token,21 亿 ÷ 1000 = 210 万,整部维基也比 BART 一次能读的长两百多万倍。

在 RAG 之前,「先查再答」已经有了,比如 REALM 和 DPR 自己。它们的做法是抽取:查到资料后,从里面挑一段原文当答案。

RAG 把最后一步换成了生成。模型读完资料,用自己的话写。答案不必在原文里逐字出现,几段资料的信息还可以拼成一个回答。

这个改动听起来不大,但它把检索和生成放进了同一个训练目标。这是这篇论文最关键的地方。

「同一个训练目标」,可以想成小组作业:一个同学查资料,一个同学写报告,两人拿同一个分数。

报告得分低,写报告的要改,查资料的也得反思找的资料行不行。没人告诉查资料的同学该找哪本书,他只能从分数里慢慢琢磨。

RAG 里,检索器是查资料的同学,生成器是写报告的同学,分数是「最后答案对不对」。这件事怎么做到,后面会算给你看。


三、怎么知道该翻哪一页

先看字面匹配错在哪。

问:「iPhone 是哪家公司做的?」

资料库里有两句话:

  • 「苹果公司发布了新手机。」
  • 「这个苹果又脆又甜。」

第一句一个「iPhone」都没有,却正好能回答;第二句有「苹果」,却和手机无关。

按字面匹配(比如 BM25 这类词频方法),第一句可能因为「手机」得一点分,第二句因为「苹果」得一点分,分数拉不开。词频方法不知道「iPhone」和「苹果公司」指的是同一家公司,也不知道两个「苹果」不是一回事。

要按意思匹配,就得把「意思」变成能计算的数字。

一个只有两个分数的玩具

假设每句话只打两个分:

  • 手机分:跟「手机」有多大的关系,0 到 10 分;
  • 水果分:跟「水果」有多大的关系,0 到 10 分。

四句话的分数是:

句子 手机分 水果分
苹果公司发布了新手机 9 1
iPhone 上市了 8 0
这个苹果又脆又甜 0 9
香蕉放久了会变黑 1 8

把手机分当横轴、水果分当纵轴,四句话就成了纸上的四个点:

四句话按手机分和水果分落成四个点,讲手机的在右下,讲水果的在左上

讲手机的两句挤在右下角,讲水果的两句挤在左上角。距离不是人摆出来的,是分数本身决定的。

提问时,问题也打这两个分。「iPhone 是哪家公司做的?」手机分高、水果分低,点落在右下角附近。离它最近的两段,正是讲手机的那两句:

问题也变成一个点,离它最近的两段就是要找的资料

到这一步,有个地方容易讲糊:分数是人打的,所以「意思近,位置就近」看起来像一句废话。

真实系统里,分数不是人打的。这句话得展开说。

真实系统:768 个数字

真实系统里,每段文字不是一个二维点,而是一串 768 个数字。这串数字叫向量。

每个数字对应一个维度。但这些维度没有「手机分」「水果分」这样的名字,人也说不清第 37 个数字代表什么。它们是模型在训练里自己学出来的,不是人设计的。

768 这个数是哪来的?DPR 用的是一个叫 BERT 的模型(下面会讲),BERT 交出来的每串数字正好 768 个,DPR 就沿用了这个长度。

还有一点和前面讲的词嵌入不一样。词嵌入是一个 token 一串数字;这里是一整段 100 个词,最后只交出一串 768 个数字。

做法是:BERT 在每段文字最前面放一个特殊 token,再把整段读一遍。读完以后,这个特殊位置上的那串数字已经「看过」全段,就拿它当整段的数字摘要。问题也一样,整个问题只交一串。

两段文字的向量有多接近,用点积算:对应位置的数字相乘,再全部加起来。两个向量在多数维度上方向一致,点积就大;方向拧着,点积就小。

用玩具版的分数试一下。假设问题也是(手机 9,水果 1):

本文是会员内容

全文 7,044 字,已试读约 29%。开通专业版可阅读全文,并解锁全部官方课程与后续更新。

开通专业版

支持 7 天无理由退款 · 早鸟价 99 元/年(售完恢复365/年)

课程中涉及的第三方项目,其著作权与商标归各自权利人所有;引用处的署名与许可见《开源与来源说明》。