RAG 检索增强生成
是深度思考/网络搜索这种功能 Retrieval Augmented Generation
RAG项目
- bilibili-Golang 基于 Redis 实现文档向量索引与检索系统(RAG)
- https://github.com/BaiZe1998/go-learning
- Redis:用于构建向量数据库
- golang
RAG基础通识
RAG三个核心
- 知识库
- 检索
- 回答
RAG流程
- 准备知识库(索引阶段 Index)
- 原始知识+切割器->知识块
- 知识块+embedding->文本向量
- 文本向量存入向量数据库
- 提问
- 检索阶段(Retrieval)
- 问题+embedding->问题向量
- 问题向量+向量数据库->找到参考文档
- 生成阶段(Generation)
- 获取提示词+LLM->输出结果
- 检索阶段(Retrieval)
准备知识库-索引
收集知识
- 知识存在哪里
- word, Excel, 数据库, pdf(是否需要采用OCR解析)
- 数据的格式
- 文字,表格,图片,视频
- 如果有图片和视频是否需要使用多模态
- 数据清洗
- 各种常见的文本清洗方法,大模型容错高,粗洗就好
文档切分
核心:语义连贯性
- 尽量保证划分后的同一段文本里面,语义是统一的,完全的
- 文本太长:语义不统一,影响检索效果 (介绍A但包括了B)
- 文本太短:语义不完全,影响回答质量 (介绍A但没介绍全)
语义: 语义A: 公司创立 苹果公司是全球知名的科技公司,由史蒂夫乔布斯,史蒂夫沃兹尼亚克和罗纳德韦恩鱼1976年4月1日创立 语义B: 公司地址 公司总部位于美国加利福尼亚州的库比蒂诺 语义C: 主要产品 苹果公司主要生产消费电子产品,包括iphone、ipad、Mac电脑等
文本向量
去重词袋法
只管有没有 不管有多少
- 有:1
- 无:0
不去重词袋法
- 有:实际数量
- 无:0
tf-idf
一、什么是 TF-IDF? TF-IDF 是 Term Frequency–Inverse Document Frequency 的缩写,是一种常用的文本特征提取方法,用于衡量某个词在一篇文档中出现的重要性。它的基本思想是:词在一篇文档中出现得越频繁,它对该文档的代表性越强;但如果这个词在整个语料库中也频繁出现,那么它的区分能力就越差,应降低其重要性。
二、TF(词频) TF 指的是某个词语在当前文档中出现的频率,计算方式如下: TF(t, d) = 词语 t 在文档 d 中出现的次数 ÷ 文档 d 的总词数
例如,词语 "data" 在某篇文档中出现了 3 次,而文档总词数是 100,那么: TF(data, d) = 3 ÷ 100 = 0.03
三、IDF(逆文档频率) IDF 衡量一个词的通用性。如果一个词出现在越多的文档中,说明它越常见,其区分能力越低,因此 IDF 应该越小。 IDF(t) = log(总文档数 ÷ 包含词语 t 的文档数 + 1)
加1是为了避免分母为0。例如,语料库中总共有1000篇文档,词语 "data" 出现在其中100篇: IDF(data) = log(1000 ÷ (100 + 1)) ≈ log(9.9) ≈ 2.29
四、TF-IDF 综合计算 TF-IDF 是 TF 和 IDF 的乘积: TF-IDF(t, d) = TF(t, d) × IDF(t)
继续前面的例子: TF-IDF(data, d) = 0.03 × 2.29 ≈ 0.0687
这个值越高,说明词语 "data" 对文档 d 越重要。
⭐️词嵌入 Word Embedding
- 稀疏向量:大部分都是0,小部分有数字 上面三个方法都有这个问题
- 稠密向量:文本不再用词向量表示,用维度表示 词嵌入优点: 语义相关性捕捉的很好
- "快乐"和"高兴"是同义词
- "北京"之于中国="巴黎"之于法国
训练阶段: 输入成吨的语料,让模型不断训练,存在embedding model 应用阶段: 文本输入embedding model,得到对应的向量
如何选择embedding mode: https://huggingface.co/spaces/mteb/leaderboard
向量存储:向量数据库
向量数据库:为向量存储和处理而生的数据库
- 主要作用:嵌入文本,存储向量,相似度分析
- 常见数据库:Chromadb , FAISS
检索阶段 Retrieval
- 相似度:语义捕捉效果更好,容错性更高
- 关键词:在部分场景下,命中率高
基于文本相似度的检索
-
问题向量 and 知识块向量
-
余弦相似度:用向量的夹角(0-180)表示这两个向量的相似度。
- 夹角越大,相似度越小
-
欧氏距离:用向量的距离表示这两个向量的相关性。
- 距离越小,相关性越高
基于关键字的检索
- 应用:关键词-文档映射表
- 构建:提问-提取关键词-匹配文档
生成阶段 Generation
提示词构造
按照需要构造提示词模版
请给予参考材料回答问题,如果不知道就直接答复"暂不清楚"。
问题:{query}
参考资料:
1.
2.
3.
回答要求:……
模型选择
- 开源:自行部署
- 安全和隐私性比较好
- 需要硬件
- ~~模型能力较低~~
- 应用:deepseek, ollama, huggingface
- 闭源:调用外部接口
- 安全性较低(需连外网)
- 模型能力较高
- 一键调用,不用维护
- 应用:各大官方api,通用框架
RAG进阶优化
RAG不是算法问题,是工程问题
检索优化-small to big
检索时:小文本块 生成时:大文本块
摘要检索
- 在一开始做知识块的时候,知识块做的大一些,然后用大模型对整个知识块进行总结,得到文本摘要 存入知识库
- 检索的时候匹配摘要,根据摘要找到原知识块的映射,用原知识块进行生成,保证了生成的质量
子问题检索
- 大模型对知识块生成几个问题,把问题存入向量数据库
句子窗口检索
- 最小语义知识块(段落,句子),获得相应的最小语义文档之后,前后文档拼接获得完整的内容
- 回答的时候拓展上下文窗口,获取信息更全面,更连贯
⭐️ 多路召回
- 检索的时候有多种检索方案(关键词/相似度),找到一个方法把多种检索结果整合起来找到一个确定答案。
- 算法:对每个文档计算多种检索方式结果的总分
- 例子(右上)文档1总分最多,取文档1里面的内容
- 例子(右下)加了个平滑指数,取内容评分较稳定的最高分文档(RRF算法)
⭐️Rerank
- 粗筛:多种检索方法的内容获得的文档,直接去重获得结果
- "4个结果+问题"放入Rerank模型进行4次运算 -> 每个文档和问题的相关性得分
- 选择得分较高的文档作为上下文
Rerank模型:Cross-Encoder模型 兼顾效率和准确度:Rerank计算消耗时间,所以不能把所有文档一起丢进去计算,需要有粗筛这一阶段
生成优化
在生成结果阶段,如何让LLM利用多个参考文档?
refine模式
分别输入知识块和提问,迭代地生成答案。避免上下文溢出。 问题:用了太多次LLM了 优化:几个相似的知识块打包丢给大模型 可以用到聚类,相似性分组等方法获取相似的知识块
tree_summarize
- 二叉树
- 适用参考文档特别多的场景
- 把问题和答案往上送
改写提问
什么时候需要改写提问?
- 提问不规范:语义模糊,歧义,语句不通顺,提问不规范
- 多轮对话:结合历史问答对提问进行改写
- 用户:三国里战力最高的是谁 RAG系统:是吕布 用户:他是哪年出生的 改写:吕布是哪年出生的
- 复杂提问:拆解成多个问题,分别提问RAG然后组成最终答案
合理利用元数据
什么是元数据:对文档的描述,如类型,作者,创建日期,来源等 检查前过滤:剔除无关文档,检索最近文档 检索中评估相关性:重要文档给予更高的权重加成 检索后重排:重要文档排在前面 生成时提升用户体验:提供参考文档来源,增加可信度
⭐️评估RAG
评估RAG的目的是量化成效,加速迭代
RAG的评估
评估指标
- ⭐️准确率:直接站在用户视角,看答案是否符合实际情况
- 忠实度:生成的内容是否忠实于提供的上下文或背景信息
- 召回率,精确率, F1:
- ⭐️召回率=C/A 有没有把参考文档尽可能多的找出来,参考文档完整不
- 精确率=C/B 找到的错误的文档的比例 和召回率是你降我升的关系
- F1=2 * 召回率 * 精确率/(召回率+精确率)
评估方法
- 人工评估:
- 准备测试样本,包含问题,标准答案,评分标准
- 执行测试,得到结果
- 人工交叉评估,准确/错误
- 统计准确率/统计得分
- 模型自动评估:
- 测试样本,问题,标准答案
- 执行测试,得到作答结果
- 模型评估方法
- 将问题和作答结果输入Cross-Encoder模型,得到两者的想关心作为得分
- 评估标准答案和作答结果的文本相似度,得到结果作为评分
- 统计得分
评估框架
LangSmith平台 Langfuse平台 Rags框架
传统RAG架构
Reference
- bilibili-新手RAG教程
- 《基于大模型的RAG应用开发与优化》