一、什么是 RAG

RAG 全称 Retrieval‑Augmented Generation,检索增强生成,2020 年 Meta 团队提出,核心逻辑一句话概括:先检索资料,再交给大模型基于资料生成答案

普通大模型的局限:

  1. 知识存在时间截止,不知道最新业务资料;
  2. 训练数据固定,无法读取企业内部 PDF、手册、文档;
  3. 容易产生幻觉,一本正经编造不存在的事实。

RAG 不是修改大模型权重,不去做微调。而是给大模型准备一份外部参考资料。就像开卷考试:不让模型凭记忆答题,给它课本片段,让它照着课本回答问题。

  • R(Retrieval 检索):从知识库找出和用户问题相关的片段
  • A(Augmented 增强):把检索出来的资料,拼接到 Prompt 提示词里面
  • G(Generation 生成):大模型结合用户问题 + 参考上下文输出答案

RAG vs 微调:

  • RAG:外部知识库,文档随时更新,成本低,适合私有文档问答;
  • 微调:修改模型权重,需要大量训练数据,成本高,适合学习风格、输出格式。

二、RAG 两大阶段:离线建库 + 在线问答

整套 RAG 分为两大阶段:索引构建(离线一次性执行)、推理问答(用户提问实时执行)

阶段 1:离线索引构建(Indexing)

提前处理文档,构建向量知识库,文档更新时重新执行。

  1. 文档加载:读取 PDF、TXT、Markdown、网页等各类文件。
  2. 数据清洗:去除空行、页眉页脚、乱码、水印,得到干净文本。
  3. 文本分块(Chunk):把长篇文档切为小段文本。

    分块非常关键,块太大语义混杂;块太小丢失完整上下文,一般 500‑1000 字符。

  4. Embedding 向量化:嵌入模型把文本片段转为高维数字向量,向量代表语义含义,语义相近向量距离更近。
  5. 存入向量数据库:保存文本片段 + 对应的向量,建立索引,用于后续快速相似度检索。

阶段 2:在线问答(Inference),用户提问实时流水线

  1. 用户输入问题;
  2. 用户问题做 Embedding 转为向量;
  3. 在向量库做相似度检索,召回 Top‑N 最相关的文档片段;
  4. (可选)重排序 Reranker,对召回结果二次打分过滤无关内容;
  5. 将检索到的上下文 + 用户问题组装成 Prompt;
  6. 大模型接收 Prompt,严格依据参考资料输出回答;
  7. 返回结果给用户。

整体流程简图: 原始文档 → 加载清洗 → 分块 → Embedding → 向量数据库 用户问题 → 向量化 → 向量检索 → reranker → 组装prompt → LLM生成 → 输出答案

三、极简 Naive‑RAG 代码示例(LangChain)

安装依赖

pip install langchain langchain‑community chromadb python‑dotenv
import os
from dotenv import load_dotenv
from langchain_community.document_loaders import TextLoader
from langchain_text_splitters import CharacterTextSplitter
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain_chroma import Chroma

load_dotenv()

# ========== 1、离线构建向量库 ==========
# 加载本地txt知识库文档
loader = TextLoader("./knowledge.txt", encoding="utf‑8")
docs = loader.load()

# 文档切分
text_splitter = CharacterTextSplitter(
    chunk_size=600,
    chunk_overlap=80
)
split_docs = text_splitter.split_documents(docs)

# 初始化向量数据库,存入文档
vector_db = Chroma.from_documents(
    documents=split_docs,
    embedding=OpenAIEmbeddings(
        api_key=os.getenv("DEEPSEEK_API_KEY"),
        base_url=os.getenv("DEEPSEEK_BASE_URL")
    ),
    persist_directory="./chroma_db"
)

# 检索器,设置返回top3相关片段
retriever = vector_db.as_retriever(search_kwargs={"k": 3})

# ========== 2、在线问答 ==========
llm = ChatOpenAI(
    model=os.getenv("DEEPSEEK_MODEL"),
    api_key=os.getenv("DEEPSEEK_API_KEY"),
    base_url=os.getenv("DEEPSEEK_BASE_URL"),
    temperature=0
)

user_query = "你的业务支持哪些功能?"

# 检索相关文档片段
related_docs = retriever.invoke(user_query)

# 拼接检索上下文
context_text = "\n".join([doc.page_content for doc in related_docs])

# 构造Prompt,约束模型只能基于资料回答
prompt = f"""
你是知识库问答助手,请严格参考下面【参考资料】回答用户问题。
如果参考资料没有相关信息,请直接回答:“知识库中未找到相关信息”,不要编造内容。

【参考资料】
{context_text}

【用户问题】
{user_query}
"""

resp = llm.invoke(prompt)
print(resp.content)

上面是基础 Naive‑RAG,真实项目还需要增加重排序、查询改写、混合检索等优化。

四、RAG 常见应用场景

  1. 企业内部知识库问答:员工手册、产品文档、运维手册;
  2. 客服智能问答机器人:产品 FAQ、售后政策;
  3. 文档助手:PDF 文档解析、论文解读、合同分析;
  4. 垂直领域助手:法律条文、医疗科普、教育资料问答;
  5. 时效性内容:新闻、公告,文档更新知识库同步更新,不用重新训练模型。

五、RAG 常见痛点与优化思路

很多同学写完基础 RAG,发现效果很差,不是 RAG 技术不行,而是流水线各个环节出问题。

1、召回差:检索不到真正相关的片段

  • 现象:返回无关文档,正确片段完全没有召回
  • 优化:
    1. 优化分块策略,不要粗暴按字符切割,优先按语义、段落切分;
    2. 使用效果更好的 Embedding 嵌入模型;
    3. 混合检索:向量语义检索 + BM25 关键词检索,多路召回;
    4. 增加 Reranker 重排序模型,对初筛结果二次精准过滤;
    5. 查询改写:把用户问题扩写、生成多个变体 query 检索,提升召回率。

2、仍然产生幻觉

误区:RAG 并不能 100% 消除幻觉!检索质量差、prompt 约束弱,模型依旧会脑补内容稀土掘金。

  • 优化:
    1. Prompt 强制约束:没有资料就如实说不知道,禁止编造;
    2. 设置相似度阈值,低于阈值直接拒答;
    3. 输出要求附带引用来源片段;
    4. 答案生成后做事实校验,比对原始检索片段,过滤矛盾内容。

3、上下文超长,超出模型 token 上限

  • 现象:检索返回太多片段,prompt 超长,报错或者模型性能下降
  • 优化:控制召回 top‑k 数量,reranker 过滤低相关性片段,精简上下文。

六、Naive‑RAG → Advanced RAG 演进

  1. Naive RAG(基础版):简单分块 + 向量检索,适合简单文档,效果有限;
  2. 进阶 RAG:增加重排序、多路召回、查询改写、文档元数据过滤;
  3. 高级 RAG:Agent‑RAG,结合 LangGraph 做流程编排;可以判断检索是否充足,不足就再次检索;支持多轮对话记忆;实现自我校验逻辑。

可以把 RAG 和 LangGraph 结合:用 LangGraph 编排 RAG 完整链路,实现:问题改写 → 检索 → 判断资料是否足够 → 不足则重新检索 → 生成答案 → 校验输出,形成完整 Agent 工作流。

七、总结

RAG 是大模型落地最实用的技术,用最低成本把私有数据赋能大模型。 RAG 不是简单调用向量库,整套系统是流水线工程:文档解析、分块、embedding、检索、重排、prompt 构造,每一步都会影响最终效果。

更多推荐