前两篇讲了”为什么”和”是什么”,这篇讲”怎么做”。RAG 入门不需要复杂的框架,五个组件 + 正确配置 = 能用的知识库问答系统。
一、RAG 五大核心组件
| 组件 | 做什么 | 常用工具 |
|---|---|---|
| 知识库 | 存储外部文档 | 企业文档、Wiki、自建数据库 |
| 文本分块器 | 把长文档切成小段 | LangChain RecursiveCharacterTextSplitter |
| 嵌入模型 | 文本转向量 | BGE-M3、OpenAI Embedding、M3E |
| 向量数据库 | 存储和搜索向量 | Chroma(入门)、Milvus(生产) |
| LLM | 生成最终答案 | 选用符合质量、延迟、成本与合规要求的模型 |
知识库质量是 RAG 的基石——垃圾进,垃圾出。花时间整理知识库,比调任何参数都管用。
二、文本分块:RAG 最容易踩的坑
为什么需要分块?
LLM 的上下文窗口有限,你不能把整个 200 页的 PDF 塞进去。而且检索时,粒度太粗(整篇文章)会让相关性变差——用户问”请假流程”,你给他整本员工手册。
四种分块策略
| 策略 | 做法 | 优点 | 缺点 |
|---|---|---|---|
| 固定长度 | 每 N 个字符或 token 切一刀 | 简单直接 | 容易截断语义,一句话分成两段 |
| 按标题层级 | 按 H1/H2/H3 切分 | 保留文档结构 | 依赖文档格式规范 |
| 语义段落 | 按自然段切分 | 语义完整 | 段落长度不一 |
| 滑动窗口 | 有重叠地切分 | 上下文连续 | 存储成本翻倍 |
推荐实践
from langchain_text_splitters import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
chunk_size=500, # 默认按字符计:每块最多约 500 个字符
chunk_overlap=50, # 默认按字符计:相邻块重叠 50 个字符
separators=["\n\n", "\n", "。", ".", " "] # 优先在自然边界切
)
关键参数建议:
- 上面这段
RecursiveCharacterTextSplitter的默认单位是字符,不是 token。若要按 token 切分,应使用 token-aware splitter,并以所选模型的 tokenizer 实测。 - 初始值可以从 300-800 个字符、10%-20% overlap 开始;不存在适用于所有文档的固定最优值,需用真实查询评测。
- 优先使用标题层级切分(保留
heading_path元数据),长度兜底。
分块时要注意
- 保留标题路径:每条 chunk 记录它来自哪个标题下,方便后续引用来源。
- 结构化内容特殊处理:表格、代码块不要从中截断。
- 元数据要补全:文档来源、创建时间、权限标签等——这些在检索过滤时非常有用。
三、Prompt 模板:RAG 的”说明书”
检索到了相关内容后,怎么写 Prompt 让 LLM 正确使用这些内容?一个典型的 RAG Prompt 模板:
你是一个专业助手,请基于以下检索结果回答问题。
如果检索结果中没有相关信息,请明确说"根据现有资料无法回答",不要编造。
问题:{query}
检索结果:
1. {doc1}
2. {doc2}
3. {doc3}
回答要求:
- 必须基于上述检索结果作答
- 引用具体片段时标注来源
- 语言简洁、准确
Prompt 设计的关键原则:
| 原则 | 做法 |
|---|---|
| 降低无依据生成 | 指示“仅基于检索结果回答,不知道就说不知道”,并用评测验证模型是否遵守 |
| 可追溯 | 要求引用来源,让用户可以查证 |
| 控长度 | 检索结果过长时截断或摘要,不要让 Prompt 超出 LLM 上下文限制 |
| 结构化 | 明确分隔”用户问题”和”检索结果”,避免指令混淆 |
诊断应先分层:检查资料是否正确、检索是否命中、重排与上下文是否完整,再检查模型是否遵守“资料不足则拒答”的约束。不要把单一 Prompt 当成幻觉的解决方案。
四、问题诊断:出错了怎么排查?
RAG 问题可能发生在数据、检索、上下文组织和生成任一环节。下面是常见问题速查:
| 现象 | 根因 | 解决 |
|---|---|---|
| 检索结果不相关 | 分块策略不对 / 查询太模糊 | 调整 chunk_size;用 LLM 扩展查询词 |
| 回答有幻觉 | 资料不足、错检索、上下文冲突或模型未遵守约束 | 先检查引用是否支撑答案;调节 Top-K、加入 reranker,并评测拒答与引用正确性 |
| 响应太慢 | 向量数据库未优化 | 开 ANN 近似搜索;换云服务 |
| 知识库更新后效果变差 | 旧向量没删 | 自动化:数据更新 → 重新分块 → 重建索引 |
| 关键信息被截断 | chunk 切得太碎 | 增大 chunk_size 或 chunk_overlap |
调试两步法
第一步:验证检索质量
手动输入几个典型的用户问题,看检索回来的 Top-3 文档是否真的相关。如果不相关:
- 用带标准答案的查询集比较 Embedding 模型、分块策略和 Top-K
- 记录 Recall@K、MRR / nDCG 与延迟,而不是按固定顺序盲调参数
第二步:检查生成逻辑
把完整的 Prompt(包括检索结果)打印出来,观察 LLM 是否忽略了关键信息。如果忽略了:
- 强化 Prompt 中的指令,并检查模型给出的每条引用是否真正支撑结论
- 让人工或独立评测器判断检索片段相关性;生成模型本身不能替代检索评测
用 LangChain 的话可以一行代码开启调试:
langchain.debug = True——它会打印每一步的输入输出。
五、入门推荐路径
如果你想亲手搭建一个 RAG 系统,推荐从最简单的组合开始:
文档 → RecursiveCharacterTextSplitter(例如 500 字符/块,实测后调整)
→ BGE-M3 Embedding
→ Chroma 向量数据库
→ GPT-4 / Qwen 生成
这个组合上手快、调试方便,适合第一个 RAG 原型。跑通之后,再根据实际场景逐步优化——换更大的模型、加混合检索、引入 Reranker 等。
如果你需要更深入的 RAG 实践,可以参考博客中的进阶文章:企业级 RAG 怎么落地和 RAG 流程类问题优化。
小结
- 五大组件:知识库、分块器、嵌入模型、向量数据库、LLM。
- 分块要可评测:明确字符或 token 单位,优先标题层级切分,再用真实问题调整参数。
- Prompt 是辅助约束:明确“仅基于检索内容回答”,并验证拒答和引用是否可靠。
- 排查要分层:分别验证资料、检索、上下文和生成,不预设某个环节占比。
- 入门推荐栈:RecursiveCharacterTextSplitter + BGE-M3 + Chroma + GPT-4。
本系列三篇文章,从 RAG 的动机到向量原理再到实战搭建,覆盖了从零理解 RAG 所需的核心知识。如果你对 LLM 本身的工作原理感兴趣,可以回看 LLM 工作原理系列;如果想学习如何更好地与 LLM 对话,Prompt Engineering 系列在等你。