RAG = Retrieval Augmented Generation。不用微调,让大模型随时获取最新知识。
为什么需要 RAG?
大模型的”知识截止”问题:GPT-4o 的知识库有截止日期,它不知道今天发生了什么。
RAG 的核心思想:把知识放在外部知识库,检索到相关内容后,连同问题一起喂给 LLM。
用户问题 → 检索相似内容 → 与问题拼接 → LLM 生成回答
这样你只需要更新知识库,无需重新训练模型。
RAG 工作流程
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ 文档切分 │ -> │ 向量嵌入 │ -> │ 存入向量库 │
└─────────────┘ └──────────────┘ └─────────────┘
│
┌─────────────┐ ┌──────────────┐ │
│ LLM 生成 │ <- │ 拼接上下文 │ <- 检索相似内容
└─────────────┘ └──────────────┘
1. 文档切分(Chunking)
将长文档切成小块(chunk),每个 chunk 单独做 Embedding。
常见策略:
- 固定长度切分:如每 500 tokens 重叠 50 tokens
- 语义切分:按段落、章节自然边界切分
- 递归字符切分:按层级结构(段落→句子→词)切分
from langchain.text_splitter import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=50,
separators=["\n\n", "\n", "。", " "]
)
chunks = splitter.split_text(long_document)
2. 向量嵌入(Embedding)
将文本块转换成向量。常用模型:
| 模型 | 维度 | 特点 | 适用场景 |
|---|---|---|---|
| text-embedding-3-large | 3072 | OpenAI 最新,性能最强 | 通用 |
| text-embedding-3-small | 1536 | 性价比高 | 快速原型 |
| bge-large-zh | 1024 | 中文优化,开源 | 中文生产环境 |
| m3e | 768 | 中文开源,轻量 | 私有部署 |
3. 向量数据库
| 数据库 | 特点 | 优势 | 缺点 |
|---|---|---|---|
| Pinecone | 云原生 | 免运维,全球加速 | 按量付费 |
| Milvus | 开源 | 功能全面,支持混合检索 | 部署复杂 |
| Chroma | 轻量 | 开发友好,本地运行 | 生产性能一般 |
| Qdrant | Rust 实现 | 高性能,Filtering 强 | 生态较小 |
| Weaviate | 混合向量+结构化 | 支持 GraphQL | 学习成本 |
import chromadb
client = chromadb.Client()
collection = client.create_collection("knowledge_base")
# 添加文档
collection.add(
documents=["RAG 是检索增强生成的缩写"],
metadatas=[{"source": "wiki"}],
ids=["doc1"]
)
# 检索
results = collection.query(
query_texts=["什么是 RAG?"],
n_results=3
)
4. 检索优化策略
Query 改写:用户问题往往不够精确,需要改写:
# HyDE: 用 LLM 生成假设性答案,再检索
hypothetical_answer = llm.invoke(
"请为这个问题生成一个简短答案:用户问:" + query
)
results = vector_db.similarity_search(hypothetical_answer)
混合检索:关键词 + 向量双路检索
# Elasticsearch 关键词检索 + 向量检索
keyword_results = bm25.search(query)
vector_results = vector_db.similarity_search(query)
# RRFF 融合排名
final_results = fuse([keyword_results, vector_results], method="rrf")
重排序(Rerank):用 Cross-Encoder 再筛一次最相关结果:
from sentence_transformers import CrossEncoder
reranker = CrossEncoder("cross-encoder/ms-marco-MiniLM-L-6")
reranked = reranker.predict([
(query, chunk) for chunk in top_k_results
])
常见 RAG 架构模式
基础 RAG(Naive RAG)
最简单:切分→嵌入→检索→拼接→生成。
高级 RAG(Advanced RAG)
加入:Query 改写、HyDE、重排序、上下文压缩。
模块化 RAG(Modular RAG)
将检索、生成、记忆等模块解耦,灵活组合。
图谱 RAG(Graph RAG)
将文档知识建图,用知识图谱做检索。微软开源了 GraphRAG 工具。
实战:构建一个本地 RAG 知识库
from langchain.document_loaders import PDFPlumberLoader
from langchain.embeddings import HuggingFaceEmbeddings
from langchain.vectorstores import Chroma
from langchain.chains import RetrievalQA
from langchain_openai import ChatOpenAI
# 1. 加载文档
loader = PDFPlumberLoader("白皮书.pdf")
docs = loader.load()
# 2. 切分
chunks = RecursiveCharacterTextSplitter(
chunk_size=500, overlap=50
).split_documents(docs)
# 3. 向量化
vectorstore = Chroma.from_documents(
documents=chunks,
embedding=HuggingFaceEmbeddings(model_name="bge-large-zh")
)
# 4. 构建问答链
qa = RetrievalQA.from_chain_type(
llm=ChatOpenAI(model="gpt-4o"),
chain_type="stuff",
retriever=vectorstore.as_retriever(search_kwargs={"k": 3})
)
# 5. 问答
result = qa.run("这份白皮书的核心结论是什么?")
RAG vs 微调(FINE-TUNING)
| 维度 | RAG | 微调 |
|---|---|---|
| 知识更新 | 随时,更新知识库即可 | 需要重新训练 |
| 成本 | 低,无需训练 | 高,GPU 训练 |
| 幻觉 | 较少,答案有据可查 | 可能更流畅但更易幻觉 |
| 定制能力 | 中等 | 强,可学特定风格 |
| 实时性 | 高 | 低 |
结论:大多数场景优先 RAG,特定风格/任务才考虑微调。
💡 小结
RAG 是当前最实用的 LLM 知识增强方案。它的本质是让模型在回答时”查资料”,而不是靠记忆。
关键要点:
- 好的切分策略往往比算法优化更重要
- 混合检索比纯向量检索效果更稳定
- 重排序是提升精度的低成本手段
- 图谱 RAG 适合处理复杂关系型知识
相关阅读:AI Agent 原理与实践