RAG质量工程师岗位深度测评与对比
摘要
检索增强生成(RAG)通过动态检索外部知识弥补大语言模型局限,但生产级部署需要精细设
检索增强生成,也就是RAG,现在基本成了给大语言模型“开外设”的标配手段。
RAG这个东西,理论上看门道挺简单——不就是把数据塞进上下文窗口嘛!可一旦落到实践,水就深了。躲在那些漂亮框图背后的,是五花八门的高级玩意儿:分块策略怎么选、要不要加个重排序、多查询检索器怎么搭、从小到大检索怎么玩、假设文档嵌入是怎么回事、预嵌入阶段要不要做数据丰富、查询是不是得动态路由、嵌入模型是不是得自己再练练……清单能拉老长。
搭个初版pipeline确实快,但要让它达到能上生产的质量,那完全是另一回事。如果不仔细推敲,RAG系统可能给你甩回一堆不相关、不准确的答案,或者干脆跑得慢吞吞、吞掉大量贵得要死的算力,再不然就是在数据规模一上去之后直接“躺平”。
想真正搞懂怎么有效又高效地评估RAG系统,首先得弄明白这个Pipeline里每个零件是怎么凑在一起干活儿的。每一环节的设计选择,都会直接砸在最终的输出质量上。这篇文章就从测试和质量把控的角度,带你把RAG的概念和模式重新捋一遍。咱们先从RAG为什么值钱说起,再拆解那些为了“生产级质量”而涌现出来的设计决策,最后再聊具体的评估方法和工具。底子打好了,后面的一切才立得住。
LLM 的局限性
要理解RAG,先得退一步,想想RAG到底是想解决LLM的什么软肋。
LLM的核心其实很直白:你丢一段提示过去,它吐一段回复出来。
但这背后,模型要跑一次推理计算,把输入和成百上千亿个参数搅在一起算。这玩意儿烧钱烧得厉害。
如果说跑推理叫“花钱”,那训练一个LLM就是“烧钱”的另一个量级。训练的过程,其实就是给模型内部的参数找最优值。先跑一遍结果,算算误差,再反向传播改改权重,反复迭代成百上千万次。模型跑一次推理可能就几秒钟,但做一次训练,哪怕是在大规模GPU集群上,也得耗上好几周。
这个恐怖的训练成本,直接堵死了给LLM塞新信息的路。大多数公司既没钱自己从头练一个,也不能靠扔点私有数据进去就指望模型自动学会。真正有实力的大厂,只能花钱在大规模公开数据集上练好一个基础模型,然后再通过RAG这种“二道工序”来给它装新能力、注入新知识。
说白了,RAG干的就是这件事:让LLM拿到海量额外的信息,却不用再花大价钱重新训练一次。
RAG 基础知识
那RAG到底是怎么干活的?来扒一扒它的机制。
发给LLM的提示,长度是有上限的,这个上限叫“上下文窗口”。窗口大小通常用token(差不多就是一个词)来量,常见的配置是1K、4K,也能更大——比如Gemini 1.5 Pro那个128K的怪物。
很多人简单地把上下文窗口理解成“我能问多长的问题”,这个想法有点窄。关键是,LLM在生成回答的时候,是能“看见”并利用窗口里所有信息的。这其实就是在做“上下文学习”。
所以,你可以把新知识直接塞进窗口里。比如问公司关于丧假的规定,把整本员工手册塞进去(只要窗口装得下),LLM就真能用这些新信息回答你。
问题是,你并不是每回都恰好有这么顺手的数据,而且数据量往往远大于窗口能装下的部分。这就需要一套机制,专门用来做信息的检索和筛选。
最原始的办法:在全量数据里搜关键词,把命中的上下文复制出来,一股脑堆进提示里。这种“关键词RAG”确实能改善回答质量,在某些场景下也管用,但容易误伤——同一关键词,在不同语境下意思可能天差地别。
还好,我们有办法做得更好:用语义搜索。不用死板地匹配单词,而是匹配文本的“含义”。具体来说,就是用嵌入模型把可能相关的数据块变成向量,然后去这些向量里搜跟问题最像的。这套方法高度简化,但它已经很像真正的RAG了。
RAG 和嵌入
要明白RAG比关键词搜索好在哪儿,得先搞清楚嵌入模型到底是干什么的。这个题目本身就很深,但对理解RAG至关重要。
嵌入模型和LLM有点像,但它的任务不是生成新内容,而是把输入压缩成一个数字列表——一个向量。这个列表通常很长,常见的维度有768或1536,也有别的尺寸。
关键在于,这个向量不是瞎编的。它是模型根据自己对输入含义的理解,提炼出的“精华”。相似的内容会被映射到相似的向量上。“相似”不只是“关键词一样”——嵌入模型专门训练过,能从非结构化数据里揪出更深层的语义。比如“Guy horses do not Fly”和“A Fly Guy horsing around”,单词相近,但向量绝对不会挨得太近。
向量的好处是你可以在上面做数学运算,而且非常快。在数百万个向量里找最相近的几个,只需要很短的时间。
好了,现在RAG Pipeline的各个零件都凑齐了,咱们来走一遍流程。
前四步只需要做一次,或者等源数据变了再更新。后面五到八步,是每个推理请求都要跑一次的:
- 收集所有可能相关的数据——数据量大到远远塞不进上下文窗口。
- 把这些数据切成小块(后面会细讲怎么切)。
- 用嵌入模型把每个小块变成一个向量,这个向量封装了小块的含义。
- 把向量存到向量数据库里。
- 收到提示后,用同一个嵌入模型把提示也变成一个向量(叫提示向量或查询向量)。
- 在向量数据库里搜跟提示向量最像的向量。返回的结果,肯定比光在原始数据里搜关键词要准得多。
- (可选)对搜出来的向量做一次重排序,然后取排名靠前的向量,取回对应的原始文本。
- 把这些原始文本和最初的提示拼在一起,一起发给LLM。
这么一来,LLM的表现就好像它真的拿那些新的专有数据训练过一样,而实际上你根本没动基础模型一个参数。
至少理想情况下是这样。现实中,这套过于简化的Pipeline很可能满足不了你的生产需求。你得针对自己的应用场景,去调参数、换零件、加模块,直到整个系统能交付一份高质量、可上线的RAG Pipeline为止。
RAG 设计和质量
上面讲了RAG的基本原理,但前面也说了,实践里的RAG要比这复杂得多。这些真实世界里的复杂性,直接影响着应用的质量。咱们逐一来看看每个环节有哪些坑、质量风险和备选方案。
1. 数据采购、摄取与丰富
一开始,你得先找到所有“可能相关的数据”。
上面那张RAG图里的单个小图标,实际上很可能是一整套数据pipeline——甚至好几条!——负责从多个源头拉数据、做切分、策展,还可能要去掉敏感信息、做标记化,以及其他常见的ETL操作。
其中一些pipeline会变得极其复杂,尤其当源数据不是纯文本时。比如,有的pipeline大量使用OCR来扫描和录入纸质文档。
如果源数据压根没进到向量数据库里,那你把RAG Pipeline调得再好都没用。而根据数据的种类、变化频率和数据量,这个摄取阶段本身就可能是很多质量问题的源头。
除了常规的pipeline操作,RAG还可以从数据丰富中获益。通常,其他系统或人的手里会有一些关于源数据的上下文信息,这些信息对评估数据的含义相当有用。比如,可以在客户数据库里加上来自别的系统的标签或备注。或者,用其他生成模型或NLP工具去生成更简洁、更清晰的元数据。所有这些都算是在生成嵌入之前的“预处理”。做对了,检索质量能明显上一个台阶。
如果你要去评估一个RAG检索系统的质量,非常值得花时间先搞清楚:数据到底是从哪来的,又是怎么被吃的。
2. 分块
数据吃进来之后,在通过嵌入模型之前,得先切成一小块一小块。怎么切?这就是分块策略要回答的问题。
多大或者多小的块是最优的?块和块之间要不要重叠?除了按页、按段落或固定长度切,还有没有更聪明的办法?非标准格式(如代码、JSON)的数据要怎么切?
不同策略对应不同的权衡。有的简单粗暴,反赌,结果也还行;有的复杂精细,能拿更好的命中率和LLM回答质量。切太粗,满屏不相关的数据挤占窗口,把有用的块挤出去,或者生成过于笼统、毫无意义的向量;切太细,又会把本来沾边的数据“剪断”。
还有一些更高级的技巧。比如“从小到大检索”:用小尺寸的块去搜索,但每个小块会链接到一个更大的“父块”,这个父块才是被喂给LLM的。再比如“上下文感知分块”,利用对文档结构的已有知识,把文档智能地拆成逻辑块。
这个清单肯定不全,但足以说明:RAG开发者面前的选项五花八门,而一个合适、经过调整的分块策略,对整个应用的质量影响之大,怎么强调也不为过。
3. 嵌入模型选择与配置
用来生成嵌入的模型选择很多,不同模型在不同场景下表现各有高低。有些是通用预训练模型,有些专门针对特定领域(比如医疗记录)做过微调。你甚至可以拿自己应用的数据专门训练一个嵌入模型。
此外,模型有不同的大小(影响嵌入生成的时间和成本)、不同的输入长度(能支持的最大块大小)和不同的输出向量维度(维度越高越准,但更占空间、更慢)。
有些嵌入模型只能走API(比如OpenAI的嵌入端点),有些完全开源,可以在本地跑或托管在云上。
还能给应用里不同的数据通路用不同的嵌入模型。
对于很多应用,一个通用的好模型可能就够用了。但对另一些应用来说,选一个特定模型或者定制训练一个,才能发挥最佳效果。
理解了嵌入策略背后的设计思考,对评估的需求和手段也就有了更深的认识。
4. 查询处理与嵌入
没有规定说,收到查询的时候就必须原封不动地把它丢进嵌入模型。实际上,有很多办法可以用来优化查询和搜索过程,从而提升整体质量。尤其当查询是真人写的,可能带着含糊、异想天开、摸不着头脑的时候,更是如此。
如果能对应用的场景或意图有更多了解,就可以借助LLM或传统逻辑,把查询变得更紧凑、更明确——也就是做一次“查询重写”,把用户实际问的,转化成他真正想问的。
一个进阶玩法是HyDE(假设文档嵌入)。它会先生成一个假设的回答文档,然后拿这个回答文档去做向量搜索(也就是回答到回答的匹配),而不是直接拿查询去搜(问题到回答)。
另一个选择是把查询拆成多个相关的子查询,并行跑,最后组合结果——这就是Multi-Query Retrieval模式。这个方案显然会增加计算开销,但能提升检索质量。
根据你的具体用例,自定义查询处理可能不是你想要的,但它确实会显著影响应用的质量和行为。
5. 向量数据库与向量搜索
向量搜索虽然快,但在向量数据库里搜最像的嵌入,仍然需要时间和成本。一种降低这种成本的方法是“语义缓存”。首次检索后,把结果缓存起来,后续类似的搜索直接从缓存里拿数据。
当然,缓存增加了复杂性(而且众所周知,缓存是计算机科学里的两大难题之一——另一个是啥我老记不住)。缓存能提升性能,但过时的缓存会损害响应质量,尤其在源数据频繁变动的环境里。
6. 重排序
上面描述里,我们天真地假设可以把向量搜索返回的所有相关数据都塞进上下文窗口。这当然是个简化。必须有一套流程来决定,在返回的那么多向量里,哪些该被优先放进窗口。
即使能塞进去,很多研究也指出,把上下文窗口填满,会引发“中间丢失”问题,影响LLM召回窗口里信息的能力。
解决方案就是在第一次向量搜索之后,加一个重排序步骤。
简而言之,嵌入模型追求速度,需要快速跑完海量文档;另一种叫“重排序模型”(也叫交叉编码器)的模型跑得慢,但追求精准度。所以,先用又快又不一定准的嵌入模型生成向量并存在向量数据库里,再拿慢但准的重排序模型在小范围内筛出最高质量的文档。这些高质量文档被优先排进上下文窗口。
这里面门道还有很多,但核心就是这样。重排序能显著提升检索到的数据与查询的相关性。窗口里多了相关数据、少了不相关数据,响应质量自然会提升。虽然增加了复杂度和延迟,但对许多RAG应用来说,这种质量上的改进非常值得。
7. 大上下文窗口与RAG
终于要调用LLM了。但在聊提示工程之前,先花点时间看看RAG和大上下文窗口之间的关系。
LLM技术在飞速发展,其中一个改进维度就是上下文窗口的大小。一个典型例子是2024年2月发布的Gemini 1.5 Pro,支持128K上下文窗口,甚至还有一个(未公开发布的)100万token的版本。
有些人最初猜测,百万级别的上下文窗口会让RAG Pipeline失业。但不是那么回事。这篇文章解释了为什么即使有超大上下文窗口,RAG仍然很重要、甚至必不可少(剧透:成本、延迟和召回质量)。
大上下文模型有价值,它帮LLM处理那些需要综合大量事实(这些事实可能已经通过RAG筛选过了)的查询。大上下文窗口和RAG的关系还会继续演变,RAG的实施者和测试人员应当理解这些权衡和对应用质量的影响。
8. 提示生成
从向量数据库拿到一堆相关数据,做完重排序,最终得到一组合适的内容。然后呢?一股脑跟原始问题一起塞到提示末尾就完事了?
用过LLM的人都知道,门道远不止这么简单。LLM很强大,但也任性得让人抓狂。提示里的细枝末节——措辞、数据的顺序、语气、“慢慢来”之类的建议、甚至用上情感语言——都会显著影响回答质量。还有策略用……你猜对了,其他专门训练过的模型来自动生成最佳提示。这整个就是快速发展的“提示工程”领域。
那个能产出最高质量响应的提示模板,通常是针对特定模型和特定应用场景的,得反复试错才能找到。考虑到RAG这个看起来不起眼的微末环节对质量的巨大影响,提示工程应当和系统其他任何部分一样,接受严格的评估和审查。
测量和评估 RAG 系统
我们已经走了一遍RAG Pipeline的主要环节,也(简要)讨论了它们对应用质量的影响。这只是个引子,但应该能让你对这些应用内在的工作机制和质量挑战有了更深入的认识。关于RAG,还有很多出色的文章、博客和论文做了更深入的探讨。
关键点在于:实现RAG的时候,有大量的选项和选择摆在面前,每个选项都伴随着权衡和质量影响。有些选择可以直截了当地评估,有些则会影响整体的检索或响应质量。理解这些选择以及它们如何影响系统,是让一个应用达到生产级质量不可回避的功课。
下一个自然的问题就是:好,那到底怎么评估RAG?如何衡量开放式、自由格式的输出质量?我该用哪些指标来真正度量?这些评估能做到多自动、哪些能自动?当LLM本质上是不确定的、它们使用的数据又是不断变化的时候,我怎么保证质量?
来源:互联网
本网站新闻资讯均来自公开渠道,力求准确但不保证绝对无误,内容观点仅代表作者本人,与本站无关。若涉及侵权,请联系我们处理。本站保留对声明的修改权,最终解释权归本站所有。