RAG 实战指南:从零搭建一个真正能用的知识问答系统
最近在折腾 Hermes Agent 的时候,碰到一个问题:怎么让 AI 记住我项目里的所有文档?
直接把文档塞进 prompt?上下文窗口不够用。fine-tune 模型?每次文档更新都得重新训练,成本太高。
后来发现,RAG 才是解决这类问题的标准答案。不是什么新概念了,但 2026 年的 RAG 工具链比两年前成熟太多了,值得重新聊聊。
RAG 是什么,用大白话说
RAG,全称 Retrieval-Augmented Generation,翻译过来就是"检索增强生成"。名字听着唬人,其实逻辑很简单:
先搜,再答。
你问 AI 一个问题,它不直接靠自己的"记忆"回答,而是先去你的知识库里搜一波相关内容,把搜到的东西作为参考,再组织语言回答你。
打个比方:一个医生不可能记住所有病例,但他知道怎么查病历系统。RAG 就是给 AI 装了一个"查病历"的能力。
这个思路的好处很明显:
- 模型不用重新训练,你只管更新知识库就行
- 回答可以引用来源,有据可查
- 私有数据不用发给模型训练,安全性更好
- 知识库可以随时更新,不存在"知识截止日期"的问题
最简 RAG 长什么样
一个能跑的 RAG 系统,核心流程就五步:
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
看起来很简单对吧?但魔鬼全在细节里。
第一步的"加载文档"就可能翻车——PDF 里的表格怎么处理?图片里的文字怎么办?中文 PDF 乱码怎么搞?
第二步的"切分"更是重灾区。切太大,检索精度低;切太小,上下文断裂,模型看不懂。
这些坑我一个个踩过,下面详细说。
文档切分:RAG 最容易翻车的环节
很多人觉得 RAG 的核心是向量数据库或者 embedding 模型,其实不是。文档切分的质量直接决定了 RAG 的上限。
切得不好,后面再怎么优化都是在给烂数据打补丁。
切分的基本策略
最简单的切法是按固定长度切,比如每 500 个字符切一块:
| 1 | |
| 2 | |
这种切法的问题在于:它完全不考虑语义。一句话可能被从中间切断,导致前后两块都不完整。
稍微好一点的是按段落或章节切:
| 1 | |
| 2 | |
但段落长度差异可能很大——有的段落只有两句话,有的段落写了两千字。
实战推荐:递归字符切分
LangChain 提供了一个 RecursiveCharacterTextSplitter,思路是先按大分隔符(比如 \n\n)切,切完如果还太长,就按小分隔符(\n)再切,依次递归:
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
chunk_overlap 很关键。不设 overlap 的话,一个概念如果刚好跨了两个块,两边都检索不到完整信息。设 50-100 字符的 overlap 就够了。
中文切分的坑
中文没有天然的空格分词,所以切分的时候要特别注意:
- 分隔符要用中文标点。默认的
["\n\n", "\n", " ", ""]是为英文设计的,中文文档应该加"。"、"!"、"?"等。 - chunk_size 不能太小。中文信息密度高,500 字符大概相当于英文 200 词,已经很短了。再小的话上下文就不够了。
- 表格和代码块别硬切。如果你的文档里有代码或表格,最好先识别出来,整块保留,不要从中间切断。
我之前处理一批中文技术文档,用默认的英文分隔符切分,结果很多句子被从中间断开,检索出来的片段全是半句话,模型根本没法用。换成中文分隔符之后效果好了很多。
Embedding 模型怎么选
Embedding 是把文本转成向量的过程。向量之间的距离代表语义相似度——距离越近,意思越像。
2026 年主流的 embedding 模型:
- OpenAI text-embedding-3-small/large:效果好,API 调用,按 token 计费。small 版本性价比很高。
- BGE 系列(BAAI):开源,中文效果好,可以本地部署。bge-large-zh-v1.5 是中文场景的首选之一。
- Jina embeddings v3:支持多语言,开源,可以自托管。
- Cohere embed-v4:多语言效果不错,API 调用。
如果你的数据主要是中文,BGE 系列是首选。不用付 API 费用,中文语义理解也比 OpenAI 的模型好一些。
本地部署 BGE 的代码:
| 1 | |
| 2 | |
| 3 | |
| 4 | |
需要注意的是,embedding 模型一旦选定就别轻易换。换模型意味着所有已存的向量都得重新生成,成本不小。
向量数据库:存和查的学问
向量数据库负责存向量、做相似度检索。2026 年的选择很多:
- ChromaDB:轻量,Python 原生,适合原型和小项目。pip install 就能用。
- Milvus/Zilliz:生产级,支持大规模数据,分布式部署。
- Qdrant:Rust 写的,性能好,API 设计干净。
- Pinecone:全托管 SaaS,不用自己运维,但要花钱。
- Weaviate:支持混合搜索(向量 + 关键词),功能丰富。
- pgvector:PostgreSQL 插件,如果你已经在用 PG,加个插件就行,不用引入新组件。
对于个人项目或者小团队,ChromaDB 或者 pgvector 就够了。别一上来就搞 Milvus 集群,杀鸡用牛刀。
我自己的 Hermes Agent 项目用的是 ChromaDB,主要是图省事:
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
代码就这么点。不需要配置服务器,不需要管连接池,数据存在本地文件夹里。
检索策略:不只是搜最近的
最基础的检索是向量相似度搜索——找到跟问题最"像"的几个文档块。但实际用下来,光靠这个不够。
问题一:语义相似 ≠ 答案相关
用户问"怎么给 Python 项目配置虚拟环境",向量搜索可能返回一堆跟"Python"和"环境"相关的段落,但具体到 venv 或 conda 的段落排在很后面。
解法:Reranking
先用向量搜索粗筛出 top-20,再用一个 reranker 模型精排,把真正相关的段落排到前面:
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
Reranker 比 embedding 模型慢,但它看的是 query 和 document 的完整交互,精度高得多。先粗筛再精排,是精度和速度的平衡。
问题二:用户的问法和文档的写法不一样
用户说"怎么部署",文档里写的是"安装和配置指南"。语义上接近,但关键词不匹配。
解法:混合搜索
把向量搜索和关键词搜索结合起来:
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
很多向量数据库已经内置了混合搜索,比如 Qdrant 和 Weaviate。不用自己手写融合逻辑。
2026 年 RAG 的新玩法
RAG 这两年进化了不少。基础的"切分-向量化-检索-生成"流程还是那个流程,但上面叠加了很多新的优化手段。
Agentic RAG
这是 2026 年最火的方向。核心思路是:让 AI Agent 来决定怎么检索,而不是写死一套检索流程。
传统的 RAG 流程是固定的:收到问题 → 搜索 → 生成回答。
Agentic RAG 把"搜索"这一步也交给 Agent 来决策:
- 这个问题需要搜哪个知识库?
- 搜出来的结果够不够?不够的话换个关键词再搜一次
- 这个问题其实不需要搜索,模型自己就能答
- 这个问题需要先拆成几个子问题,分别搜索再汇总
用 LangChain 的 Agent 来实现:
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
Agent 会自己决定要不要搜索、搜几次、用什么关键词。比写死的流程灵活得多。
Graph RAG
微软搞了个 GraphRAG,思路是在 RAG 的基础上加一层知识图谱。
普通的 RAG 检索的是"文本块",Graph RAG 检索的是"实体和关系"。比如你问"张三负责哪个项目?",普通 RAG 可能搜到一段包含"张三"的文档,但那段文档可能没提到项目信息。Graph RAG 可以通过知识图谱里的关系直接找到"张三 → 负责 → 项目X"这条边。
适合处理关系复杂的场景,比如组织架构、供应链、法律条文之间的引用关系。
缺点是构建知识图谱本身就很麻烦,小项目不值得搞。
Contextual Retrieval
Anthropic 提出的一个优化:在切分文档的时候,给每个块加上一段"上下文说明"。
比如原文是:"该产品支持单点登录(SSO)。"
切分之后,这个块可能会丢失它是哪个产品的信息。Contextual Retrieval 的做法是让模型给每个块补一句上下文:"这是关于 XX 产品的功能说明:该产品支持单点登录(SSO)。"
检索的时候,有上下文的块比没上下文的块准确率高得多。Anthropic 的测试显示,这个简单的方法把检索失败率降低了 35%。
RAG 效果怎么评估
搭完 RAG 之后,怎么知道它好不好用?光靠"我试了几个问题感觉还行"是不够的。
核心指标
RAG 的质量主要看两个维度:
检索质量:搜出来的文档块跟问题相不相关。指标是 Recall@K(top-K 个结果里有多少是真正相关的)和 MRR(第一个相关结果排在第几位)。
生成质量:模型基于检索结果生成的回答好不好。指标包括准确性(回答是否正确)、完整性(是否遗漏关键信息)、忠实度(是否编造了检索结果里没有的内容)。
最后这个"忠实度"特别重要。RAG 的一个常见问题是模型"幻觉"——检索结果里没有的信息,模型自己编了一段看起来很对的话。你得专门检测这种情况。
简单的评估方法
如果你不想搞复杂的评估框架,可以用这种土办法:
- 准备 20-30 个测试问题,覆盖你知识库的主要内容
- 每个问题手动标注"正确答案"和"应该检索到的文档"
- 跑一遍 RAG pipeline,对比检索结果和生成回答
- 统计检索召回率和回答准确率
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
| 16 | |
正式一点的话,可以用 RAGAS 这个评估框架,它专门做 RAG 效果评估,支持 Faithfulness、Answer Relevancy、Context Recall 等指标。
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
说实话,很多人搭完 RAG 就不管了,从来没评估过效果。结果用户用起来各种问题,回头一看,检索召回率才 40%,一大半问题都搜不到正确文档。花半天时间做个评估,能省很多后面的麻烦。
RAG vs Fine-tuning vs 长上下文
2026 年,解决"让模型理解你的数据"这个问题,有三条路:
RAG:不改模型,实时检索参考内容。适合数据经常更新、需要引用来源、数据量大的场景。
Fine-tuning:用你的数据重新训练模型的部分参数。适合需要改变模型行为(比如输出风格、专业术语)的场景。但数据更新了就得重新训,成本高。
长上下文:直接把所有数据塞进 prompt。现在模型的上下文窗口越来越大,Claude 支持 200K token,Gemini 支持 1M token。如果数据量不大,直接塞进去可能比搞 RAG 简单得多。
怎么选?
- 数据量小(几万字以内)→ 长上下文,最简单
- 数据量大、经常更新 → RAG
- 需要改变模型的行为和风格 → Fine-tuning
- 需要引用来源、可解释性 → RAG
- 预算有限、不想维护基础设施 → 长上下文或 API 调用
说实话,很多人搞 RAG 是因为觉得它"高级",但如果你的数据量不大,长上下文方案可能更简单有效。别为了用技术而用技术。
我踩过的坑
坑一:chunk_size 设太大
一开始我把 chunk_size 设成 2000,觉得大一点上下文更完整。结果检索出来的每块都很大,top_k=5 就把 context window 塞满了,模型反而抓不住重点。
后来改成 500,配合 reranking,效果好了很多。宁可切小一点,用 reranking 来保证相关性,也别切太大导致噪音太多。
坑二:没做 metadata 过滤
我的知识库里有文档、issue 记录、配置文件三种类型的数据。用户问"怎么配置 XXX"的时候,向量搜索同时返回了文档说明和 issue 讨论,两种内容混在一起,模型的回答自相矛盾。
加上 metadata 过滤之后,可以指定只搜某一类文档:
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
坑三:embedding 模型和查询语言不匹配
我的文档是中文的,但用户有时候用英文提问。用中文 embedding 模型处理英文查询,效果很差。
解决方案是用多语言 embedding 模型,比如 BGE-M3 或者 Jina embeddings v3,中英文都能处理。
坑四:忘了处理文档更新
一开始我只做了"索引",没做"更新"。文档改了之后,向量数据库里还是旧的版本,回答出来的信息过时了。
后来加了一个简单的机制:给每个文档块算 hash,文档更新的时候对比 hash,变了的重新 embedding。
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
实际动手:20 分钟搭一个最小 RAG
说了这么多,不如自己动手试试。下面是一个最小可运行的 RAG 示例,用 ChromaDB + OpenAI:
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
| 16 | |
| 17 | |
| 18 | |
| 19 | |
| 20 | |
| 21 | |
| 22 | |
| 23 | |
| 24 | |
| 25 | |
| 26 | |
| 27 | |
| 28 | |
| 29 | |
| 30 | |
| 31 | |
| 32 | |
| 33 | |
| 34 | |
| 35 | |
| 36 | |
| 37 | |
就这么多代码。能跑,能回答问题,能引用来源。
当然,生产环境还需要加很多东西:错误处理、日志、文档更新机制、reranking、混合搜索。但这个最小版本能让你在 20 分钟内理解 RAG 的核心流程。
工具推荐
如果你想快速搭一个 RAG 应用,不用从零开始,这些工具可以帮到你:
- LangChain:最流行的 RAG 框架,生态丰富,但 API 变动频繁,文档有时候跟不上代码。
- LlamaIndex:专注 RAG 的框架,比 LangChain 更聚焦,数据索引和查询的设计更优雅。
- Dify:开源的 LLM 应用平台,拖拽式搭建 RAG 工作流,不用写代码。
- RAGFlow:国产开源项目,支持深度文档解析(表格、图片 OCR),中文文档处理能力很强。
- FastGPT:也是国产,UI 友好,适合快速搭建知识库问答系统。
如果你只是想给自己的项目加个文档问答,LlamaIndex 够用了。如果要做成产品给用户用,Dify 或 RAGFlow 更合适。
写在最后
RAG 不是什么银弹。它解决的是"让模型访问你的数据"这个问题,但它引入了新的复杂度:文档切分策略、embedding 模型选择、向量数据库运维、检索质量调优。
2026 年的好处是工具链成熟了很多,不用自己造轮子。ChromaDB、LlamaIndex、Dify 这些工具让搭建 RAG 的门槛低了不少。
但核心的那些问题——怎么切分文档、怎么保证检索质量、怎么处理数据更新——还是得你自己根据业务场景去调。没有一套配置适用于所有场景。
我后面打算试试 Agentic RAG,让 Agent 自己决定检索策略,而不是写死流程。到时候再写一篇踩坑记录。
有啥问题评论区聊。