从零理解检索增强生成(RAG):让大模型拥有“外挂知识库”

前言

你可能已经体验过大模型的惊艳之处,但也一定碰到过它一本正经地胡说八道的时刻——这种现象叫“幻觉”。大模型就像一个记忆力超强但知识只停留在训练截止日的通才,它不知道你公司的内部文档,也不了解昨天刚发生的新闻。

RAG(Retrieval-Augmented Generation,检索增强生成) 就是为此而生的一种架构。它给大模型接上一个“知识外挂”,让模型在回答问题前,先去一个外部知识库里翻一翻“参考资料”,然后根据这些资料来组织答案。这样不仅大幅减少了幻觉,还能让答案有据可查。

本文带你从头拆解 RAG 的工作原理、核心组件、完整流程以及落地时的常见挑战,无论你是刚入门 AI 应用开发,还是需要给团队做技术科普,都能找到有用的内容。


一、RAG 的核心思想:开卷考试 vs 闭卷考试

想象两个考试场景:

  • 闭卷考试:你只能靠脑子里的记忆作答。遇到没背过的题,只好蒙一个。
  • 开卷考试:允许你翻书、查资料。你找到相关段落,消化后用自己的话写出答案。

传统的大模型就是“闭卷考试”选手。它把所有知识压缩进模型参数里,一旦问到训练数据之外的东西,要么拒绝回答,要么编造内容。

而 RAG 做的是 “开卷考试”:用户提问后,系统先去一个外部知识库(比如公司文档、网页、论文库)检索最相关的片段,然后把问题和这些“参考资料”一起喂给大模型,让模型基于资料来回答。

这样做的直接好处:

  1. 降低幻觉:模型必须基于检索到的材料说话,不能天马行空。
  2. 知识即时更新:只需更新外部知识库,模型不用重新训练就能回答最新信息。
  3. 可解释性与溯源:答案可以附上引用来源,用户可以核实。
  4. 保护私有数据:私域文档不需要拿去微调模型,只需放进本地向量库,安全性更高。

二、RAG 的系统架构与工作流

一个典型的 RAG 系统包含 离线索引 和 在线检索与生成 两大阶段。

工作流步骤拆解:

1. 准备知识库(离线)

  • 收集所有想让模型“知道”的文档:PDF、网页、Word、Markdown 等。
  • 将文档切割成适当大小的“块”(chunk),通常几百字左右。
  • 用 Embedding 模型把每个文档块转换成向量(一串数字),存入向量数据库。

2. 处理用户提问(在线)

  • 用户输入问题后,用同一个 Embedding 模型把问题也转成向量。
  • 在向量数据库中以余弦相似度等方式寻找与问题向量最接近的 top-K 个文档块。
  • 将这些文档块作为“上下文”,和用户原始问题拼装成一份完整的 Prompt。
  • 把拼好的 Prompt 送给大语言模型,让它生成最终答案。

整个过程用 Python 伪代码表示大致这样:

# 1. 知识库索引
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.embeddings import HuggingFaceEmbeddings
from langchain.vectorstores import Chroma

documents = load_your_docs()  # 加载文档
text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
chunks = text_splitter.split_documents(documents)

embeddings = HuggingFaceEmbeddings(model_name="moka-ai/m3e-base")
vectorstore = Chroma.from_documents(chunks, embeddings)

# 2. 检索与生成
query = "什么是RAG?"
retriever = vectorstore.as_retriever(search_kwargs={"k": 4})
relevant_docs = retriever.get_relevant_documents(query)

context = "\n".join([doc.page_content for doc in relevant_docs])
prompt = f"基于以下资料回答问题:\n\n{context}\n\n问题:{query}\n答案:"
response = your_llm(prompt)

三、RAG 的核心组件详解

RAG 的性能,很大程度上取决于里面每个组件的选择和调优。下面逐个拆开看。

1. 嵌入模型(Embedding Model)

它的任务是把文字转成“语义向量”,让意思相近的句子在向量空间里距离也近。对于中文场景,通常使用开源模型如:

  • moka-ai/m3e-base / m3e-large
  • BAAI/bge-large-zh-v1.5
  • shibing624/text2vec-base-chinese

选择时关注两点:模型维度和模型质量。高维度通常能编码更细粒度的语义,但计算和存储开销更大。如果你需要高性能多语言支持,也可以调用商业 API,比如 OpenAI 的 text-embedding-3 系列。

2. 向量数据库(Vector Database)

专门用来存储和检索高维向量,支持近似最近邻(ANN)搜索。推荐的选型:

数据库 特点 适用场景
Chroma 轻量、纯Python、上手极快 本地原型开发、小规模知识库
FAISS Meta开源,搜索速度极快 需要高性能检索的生产环境
Milvus 分布式,云原生,功能完善 大规模、高并发企业级应用
Pinecone 全托管服务,免运维 不想自己维护基础设施的团队
Weaviate 自带向量化与多模态能力 混合检索(向量+关键词)

3. 文档切割策略(Chunking)

这是很多人忽视但影响巨大的环节。切得太大,检索精度下降,大模型可能被无关信息淹没;切得太小,语义碎片化,丢失上下文。

常用策略:

  • 固定大小切割:按 token 数或字符数,适合结构均匀的文档。
  • 递归分割:用分隔符优先级(段落 > 句子 > 词)逐步拆分,LangChain 的 RecursiveCharacterTextSplitter 就是典型。
  • 语义切割:用模型判断句子的语义转折点,在断点处切割,效果最好但较慢。
  • 父子文档策略:父块保留大段上下文,子块用来检索。检索返回子块,但喂给 LLM 时把父块也带上,兼顾精度和上下文。

4. 检索策略(Retrieval)

