1 概念与原理
概念
RAG把一个信息检索组件和文本生成模型结合,RAG可以微调且不需要对整个模型进行重新训练
解决的问题:
- 模型存在上下文窗口大小限制,不能一次性给大模型所有信息
- 模型推理成本高
- 模型推理时间长
- 信息时效性低,需要不断更新
- 企业私有数据不能公开
1.1 RAG工作流程
1.1.1 存储过程
- 分片 2 分片(Chunking)
- 按字数划分
- 按段落划分
- 按章节划分
- 按页码划分
- 索引
- Embedded:通过Embedding模型将片段文本转化为向量
- Store:把片段文本和对应的向量存储进向量数据库
1.1.2 查询过程
- 通过Embedding模型将用户问题转化的向量
- 向量数据库中存储的向量
- 召回(计算1和2向量的向量相似度向用户返回10个最相似的片段)(👍成本低、👍耗时短、👎准确率低)
- 余弦相似度[@steckCosinesimilarityEmbeddingsReally2024]
- 欧氏距离
- 点积
- Bi-Encoder
- 重排(👎成本高、👎耗时长、👍准确率高)
- cross-encoder:BGE-Reranker
- 生成(发送给大模型的知识)
参考文献
论文:[@lewisRetrievalaugmentedGenerationKnowledgeintensive2021]
2 分片(Chunking)
一次性输入所有(相关和不相关)的内容会有以下问题:
- 所有内容被平均,不能精确表示特定主题,章节或页码,降低了相关性搜索精度
- 大模型上下文窗口(conetxt window)很容易被耗尽
概念
把长本文切分成多个更小的片段的操作成为分片(Chunking)。
分片问题
分片太大的问题同一次性输入所有(相关和不相关)的内容。
分片太小会失去上下文联系,也会导致见底相关性搜索精度。
2.1 固定大小分片(Fix Size Chunking)
概念
例如一个分片250个字符
存在一段连贯内容被分割的情况,可以通过重叠分片(Overlapping Chunking)的方式让分片边缘两次都有相应的上下文
| 优点 | 缺点 |
|---|---|
| 新的块与前一个块内容重叠,更好的捕捉每个块周围的上下文 | 可能导致文本被打断,产生无意义的块 |
2.2 递归字符分割(Recursive Character Splitting)
概念
根据某一特定字符进行分片,比如换行符
| 优点 | 缺点 |
|---|---|
| 相比固定大小分片更加灵活 | 前提和结果可能分布在不同分片中,可能存在幻觉 |
前提和结果可能分布在不同分片中,可能存在幻觉示例:
小明做了一个梦,他得了ACM金牌!如果把逗号前和后分开,可能会得出小明得了ACM金牌的错误答案,而正确答案是小明做梦得了ACM金牌,现实中小明没有得ACM金牌。
2.3 文档特定分片(Document Specific Chunking)
概念
考虑文档的结构,创建与文档的逻辑部分(如字数、段落、章节、页码)对齐的块。
| 优点 | 缺点 |
|---|---|
| 保持作者对内容的组织和文本连贯性 | |
| 对于Markdown、HTML等结构化文档的格式更加有效 |
2.4 语义分片(Semantic Chunking)
概念
根据相似意思对句子进行灵活的分片
工作流程:(sentence by sentence)
- 对当前句子(sentence)和下一个句子都进行向量化
- 计算两个向量之间的相似度(计算方法参看 3.1.3 语义检索(Semantic Search))是否低于某个阈值,如果低于则把句子加入到当前分片,高于则当前分片结束开始新的分片
- 如果分片没有结束则循环对下一个句子做以上两个操作
| 优点 | 缺点 |
|---|---|
| 更高的召回率和准确率 | 需要重复计算句子的向量距离,计算成本高 |
| 相比不需要计算的方法速度要慢很多 |
2.5 基于大模型的分片(Language Based Chunking)
概念
通过分片提示词(保持概念的连贯性、当有新话题开始时做分割)让LLM对文档做分片,并可对每个分片做相应的总结(总结帮助大模型快速理解分片内容并促进理解文档整体内容)
| 优点 | 缺点 |
|---|---|
| 高性能 | |
| 成本会随大模型调用的成本降低而降低 |
3 查询语句解析(Query Parsing)
3.1 重写查询语句(Query Rewriting)
概念
在prompt提交到检索器之前使用LLM进行提示词优化(Prompt Optimization)
3.2 命名实体识别(Named Entity Recognition | NER)
概念
命名实体识别(NER)是一种自然语言处理(NLP)技术,主要用于识别和分类文本中提到的重要信息(关键词)。这些实体包含3大类(实体类,时间类,数字类)和7小类(人名、地名、组织机构名、时间、日期、货币、百分比)。
NER的目标是将文本中的非结构化信息转为结构化信息,以便计算机能够更容易地理解和处理。
参考文献
3.2.1 GLINER Name Entity Recognition
| 优点 | 缺点 |
|---|---|
| 对长序列提取、长实体提取、摘要、文本清理等任务很有效 | 增加了额外的延迟 |
参考文献
论文:[@stepanovGLiNERMultitaskGeneralist2024][@zaratianaGLiNERGeneralistModel2023]
开源项目:https://github.com/urchade/GLiNER
参考资料:https://zhuanlan.zhihu.com/p/721476019
3.3 假设文档嵌入(Hyypothetical Document Embeddings | HyDE)
概念
使用基于LLM生成的“假设文档”处理搜索结果改进检索系统的语义对齐和检索结果
工作流程如下:
- 生成假设文档:利用LLM根据用户查询生成一段描述性文档。
- 向量化处理:将生成的假设文档通过稠密编码器映射到向量空间。
- 检索匹配:使用生成的向量在向量数据库中检索相关文档。
- 返回结果
| 优点 | 缺点 |
|---|---|
| 无需标注数据且无需训练额外模型,减少对数据的依赖 | 特定领域可能需要定制化调整以提高效果 |
| 通过假设文档辅助查询与文档的语义匹配来提升语义对齐 | 假设文档可能存在错误细节且LLM可能引入偏差,影响检索结果 |
| 提高检索的召回率和准确率 | 延迟:生成和编码过程可能增加检索延迟 |
| 计算资源:生成和向量化处理需要额外的计算资源 |
4 召回-检索器
4.1 检索方法
- 4.1.1 元数据检索(Metadata Search)
- 4.1.2 关键词检索(Keyword Search)
- 4.1.3 语义检索(Semantic Search)
- 4.1.4 混合检索(Hybrid Search)
4.1.1 元数据检索(Metadata Search)
概念
对文档的标题、作者、编写时间、限定地区等元数据进行过滤
| 优点 | 缺点 |
|---|---|
| 简单且容易调试 | 不考虑文档内容 |
| 快速、成熟、可靠 | 无法对筛选后的数据进行排序 |
| 合适匹配精准的检索规则 |
4.1.2 关键词检索(Keyword Search)
概念
量化一个文档和查询语句匹配的程度
| 优点 | 缺点 |
|---|---|
| 简单 | 无法搜索到语义一致,但用词不精确的提示词 |
| 保证准确匹配结果 |
4.1.2.1 TF-IDF
- 词频TF(Term Frequency):一个词(term)在一个文档(doc)中出现的频率越高,那么文档的相关性越高
- 逆向文档频率IDF(Inverse Document Frequency):每个检索词分布在不同文档的总文档数量越多,对应的文档与该检索词的相关性就越高,比如一些专业术语仅在很少的文档中出现,则这些文档与该专业术语的相关性就很高
- TF和IDF结合起来计算一个词的TF-IDF值,公式如下:
| 优点 | 缺点 |
|---|---|
| 简单有效 | 不考虑词序和上下文信息 |
4.1.2.2 BM25(Best Matching 25)
概念
BM25是基于TF-IDF增加了词频率饱和度(Term Frequency Saturation)和文档长度归一化(Document Length Normalization)可调节参数的改进算法
- 是文档D与查询Q的相关性得分
- 是查询中第个词
- 是词的在文档D中的频率
- 是词的你文档频率,公式如下:
- 是文档D的长度
- ,即average document length,是所有文档的平均长度
- 是可调超参数:词频饱和度(Term Frequency Saturation),控制词频影响分数的程度,一般调节范围为[1.2, 2.0],值越高词频影响分数的程度越大,值越低影响程度越小
- b是可调超参数:文档长度归一化(Document Length Normalization),控制文档长度归一化的程度,范围为[0, 1.0],通常设置为0.75,平衡对长文本的惩罚力度
4.1.2.3 BM25变体
- BM25+:基于BM25进一步考量了query里term的频率(查询项权重)对得分的影响,
- BM25L:基于BM25进一步考量了文档长度对得分的影响
- BM25T:基于BM25引入词权重,通过考虑词频、你文档频率以及文档长度等特征,以确定每个词项在文本中的重要性
- BM25F:基于BM25将多个字段(标题、正文、标签等)考虑在内的改进算法
其他参考资料: - 端到端BM25[@chenBM25QueryAugmentation2023][@samelEndtoendQueryTerm2023]
4.1.3 语义检索(Semantic Search)
- 余弦相似性(Cosine Similarity)
- 点积(Dot product)
- 欧氏距离(Euclidean Distance)
/cos.png)
4.1.4 混合检索(Hybrid Search)
/hybrid-search.png)
混合检索通过倒数排序融合(Reciprocal Rank Fusion)来合并关键词检索与语义检索产生的结果
倒数排序融合(RRF Reciprocal Rank Fusion)的工作公式:
- :文档d最终的RRF融合分数
- :文档d在第i个检索系统(或排序列表)中的排名。如果文档d没有出现在第i个列表中,那么在计算这个列表时,他对总分的贡献就是0,即
- :一个平滑常数(smoothing constant)
- 避免除以零,给所有文档一个基础分母
- 调节高排名文档和低排名文档的权重差异,避免排名很靠后的文档因为分母过大导致影响力过小
注意
RRF仅关心文档的排名,不关心分数大小
检索器通常还包含可调参数,可以调节关键词检索和语义检索生成结果的占比,一般设置为0.7,即语义检索结果占70%,关键词检索占30%。
Note
精确的场景可以通过参数提升关键词检索结果的占比
检索器返回的相似结果数量可以通过top_p参数控制。
4.2 召回方法
4.2.1 多路召回
4.2.2 稀疏召回
4.2.3 语义召回
4.3 vector database向量搜索算法^03b275
4.3.1 KNN(K Nearest Neighbor | K最近邻)
概念
每次给定一个Query向量,计算给定Query向量到其他每个点的距离
4.3.1.1 FLAT
概念
也称IDMap,暴力搜索
| 优点 | 缺点 |
|---|---|
| 检索精度:100% | 查询速度:慢,时间复杂度为 |
| 计算资源:计算资源消耗大 | |
| 存储占用:高,所有向量都需要加载到内存中 | |
| 4.3.2 ANN(Approximate Nearest Neighbor | 近似最近邻) |
概念
查询前构建近邻图。每次给定一个Query向量,判断搜索向量属于哪个簇,在该簇中进行搜索
4.3.2.1 K-Means
概念
当搜索向量处于两个聚类区域中间时,容易遗漏部分近似向量
4.3.2.2 Faiss
概念
为了解决搜索向量处于多个聚类区域中间的问题
4.3.2.3 IVF(Inverted File Index | 倒排文件索引)
概念
通过k-means聚类将向量划分到多个簇中,每个簇都有一个聚类中心向量。通过构建倒排表,将聚类中心向量与属于该簇其他向量进行关联。搜索时,查询给定Query向量找到与之最相关的聚类中心向量,在对应倒排表中查找近似向量。
Milvus提供多种变体:
- IVF_FLAT
- IVF_PQ
- IVF_SQ8
| 优点 | 缺点 |
|---|---|
| 查询速度:比FLAT快很多,复杂度为 | 检索精度:精度比FLAT低 |
| 计算资源:两级索引减少计算量 | 预训练索引:需要具备一定数据量后才可以开始训练(k-means聚类),且需要定期重建IVF索引表 |
| 存储占用:存储占用较低,可结合量化(PQ/SQ8)进一步压缩数据 |
4.3.2.4 HNSW图索引^fd9c42
概念
基于NSW原理构造多层图,每一层都是一个小世界图(Small World Graph),使高层节点连接更远的点,低层节点连接更近的点,并使用跳表连接高层与低层。搜索时,首先从高层搜索,逐层向下递归找到最近的向量
| 优点 | 缺点 |
|---|---|
| 检索精度:高,接近FLAT | 存储占用:较高,需要存储图结构,内存占用也较大 |
| 查询速度:快,通常比IVF更快,接近 | 索引:构建索引时间较长 |
| 计算资源:需求较少 |
4.4 检索编码器
4.4.1 双编码器(Bi-Encoder)
- 分离语义向量:文档(documents)和提示词(prompts)通过嵌入模型(Embedding Model)分别被嵌入(embedded)
- 近似最近邻搜索(ANN Search):向量数据库通过ANN快速识别与提示词最相关的文档
| 优点 | 缺点 |
|---|---|
| 文档向量可以提前被嵌入。查询时耗时短,计算资源需求量小 | 相对Cross-Encoder较低质量的检索结果 |
4.4.2 交叉编码器(Cross-Encoder)
- 每个文档(documents)都要和提示词(prompts)连接一次反馈到交叉编码器
- 反馈给交叉编码器:连接好的文本输入到专用嵌入模型中,深度理解提示词和文档的上下文关系并输出相关的文档
| 优点 | 缺点 |
|---|---|
| 更高质量的检索结果 | 只有查询时输入提示词并连接后,文档才会被嵌入。查询时耗时长,计算资源需求量大 |
4.4.2.1 实现
4.4.2.1.1 BGE-Reranker-v2-M3
核心组成部分:
- 骨干网络:基于XML-RoBERTa多语言预训练模型,对原始模型做了重排序任务的优化
- 输入层:采用特殊的输入编码方式,将查询和文档拼接为单一序列
- 格式:[CLS]查询文本[SEP]文档文本[SEP]
- 支持512个token的输入序列长度
- 中间表示层:多层Transformer编码器,捕捉查询-文档之间的交互信息
- 输出层:基于[CLS]标记的表示,通过简单的线性分类器输出相关性得分
- 池化层:从序列标识中提取固定维度的特征向量(通常取[CLS]标记的表示)
- 得分预测层:将表示映射到标量相关性得分
| 优点 | 缺点 |
|---|---|
| 高效的交叉编码器架构,平衡了精度和计算效率 | 计算开销:计算复杂度仍然与文档数量呈线性关系 |
| 优秀的多语言处理能力 | 上下文长度限制 |
| 与初步检索模型良好的互补性,能显著提升整体检索性能 | 实时性:对于严格的实时系统,仍需进一步优化推理速度 |
参考文献
4.4.3 ColBERT(Contextualized Late Interaction Over BERT | 基于BERT的上下文延迟交互)
概念
能够像Bi-Encoder一样提前嵌入文档向量,又能像Cross-Encoder一样深度理解提示词和文档的上下文关系
工作流程:
- Document通过Document Encoder后分割成组成标记
- 当查询时,Query通过Query Encoder后分割为,通过与每个文档标记做MaxSim后加和得到相关性分数
/colbert.png)
| 优点 | 缺点 |
|---|---|
| 具有Bi-Encoder的可扩展性 | 向量存储:需要一个与文档成线性增长的稠密向量 |
| 具有和Cross-Encoder一样更高质量的检索结果 |
参考文献
论文:[@khattabColBERTEfficientEffective2020]
5 重排
概念
重新打分,提升RAG的检索结果。使用高精度和高召回率应用,但会提高检索延迟
- 4.4.2 交叉编码器(Cross-Encoder)
- 4.4.3 ColBERT(Contextualized Late Interaction Over BERT | 基于BERT的上下文延迟交互)
- 基于大模型的打分
6 评估策略
6.1 性能指标(Performance Metrics)
基于代码收集的指标:
- 延迟(Latency)
- 吞吐量(Throughput)
- 内存使用量(Memory usage)
- 计算资源使用量(compute usage)
- 每秒生成的token数(Tokens/Second)
6.2 质量指标(Quality Metrics)
6.2.1 检索器的质量评估
6.2.1.1 人类指标
输入人类注解的数据集后的人类反馈
6.2.1.2 系统指标
- percision(精确度):,测量有多少文档是相关的,表现总文档的可信度
- recall(召回率):,测量遗漏了多少相关文档,表现相关文档检索覆盖率
6.2.1.2.1 MAP@K(Mean Average Percision At Top_K)
怎么做?
MAP为评估前n个文档相关文档的精确度,MAP@K则为评估前k个文档相关文档的精确度,MAP@K越高表明越精确
6.2.1.2.2 MRR(Mean Reciprocal rank)
怎么做?
测量返回列表第一相关文档的排名,强调相关文档的排名位置,相关文档越靠前分数越高
- :样本数量
- :第i个相关文档在列表中的排名,若第i个相关文档不在列表中,则为0
6.2.2 LLM(RAGAS)
- 响应的相关性
- 引用质量
- 过滤的噪音
7 RAG的监测
8 平衡RAG的延迟和响应时间
| 优先项\项目类型 | 电商平台 | 医学诊断 |
|---|---|---|
| 速度 | VERY HIGH | LOWER |
| 质量 | MEDIUM | VERY HIGH |
下图展示了RAG延迟的主要来源:
/latecy.png)
以下是减少模型延迟的解决方案:
- 使用小模型或量化的模型
- 使用路由(Router)决定使用何种规模的模型
- 缓存 - 直接缓存:找到相关的匹配项就立即返回,完全跳过拖慢进程的生成步骤 - 个性化缓存:把缓存的响应和用户提示词输入给快速的小模型,以便调整提高相关性
针对向量数据库的解决方案: - 分库:将一个大的数据库拆分成多个示例
- 向量数据库提供的其他工具…