1. 什么是 RAG
RAG(Retrieval-Augmented Generation,检索增强生成)是一种将信息检索与大语言模型(LLM)生成能力相结合的技术范式。它的核心思想是:在模型生成回答之前,先从外部知识库中检索与用户问题相关的文档片段,将这些片段作为上下文提供给大语言模型,从而让模型基于真实、最新的信息生成回答。
RAG 的出现主要为了解决大语言模型的三大痛点:
- 知识时效性差:模型训练数据存在截止日期,无法回答训练之后发生的事件。
- 幻觉问题:模型可能编造不存在的事实,尤其在专业领域。
- 缺乏私有知识:模型无法访问企业内部的文档、数据库等私有数据。
通过引入外部检索,RAG 让模型能够"先查资料、再回答",显著提升了回答的准确性和可信度。
2. RAG 的核心架构
一个典型的 RAG 系统由三个核心模块组成:
2.1 索引阶段(Indexing)
索引阶段负责将原始文档处理成可供检索的形式,主要步骤包括:
- 文档加载:从 PDF、Word、网页、数据库等来源读取原始文档。
- 文本切分(Chunking):将长文档切分为适当大小的文本块。切分策略直接影响检索效果。
- 向量化(Embedding):使用嵌入模型将每个文本块转换为高维向量。
- 向量存储:将向量及其对应的原始文本存入向量数据库(如 FAISS、Milvus、Chroma、pgvector)。
2.2 检索阶段(Retrieval)
当用户提出问题时,系统执行以下操作:
- 将用户问题用同一个嵌入模型转换为查询向量。
- 在向量数据库中执行相似度检索(如余弦相似度、欧氏距离),召回最相关的 Top-K 个文本块。
- 可选地结合重排序(Rerank) 模型,对召回结果做精细化排序,提升相关性。
2.3 生成阶段(Generation)
将检索到的相关文本块与用户问题一起组装成 Prompt,交给大语言模型生成最终回答。模型可以引用检索到的内容作答,从而减少幻觉。
下面是 RAG 系统的整体流程图:
#mermaid-svg-egwnlFgy3t46ai5W{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-egwnlFgy3t46ai5W .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-egwnlFgy3t46ai5W .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-egwnlFgy3t46ai5W .error-icon{fill:#552222;}#mermaid-svg-egwnlFgy3t46ai5W .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-egwnlFgy3t46ai5W .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-egwnlFgy3t46ai5W .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-egwnlFgy3t46ai5W .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-egwnlFgy3t46ai5W .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-egwnlFgy3t46ai5W .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-egwnlFgy3t46ai5W .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-egwnlFgy3t46ai5W .marker{fill:#333333;stroke:#333333;}#mermaid-svg-egwnlFgy3t46ai5W .marker.cross{stroke:#333333;}#mermaid-svg-egwnlFgy3t46ai5W svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-egwnlFgy3t46ai5W p{margin:0;}#mermaid-svg-egwnlFgy3t46ai5W .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-egwnlFgy3t46ai5W .cluster-label text{fill:#333;}#mermaid-svg-egwnlFgy3t46ai5W .cluster-label span{color:#333;}#mermaid-svg-egwnlFgy3t46ai5W .cluster-label span p{background-color:transparent;}#mermaid-svg-egwnlFgy3t46ai5W .label text,#mermaid-svg-egwnlFgy3t46ai5W span{fill:#333;color:#333;}#mermaid-svg-egwnlFgy3t46ai5W .node rect,#mermaid-svg-egwnlFgy3t46ai5W .node circle,#mermaid-svg-egwnlFgy3t46ai5W .node ellipse,#mermaid-svg-egwnlFgy3t46ai5W .node polygon,#mermaid-svg-egwnlFgy3t46ai5W .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-egwnlFgy3t46ai5W .rough-node .label text,#mermaid-svg-egwnlFgy3t46ai5W .node .label text,#mermaid-svg-egwnlFgy3t46ai5W .image-shape .label,#mermaid-svg-egwnlFgy3t46ai5W .icon-shape .label{text-anchor:middle;}#mermaid-svg-egwnlFgy3t46ai5W .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-egwnlFgy3t46ai5W .rough-node .label,#mermaid-svg-egwnlFgy3t46ai5W .node .label,#mermaid-svg-egwnlFgy3t46ai5W .image-shape .label,#mermaid-svg-egwnlFgy3t46ai5W .icon-shape .label{text-align:center;}#mermaid-svg-egwnlFgy3t46ai5W .node.clickable{cursor:pointer;}#mermaid-svg-egwnlFgy3t46ai5W .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-egwnlFgy3t46ai5W .arrowheadPath{fill:#333333;}#mermaid-svg-egwnlFgy3t46ai5W .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-egwnlFgy3t46ai5W .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-egwnlFgy3t46ai5W .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-egwnlFgy3t46ai5W .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-egwnlFgy3t46ai5W .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-egwnlFgy3t46ai5W .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-egwnlFgy3t46ai5W .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-egwnlFgy3t46ai5W .cluster text{fill:#333;}#mermaid-svg-egwnlFgy3t46ai5W .cluster span{color:#333;}#mermaid-svg-egwnlFgy3t46ai5W div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-egwnlFgy3t46ai5W .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-egwnlFgy3t46ai5W rect.text{fill:none;stroke-width:0;}#mermaid-svg-egwnlFgy3t46ai5W .icon-shape,#mermaid-svg-egwnlFgy3t46ai5W .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-egwnlFgy3t46ai5W .icon-shape p,#mermaid-svg-egwnlFgy3t46ai5W .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-egwnlFgy3t46ai5W .icon-shape .label rect,#mermaid-svg-egwnlFgy3t46ai5W .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-egwnlFgy3t46ai5W .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-egwnlFgy3t46ai5W .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-egwnlFgy3t46ai5W :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 用户提问
查询向量化
向量数据库检索
Top-K 相关文档块
重排序 Rerank
组装 Prompt
大语言模型生成
最终回答
3. 为什么需要 RAG:与微调的对比
在引入 RAG 之前,让模型掌握特定领域知识的主流方案是微调(Fine-tuning)。两者各有适用场景:
| 维度 | RAG | 微调 |
|---|---|---|
| 知识更新 | 更新知识库即可,成本低 | 需重新训练,周期长 |
| 幻觉控制 | 可引用检索来源,幻觉较低 | 仍可能产生幻觉 |
| 私有数据 | 天然支持外部知识库 | 需构造训练数据 |
| 推理成本 | 需维护检索链路 | 推理相对简单 |
| 适用场景 | 知识问答、客服、文档解读 | 风格模仿、格式遵循、特定任务能力 |
RAG 适合知识密集型 任务,微调适合能力与风格调整任务。在实际工程中,两者也常结合使用:先微调让模型适应领域表达,再用 RAG 注入实时知识。
4. RAG 的关键技术细节
4.1 文本切分策略
切分粒度直接影响检索质量:
- 切分过小:语义不完整,检索到的片段缺乏上下文。
- 切分过大:噪声多,且可能超出模型上下文窗口。
常用策略包括固定长度切分、按段落/标题结构切分、递归字符切分,以及基于语义的智能切分。实践中通常设置 chunk_size=500 左右并保留 overlap=50 的重叠,以保持语义连贯。
4.2 嵌入模型选择
嵌入模型决定了向量空间的语义表达能力。选择时需考虑:
- 是否支持中文等多语言;
- 向量维度与检索性能的平衡;
- 与向量数据库的兼容性。
4.3 混合检索
仅靠向量检索有时会漏掉关键词精确匹配的场景。生产环境常采用混合检索:同时执行向量检索与 BM25 关键词检索,再用 RRF(Reciprocal Rank Fusion)融合排序,兼顾语义与字面匹配。
4.4 重排序
向量检索召回 Top-50,再用重排序模型精排取 Top-5 送入生成,是兼顾效果与成本的常见做法。
5. 代码实战:基于 LangChain 搭建 RAG
下面用一个可运行的示例演示如何搭建一个最小可用的 RAG 系统。
5.1 安装依赖
bash
pip install langchain langchain-community langchain-openai chromadb
5.2 构建知识库索引
python
from langchain_community.document_loaders import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
# 1. 加载文档
loader = TextLoader("knowledge.txt", encoding="utf-8")
documents = loader.load()
# 2. 文本切分
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=50,
)
chunks = text_splitter.split_documents(documents)
# 3. 向量化并存储
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
vectorstore = Chroma.from_documents(
documents=chunks,
embedding=embeddings,
persist_directory="./chroma_db",
)
5.3 检索并生成回答
python
from langchain_openai import ChatOpenAI
from langchain.chains import RetrievalQA
# 创建检索器
retriever = vectorstore.as_retriever(search_kwargs={"k": 4})
# 创建问答链
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
retriever=retriever,
return_source_documents=True,
)
# 提问
result = qa_chain.invoke({"query": "什么是 RAG?"})
print(result["result"])
5.4 手动组装 Prompt 的方式
不依赖封装好的链,也可以手动控制检索与生成的衔接:
python
from langchain.prompts import PromptTemplate
# 检索相关文档
docs = retriever.invoke("什么是 RAG?")
context = "\n\n".join([doc.page_content for doc in docs])
# 组装 Prompt
prompt = PromptTemplate.from_template(
"请基于以下资料回答问题:\n\n{context}\n\n问题:{question}"
)
final_prompt = prompt.format(context=context, question="什么是 RAG?")
# 生成回答
response = llm.invoke(final_prompt)
print(response.content)
6. RAG 的常见挑战与优化方向
6.1 检索质量不佳
- 症状:召回的文档与问题不相关。
- 优化:调整切分策略、更换更强的嵌入模型、引入混合检索与重排序。
6.2 上下文被噪声干扰
- 症状:相关文档混入大量无关内容,模型被带偏。
- 优化:提高召回精度、压缩上下文、对检索结果做相关性过滤。
6.3 答案缺乏引用来源
- 症状:用户无法验证回答依据。
- 优化 :在 Prompt 中要求模型标注引用来源,并返回
source_documents供前端展示。
6.4 高级 RAG 架构
生产级系统通常演进为更复杂的流水线,包括查询改写、多路召回、重排、以及基于评分的自适应检索等。
7. 总结
RAG 通过"检索 + 生成"的组合,让大语言模型能够访问外部知识库,有效缓解了幻觉问题并支持知识实时更新。构建一个可用的 RAG 系统,核心在于文档切分、向量检索、上下文组装三个环节的精细调优。
对于知识库问答、企业文档助手、智能客服等场景,RAG 是目前落地成本最低、效果最稳定的技术路线之一。建议初学者从 LangChain + Chroma 的最小示例入手,逐步加入混合检索与重排序,再根据业务效果持续迭代。