一、为什么需要 RAG?
大语言模型(LLM)虽然强大,但有两个先天不足:知识截止和幻觉。模型只知道训练数据截止之前的信息,而且面对不知道的问题时,它会"一本正经地胡说八道"。
重新微调模型?成本高、周期长、无法实时更新。RAG(Retrieval-Augmented Generation,检索增强生成)给出了更优雅的解决方案:在让模型作答之前,先去外部知识库检索相关信息,然后把检索结果连同问题一起交给模型。
你可以把它理解成一场"开卷考试"——大模型不需要把知识背进脑子里,只要知道去哪里查,以及如何用查到的内容组织答案。
二、RAG 的核心流程
一个标准的 RAG 系统包含两大阶段:
阶段一:索引(Indexing)
- 文档切分(Chunking):将原始文档切分成小块。切分策略直接影响检索质量,推荐 300-500 Token,带 10-15% 重叠窗口。
- 向量化嵌入(Embedding):用 Embedding 模型将每个文本块转换成向量(语义的数字表示)。
- 存入向量数据库:将向量和元数据一起存入向量数据库,如 ChromaDB、Qdrant、Milvus。
阶段二:查询(Querying)
- 查询向量化:用相同的 Embedding 模型将用户问题转成向量。
- 相似度检索:在向量数据库中找出最相似的 Top-K 个文本块(通常 K=5-10)。
- 重排序(Reranking):用 Cross-Encoder 模型对召回结果精细打分,这是提升质量的关键一步。
- 增强生成:将检索结果拼入 Prompt,让 LLM 基于提供的上下文生成答案。
# 一个极简的 RAG 代码示例
from langchain_text_splitters import RecursiveCharacterTextSplitter
# 1. 加载文档并切分
docs = TextLoader("document.txt").load()
chunks = RecursiveCharacterTextSplitter(
chunk_size=512, chunk_overlap=50
).split_documents(docs)
# 2. 嵌入并存储
embeddings = OllamaEmbeddings(model="nomic-embed-text")
store = Chroma.from_documents(chunks, embeddings)
# 3. 检索 + 生成
retriever = store.as_retriever(search_kwargs={"k": 4})
context = "\n\n".join(d.page_content for d in retriever.invoke(question))
prompt = f"基于以下上下文回答问题:\n\n{{context}}\n\n问题:{{question}}"
answer = llm.invoke(prompt)
print(answer)
三、实战中的关键优化
3.1 切分策略是成败关键
切分是 RAG 中最被低估的环节。常见策略包括:
- 固定大小切分:按 Token 数截断,简单高效。推荐 300-500 Token,50 Token 重叠。
- 语义切分:按句子嵌入相似度在语义断点切割,保持语义完整。
- 父子文档切分:用小 Chunk(128 Token)定位,对应返回大 Chunk(512-1024 Token)提供上下文。这是生产环境中最推荐的方式。
- 文档感知切分:按 Markdown 标题层级或代码函数边界切分,适合结构化文档。
3.2 混合检索 + 重排序 = 质的飞跃
纯向量检索对大语言同义替换效果好,但对精确匹配(型号、人名、代码)效果差。推荐方案:
- 混合检索:向量检索(语义)+ BM25(关键词)并行,结果去重合并。
- 重排序:用 Cohere Rerank 或 BGE-reranker 对 Top-50 结果精细打分,保留 Top-5。这步可将答案质量提升 20-30%。
# 混合检索 + 重排序流程
initial = vector_db.query(question, n=20) # 语义搜索
kw_results = bm25_search(question, n=20) # 关键词搜索
merged = deduplicate(initial + kw_results) # 去重合并
final = reranker.rank(question, merged, top_n=5) # 重排序
3.3 Embedding 模型选型
不同场景需要不同的 Embedding 模型:
- 中文场景优先:BGE-M3(1024 维,中英双语强)、BGE-large-zh(中文专项优化)、m3e-base/m3e-large(国产社区常用)
- 纯 API 路线:OpenAI text-embedding-3-small(性价比高)
- 本地部署:nomic-embed-text(768 维,轻量友好)
核心原则:索引和查询必须用同一个 Embedding 模型,混用模型结果不可靠。
四、RAG 的五代演进
| 阶段 | 时间 | 特点 |
|---|---|---|
| 第一代 | 2020 | 概念诞生:端到端联合训练,检索器+生成器一起优化,但成本高、落地方案不成熟 |
| 第二代 | 2022-2023 | 范式确立:独立检索器+生成器,LangChain、LlamaIndex 降低门槛,5分钟搭 Demo |
| 第三代 | 2023-2024 | Advanced RAG:查询改写、混合检索、重排序、父文档检索等优化手段成熟 |
| 第四代 | 2024 | Modular RAG:各环节抽象为独立模块,按需组合,更像平台而非流水线 |
| 第五代 | 2025-2026 | Agentic RAG:让 LLM 自主决策检索策略,多跳推理、工具调用、质量自评 |
当前业界主流处于第三代到第四代之间,前沿探索正在向第五代演进。
五、技术选型建议
文档解析层:数据工程是 RAG 效果的天花板。推荐路线:PyMuPDF(快速轻量)→ Unstructured(多格式)→ MinerU(中文好)→ Docling(生产级)。
向量数据库:ChromaDB(原型开发)→ pgvector(已有 PostgreSQL)→ Qdrant(高性能过滤)→ Milvus(企业规模)。
框架选择:简单场景 40 行原生代码就够了;复杂流程选 LangChain 1.x(LangGraph 支持 Agentic 流程);检索密集型选 LlamaIndex 0.14.x。
评估不容跳过:用 RAGAS 工具衡量 Faithfulness、Context Precision、Context Recall,建立 20-50 个 QA 对,每次改动都跑一遍。不度量的 RAG 系统永远停留在 Demo 阶段。
六、总结
RAG 已是 LLM 落地的核心范式。它的核心价值在于:用最小的成本让模型获得最新、最准确的外部知识。相比微调,RAG 更新灵活、成本可控、答案可追溯。
但 RAG 不是万能药。复杂推理、跨文档联合推理仍是难点,这些正是 Agentic RAG 要解决的问题。对于大多数企业场景,基础 RAG + 混合检索 + 重排序已经能解决 80% 的问题。不要为了炫技引入不必要的复杂度——先跑通,再优化。
最后记住一句话:在 RAG 系统中,检索质量比模型大小更重要——干净的 Chunk、好的 Embedding、加上一个精确的 Reranker,远胜于用大模型吞下一堆垃圾内容。