基础 RAG 只做一步向量检索(单轮 dense retrieval),但在复杂场景下往往不够。进阶技巧:

  • 多路召回:同时使用关键词检索(BM25)和向量检索,互补长短。
  • 重排序(Re-ranking):先召回较多的候选文档(如20个),再用一个精排模型(如 bge-reranker)对它们重新打分排序,取前几个送入 LLM。
  • 查询改写(Query Rewriting):当用户问题过于模糊时,先用 LLM 把问题改造成更适合检索的表达,再做检索。

5. 提示词模板(Prompt Engineering)

好的 Prompt 是让模型听话的关键。通常包含以下几个部分:

  • 角色设定:你是一个专业的客服助手。
  • 指令:请严格基于提供的资料回答问题。
  • 上下文:这里填写检索到的文档片段。
  • 用户问题:用户的原始提问。
  • 约束:如果资料中没有答案,请直接说明“不知道”,不要编造。

一个完整的英文 prompt 示例:

You are a helpful assistant. Use the following pieces of context to answer the question at the end.
If you don't know the answer, just say that you don't know, don't try to make up an answer.

Context: {context}

Question: {question}
Helpful Answer:

四、RAG 的进阶变体

基础 RAG 容易碰到检索不准、回答质量不高的问题。因此衍生出了多种改进范式。

1. 预检索处理(Pre-Retrieval)

在检索之前优化问题本身,比如:

  • 查询分解:把复杂问题拆成多个子问题分别检索。
  • 假设文档嵌入(HyDE):让 LLM 先生成一个假想答案,再用这个假想答案的向量去检索真实文档,能提高召回率。

2. 半结构化数据的处理

如果你的知识库里有很多表格、图表,则需要结合文档解析工具(如 Unstructured.io)提取结构化信息,再用专门的存储与检索方式。

3. 自反思与自我纠正(Self-RAG)

让模型在生成后,主动检查答案是否完全由检索材料支持,如果不充分则自动触发二次检索。这类方法可以在 LangGraph 等 Agent 框架中实现。

4. Graph RAG

当文档之间存在复杂的关联关系时,可以结合知识图谱,将实体和关系也整理出来辅助检索,提升多跳推理能力。


五、RAG vs 微调:什么时候选谁?

很多人纠结是直接微调模型,还是用 RAG。其实二者并不互斥,组合使用效果更佳。

维度 RAG 微调
知识更新 即时更新知识库即可 需重新训练
可解释性 可追溯到具体来源 黑盒,难以解释为何这样答
外部知识集成 原生优势 需要植入训练数据
风格与行为控制 依赖 Prompt,不够稳定 可通过训练固化特定语气、格式
幻觉控制 好,如果资料里没有会拒答 较差,可能捏造知识
成本 推理时调用检索和拼装 Prompt,额外延时和成本 训练一次性投入,推理成本低

简单建议:如果你需要模型回答动态变化的、私有的知识,优先选 RAG。如果你需要模型遵循特定的风格、格式或者领域术语,可以微调一个轻量级 adapter(比如 LoRA)。两者结合:用微调后的模型来做 RAG 的生成模块,效果往往最佳。


六、RAG 的典型应用场景

  • 企业知识库问答:内部规章、产品手册、运维文档的智能客服。
  • 科研文献检索:基于论文库的文献总结与问答。
  • 法律与合规审查:根据合同库回答条款问题,并给出出处。
  • 教育辅导:基于教材内容生成习题、答疑解惑。
  • 个人知识管理:比如基于你的笔记、日志做回顾与联想。

七、常见问题与落地挑战

  1. 检索不准:试试调整 chunk 大小,加入关键词召回,或者使用 rerank 模型。
  2. 生成质量差:优化 Prompt 模板,换更强的大模型,或者检查文档本身质量。
  3. 无关信息分散注意力:严格控制 top-K 数量,使用 lost in the middle 现象的缓解策略——把最重要的文档放在 Prompt 的开头或结尾。
  4. 成本与延迟:向量检索和 LLM 推理都会增加延迟。可以通过缓存常见问题、选择更轻量的模型、异步处理等方式优化。
  5. 安全与权限:注意不同用户可能看到的知识范围不同,需要在检索阶段加入文档权限过滤。

八、从零实践的建议

如果你现在就想在本地搭一个 RAG 应用,推荐技术栈组合:

  • 框架:LangChain 或 LlamaIndex,都提供了完整的 RAG 流水线封装。
  • 嵌入模型:BAAI/bge-small-zh-v1.5(轻量)或 moka-ai/m3e-base。
  • 向量数据库:开发用 Chroma,生产可换 Milvus 或 Qdrant。
  • 大模型:本地可用 Ollama 跑 llama3、qwen2,或者调用 OpenAI / DeepSeek API。
  • 前端:Gradio 或 Streamlit,10分钟搭出可交互界面。

完整流程就是:加载文档 → 切分 → 向量化入库 → 构建检索链 → 提供 Web 界面。网上这方面的 Demo 非常多,建议先跑通一个最小 MVP,理解了每个环节后再逐一优化。


结语

RAG 是大模型应用落地最直接、最有效的范式之一。它把模型从“百科全书”变成“懂得查资料的研究员”,让 AI 能够处理实时、私有、可验证的知识。理解它并不需要高深的数学基础,但要想在实际场景里做出好的效果,则需要在文档处理、检索策略、Prompt 设计上不断打磨。

希望这篇文章帮你建立起 RAG 的全局视图。如果你对某个具体组件或进阶技巧有兴趣,欢迎在评论区留言,我们可以继续深挖。


博客首发于 https://www.cnblogs.com/wsyl ,转载请注明出处。

posted @ 2026-04-27 16:40  Petula  阅读(132)  评论(0)    收藏  举报