一文搞懂 RAG:从原理到实战,带你玩转检索增强生成
你是否遇到过这样的问题:大模型知识陈旧、爱“编造”答案、无法处理私有数据?RAG 就是解决这些痛点的利器。本文将用最通俗的语言 + 流程图 + 代码,带你彻底掌握 RAG。
1. 什么是 RAG?
RAG(Retrieval-Augmented Generation,检索增强生成)是一种结合信息检索与大语言模型生成能力的技术架构。
简单说:让 LLM 在回答问题时,先从你的知识库(或外部数据源)中“查资料”,再基于查到的资料生成答案。
这就像一位聪明的助手:你问它一个专业问题,它不会瞎猜,而是先翻翻你给的参考手册,找到相关段落,然后结合手册内容给你准确答案。
为什么需要 RAG?
| 问题 | 纯 LLM | RAG |
|---|---|---|
| 知识截止到训练数据(如 GPT-4 到 2023 年) | ❌ 不知道新事件 | ✅ 可检索最新文档 |
| 会“幻觉”编造不存在的事实 | ❌ 容易胡说 | ✅ 基于检索内容,幻觉大幅降低 |
| 无法访问企业私有文档 | ❌ 无能为力 | ✅ 检索公司内部 Wiki/数据库 |
| 每次更新知识需重新训练 | ❌ 昂贵且慢 | ✅ 只需更新文档库 |
2. RAG 的基本流程(配流程图)
RAG 分为两大阶段:索引(Indexing)和检索与生成(Retrieval & Generation)。
2.1 整体流程图
2.2 分步详解
步骤 1:文档分块(Chunking)
- 将长文档切分成若干小段落(如 300~500 tokens)。
- 常用策略:按句子、按段落、滑动窗口等。
步骤 2:向量化(Embedding)
- 使用 Embedding 模型(如
text-embedding-ada-002、bge-large-zh)将每个文本块转换成固定长度的浮点数向量(向量维度通常 768/1536)。 - 向量能捕捉语义信息 —— “苹果手机” 和 “iPhone” 的向量非常接近。
步骤 3:存储索引(Vector Database)
- 将向量存入专用数据库,如Chroma、FAISS、Pinecone、Milvus。
- 数据库会为向量建立索引,方便快速近邻搜索。
步骤 4:用户提问
- 用户输入自然语言问题,比如:“我们公司今年Q3的营收是多少?”
步骤 5:问题向量化 + 检索
- 用同一个 Embedding 模型将问题转换成向量。
- 在向量数据库中检索最相似的 k 个文本块(k 通常为 3~5)。
- 常用相似度度量:余弦相似度、欧氏距离。
步骤 6:增强生成(Augmented Generation)
- 将检索到的文本块作为上下文(Context),与用户问题一起填入提示模板。
- 模板示例:
请基于以下参考信息回答问题。如果参考信息中没有答案,请直接说“不知道”。 参考信息: {context} 问题:{question} 回答: - 将提示发送给 LLM(如 GPT-4、ChatGLM、Llama),生成最终答案。
3. 怎么使用 RAG?—— 极简实战代码
我们以LangChain + Chroma + OpenAI为例,实现一个本地知识库问答系统。
前提:安装依赖
pip install langchain chromadb openai tiktoken
3.1 离线索引代码
fromlangchain.document_loadersimportTextLoaderfromlangchain.text_splitterimportCharacterTextSplitterfromlangchain.embeddingsimportOpenAIEmbeddingsfromlangchain.vectorstoresimportChroma# 1. 加载文档loader=TextLoader("knowledge.txt")# 你的知识文件documents=loader.load()# 2. 分块text_splitter=CharacterTextSplitter(chunk_size=300,chunk_overlap=50)docs=text_splitter.split_documents(documents)# 3. 向量化 + 存储embeddings=OpenAIEmbeddings()# 需设置 OPENAI_API_KEYvectorstore=Chroma.from_documents(docs,embeddings,persist_directory="./chroma_db")vectorstore.persist()print("索引构建完成!")3.2 在线查询代码
fromlangchain.embeddingsimportOpenAIEmbeddingsfromlangchain.vectorstoresimportChromafromlangchain.chat_modelsimportChatOpenAIfromlangchain.chainsimportRetrievalQA# 1. 加载已建好的向量库embeddings=OpenAIEmbeddings()vectorstore=Chroma(persist_directory="./chroma_db",embedding_function=embeddings)# 2. 创建检索器 (检索 top-3 相似块)retriever=vectorstore.as_retriever(search_kwargs={"k":3})# 3. 构建 RAG 链llm=ChatOpenAI(model_name="gpt-3.5-turbo",temperature=0)qa_chain=RetrievalQA.from_chain_type(llm=llm,chain_type="stuff",# "stuff" 表示将所有检索内容拼接后输入retriever=retriever,return_source_documents=True# 方便查看引用了哪些原文)# 4. 提问query="我们公司的退款政策是什么?"result=qa_chain({"query":query})print("答案:",result["result"])print("参考来源:",result["source_documents"])若不想用 OpenAI,可使用本地模型(如 HuggingFaceEmbeddings + ChatGLM),只需替换 embedding 和 llm 对象。
4. RAG 的高级优化技巧
| 优化方向 | 具体方法 |
|---|---|
| 分块策略 | 按语义分块(使用LangChain的RecursiveCharacterTextSplitter),避免切断重要信息 |
| 混合检索 | 结合关键词检索(BM25)和向量检索,取长补短 |
| 重排序(Re-rank) | 检索后用一个更精准的模型(如Cohere Re-rank)对召回块再排序 |
| 提示词工程 | 明确指示 LLM “仅基于下方内容回答,不要编造”,并给出否定回答格式 |
| 对话记忆 | 将历史对话也存入检索上下文,实现多轮问答 |
5. RAG vs 微调(Fine-tuning)—— 该选哪个?
| 维度 | RAG | 微调 |
|---|---|---|
| 知识更新 | 即时(换文档即可) | 需要重新训练,成本高 |
| 处理私有数据 | 完美支持 | 需要大量标注数据 |
| 减少幻觉 | 强(强制引用原文) | 有一定效果,但仍可能编造 |
| 推理开销 | 额外检索时间 + LLM | 仅 LLM |
| 实现难度 | 低(无训练流程) | 高(需GPU、数据、调参) |
结论:
- 首选 RAG:绝大多数场景,特别是需要引用原文、知识频繁变化、减少幻觉的场景。
- 考虑微调:需要模型改变风格/格式/特定领域的术语生成,且数据充足、预算允许时。
6. 总结
- RAG = 检索 + 生成,让大模型学会“查资料再回答”。
- 核心流程:文档分块 → 向量化 → 存入向量库 → 问题检索 → LLM 增强生成。
- 使用门槛极低:LangChain 几行代码即可搭建。
- 进阶方向:混合检索、重排序、多模态 RAG(图片/表格)、Agent 式 RAG。
掌握 RAG,相当于给你的大模型装上了“外挂知识库”,无论是做企业知识问答、客服机器人,还是个人笔记助手,都能轻松实现。
📌附:Mermaid 流程图源码