RAG深度解析
为什么需要RAG
RAG = 检索(Retrieval)+ 增强(Augmented)+ 生成(Generation)。在 LLM 生成回答之前,先从外部知识库检索相关信息,拼接后一起送入模型。
| 方案 | 知识来源 | 准确性 | 更新成本 | 典型场景 |
|---|---|---|---|---|
| 纯 LLM | 训练参数中的记忆 | 幻觉风险高 | 重新训练/微调 | 通用对话 |
| 微调 LLM | 微调数据 + 原始参数 | 领域内较好 | 新数据需重新微调 | 垂直领域问答 |
| RAG | 外部知识库(实时) | 可溯源、可验证 | 更新文档即可 | 企业知识库、客服、法律 |
RAG 解决的三个核心痛点:
① 幻觉——LLM 不知道的事会编造,RAG 提供事实依据;
② 知识时效——训练数据有截止日期,RAG 可接入最新文档;
③ 可解释性——每个回答都能溯源到具体文档,不是黑箱。
RAG完整流程
# ============ 离线阶段(Indexing)============
原始文档(PDF/Word/HTML)
│
▼ ① 文档解析 & 分块
文本块 [chunk_1, chunk_2, ..., chunk_N]
│
▼ ② Embedding 向量化
向量 [v_1, v_2, ..., v_N]
│
▼ ③ 存入向量数据库
Milvus / Pinecone / Weaviate / Qdrant
# ============ 在线阶段(Retrieval & Generation)============
用户提问: "如何配置 Nginx 反向代理?"
│
▼ ④ Query 向量化(同 Embedding 模型)
│
▼ ⑤ 向量检索(ANN 近似最近邻)
Top-K 相关文档块
│
▼ ⑥ 重排序(Rerank)
精排后的 Top-M 结果
│
▼ ⑦ Prompt 组装
System: "根据以下文档回答问题:{docs}\n\n问题:{query}"
│
▼ ⑧ LLM 生成
最终回答(带引用来源)
文档解析与分块
文档解析
| 文档类型 | 工具 | 常见问题 |
|---|---|---|
| 纯文本 / Markdown | 直接读取 | 编码问题、特殊字符 |
| PyMuPDF, PDFPlumber, Unstructured | 扫描版 PDF 无文字层;表格/多栏排版错乱 | |
| Word | python-docx | 嵌入图片/公式丢失 |
| HTML | BeautifulSoup, Trafilatura | 导航栏/广告等噪声混入正文 |
| PPT | python-pptx | SmartArt/图表文字丢失 |
⚠ 最大痛点:扫描件与复杂排版
扫描版 PDF 需要 OCR(Tesseract / PaddleOCR / LLM Vision),但识别准确率受限。表格和多栏排版容易被解析成乱序文本——这是 RAG 系统的第一道坎,文档解析的质量直接决定了后续所有环节的上限。
文本分块(Chunking)
分块是 RAG 中最容易被低估的环节。切太细→语义不完整;切太粗→检索精度下降。
| 策略 | 做法 | 优点 | 缺点 |
|---|---|---|---|
| 固定长度 | 每 N 个 token 一刀切 | 简单、速度快 | 经常切断句子/段落 |
| 基于分隔符 | 按 \\n\\n、\\n、。!?等分隔 | 较自然 | 复杂文档分隔符不统一 |
| 语义分块 | 用 Embedding 算句子相似度,断在"语义突变"处 | 最自然 | 计算成本高 |
| 递归分块 | 先大后小逐层尝试:段落→句→词 | 兼顾精度与完整性 | 工程复杂度高 |
| Small-to-Big | 检索用小块(精确匹配),生成用大块(完整上下文) | 检索与生成各取所需 | 需维护两种索引 |
⚠ 分块陷阱:Chunk Overlap 的权衡
overlap 太小→相邻 chunk 间的信息断裂;overlap 太大→冗余信息挤占上下文窗口。通常设置为 chunk_size 的 10%~20%。举个例子:chunk_size=512 tokens,overlap=50~100 tokens。没有普适最优值——取决于文档结构和下游任务。
前沿方案
LlamaIndex / LangChain 的智能解析
Hierarchical Chunking(层级分块):文档 → 章节 → 段落 → 句子,不同粒度同时建索引。检索时先用粗粒度定位,再精细召回。
Metadata 增强:每个 chunk 附带标题层级、页码、文档来源等元信息,生成时用于引用溯源。
LLM 辅助清洗:用 LLM 对原始文档做"结构化改写"——把杂乱格式统一成标准 Markdown,表格转文字描述——然后再分块入库。
Embedding嵌入模型
模型选型
| 模型 | 维度 | 最大长度 | 中文效果 | 适用场景 |
|---|---|---|---|---|
| text-embedding-3-small | 512/1536 | 8191 | 中 | 通用,英文为主 |
| text-embedding-3-large | 256~3072 | 8191 | 较好 | 高质量需求 |
| bge-large-zh-v1.5 | 1024 | 512 | 优 | 中文场景首选 |
| bge-m3 | 1024 | 8192 | 优 | 多语言、长文本、稀疏+稠密双表征 |
| stella-base-zh-v3-1792d | 1792 | 512 | 优 | 高维度,精度优先 |
| GTE-Qwen2-7B-instruct | 3584 | 32768 | 最优 | LLM-based Embedding,需 GPU |
核心问题
问题一:Embedding 模型的"语义盲区"
稠密向量擅长捕捉语义相似度,但对精确关键词匹配不敏感。查询"AK-47 参数"时,向量检索可能返回"步枪发展史"(语义相近)而不是具体的 AK-47 技术手册(关键词精确)。
解决:混合检索(Hybrid Search)= 稠密向量 + BM25 关键词检索,取长补短。
问题二:不对称语义(Query-Document Mismatch)
用户问"怎么修漏水的水龙头",文档写的是"水龙头维修指南"。Query 和 Document 的表达方式不一样——Embedding 模型必须理解它们是同一件事。使用专门做过对比学习训练的 Embedding 模型(如 BGE、E5 系列),它们在训练时就用 (query, positive_doc, negative_doc) 三元组优化过这种对齐能力。
问题三:长文本截断
大多数 Embedding 模型有最大输入长度限制(512/8192 tokens),超过部分直接截断→信息丢失。
解决:
① 用 bge-m3 (8192) 或 GTE-Qwen2 (32768);
② 对超长文档先摘要再 Embedding;
③ 分块时保证每块在限制内。
向量数据库与索引
主流选型
| 数据库 | 定位 | 索引算法 | 特点 |
|---|---|---|---|
| Milvus | 分布式向量数据库 | HNSW, IVF_FLAT, DiskANN | 十亿级向量、混合检索、多租户 |
| Pinecone | 云原生向量数据库 | 自研 | 免运维、按量付费 |
| Weaviate | 开源向量数据库 | HNSW | 内置 GraphQL + 混合检索 |
| Qdrant | 高性能向量数据库 | HNSW | Rust 实现、过滤能力强 |
| Chroma | 轻量向量数据库 | HNSW | 适合原型、Python 原生 |
| Elasticsearch | 搜索引擎 + 向量 | HNSW | 已有 ES 集群的首选 |
ANN 索引算法
底层需求
你手里有几百万 / 上亿条高维向量(图片、文本、音频转出来的数字特征),现在输入一条新向量,要找出库里和它最像的 N 条。
如果逐条对比全部向量,速度慢到爆炸,ANN 近似最近邻就是「不用全部比对,牺牲一丢丢精准度,换极速查找」的算法,HNSW、IVF_PQ 是两种主流方案。
HNSW(Hierarchical Navigable Small World)
当前最主流的 ANN 算法。构建多层图结构,上层稀疏、下层密集。检索时从顶层快速"跳"到目标区域,再在下层精确搜索。内存占用高(需存全图),但查询速度最快。
关键参数:M(每层节点连接数,越大精度越高但内存越大)、ef_construction(构建时搜索宽度)、ef_search(查询时搜索宽度)。
IVF_FLAT + PQ(Product Quantization)
IVF:用 K-means 聚类将向量空间分成 N 个区域,检索时只搜最近的几个区域。PQ:将高维向量压缩为短码,大幅降低内存占用。适合内存受限场景,但精度略低于 HNSW。
⚠ 索引构建慢、内存爆炸、精度衰减
索引构建:HNSW 构建 O(N·logN·M),百万级向量可能耗时数小时。解决——增量索引、分布式构建。
内存爆炸:1024 维 × 1000 万向量 × 4 bytes ≈ 40GB。解决——PQ 量化压缩、DiskANN 磁盘索引。
精度衰减:ANN 是近似检索,召回率不是 100%。解决——适当增大 ef_search,或 ANN + 精确重排两阶段。
检索策略
稀疏检索(Sparse Retrieval)— BM25
基于词频-逆文档频率(TF-IDF)的经典算法。核心公式:
优势:精确关键词匹配(人名、专有名词、代码变量名),不会被"语义相似"带偏。
劣势:同义词、近义词完全不懂——搜"汽车"不会返回"轿车"。
稠密检索(Dense Retrieval)— 向量相似度
将 Query 和 Document 都用 Embedding 模型变成向量,算余弦相似度。
优势:语义理解——"怎么退钱"能匹配到"退款流程说明"。
劣势:精确匹配能力弱,边界 case 容易出错。
混合检索(Hybrid Search)
⭐ 生产环境标配:BM25 + 向量,双路召回 → 融合排序
两路各自返回 Top-K,然后通过 RRF(Reciprocal Rank Fusion)合并:
文档在多路中同时靠前→总分最高→最终排名最前。这是目前工业界最成熟的混合检索方案。
检索阶段的常见问题
问题一:检索到的文档和问题无关(Low Recall)
原因:Embedding 模型不够好、chunk 切得太碎或太粗、索引参数不合理。
解决:
① 换更强 Embedding 模型;
② Query 改写(Query Rewriting)——用 LLM 把口语化提问改写成检索友好的查询;
③ 多轮检索(Multi-hop Retrieval)——第一轮召回→提取关键实体→第二轮精确搜索。
问题二:检索到的文档太多太杂(Low Precision)
解决:
① Rerank 精排(见下一节);
② 元数据过滤(按日期/来源/类别预筛选);
③ Self-Query Retrieval——LLM 先解析 query 中的过滤条件("最近的"→date>2026-01-01),再检索。
问题三:信息重复——检索回来的 N 个 chunk 内容高度重叠
解决:
① 检索后去重(MinHash / 向量相似度阈值);
② 多样性重排(MMR——Maximal Marginal Relevance),在相关性和多样性之间平衡。
重排序
粗排(向量检索)追求"快",精排(Rerank)追求"准"——两阶段是工业界标准范式。
常见Rerank模型
| 模型 | 类型 | 速度 | 精度 |
|---|---|---|---|
| bge-reranker-v2-m3 | Cross-Encoder | 慢 | 高 |
| Cohere Rerank v3 | API | 快 | 高 |
| Jina Reranker v2 | Cross-Encoder | 中 | 高 |
| LLM-as-Reranker | GPT/DeepSeek 打分 | 很慢 | 最高 |
Cross-Encoder vs Bi-Encoder
Bi-Encoder(向量检索)
Query 和 Document 分别独立编码成向量。检索时只需算向量距离——快,但 Query 和 Document 之间没有交互。
Cross-Encoder(Rerank 精排)
把 [Query, Document] 拼接后一起送入模型,输出一个相关性分数。Query 和 Document 在 Transformer 内部充分交互——准,但每对都要过一遍模型,无法用于大规模检索。
常见问题
⚠ Rerank 会不会把正确的排下去?
会的。Cross-Encoder 通常比 Bi-Encoder 更准,但并非绝对。
解决:
① 保留多路结果,Reranker 只做加分不做减法(被翻下去的文档在生成阶段仍有概率被用到);
② 用 LLM 再验证一遍 Top-3 结果是否真的相关。
增强与生成
Prompt 组装策略
# 标准 RAG Prompt 模板
system_prompt = """
你是一个专业的技术文档助手。请根据以下参考资料回答用户问题。
如果参考资料不足以回答,请明确说"根据现有资料无法确定",
不要编造信息。
参考资料:
{retrieved_docs}
要求:
- 回答末尾列出引用的文档来源
- 如果参考资料中有矛盾,指出矛盾点
"""
user_prompt = f"问题:{query}"
常见问题与解决方案
⚠ 幻觉依然存在——模型可能无视检索结果
即使检索回来了正确答案,LLM 有时会"坚持己见",忽略给定文档。这通常发生在:模型对某领域有很强的先验信念、检索结果和模型训练记忆冲突。
解决:
① Prompt 中加"只能用参考资料中的信息回答"的硬约束;
② SELF-RAG——让模型在生成时主动判断是否需要检索,以及检索结果是否可信;
③ Citation-Enhanced(引用增强)——要求模型每句话标注来源 chunk_id,用约束解码强制引用格式。
⚠ 上下文窗口不够——检索到的文档塞不下
GPT-4 128K、Claude 200K 看起来很大,但 RAG 中如果有 5 个 chunk 各 2000 tokens + 对话历史 + system prompt,轻松突破 20K。况且 token 越多越贵,延迟越高。
解决:
① 对检索结果做摘要压缩再送入 LLM;
② Lost in the Middle——LLM 对中间位置的文本关注度最低,重要的文档放最前面或最后面;
③ Long-Context Reorder——按相关性降序排列文档,越相关越靠前。
⚠ 多文档冲突——检索回来的文档互相矛盾
解决:
① Prompt 中明确要求"指出矛盾";
② 分文档生成、再综合——每个文档独立生成回答,再用 LLM 合并、标注分歧点;
③ 可信度加权——每个文档有可信度分数,高可信度的优先采纳。
前沿方案
1、 GraphRAG(Microsoft, 2024)
从"块检索"到"图推理"
传统 RAG 检索的是孤立的文本块。GraphRAG 先对文档做实体抽取+关系构建,形成知识图谱,然后检索时在图上做多跳推理。
优势:能回答需要跨文档推理的复杂问题("A 公司和 B 公司有哪些共同供应商?"),普通 RAG 做不到。
代价:离线构建图成本高(需要 LLM 做实体/关系抽取),图更新不如向量库灵活。
2、 Agentic RAG(智能体 RAG)
从"固定流程"到"动态决策"
标准 RAG 的流程是死的:检索→生成。Agentic RAG 给 LLM 配工具(搜索、数据库查询、计算器),让模型自己决定:什么时候检索、检索什么、检索结果够不够、要不要再搜一轮。
关键能力:Query 分解(复杂问题拆成子问题逐个检索)、工具选择(向量库 vs SQL vs 搜索引擎)、自反思(检索结果不好→改写Query→重新检索)。
3、Self-RAG(自我反思 RAG)
生成时动态判断是否检索
训练模型输出特殊 token:<Retrieve>(需要检索)、<ISREL>(文档相关)、<ISSUP>(文档支持该结论)、<ISUSE>(回答有用)。模型在生成过程中自己决定每一步。
优势:不需要外部触发器,模型自己判断什么时候要查资料、查到的资料能不能用。
4、ColBERT — 延迟交互(Late Interaction)
介于 Bi-Encoder 和 Cross-Encoder 之间
Query 和 Document 分别编码成多个 token-level 向量,然后在检索时做 token-by-token 的 MaxSim 匹配。既保留了 Bi-Encoder 的离线索引能力(Document 向量可以预计算),又获得了 Cross-Encoder 的细粒度交互。
ColBERTv2 + PLAID 引擎可以在毫秒级完成大规模检索+交互式匹配。
5、HyDE(假设文档嵌入)
让 LLM 先"编"一个答案,再用这个答案去检索
Query → LLM 生成一个假设的答案文档(可能不准确)→ 将假设答案的 Embedding 作为检索向量。原理:LLM 生成的答案在语义空间中和真实文档更近——因为它是"文档风格"的,而不是"问题风格"的。
代价:多一次 LLM 调用,延迟翻倍。
关键问答
参考文献
| # | 论文 | 核心贡献 |
|---|---|---|
| 1 | Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks Lewis et al., Facebook AI, 2020 |
RAG 开山之作。提出 RAG-Sequence 和 RAG-Token 两种架构,用 DPR 做检索 + BART 做生成,验证了知识密集型任务上 RAG 优于纯参数化模型。 |
| 2 | Dense Passage Retrieval for Open-Domain Question Answering Karpukhin et al., Facebook AI, 2020 |
提出 DPR(Dense Passage Retriever):用对比学习训练双塔模型,Query 和 Passage 独立编码后做点积,大幅超越 BM25 在开放域 QA 上的表现。 |
| 3 | Self-RAG: Learning to Retrieve, Generate, and Critique through Self-Reflection Asai et al., 2023 |
训练模型输出反思 token(Retrieve/ISREL/ISSUP/ISUSE),在生成过程中自主决定何时检索、检索结果是否相关、回答是否有据可依。 |
| 4 | GraphRAG: Unlocking the Power of Knowledge Graphs for Retrieval-Augmented Generation Microsoft Research, 2024 |
从文档中构建知识图谱(实体+关系+社区),通过图上的社区摘要和遍历实现跨文档推理,解决传统 RAG 无法处理的多跳问题。 |
| 5 | ColBERT: Efficient and Effective Passage Search via Contextualized Late Interaction over BERT Khattab & Zaharia, Stanford, 2020 |
延迟交互范式:Query 和 Document 分别编码后在 token 级别做 MaxSim 匹配,兼顾 Bi-Encoder 的效率和 Cross-Encoder 的精度。 |
| 6 | Precise Zero-Shot Dense Retrieval without Relevance Labels (HyDE) Gao et al., 2022 |
用 LLM 生成假设文档,以其 Embedding 作为检索向量——利用 LLM 的"文档风格"生成能力桥接 Query-Document 语义鸿沟。 |

浙公网安备 33010602011771号