我花一个下午,搞懂了 AI 最重要的技术之一:RAG
网上说 RAG 很重要,但讲清楚的文章不多。这篇文章用一个真实跑通的银行合规助手项目,带你从零理解 RAG 到底在做什么。
一、先问你一个问题
假设你问 ChatGPT:"我们公司的请假流程是什么?"
它肯定答不上来。
不是因为它不够聪明,而是因为你公司的请假流程这份文件,根本没有出现在它的训练数据里。
这就是大语言模型(LLM)的根本局限:它只知道训练时见过的内容,对于你的公司内部文档、最新政策、私有知识库,它一无所知。
硬要它回答,它只会"一本正经地胡说八道"——这就是大家常说的AI 幻觉。
二、RAG 是什么:一个比喻
RAG 的全称是 Retrieval-Augmented Generation,检索增强生成。
先别管这个名字,我给你打个比方。
想象两种考试场景:
闭卷考试:考前背书,考场里凭记忆作答。AI 平时就是这种模式——它的"记忆"就是训练时见过的数据。一旦你问它没见过的内容,它只能靠"猜"。
开卷考试:考场里可以翻书。不需要提前背下所有内容,遇到不会的题,翻到相关章节,找到答案,再写进卷子里。
RAG 就是给 AI 开了一本"参考书"。
流程很简单:
1. 把你的私有文档存好 2. 用户提问时,先去文档里找相关内容 3. 把找到的内容和问题一起交给 AI 4. AI 基于这些内容给出有依据的回答
就这么简单。
三、我用一个下午做了什么
为了真正理解 RAG,我用 Python 从零搭了一个银行合规知识助手。
知识库是 5 份模拟的银行合规文档,包括:
• 个人贷款产品说明 • 信用卡逾期处理规定 • 理财产品风险揭示书 • 个人征信查询规定 • 客户投诉处理流程
这类文档有个特点:条款密集、措辞严谨,一个问题的答案可能藏在某一条的某一款里——非常适合验证 RAG 的效果。
整个系统不到 300 行 Python 代码,用了 4 个模块:
chunking.py → 文档切块embedding.py → 文本向量化vectorstore.py → 向量数据库存取generate.py → 调用 LLM 生成回答下面我把每一步都说清楚。
四、RAG 的四个步骤
步骤一:把文档切成小块(Chunking)
整篇文档直接扔给 AI 有两个问题:一是太长塞不下,二是语义太稀释,搜索时找不准。
所以第一步是把文档切成一小段一小段的文字块,每块约 400 个字。
切完之后,5 份文档变成了 55 个文本块:
个人征信查询规定.txt → 12 个文本块个人贷款产品说明.txt → 9 个文本块信用卡逾期处理规定.txt → 10 个文本块客户投诉处理流程.txt → 12 个文本块理财产品风险揭示书.txt → 12 个文本块有一个小细节:相邻的文本块之间会有 50 字的重叠(overlap)。原因是:如果关键信息恰好跨在两段的边界,重叠能保证它至少完整地出现在其中一个块里,不会"两边不靠"地丢失。
步骤二:把文字变成向量(Embedding)
这是 RAG 最关键,也最难理解的一步。
计算机不能直接比较"语义相不相关"。但如果把每段文字映射成一串数字(向量),就能用数学方法计算相关性了。
语义相近的文字,向量的方向也相近。
举个例子:
• "信用卡逾期罚息" 和 "逾期利息计收标准" • 这两句话词不同,但语义相近 • 向量化之后,它们在空间中的方向几乎一致
这个过程用一个叫 sentence-transformers的开源模型来完成,完全在本地运行,免费,中文支持也不错。
55 个文本块,每块都被转成一个 384 维的向量,存进本地的向量数据库(Chroma)。
步骤三:检索相关内容(Retrieval)
用户提问时,把问题也用同样的模型转成向量,然后在向量数据库里找"方向最接近"的几个文本块。
这个相似度叫做余弦相似度,值在 0 到 1 之间,越接近 1 越相关。
来看一个真实的检索结果:
问题:信用卡逾期30天会有什么后果?
块 1 │ 来源:《信用卡逾期处理规定》 相似度:70.6% │ 内容:第10条 M2中度逾期处理(31-60天) │ 第10.1款 移交至信用卡催收专员负责... │ 第10.3款 可提供分期还款方案,最长24期...块 2 │ 来源:《个人贷款产品说明》 相似度:62.2% │ 内容:第9.3款 二次扣款仍未成功的,视为逾期...块 3 │ 来源:《信用卡逾期处理规定》 相似度:61.2% │ 内容:文件头部及总则内容...系统准确地找到了最相关的条款,而且每个结果都标注了来自哪份文档、相似度多少。
步骤四:生成带引用的回答(Generation)
把检索到的 3 个文本块和用户问题一起送给 LLM,要求它:
• 只基于这些材料回答,不要"编" • 必须标注引用了哪条哪款
最终输出:
根据《信用卡逾期处理规定》第10条M2中度逾期处理(31-60天):
• 逾期后将由信用卡催收专员负责跟进(来源:第10.1款) • 每周至少进行一次电话催收(来源:第10.2款) • 可申请分期还款方案,最长不超过24期(来源:第10.3款) • 超过90天将上报征信系统(来源:第10.4款)
有出处,有条款,有依据。这就是 RAG 的价值所在。
五、RAG 也有不完美的时候
为了展示 RAG 的局限,我问了第二个问题:
问题:征信报告被频繁查询会有什么影响?
系统虽然检索到了 3 个文本块,但全部来自《客户投诉处理流程》,相似度只有 55-58%,明显不够准。
最终回答是:
根据现有材料暂无相关规定。
这个回答……其实是对的!
因为我们的文档里确实有《个人征信查询规定》,但相关条款的那几个文本块,这次没被检索出来——embedding 模型没有准确捕捉到问题和文档内容的语义关联。
这说明 RAG 有两个核心质量瓶颈:
1. Embedding 质量:向量化模型越强,语义理解越准,检索命中率越高。
2. 文本块设计:chunk 太小,上下文不够;chunk 太大,语义稀释。块的划分方式直接影响能不能找到对的内容。
好消息是:这两个都是可以优化的工程问题,不是死局。
六、整体架构一眼看懂
你的文档(.txt / .pdf / .docx) │ ▼ 切块(Chunking) 55 个文本块 │ ▼ 向量化(Embedding) ← sentence-transformers,本地运行 55 个 384 维向量 │ ▼ 存入向量数据库(Chroma) │用户提问 ──▶ 向量化 ──▶ 相似度搜索 ──▶ Top-3 相关块 │ ▼ 拼进 Prompt ──▶ LLM 生成回答 (Ollama 本地 / Claude API)整个系统完全可以在本地免费运行:
• Embedding:sentence-transformers(开源,本地) • 向量库:Chroma(开源,本地文件) • LLM:Ollama + qwen2.5:7b(开源,本地) • 不需要任何 API Key
七、学到了什么
做完这个项目,我对 RAG 有了几个更直观的理解:
RAG 不是万能的,它的上限取决于检索质量。找错了内容,再强的模型也没用。
向量化是核心黑盒。文字怎么变成向量、语义怎么被保留,这个过程至今没有完美的解释,但它确实有效。
chunk_size 是最值得调的参数。切 200 字、400 字、800 字,效果差异肉眼可见,强烈建议自己动手试。
LLM 在这里是"理解和表达",不是"记忆"。事实由文档提供,语言由模型组织——这是 RAG 不产生幻觉的根本原因。
尾声
从"AI 只会瞎编"到"AI 能精准引用你的内部文档",中间就差了一个 RAG。
它不复杂,但每一步都有值得深入的细节。
如果你也想动手试试,留言我发代码。5 份模拟银行文档、4 个核心模块、不到 300 行 Python——跑起来大概只需要一个下午。
理解一项技术最好的方式,就是让它在你的电脑上跑起来。
项目基于 Python + sentence-transformers + Chroma + Ollama 构建,完全本地运行,无需 API Key。
夜雨聆风