RAG高级技术与最佳实践
RAG技术树
![[Pasted image 20250323163322.png]]
RAG研究的技术树主要涉及预训练(Pre-training)- 微调(Fine-tuning)- 推理(Inference)等阶段
随着LLM的出现,RAG的研究最初侧重于利用LLMs强大的上下文学习能力,主要集中在推理阶段。
随后进一步深入,逐渐与LLMs的模型微调阶段更加融合。研究人员也在探索通过检索增强技术来提升预训练阶段语言模型的性能
回顾NativeRAG过程:
indexing:如何更好的把知识存起来 (分割、embedding、存入)
retrieval:如何在大量的知识中,找到一部分有用的,给模型参考
generation:如何结合用户的提问和检索的知识,让模型生成有用的答案
Qwen-Agent
之前使用了coze或者完全自己编码去使用了RAG,除此之外还可以使用Qwen-Agent这样的工具库来更好的应用上RAG
![[Pasted image 20250319183148.png]]
Qwen-Agent构建的智能体包含三个复杂的级别,每一层都建立在前一层的基础上:
级别一:检索
处理大上下文时采用RAG进行分割,挑战在于如何定位最相关的快
步骤1:指导聊天模型将用户查询中的指令与非指令信息分开
步骤2:要求聊天模型从查询的部分信息推到出更多的语言关键字
步骤3:运用BM25这一传统的基于关键字检索的方法找到与提取关键字最相关的块
级别二:分块阅读
直接RAG很快,但是在相关块与用户查询的关键词重叠度不足时失效=>导致这些相关的块未被检索到
尽管我们会使用到向量检索来缓解这一个问题,但是实际效果有限。为了解决这个局限,我们采用一种暴力策略:
- 步骤1:对于每个chunk让聊天模型评估与用户查询的相关性,不相干则输出无,否则输出
- 步骤2:取出那些非“无”的句子,用他们作为搜索的查询词,通过BM25匹配出最相关的块(总结果控制在上下文限制数量内)
- 步骤3:基于检索到的上下文生成最终答案,和通常的RAG相同
级别三:逐步推理
在基于文档的问题回答中,一个典型的挑战是多跳推理。
例如:“与第五交响曲”创作与同一世纪的交通工具是什么?
实际上他需要先找到第五交响曲是哪个世纪?这个问题解决后知道是十九世纪,再寻找19世纪产生了什么交通工具。
实际上这是一个循环的Agent的过程,直到最终得到结果
评测结果
![[Pasted image 20250319190718.png]]
![[Pasted image 20250319190744.png]]
代码示例
https://github.com/Jasper-zh/agi_study/tree/main/embeding/rag/qwen_agent
RAFT方法
全称:Retrieval Augmented Fine Tuning
在RAFT之前我们一般有两种方式来让大模型符合预期:
- 基础的RAG
- Fine-Tune微调
对于前者,就是不用学习直接给大模型进行一个开卷考试,可以参考知识;对于后者就是先去学习然后闭卷考试。
那么都存在一些优缺点可能是效果上的可能是成本上的,那么RAFT就是结合了这两种。带着开卷的情况下进行训练,让大模型对知识库里面知识相关的概念更熟悉,相当于仍然是RAG的开卷考试,但是对于旁边的课本更熟悉,对于查找的知识判断是否符合更准。
![[Pasted image 20250319164825.png]]
![[Pasted image 20250319165406.png]]
大概对于RAFT训练的话,样本数量可以一千个差不多了,尽量列举所有场景类型的例子平均一点
RAG高效召回
改进检索算法
利用知识图谱中的语义信息和实体关系,增强对查询和文档的理解,提升召回的相关性
引入重排序(Reranking)
重排序模型:对召回结果进行重新排序,提高问题和文档的相关性。常见的重排序模型有BGE-Rerank和Cohere Rerank
混合检索:结合向量检索和关键字检索进行归一化处理
优化查询扩展
相似语义改写:使用大模型将用户问题改写成多个语义相近的查询,提高召回多样性。例如Langchain的MultiQueryRetriever
双向改写
将查询改成文档,或者将文档改成查询,缓解短文本向量化效果差的问题
![[Pasted image 20250319174149.png]]
索引扩展
- 离散索引扩展:使用关键字抽取、实体识别等技术生成离散索引,与向量检索互补,提高召回准确性。
![[Pasted image 20250319175056.png]]
连续索引扩展:结合多种向量模型(如OpenAI的Ada、智源的BGE)进行多路召回,取长补短
混合索引召回:将BM25等离散索引与向量索引结合,通过Ensemble Retriever实现混合召回,提升召回多样性
Small-to-Big:以文档的摘要作为索引,先检索出摘要再补充信息(因为目前大模型对于上下文的尺寸还是挺大的,所以一篇几万字给大模型进行总结分析比RAG的分割更加有效率,因此存在这样的策略直接检索小规模的内容,匹配上后可以贴出大规模的内容)也是比较不错的策略。
GraphRAG
使用知识图谱来推理复杂信息时显著提升问答性能,但是由于前期需要依赖大模型来进行构建图谱因此需要对于大模型本身的能力有一定的要求且消耗量大,虽然新版本已经好了很多但是仍然还是消耗很大,所以需要选择性价比高一些的模型。
仍然是分三个步骤:索引、查询、回答(提示词)
索引: 除了分割之外,额外从分割内容去分析建实体来通过Leiden算法构建知识图谱,构建每个分类社区以及实体的摘要总结
查询: 全局搜索global通过检索分类去匹配返回下面的所有实体、local局部搜索直接搜索实体、DRIFT获取的实体的上下文信息 ;追求完整的信息则选用全局搜索
本来简单试一下结果把我token余额干完了,也就六篇文档。构建过程会生成一些知识图谱的表比如实体信息、社区报告啥的
- 社区列表
- 社区报告
- 文档列表
- 实体列表
- 节点表
- 关系实体表
- 切分区块表
于是乎我又通过本地部署的方式来对接,好像我的电脑显卡有点垃了,七个文本大概是有三万字,体会到了构建知识图谱数据的过程这么慢。估计得个把小时完成
![[Pasted image 20250326123210.png]]
生成完后就可以基于知识图谱进行RAG问答了
1 | graphrag query --root ./input --method local --query "有哪些产品啊介绍一下" |
总体来说这种方式算是通过策略提高了召回的准确性但需要的算力很大
总结
目前来说没有哪一种方式就是最好,一般采用”MVP验证→渐进增强”路径:先用Qwen-Agent搭建基础流程,针对bad case逐步引入RAFT微调或GraphRAG组件,同时通过检索算法优化(如重排序+混合检索)降低后期迭代成本。
检索环节的优化仍是核心突破口,混合检索、查询双向改写、Small-to-Big等策略已证明局部最优解的存在,但尚未形成通用范式,可以持续关注。