RAG · 检索增强生成¶
本页是 RAG 范式 canonical (按 ADR-0006)
本页讲 RAG 算法范式 + 演进路线 · 是 RAG 主题的 canonical 入口。
- 湖仓上的 RAG 工程实践(5 表架构 / 端到端流水线 / 延迟预算)→ scenarios/rag-on-lake
- RAG 评估方法(RAGAS / BEIR / 离线 + 在线闭环)→ rag-evaluation
- 公司切面(Databricks / Snowflake / Netflix 各自 RAG 实现)→ 对应 cases/ 深度页
一句话理解
在生成前先检索把"语料库中最相关的片段"作为上下文塞给 LLM。对抗幻觉、让知识可更新、让企业私有数据可问答的最主流范式。2025 年工业 RAG = Hybrid 召回 + Rerank + Contextual 压缩 + LLM + 引用回写。
TL;DR
- 核心命题:LLM 知识截止 + 私有数据 + 实时更新 → 检索 + 生成
- 为什么不直接微调:私有数据每天变、微调成本高、易忘记
- 工业管线:chunk → embed → Hybrid 检索 → Rerank → Prompt → LLM → 引用
- 评估必做:RAGAS(faithfulness / relevancy / context precision / context recall)
- 前沿:Contextual Retrieval(Anthropic)· CRAG · Self-RAG · Agentic RAG
- 不加 Rerank 是 RAG 第一大死因;其次是 chunk 策略
1. 业务痛点 · LLM 为什么不够用¶
纯 LLM 的三个天花板¶
| 局限 | 症状 |
|---|---|
| 知识截止 | "我不知道 2024 年后的事" |
| 私有数据盲区 | 问不了公司内部文档、代码库 |
| 幻觉 | 瞎编事实、引用不存在的论文 |
| 不可追溯 | "为什么这么回答?"说不清 |
微调替代不了 RAG¶
| 微调(SFT / LoRA) | RAG | |
|---|---|---|
| 适合场景 | 改变风格、语气、格式 | 事实、知识、数据 |
| 成本 | GPU / 训练数据 / 时间 | 向量库 + LLM 调用 |
| 更新成本 | 每次新数据要重训 | 增量写向量库 |
| 可审计 | 黑盒 | 可引用 |
| 混合使用 | 都要 | 都要 |
结论:微调调"模型说话方式",RAG 解"给模型什么信息"——两者互补不替代。
工业典型场景¶
| 场景 | RAG 价值 |
|---|---|
| 企业客服 / 工单 | RAG 后答案可用率显著提升(经验值 · 依基线 / 场景 / 评估标准变化大 · [来源未验证] 通用数字不要直接引用) |
| 代码助手 | 了解私有代码库 |
| 合规 / 法务 | 强制引用、零幻觉 |
| 研究辅助 | 快速翻遍论文库 |
| 运维诊断 | 从历史故障 + 文档找线索 |
2. 原理深度 · RAG 工作机制¶
基础管线(Vanilla RAG)¶
flowchart LR
q[用户问题] --> qe[Query Encoder]
qe --> retrieve[向量库 + BM25<br/>TopN 召回]
retrieve --> rerank[Cross-Encoder Rerank<br/>TopK]
rerank --> prompt[拼 Prompt<br/>问题 + 片段]
prompt --> llm[LLM 生成]
llm --> ans[答案 + 引用]
docs[(企业文档<br/>持续更新)] -.-> ingest[Ingest + Chunk + Embed]
ingest -.-> retrieve
三阶段拆解¶
阶段 1 · 索引(离线)
阶段 2 · 检索(在线)
阶段 3 · 生成(在线)
为什么"对抗幻觉"¶
LLM 在给定上下文后的输出分布会被锚定——token 级别概率大幅向 context 中的事实倾斜。
但光给 context 不够,还要: - Prompt 强制要求"只基于引用" - 答案里显式带引用编号 - 无引用时拒答("资料中没找到")
这三件都做到 · 在可控 golden set 上测得的幻觉率能显著下降(典型经验 · 依数据分布 / LLM / 评估定义变化大 · 生产必须自测 · 不要直接套用具体百分比)。
3. 关键机制¶
机制 1 · Chunk 策略¶
Chunk 决定召回上限:
| 策略 | 适合 | 优 | 劣 |
|---|---|---|---|
| 定长切分 | 纯文本、快速起步 | 简单 | 切断语义 |
| 结构感知 | Markdown / HTML / 代码 | 尊重标题层级 | 实现复杂 |
| 语义切分 | 长散文 / PDF | 语义聚合 | 耗时、需额外模型 |
| Contextual Chunking | 每 chunk 加背景描述 | Anthropic 新范式 · 显著减少检索失败率(详见下方 §4 · 不直接引用 recall 数字) | 需 LLM 预处理 |
推荐默认:结构感知 + 长度约束(200-800 tokens)+ 10% overlap。
机制 2 · Embedding 选型¶
详见 Embedding 模型横比。实务: - 私有 + 中文 → BGE-large-zh / multilingual - 多语 → E5-multilingual / Cohere embed-multilingual - 快速起步 → OpenAI text-embedding-3 - 代码 → Voyage AI code 或 CodeBERT
机制 3 · Hybrid 检索¶
纯向量不够。工业标配 = BM25 + Dense + RRF 融合。
详见 Hybrid Search。
机制 4 · Rerank¶
差异化关键。bge-reranker-v2-large / Cohere Rerank v3.5(2024-12 · 100+ 语言 SOTA)/ Jina Reranker v2。
召回 50-100 → Rerank → Top 5-10。NDCG 提升 5-10 个点。
详见 Rerank。
机制 5 · Prompt 构造¶
经典模板:
你是 XXX 的内部助手。请**仅基于下面的参考资料**回答问题。
若资料不足,请回答"资料中没有找到相关信息"。
每个答案必须带引用编号 [n]。
# 参考资料
[1] {chunks[0].title} ({chunks[0].url})
{chunks[0].content}
[2] {chunks[1].title}
{chunks[1].content}
# 问题
{user_query}
# 你的回答(使用引用格式 [n])
关键技巧: - 最相关 chunk 放 prompt 最后("Lost in the Middle"现象) - 压缩 context(LLMLingua / Contextual Compression)省 token - 引用编号在 prompt 里明确,LLM 更愿意写引用
机制 6 · 引用与溯源¶
产品化上必须做: - 每个答案带引用编号([1], [2]) - 点击引用 → 跳转原文位置 - 便于人工核查,审计场景刚需
4. 工程细节 · 2024-2025 高级范式¶
稳定路径 vs 演进跟踪 · 别把"值得了解"误读成"应优先采用"
2026 生产默认路径就是 § 3 基础管线:chunk → Hybrid(BM25+Dense)→ Rerank(v2-m3 / Cohere v3.5)→ Prompt → LLM + 引用。这 5 步做扎实 · 加上 评估 闭环 · 已经能覆盖 80%+ 生产场景。
以下范式是演进跟踪 · 按顺序选择性采用 · 不要一上来全部: - ✅ Contextual Retrieval(Anthropic 2024)· 效果确证 · 可优先尝试 - 🟡 CRAG / Self-RAG · 实验验证 · 适合复杂检索可用性不稳定的场景 - 🟡 Agentic RAG · 需 Agent 能力成熟 · 成本显著高 - 🟡 GraphRAG · 综合性查询优势 · 但 10-100× 离线构建成本 - 🟡 Multi-Query / HyDE · query 改写 · 多一次 LLM 调用 - 🟡 ColBERT v2 / Late Interaction · 精度高但存储 10-20× - 🟡 LLMLingua 上下文压缩 · 长文档场景省 60-80% token
Contextual Retrieval(Anthropic 2024)¶
给每个 chunk 前置补充"这个 chunk 在整份文档中的背景描述"(用 LLM 预处理),embed 整体。
原 chunk: "M 参数默认 16"
↓
Contextual Chunk:
"《HNSW 调优指南》的"参数详解"章节:HNSW 算法中的 M 参数默认 16,
控制图的邻居数。M 参数默认 16。"
效果(Anthropic 2024 Contextual Retrieval 报告原文解读):检索失败率相对降低 35%(5.7% → 3.7%)· 配合 reranker 后失败率相对降 67%(5.7% → 2.9%)。注意原报告讲的是"失败率降幅"· 不是"recall 绝对提升 35 个百分点"——这两个指标容易混淆。
CRAG (Corrective RAG)¶
Self-RAG¶
模型自己决定: - 是否需要检索(有些问题不需要) - 检索到的片段是否相关 - 生成的答案是否 grounded
Agentic RAG¶
- 把 RAG 当成 Agent 的一个 Tool
- Agent 可以决定 多轮检索(多 hop reasoning)
- 结合其他工具(SQL / 代码执行 / API)
详见 Agent Patterns 机制 · Agentic Workflows 场景。
GraphRAG · 知识图谱增强(2024-2026)¶
Vector RAG 的极限:无法处理"跨多个 chunk 的综合性问题"(如 "介绍我们公司所有主要竞争对手及其核心产品")· 因为 vector 召回是"点对点相关" · 不理解实体之间关系。
GraphRAG 思路(Microsoft 2024-07 开源): 1. 离线:从语料库抽取实体 + 关系 → 构建 知识图谱(Neo4j / 自建 graph) 2. 离线:对图做 社区检测(Louvain / Leiden)· 每个社区生成 summary 3. 在线:Query 时两阶段 - 找相关社区 summary(回答综合性问题) - 找相关实体 + 关系(回答具体细节) 4. 组合 context 给 LLM
用户:"我们团队 2025 年的主要技术挑战"
↓
Vector RAG: 找相关 chunk → 碎片化
GraphRAG:
1. 相关社区 = [性能优化社区、AI 集成社区、合规社区]
2. 每个社区的 summary 作为 context
3. LLM 综合归纳 → 完整回答
代表方案: - Microsoft GraphRAG(2024-07 开源 · 2025 进入 Azure AI Foundry)· 完整工程实现 - LightRAG(2024 · 香港大学)· 更轻量 · dual-level retrieval - LlamaIndex KnowledgeGraphIndex · 嵌入式图谱构建 - Neo4j + LLM · 商业图数据库 + Cypher 查询
成本: - 离线构建:10-100× 于 vector RAG 的 embedding 成本(大量 LLM 调用做实体抽取 + 社区 summary) - 在线查询:和 vector RAG 相当 · 甚至更快(社区 summary 是预算好的 context)
何时用 GraphRAG: - ✅ 综合性 / 主题性查询("主要 / 所有 / 对比") - ✅ 关系复杂的领域(法律 / 学术文献 / 企业组织 / 医药) - ✅ 可接受 10-100× 离线成本换取质量跃升 - ❌ 简单事实问答 · vector RAG 足够 - ❌ 语料频繁变化 · 图谱重建成本高 - ❌ 小规模(< 10k 文档)· 建图 ROI 不划算
2026 状态:采用率快速上升但仍非主流 · Microsoft / 企业 KG 场景领先 · 是 Vector RAG 的补充不是替代。
Query 改写 · Multi-Query / HyDE¶
Multi-Query:LLM 把原 query 改写成 N 个变体并行检索 · 结果用 RRF 融合。
Query: "怎么提升 RAG 的 recall"
↓ LLM 改写
- "如何优化 RAG 检索的召回率"
- "Hybrid search 怎么提升 recall"
- "Rerank 对 RAG 效果的影响"
↓ 并行检索 + RRF 融合
HyDE (Hypothetical Document Embeddings · Gao et al. 2022):先让 LLM 生成"假设答案"· 用假设答案的 embedding 检索 · 直觉是假设答案和真实文档分布接近。
评价: - ✅ LlamaIndex / LangChain 原生支持 · 集成成本低 - 🟡 Multi-Query 在 recall 受限场景(query 歧义 / 多角度)有效 · 典型提升 5-8% - 🟡 HyDE 在 factoid 问题上有效 · 探索性 / 开放式问题可能误导(假设答案错会偏 · 实测常 < 5%) - ❌ 两者都多一次 LLM 调用 · 延迟 + 成本上升 · 先测基线是否真缺 recall 再引入
ColBERT v2 · Late Interaction¶
核心思想:每个 token 保留独立向量 · 检索时 query × doc token 级 MaxSim 聚合 · 不是单向量压成一个。
评价: - ✅ 精度接近 Cross-Encoder Rerank · 延迟显著低于 rerank - ❌ 存储成本 10-20× 于普通 dense · 规模上不去(百万 doc 级别尚可 · 亿级不现实) - 🟡 适合重精度轻规模场景(代码助手 / 文档图像 retrieval 即 ColPali / 领域精搜) - 详细 late-interaction 机制见 retrieval/multimodal-retrieval-patterns Pattern E
Contextual Compression · LLMLingua¶
用小模型压缩 retrieved contexts · 减少输入给主 LLM 的 token 数:
效果:Token 成本降 60-80% · 质量下降 < 5%(原文报告 · 自家数据需实测)· 长文档场景 ROI 显著。
§4 小结 · 现实检视 · 已验证 vs 仅论文¶
已在工业规模验证(可上): - Hybrid Search(BM25 + Dense + RRF)· Cross-Encoder Rerank · Contextual Retrieval —— 2025 "新 baseline"
论文好 / 工业复现有限: - CRAG · Self-RAG · Agentic RAG · HyDE —— 自家数据实测再决定
学术信号 / 规模限制: - ColBERT v2 · LLM-as-Reranker · Self-RAG 需 fine-tune —— 特定场景有效
坏信号识别: - 论文报告 NDCG +20% 但没提推理成本 → 警惕 - 只在 Wikipedia / 新闻上验证 → 企业闭域可能失效 - "我们用 XXX 做到 95% 准确率"但不说 baseline → 几乎无信息
5. 性能数字 · 评估指标¶
离线评估¶
| 指标 | 工具 | 典型基线 |
|---|---|---|
| Retrieval Recall@10 | BEIR / 自建 | 0.60-0.80 |
| NDCG@10 | BEIR | 0.50-0.65 |
| Faithfulness(答案忠于 context) | RAGAS / TruLens | > 0.90 |
| Answer Relevance | RAGAS | > 0.85 |
| Context Precision | RAGAS | > 0.80 |
在线评估¶
- 用户点赞 / 点踩率(生产必收集)
- Follow-up 率(问了又问 = 没答好)
- 解决率(客服场景)
- 平均引用数(太少 = 幻觉风险)
延迟分解¶
用户输入 → 答案 p95 < 1.5s 的打法:
50ms Query embedding
150ms Hybrid retrieve
100ms Rerank
400ms Prompt + LLM 首 token
1200ms LLM 流式完成
100ms 日志落表 (async)
───────
1.5s
6. 代码示例¶
最小 LlamaIndex RAG¶
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
docs = SimpleDirectoryReader("data/").load_data()
index = VectorStoreIndex.from_documents(docs)
query_engine = index.as_query_engine(similarity_top_k=10)
response = query_engine.query("HNSW 的 M 参数如何调优?")
print(response)
print(response.source_nodes) # 引用
LanceDB + BGE Embedding + bge-reranker Hybrid¶
import lancedb
from FlagEmbedding import FlagModel, FlagReranker
embed_model = FlagModel('BAAI/bge-large-zh')
reranker = FlagReranker('BAAI/bge-reranker-v2-m3') # 推 v2 · v1 已被超越
db = lancedb.connect("s3://lake/lancedb")
table = db.open_table("docs")
def rag_answer(query: str) -> str:
# 1. Hybrid 召回
q_vec = embed_model.encode(query)
candidates = (table.search(q_vec, query_type="hybrid")
.text(query)
.limit(50)
.to_list())
# 2. Rerank
pairs = [[query, c["content"]] for c in candidates]
scores = reranker.compute_score(pairs)
top_k = sorted(zip(candidates, scores), key=lambda x: -x[1])[:10]
# 3. LLM
context = "\n\n".join(
f"[{i+1}] {c['title']} ({c['url']})\n{c['content']}"
for i, (c, _) in enumerate(top_k)
)
prompt = f"""仅基于以下资料回答,每段答案带引用 [n]。
# 资料
{context}
# 问题
{query}
# 答案
"""
return llm.generate(prompt)
RAGAS 评估¶
from ragas import evaluate
from ragas.metrics import faithfulness, answer_relevancy, context_precision, context_recall
ds = Dataset.from_dict({
"question": [...],
"answer": [...],
"contexts": [...],
"ground_truth": [...],
})
result = evaluate(ds, metrics=[faithfulness, answer_relevancy, context_precision, context_recall])
print(result)
7. 陷阱与反模式¶
- 不加 Rerank:RAG 效果失败 #1 原因
- 定长 512 tokens 切分走天下:代码 / 表格 / PDF 效果崩
- Embedding 和 query 侧不一致:库用 BGE 查用 OpenAI → 分布不同
- 没做 Evaluation:改一版就上线 → 盲飞;RAGAS 是最低配
- 幻觉不管:LLM 会编事实 → 强制引用 + 引用不足拒答
- 权限在 Prompt 里:一定被绕过 → 向量库侧 metadata filter
- Context 塞满:Token 预算爆、"Lost in the Middle"、成本高
- 一次检索打天下:复杂问题要多跳检索(Agentic / CRAG / Self-RAG)
- 没有降级:向量库挂了全站挂 → BM25 / 规则兜底
- 成本失控:LLM 调用没限流 / 没缓存 → 每月 $ 炸
- Chunk 不带元信息:丢了 source / url / tag → 无法引用、无法过滤
8. 横向对比 · 延伸阅读¶
- RAG on Lake 场景 —— 工程管线细节
- RAG 评估 —— 独立一页
- 60 分钟 RAG on Iceberg tutorial
- Agentic Workflows —— RAG 的进化
权威阅读¶
- Lewis et al., Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks (NeurIPS 2020) —— 原论文
- Anthropic Contextual Retrieval (2024)
- Lost in the Middle (Liu et al., 2023)
- RAGAS paper (Es et al., 2023)
- CRAG (Yan et al., 2024) · Self-RAG (Asai et al., 2023)
- Microsoft GraphRAG (2024-07) · GraphRAG paper
- LightRAG (HKU 2024) · LlamaIndex KnowledgeGraphIndex
- LlamaIndex · LangChain · Haystack
相关¶
- 向量数据库 · Hybrid Search · Rerank · Embedding
- RAG on Lake 场景 · Agentic Workflows
- Feature Store —— RAG 的姊妹基础设施