RAG (检索增强生成)
RAG 是通过在推理时动态检索外部知识来增强 LLM 输出的架构模式。它解决了模型知识过时和缺乏私有数据的问题,是 AI Agent 获取外部知识的核心机制。
#type / concept
#status / evergreen
#tech / ai
#tech / architecture
[!info] related notes
- 所属 MOC: RAG Engineering MOC, AI Agent Application MOC
- 子主题: 文档分块, Embedding 模型, 向量数据库, [[reranker|Reranker]], 引用生成
- 实践: RAG 知识库与 pgvector, Python RAG Agent
- 质量: RAG Faithfulness 校验
RAG (检索增强生成)
一句话定义
RAG (Retrieval-Augmented Generation) 是在 LLM 生成回答之前,先从外部知识库中检索相关信息,然后把检索结果注入到上下文中,让模型基于这些信息生成回答的架构模式。
它解决什么问题
LLM 有两个固有局限:
- 知识截止: 模型的训练数据有时间 cutoff,不知道最新信息
- 缺乏私有数据: 模型没有你的企业文档、产品手册、内部知识库
RAG 的核心思想是:不要让模型”记住”所有知识,而是让它”查找”需要的知识。
没有 RAG:
用户问题 → LLM (用训练数据回答) → 可能过时或编造
有 RAG:
用户问题 → 检索相关文档 → LLM (基于检索结果回答) → 有据可查
核心原理
RAG 的五阶段管线
1. Loading (摄入)
文档 → 解析 → 标准化
PDF/Word/网页/数据库 → Document 对象
2. Chunking (分块)
Document → 切分成小块 → 每块带元数据
按段落/句子/固定长度/语义边界切分
3. Embedding (向量化)
Chunk → Embedding Model → 向量
文本变成 384/768/1536 维的数字数组
4. Retrieval (检索)
用户问题 → Embedding → 向量 → 在向量库中找最近的 K 个块
可以混合:语义搜索 + 关键词搜索
5. Generation (生成)
检索结果 + 用户问题 → 注入上下文 → LLM 生成回答
检索策略
| 策略 | 原理 | 适用场景 |
|---|---|---|
| 语义搜索 | 向量相似度 | 自然语言查询 |
| 关键词搜索 | BM25/TF-IDF | 精确术语匹配 |
| 混合搜索 | 两者加权 | 通用场景(推荐) |
| 多查询检索 | 改写问题多次检索 | 复杂问题 |
| 上下文检索 | 带上下文的 chunk | 长文档场景 |
RAG vs Fine-tuning
| RAG | Fine-tuning | |
|---|---|---|
| 知识更新 | 更新文档即可 | 需要重新训练 |
| 成本 | 低(只需向量库) | 高(GPU 训练) |
| 可解释性 | 高(可引用来源) | 低(黑盒) |
| 适用场景 | 知识密集型任务 | 风格/格式调整 |
在 React + Go + Python AI Service 架构中的位置
Go 后端:
Context Builder 加载用户问题
│
▼
Python AI Service:
RAG Engine:
1. Query Rewriting (改写问题)
2. Retriever 检索 (向量 + 关键词)
3. Reranker 重排序
4. Contextual Compression (压缩)
5. 注入到 LLM 上下文
│
▼
LLM 基于检索结果生成回答
│
▼
输出: 文本 + 引用来源
典型工程实现
最小 RAG 管线
class RAGEngine:
def __init__(self, embedder, vector_store, llm):
self.embedder = embedder
self.vector_store = vector_store
self.llm = llm
async def query(self, question: str, top_k: int = 5) -> RAGResponse:
# 1. 问题向量化
query_embedding = await self.embedder.embed(question)
# 2. 向量检索
chunks = await self.vector_store.search(query_embedding, top_k=top_k)
# 3. 构建上下文
context = "\n\n".join([f"[{i+1}] {c.text}" for i, c in enumerate(chunks)])
# 4. 调用 LLM
prompt = f"""基于以下参考资料回答问题。如果资料中没有相关信息,请说明。
参考资料:
{context}
问题: {question}"""
answer = await self.llm.chat(prompt)
# 5. 附加引用
return RAGResponse(
answer=answer,
sources=[{"title": c.metadata["title"], "chunk_id": c.id} for c in chunks]
)
文档摄入管线
class DocumentIngestionPipeline:
async def ingest(self, document_path: str):
# 1. 加载文档
doc = self.loader.load(document_path)
# 2. 分块
chunks = self.chunker.chunk(doc)
# 3. 生成 Embedding
embeddings = await self.embedder.embed_batch([c.text for c in chunks])
# 4. 存入向量库
await self.vector_store.upsert(chunks, embeddings)
常见设计模式
1. Naive RAG
最简单的 RAG:检索 → 注入 → 生成。适合 MVP。
2. Advanced RAG
加入查询改写、多查询检索、重排序、上下文压缩等优化。
3. Modular RAG
把 RAG 拆成可组合的模块(检索器、重排序器、压缩器、生成器),按需组装。
4. Agentic RAG
Agent 自己决定何时检索、检索什么、检索结果够不够用。
常见坑
- Chunk 太大或太小: 太大浪费 token,太小丢失上下文
- 只用语义搜索: 精确术语(如错误码、产品型号)语义搜索找不到
- 不做重排序: 向量搜索的排序不一定是最佳排序
- 不标注来源: 模型回答无法溯源,用户无法验证
- 不监控检索质量: 只看最终回答质量,不看检索召回率
和其他概念的关系
- vs Context Engineering: RAG 是 Context 的重要来源之一
- vs Embedding Model: Embedding 是 RAG 管线的关键步骤
- vs Vector Database: 向量库是 RAG 的存储层
- vs [[reranker|Reranker]]: 重排序是 RAG 的后处理优化
- vs Agent Engine: Engine 决定何时触发 RAG
总结
RAG 的本质是把”模型记知识”变成”模型查知识”。它让 LLM 能够基于最新、私有、可验证的信息回答问题,是构建可靠 AI Agent 的基础架构。