检索增强生成(RAG)优化策略篇
来源:AiGC面试宝典 作者:宁静致远 日期:2024年01月28日 10:12
一、RAG基础功能篇
1.1 RAG 工作流程
检索增强生成(RAG)是一种将外部知识检索与大语言模型生成相结合的技术。其核心工作流程如下:
- 文档处理:将原始文档进行分块(Chunking)处理
- 向量化存储:将文档块通过嵌入模型转换为向量,存储到向量数据库
- 检索:当用户提出问题时,将问题向量化,从向量数据库中检索相关文档块
- 生成:将检索到的上下文与问题一起组成提示词(Prompt),发送给大语言模型生成答案
📝通俗解释:RAG就像一个"开卷考试"系统。想象你有一本百科全书,当有人问你问题时,你会先从书里找到相关页面,然后结合这些信息来回答问题。RAG就是这个原理——先从知识库找到相关内容,再让AI根据这些内容来生成答案。
二、RAG各模块有哪些优化策略?
| 模块 | 优化策略 |
|---|---|
| 文档块切分 | 设置适当的块间重叠、多粒度文档块切分、基于语义的文档切分、文档块摘要 |
| 文本嵌入模型 | 基于新语料微调嵌入模型、动态表征 |
| 提示工程优化 | 优化模板增加提示词约束、提示词改写 |
| 大模型迭代 | 基于正反馈微调模型、量化感知训练、提供大context window的推理模型 |
此外,还可对query召回的文档块集合进行处理,比如:元数据过滤、重排序减少文档块数量。
📝通俗解释:RAG就像一条生产线,每个环节都可以优化。比如切分文档就像切蛋糕——切得太小会丢失上下文,切得太大会引入噪音。嵌入模型就像翻译官,把文字转换成AI能理解的"语言"。提示工程就像给AI写工作说明书,越清晰明确,答案越准确。
三、RAG架构优化有哪些优化策略?
3.1 如何利用知识图谱(KG)进行上下文增强?
3.1.1 典型RAG架构中,向量数据库进行上下文增强存在哪些问题?
- 无法获取长程关联知识:向量检索主要依赖语义相似度,难以捕捉实体之间的复杂关系
- 信息密度低:尤其当LLM context window较小时,大量无关信息会稀释关键内容
📝通俗解释:比如问"爱因斯坦的学生的学生获得了什么奖项?",向量数据库可能难以准确捕捉这种多跳的关联关系,就像问"你妈妈的姐姐的儿子是谁"需要推理多步一样。
3.1.2 如何利用知识图谱进行上下文增强?
- 策略:增加一路与向量库平行的知识图谱上下文增强策略
图2 基于KG+VS进行上下文增强 图片描述:数据源Wikipedia经过Text Chunking生成Text chunks,进而Embed并存储到Neo4j Vector Index;同时Wikipedia经过Entity extraction生成Entity,构建Knowledge graph存入Neo4j Graph Database。右侧展示了用户提出Natural language question,通过NL2Cypher Generation转化为Cypher query查询Graph Database,同时检索Vector Index获取非结构化信息。
- 具体方式:对于用户query,通过利用NL2Cypher进行知识图谱增强
- 优化策略:常用图采样技术来进行知识图谱上下文增强
- 处理方式:根据query抽取实体,然后把实体作为种子节点对图进行采样(必要时,可把知识图谱中节点和query中实体先向量化,通过向量相似度设置种子节点),然后把获取的子图转换成文本片段,从而达到上下文增强的效果
📝通俗解释:知识图谱就像一张"关系网",上面有各种实体(人名、地点、概念)以及它们之间的关系(谁是谁的谁、做什么的)。通过查询这张网,可以找到直接相关的信息,也可以沿着关系链条找到间接相关的信息,比单纯用向量相似度更能捕捉复杂关系。
3.2 Self-RAG:如何让大模型对召回结果进行筛选?
3.2.1 典型RAG架构中,向量数据库存在哪些问题?
经典的RAG架构中(包括知识图谱进行上下文增强),对召回的上下文无差别地与query进行合并,然后访问大模型输出应答。但有时召回的上下文可能与query无关或者矛盾,此时就应舍弃这个上下文,尤其当大模型上下文窗口较小时非常必要。
📝通俗解释:就像考试时给你很多参考资料,有些资料可能相关,有些可能无关甚至误导你。普通的RAG会把所有资料都给你,而Self-RAG会帮你筛选出真正有用的资料。
3.2.2 Self-RAG的工作流程
Self-RAG是一种更加主动和智能的实现方式,主要步骤概括如下:
- 判断是否需要检索:仅当有需要时才召回(Retrieve on demand)
- 平行处理每个片段:生成prompt + 一个片段的生成结果
- 使用反思字段:检查输出是否相关,选择最符合需要的片段
- 重复检索:根据需要继续检索
- 生成结果:会引用相关片段,以及输出结果是否符合该片段,便于查证事实
图3 RAG vs Self-RAG 图片描述:左侧是传统RAG,直接检索K个文档后生成;右侧是Self-RAG,先判断是否需要检索,然后并行生成多个片段,通过Critique选择最佳片段
3.2.3 Self-RAG的创新点是什么?
Self-RAG的重要创新:Reflection tokens(反思令牌)。通过生成反思令牌这一特殊标记来检查输出。这些令牌会分为Retrieve和Critique两种类型:
| 令牌类型 | 输入 | 输出 | 定义 |
|---|---|---|---|
| Retrieve | x / x, y | (yes, no, continue) | 决定何时需要检索 |
| ISREL | x, d | (relevant, irrelevant) | 文档d是否对解决问题x有用 |
| ISSUP | x, d, y | (fully supported, partially supported, no support) | 输出y中的陈述是否被文档d支持 |
| ISUSE | x, y | (5, 4, 3, 2, 1) | 输出y对问题x的有用程度 |
📝通俗解释:反思令牌就像AI的"自我检查清单"。当AI生成答案时,它会问自己:"这个答案有事实依据吗?""引用的文档真的支持我的说法吗?""这个回答对问题真的有帮助吗?"通过这种自我反思,AI能够更准确地判断检索到的内容是否真正有用。
3.2.4 Self-RAG的训练过程
- ** Critic模型训练**:使用GPT-4生成反思令牌,然后将这些知识蒸馏到内部的Critic模型中
- 生成模型训练:
- 使用检索和Critic模型来增强原始输出以模拟推理过程
- 对于每个片段,Critic模型都会确定额外的段落是否会改善生成
- 如果是,则添加Retrieve=Yes标记,并检索前K个段落
- 然后Critic评估每段文章的相关性和支持性,并相应地附加标记
- 使用标准的next token目标在此增强语料库上训练生成模型
📝通俗解释:Self-RAG的训练过程就像培养一个学生——先让一个经验丰富的老师(GPT-4)给出标准答案和评价,然后让学生学习这些评价标准,最终学生能够自己判断答案的好坏。
3.2.5 Self-RAG的推理过程
Self-RAG使用反思令牌来自我评估输出,使其在推理过程中具有适应性。根据任务的不同,可以定制模型:
- 通过检索更多段落来优先考虑事实准确性
- 或强调开放式任务的创造力
该模型可以决定何时检索段落或使用设定的阈值来触发检索。当需要检索时,生成器同时处理多个段落,产生不同的候选。进行片段级beam search以获得最佳序列。
📝通俗解释:推理过程中,Self-RAG就像一个智能助手,它会自己决定什么时候需要查资料,什么时候可以凭已有知识回答,并且能够同时尝试多个答案,最后选最好的那个。
3.2.6 Self-RAG的代码实战
from vllm import LLM, SamplingParams
model = LLM("selfrag/selfrag_llama2_7b", download_dir="/gscratch/h2lab/akari/model_cache",
dtype="half")
sampling_params = SamplingParams(temperature=0.0, top_p=1.0, max_tokens=100,
skip_special_tokens=False)
def format_prompt(input, paragraph=None):
prompt = "### Instruction:\n{0}\n\n### Response:\n".format(input)
if paragraph is not None:
prompt += "[Retrieval]<paragraph>{0}</paragraph>".format(paragraph)
return prompt
query_1 = "Leave odd one out: twitter, instagram, whatsapp."
query_2 = "What is China?"
queries = [query_1, query_2]
# for a query that doesn't require retrieval
preds = model.generate([format_prompt(query) for query in queries], sampling_params)
for pred in preds:
print("Model prediction: {0}".format(pred.outputs[0].text))输出结果:
Model prediction: Twitter:[Utility:5]</s>
Model prediction: China is a country located in East Asia.[Retrieval]<paragraph>It is the most populous country in the world, with a population of over 1.4 billion people.[Retrieval]...📝通俗解释:第一个问题"找出不同的社交媒体"不需要检索,因为答案很直接。第二个问题"中国是什么"需要检索,所以模型自动插入了[Retrieval]标签,表示需要查找更多信息来回答。
3.3 多向量检索器多模态RAG篇
多向量检索器(Multi-Vector Retriever)核心思想:将文档(用于答案合成)和引用(用于检索)分离,这样可以针对不同的数据类型生成适合自然语言检索的摘要,同时保留原始的数据内容。它可以与多模态LLM结合,实现跨模态的RAG。
📝通俗解释:多向量检索器就像一个图书管理员,他不仅保存原书(原始数据),还为每本书写了简短的摘要(用于检索)。当读者问问题时,管理员先通过摘要快速找到相关书籍,然后再提供完整的书籍内容。
3.3.1 如何让RAG支持半结构化RAG(文本+表格)?
核心流程:
- 将原始文档进行版面分析(基于Unstructured工具),生成原始文本和原始表格
- 原始文本和原始表格经summary LLM处理,生成文本summary和表格summary
- 用同一个embedding模型把文本summary和表格summary向量化,并存入多向量检索器
- 多向量检索器存入文本/表格embedding的同时,也会存入相应的summary and raw data
- 用户query向量化后,用ANN检索召回raw text and raw table
- 根据query+raw text+raw table构造完整prompt, 访问LLM生成最终结果
📝通俗解释:处理表格数据就像把Excel文件变成AI能理解的形式。表格的摘要可以帮助AI快速判断这个表格是否相关,然后AI再仔细阅读表格内容来回答问题。
3.3.2 如何让RAG支持多模态RAG(文本+表格+图片)?
有三种技术路线:
选项1:对文本和表格生成summary,然后应用多模态embedding模型把文本/表格summary、原始图片转化成embedding存入多向量检索器。对话时,根据query召回原始文本/表格/图像,然后将其喂给多模态LLM生成应答结果
选项2:首先应用多模态大模型(GPT4-V、LLaVA、FUYU-8b)生成图片summary。然后对文本/表格/图片summary进行向量化存入多向量检索器中。当生成应答的多模态大模型不具备时,可根据query召回原始文本/表格+图片summary
选项3:前置阶段同选项2相同。对话时,根据query召回原始文本/表格/图片。构造完整Prompt,访问多模态大模型生成应答结果
📝通俗解释:多模态RAG就像一个能看图、能读表格的全能助手。选项1是直接看原图,选项2是先用AI描述图片再处理,选项3是描述加原图都用。三种方式各有优劣,取决于具体需求和资源。
3.3.3 如何让RAG支持私有化多模态RAG?
如果数据安全是重要考量,那就需要把RAG流水线进行本地部署。可用技术栈:
- LLaVA-7b:生成图片摘要
- Chroma:作为向量数据库
- Nomic's GPT4All:作为开源嵌入模型
- 多向量检索器
- Ollama.ai中的LLaMA2-13b-chat:用于生成应答
📝通俗解释:私有化部署就像把图书馆开在自己家里,所有数据都不离开你的服务器,适合对数据安全要求高的企业。
3.4 RAG Fusion优化策略
思路:当接收用户query时,让大模型生成5-10个相似的query,然后每个query去匹配5-10个文本块,接着对所有返回的文本块再做个倒序融合排序,如果有需求就再加个精排,最后取Top K个文本块拼接至prompt
优点:
- 增加了相关文本块的召回率
- 对用户的query自动进行了文本纠错、分解长句等功能
缺点:无法从根本上解决理解用户意图的问题
📝通俗解释:RAG Fusion就像"一人提问,多人帮忙"。你问一个问题,AI会帮你生成好几种相似的问题,然后从各个角度去查找资料,最后把结果汇总起来。这样就不容易遗漏重要信息。
3.5 模块化RAG优化策略
RAG架构演进:Naive RAG → Advanced RAG → Modular RAG
Naive RAG:基础流程为 User Query → Document Chunks → Vector Database → Related Document Chunks → Prompt → LLM
Advanced RAG:在Naive RAG基础上增加了Pre-Retrieval(如Fine-grained Data Cleaning, Sliding Window, Metadata等)和Post-Retrieval(如Rerank, Filter, Prompt Compression)步骤
Modular RAG:提供了更广泛的多样性和更高的灵活性,各模块可自由组合
模块介绍:
| 模块 | 功能描述 |
|---|---|
| 搜索模块 | 融合了直接在语料库中进行搜索的方法,利用LLM生成的代码、SQL、Cypher等查询语言进行搜索 |
| 记忆模块 | 充分利用LLM本身的记忆功能来引导信息检索,寻找与当前输入最为匹配的记忆 |
| 额外生成模块 | 通过LLM生成必要的上下文,而非直接从数据源进行检索,解决检索内容中的冗余和噪声问题 |
| 任务适应模块 | 将RAG调整以适应各种下游任务 |
| 对齐模块 | 在检索器中添加可训练的Adapter模块解决查询与文本之间的对齐问题 |
| 验证模块 | 在检索文档后加入验证模块,评估检索到的文档与查询之间的相关性 |
📝通俗解释:模块化RAG就像乐高积木,不同的模块有不同的功能,你可以根据需要自由组合。比如需要搜索功能就加搜索模块,需要验证功能就加验证模块,非常灵活。
3.6 RAG新模式优化策略
RAG的两种主要组织模式:
增加或替换模块:保留原有的检索-阅读结构,同时加入新模块以增强特定功能
- 例如:RRR(重写-检索-阅读)提出利用LLM的性能作为强化学习中重写模块的奖励机制
调整模块间的工作流程:重点在于加强语言模型与检索模型之间的互动
📝通俗解释:RAG新模式就像不断升级的考试方法。有时候是增加新的考试环节(比如先重写问题再检索),有时候是改变各个环节的配合方式(让检索和阅读更好地协作)。
3.7 RAG结合SFT
RA-DIT方法策略:
- 更新LLM:以最大限度地提高在给定检索增强指令的情况下正确答案的概率
- 更新检索器:以最大限度地减少文档与查询在语义上相似(相关)的程度
优点:通过这种方式,使LLM更好地利用相关背景知识,并训练LLM即使在检索错误块的情况下也能产生准确的预测,从而使模型能够依赖自己的知识
📝通俗解释:RA-DIT就像同时训练学生和图书管理员。学生(LLM)学习如何更好地利用参考资料,管理员(检索器)学习如何更准确地找到学生需要的资料。两者配合默契,学习效率更高。
3.8 查询转换(Query Transformations)
- 动机:在某些情况下,用户的query可能出现表述不清、需求复杂、内容无关等问题
- 核心思想:用户的原始查询可能不总是最适合检索的,需要通过某种方式改进或扩展它
- 实现方法:利用LLM的强大能力,通过某种提示或方法将原始的用户问题转换或重写为更合适的查询
📝通俗解释:查询转换就像"翻译"用户的问题。有时候用户问得很模糊(比如"那个很厉害的电影"),AI需要先把这个模糊的问题转换成具体的问题("获得奥斯卡最佳影片奖的电影"),然后再去检索,这样更容易找到准确答案。
3.9 BERT在RAG中具体起什么作用?
RAG中,对于一些传统任务(如分类、抽取等)用BERT效率会快很多,虽然会牺牲一点点效果,但是比起推理时间,前者更被容忍;而对于一些生成式任务(改写、摘要等),必须得用LLMs,原因:
- BERT窗口有限,只支持512个字符,对于这些生成任务是远远不够的
- LLMs生成能力比BERT系列要强很多,这个时候,时间换性能就变得很有意义
📝通俗解释:BERT就像一个高效的"专科医生",处理一些特定任务很快很准,但能力有限。LLM就像一个"全科博士",什么都能做,但需要更多时间。在RAG系统中,我们可以让BERT先做一些快速筛选,再用LLM做最终生成,这样既快又准。
四、RAG索引优化有哪些优化策略?
4.1 嵌入优化策略
1. 微调嵌入
- 影响因素:影响到RAG的有效性
- 目的:让检索到的内容与查询之间的相关性更加紧密
- 作用:可以比作在语音生成前对"听觉"进行调整,优化检索内容对最终输出的影响。特别是在处理不断变化或罕见术语的专业领域,这些定制化的嵌入方法能够显著提高检索的相关性
📝通俗解释:微调嵌入就像训练一个"专业翻译"。比如医疗领域的术语,普通的翻译可能翻不准,但经过医疗数据训练的翻译就能准确理解"心肌梗死"这样的专业术语。
2. 动态嵌入(Dynamic Embedding)
不同于静态嵌入,动态嵌入根据单词出现的上下文进行调整,为每个单词提供不同的向量表示。例如,在Transformer模型(如BERT)中,同一单词根据周围词汇的不同,其嵌入也会有所变化
📝通俗解释:动态嵌入就像理解"银行"的含义——在"去银行存钱"和"河银行"中,"银行"的意思完全不同。动态嵌入能根据上下文理解这个词的具体含义。
3. 检索后处理流程
动机:
- 一次性向大语言模型展示所有相关文档可能会超出其处理的上下文窗口限制
- 将多个文档拼接成一个冗长的检索提示不仅效率低,还会引入噪声,影响大语言模型聚焦关键信息
优化方法:
- ReRank(重新排序)
- Prompt压缩
- RAG管道优化
- 混合搜索的探索
- 递归检索与查询引擎
- StepBack-prompt方法
- 子查询
- HyDE方法
📝通俗解释:检索后处理就像考前的复习和整理。找到一堆参考资料后,需要筛选重点、排除干扰、按照重要程度排序,这样才能在有限的时间内高效学习。
4.2 RAG检索召回率低,一般都有哪些解决方案?
个人排查方式:
- 知识库里面是否有对应答案? 如果没有那就是知识库覆盖不全问题
- 知识库有,但是没召回:
- 问题1:知识库知识是否被分割掉,导致召回出错
- 解决方法:修改分割方式 or 利用BERT进行上下句预测保证知识点完整性
- 问题2:知识没有被召回,分析query and doc的特点:字相关还是语义相关
- 一般建议:先用ES(ElasticSearch)做召回,然后才用模型做精排
- 问题1:知识库知识是否被分割掉,导致召回出错
📝通俗解释:召回率低就像找不到东西一样。先检查是不是东西本来就不在仓库里(知识库不全),再检查是不是仓库管理有问题(分割方式不对),最后检查是不是搜索方式不对(检索策略需要调整)。
4.3 RAG如何优化索引结构?
构建RAG时,块大小是一个关键参数。它决定了从向量存储中检索的文档的长度。小块可能导致文档缺失一些关键信息,而大块可能引入无关的噪音。
找到最佳块大小的方法:
- 试错法(反复验证)
- 在测试集上运行评估并计算指标来找到最佳块大小
📝通俗解释:块大小就像切披萨——切得太小块太小气,切得太大大口吃不完还可能咬到配料。找到合适的大小需要根据实际需求来调整,可以用不同大小试试哪个效果最好。
4.4 如何通过混合检索提升RAG效果?
虽然向量搜索有助于检索与给定查询相关的语义相关块,但有时在匹配特定关键词方面缺乏精度。根据用例,有时可能需要精确匹配。
混合检索是一种解决方案,该策略利用了矢量搜索和关键词搜索等不同检索技术的优势,并将它们智能地结合起来。通过这种混合方法,可以匹配相关关键字,同时保持对查询意图的控制。
📝通俗解释:混合检索就像同时使用"语义理解"和"关键词搜索"。比如搜索"白色的阿迪达斯运动鞋",向量搜索理解你想要运动鞋,关键词搜索精确匹配"阿迪达斯",两者结合既智能又准确。
4.5 如何通过重新排序提升RAG效果?
当查询向量存储时,前K个结果不一定按最相关的方式排序。当然,它们都是相关的,但在这些相关块中,最相关的块可能是第5或第7个,而不是第1或第2个。
重新排序的简单概念是将最相关的信息重新定位到提示的边缘。
例如:
- Diversity Ranker:专注于根据文档的多样性进行重新排序
- LostInTheMiddleRanker:在上下文窗口的开始和结束之间交替放置最佳文档
📝通俗解释:重新排序就像考试前调整复习资料的顺序。把最重要的放在最前面和最后面(因为人最容易记住开头和结尾的内容),中间放一些辅助资料,这样复习效率最高。
五、RAG索引数据优化有哪些优化策略?
5.1 RAG如何提升索引数据的质量?
索引的数据决定了RAG答案的质量,因此首要任务是在摄取数据之前尽可能对其进行整理。(垃圾输入,垃圾输出仍然适用于此)
优化方法:
- 通过删除重复/冗余信息,识别不相关的文档,检查事实的准确性
- 使用过程中,对RAG的维护也很重要,需要添加机制来更新过时的文档
数据清理步骤:
- 通过清理特殊字符、奇怪的编码、不必要的HTML标签来消除文本噪音
- 通过实施一些主题提取、降维技术 and 数据可视化,发现与主题无关的文档,删除它们
- 通过使用相似性度量删除冗余文档
📝通俗解释:提升数据质量就像在考试前复习笔记。把笔记整理得清晰、准确、完整,考试时才能答对。如果笔记里有很多无关内容、错误信息,反而会误导考试。
5.2 如何通过添加元数据提升RAG效果?
将元数据与索引向量结合使用有助于更好地构建它们,同时提高搜索相关性。
元数据有用的情景:
- 如果搜索的项目中,时间是一个维度,可以根据日期元数据进行排序
- 如果搜索科学论文,事先知道要找的信息总是位于特定部分(比如实验部分),可以将文章部分添加为每个块的元数据并对其进行过滤,仅匹配实验部分
📝通俗解释:元数据灏卞儚鍥句功鐨勫垎绫绘爣绛惧拰绱㈠紩銆傜煡閬撹繖鏈功鐨勫嚭鐗堟棩鏈熴€佷綔鑰呫€佺珷鑺傦紝灏辫兘鏇村揩鍦版壘鍒伴渶瑕佺殑鍐呭锛岃€屼笉鏄洸鐩湴鍏ㄦ枃鎼滅储銆?