掌握 RAG:从核心原理到生产级优化
检索增强生成(Retrieval Augmented Generation,RAG)是当前大语言模型落地中最具实用价值的技术之一。本文将从零开始,带你彻底搞懂 RAG 是什么、为何需要它、核心流程如何运作,以及如何一步步优化系统性能。内容涵盖文档分块、相似度算法、重排序、知识图谱增强、效果评估与常见缺陷,适合所有希望将 LLM 真正用于业务的开发者。
在开始之前,先尝试回答下面这些问题——读完本文你会找到所有答案。
- 什么是 RAG?RAG 的流程是什么?为什么需要 RAG?
- 如何对文档分块(Chunking)?分块大小如何选择?
- 检索时如何计算相似度?余弦相似度有什么缺点?
- 如何优化 RAG 流程?
- 什么是 Re-rank?如何重排序?
- 什么是 GraphRAG?
- 如何评估 RAG 系统的效果?
- RAG 有哪些缺点?

一、RAG 介绍
RAG(Retrieval Augmented Generation)是一种无需微调即可扩充模型知识的常用方法。借助 RAG,LLM 可以从数据库中检索上下文文档,从而提高答案的准确性。
因为 LLM 大模型通过海量数据进行训练,数据具有时效性。如果询问最新的文档或专业领域知识,LLM 无法回答。而检索增强生成(RAG)通过将你的数据添加到 LLM 已有的数据中来解决这一问题。
RAG 解决了纯生成模型的局限性(如幻觉、知识过时等),通过动态检索外部知识增强生成结果的可信度和时效性。
小提示:如果你只关心最新新闻或企业内部知识库,RAG 是最快、成本最低的方案,无需重新训练模型。
二、RAG 流程
典型的 RAG 流程分为两个部分:
1. 构建向量存储
创建向量存储是构建 RAG 流程的第一步。文档会被加载(Load)、拆分(Split)、Embedding,并存储到向量数据库中。
- 加载文档(Load):加载各种非结构化数据,例如 TXT 文本、PDF、JSON、HTML、Markdown 等。LangChain 封装了各种格式的 DocumentLoaders 文档加载器。
- 切分文本(Split):将文本切分成更小的文本块(Chunk)。
- 转化向量(Embedding):使用 Embedding 模型将文本转换为向量(浮点数数组)表示。
- 向量数据库(VectorStore):存储 Embedding 向量,能够基于向量相似度高效地检索与查询“最相似”的数据。
2. 检索生成
根据用户输入,用向量数据库进行相似性搜索,然后把用户的 question 和搜索到的 context 作为上下文喂给 LLM 大模型,LLM 分析推理后回答用户的问题。
我使用 LangGraph 构建了基本的 RAG 流程:
调用 Retrieval Tool 搜索相关文档,然后 GradeDocument 对文档进行评分:如果检索到的文档与用户输入的内容相关,则 GenerateAnswer 生成答案返回;如果不相关,则 Rewrite 重新生成 query 进行检索。
代码已上传 GitHub:https://github.com/Liu-Shihao/ai-agent-demo/tree/main/src/rag_agent
三、进阶 - RAG 优化
3.1 文档 Chunking
大模型对话的 token 数量有限制,文档切分是为了将文档切分为小的文本块,适合检索并节省 token。切分的文本块长度会影响 LLM 回答的质量。
常见的切分文档方法:
- 固定长度切分(重叠分块边界):按照字符或 Token 数(如 512 个 token)切分。重叠分块可以避免边界信息丢失。这种方法最简单,但有可能截断语义。
- 按照句子边界(标点符号)分块:例如使用 NLP 框架
SpaCy,但长段落可能语义断裂。 - 自定义规则分割:用正则表达式或 DOM 解析器(如 BeautifulSoup)按照逻辑结构(标题、段落)分块。适合结构化文档,但需要手动设计分割规则。
- 基于语义的分块:用 Transformer 模型分析语义关系分块。
优化原则:
- chunk 块大小需要匹配 embedding 模型和 LLM 大模型的 token 限制。
- 关键信息(实体、关系)尽量保留在同一块中。
小提示:如果文档结构清晰(如说明书带标题),优先使用自定义规则分割;如果内容偏自然语言(如新闻),基于语义的分块效果更好。
3.2 相似性算法
在 RAG 和其他信息检索任务中,相似性算法用于衡量文本、向量或实体之间的关联程度。
-
欧氏距离(L2):欧几里得距离测量连接两点的线段的长度(计算向量间的直线距离)。它是最常用的距离度量,当数据连续时非常有用。值越小,相似度越高。 -
余弦相似度(COSINE):余弦相似度使用两组向量之间夹角的余弦来衡量它们的相似程度。余弦相似度始终在 区间[-1, 1]内。余弦值越大,两个向量之间的夹角越小,表明这两个向量彼此越相似。 适合文本 embedding 比较。 -
BM25(Best Matching 25):BM25 基于词频(TF)和逆文档频率(IDF)。根据词频、倒排文档频率、文档规范化对相关性进行评分,用于评估文档与查询的相关性。广泛应用于搜索引擎和问答系统,如 Elasticsearch 默认使用 BM25 排序。- 词频(TF):衡量查询词在文档中的出现频率,但通过参数 k1 控制词频的饱和效应,避免高频词过度影响得分。
- 逆文档频率(IDF):惩罚常见词(如“的”“是”),提升罕见词的权重。反映某个术语在整个语料库中的重要性。
- 文档长度归一化:较长的文档由于包含更多术语,往往得分更高。BM25 通过归一化文档长度来缓解这种偏差。
-
Jaccard 相似度(Jaccard Index):比较集合的交集与并集比例。适用场景:关键词集合、推荐系统(如用户兴趣匹配)。范围[0,1],值越小,相似度越高。
RAG 中的典型应用:
- 初步检索:余弦相似度(快速筛选候选文档)。
- 重排序:交叉编码器(精细排序 Top-K 结果)。
- 去重:Jaccard 相似度(合并重复片段)。
通过灵活组合这些算法,可以优化 RAG 系统的召回率、准确率和响应速度。
3.3 余弦相似度(COSINE)的缺点
-
忽视向量长度信息:余弦相似度仅计算向量方向的夹角,忽略向量的长度(模)。
- 高频词干扰:TF-IDF 或词频高的长文本可能主导方向,但实际语义不相关。
- 归一化依赖:未归一化的向量可能导致相似度计算偏差。长文本包含更多词汇,其向量各维度值累加后长度(模)显著大于短文本。
-
语义相似度 ≠ 相关性:余弦相似度基于表面语义匹配。
- 表面匹配,但相关文档不一定语义相似:例如,“猫和狗是常见的宠物”与“猫和狗不适合作为宠物”,余弦相似度高,但语义相反。
- 词序颠倒,但余弦相似度相同:例如,“医生治疗病人”与“病人治疗医生”余弦相似度一样。
解决方案:
- 向量归一化:强制所有向量的单位长度(如 L2 归一化)。
- 结合其他指标:如点积相似度(考虑长度)或 BM25(词频加权)。
- 重排序(Re-rank):用交叉编码器(如 MiniLM)精细化排序。
- 混合检索:结合关键词匹配(BM25)或知识图谱关系。
小提示:在实际项目中,建议先用余弦相似度快速召回 Top-100,再通过重排序筛选出 Top-10,兼顾速度和精度。
3.4 Rerank 重排序
重排序(Reranking)是对初步检索结果进行优化排序的技术,旨在提升结果的相关性和准确性。
初次检索(如余弦相似度)可能返回语义相关但冗余或低质量片段,重排序可结合更多特征优化顺序。
方法:
- 交叉编码器(Cross-Encoder):如 MiniLM-L6-v2,计算查询与每个文档的相关性分数(比嵌入模型更准但更慢)。
- 学习排序(Learning to Rank):训练模型综合多特征(如关键词匹配、点击率)排序。
- 规则调整:去除重复内容,优先新鲜度高的文档。
3.5 GraphRAG
使用知识图谱(Knowledge Graph, KG)增强 RAG 可以显著提升复杂推理、多跳问答和关系挖掘的能力。通过将文档中的 实体(Entities) 和 关系(Relations) 提取为知识图谱,在检索阶段不仅返回文本片段,还返回相关的子图结构,从而增强生成模型的上下文理解能力。
与传统 RAG 的区别:
| 特性 | 传统 RAG | GraphRAG |
|---|---|---|
| 检索单元 | 文本片段(Chunks) | 实体+关系子图 |
| 推理能力 | 单跳语义匹配 | 多跳推理(如 A→B→C) |
| 适用场景 | 简单问答 | 复杂关系查询 |
实现步骤:
- 实体识别(NER):使用 SpaCy NLP 模型或者 LLM 大模型进行命名实体提取,从文本中识别提取人名、地名、组织名、地点、日期等实体。
- 关系抽取:利用 LLM 大模型抽取三元组(<主体 (Subject), 关系 (Predicate), 客体 (Object)>)。
- 图谱存储:将节点 Node 和关系 Relations 存储到图数据库中,如 Neo4j。
三元组(Triple)是知识图谱中的基本数据单元,用于表示实体之间的关系,其结构为:〈主体 (Subject), 关系 (Predicate), 客体 (Object)〉
通过知识图谱的引入,RAG 系统能够从 “平面检索” 升级为 “立体推理”,尤其适合需要深挖实体关系的复杂场景。
四、RAG Evaluate 评估
对 RAG 的评估可以从以下两个部分进行:
4.1 检索质量
- 上下文准确率(Context Precision):是衡量上下文中相关词块比例的指标。准确率是排名为 k 的相关词块数量与排名为 k 的词块总数之比。
- 上下文召回率(Context Recall):前 K 个结果中相关文档的比例。衡量成功检索到的相关文档(或信息片段)数量。更高的召回率意味着遗漏的相关文档更少。
4.2 生成质量
答案相关度(Response Relevancy):生成答案与问题的契合度。衡量答案与用户输入的相关性。分数越高,表示与用户输入的匹配度越高;如果生成答案不完整或包含冗余信息,则分数越低。
忠诚度(Faithfulness):衡量的是 答案 与 检索内容 的事实一致性。答案是否严格基于检索内容,减少幻觉。
小提示:可以使用 RAGAS 框架或 LangChain 的内置评估器自动化计算这些指标。
五、RAG 有哪些缺点?
-
检索的质量依赖外部数据库:如果知识库不完整、过时或噪声多,检索到的内容可能不相关或错误,导致生成的答案质量下降。
解决方案:定期更新知识库(实时爬取权威数据源)。
-
分块(Chunking)导致上下文碎片化:固定大小的分块可能截断关键信息,答案可能分散在多个 chunk 块中。
解决方案:动态分块(按照语义边界切分,如段落、章节)。
-
语义相关不等于答案相关:向量检索(如余弦相似度)可能返回语义相关但无实际答案的文档(如查询“如何治疗感冒”,可能检索到“感冒症状描述”而非治疗方案)。
解决方案:引入重排序(Re-rank)模型(如交叉编码器);混合检索(结合关键词检索,如 BM25)。
-
生成模型忽视检索内容:生成模型可能忽略检索到的文档,仍依赖自身知识(幻觉)。
解决方案:强化提示工程(如“严格基于以下上下文回答”)。
-
无法处理多跳推理:传统 RAG 难以回答需要多步推理的问题(如“A 公司的竞争对手的 CEO 是谁?”)。
解决方案:引入知识图谱(GraphRAG)显式建模实体关系。
-
RAG 流程时间长:检索+生成两阶段流程导致响应时间较长(尤其涉及重排序时)。
解决方案:缓存高频查询结果。
| 缺点类别 | 具体问题 | 解决方案 |
|---|---|---|
| 检索质量 | 知识库不完整/碎片化 | 动态更新知识库、语义分块、重排序 |
| 生成偏差 | 忽视检索内容/幻觉 | 提示工程、模型微调 |
| 效率问题 | 高延迟/高计算成本 | 缓存、量化、分层检索 |
| 知识覆盖 | 领域盲区/偏见 | 多源数据融合、去偏处理 |
| 复杂推理 | 多跳推理困难 | GraphRAG、迭代检索 |
常见问题 FAQ
1. 什么是 RAG 的核心优势?
RAG 无需微调即可让 LLM 访问最新或私有数据,有效缓解幻觉和知识过时问题,且部署成本低。
2. 如何选择分块大小?
一般推荐 256-1024 tokens(取决于 Embedding 模型和 LLM 的上下文窗口)。可以先测试几种大小,比如 512 tokens 配合 10% 重叠,观察检索效果。
3. 余弦相似度与欧氏距离哪个更适合文本检索?
余弦相似度更适合文本 Embedding,因为它关注方向而非长度,能更好捕获语义相似性;欧氏距离对向量长度敏感,适合数值特征。
4. 重排序一定会提升效果吗?
重排序通常会显著提升最终答案的相关性,但会带来额外延迟。建议在实时性要求不高的场景(如内部知识库问答)中使用,或在响应速度要求高的场景下对 Top-5 以内结果重排序。
5. GraphRAG 适合哪些场景?
适合需要多跳推理、实体关系复杂的场景,比如金融风控、医疗诊断、法律条文关联等。如果只是简单的关键词问答,传统 RAG 已经足够。
6. 如何评估 RAG 系统是否值得上线?
至少需要衡量 上下文召回率(检索是否全面)和 忠诚度(答案是否基于检索内容)。如果这两项指标都较低,说明系统不可靠,需要优化分块或重排序策略。
通过本文的系统学习,相信你已经掌握了 RAG 从原理到优化的完整知识体系。接下来,建议你动手实践一下——从搭建一个简单的文档问答系统开始,逐步加入重排序、GraphRAG 等进阶技术,你会对每个优化点有更深的理解。
