很多人第一次接触 AI 时都有一个疑问:
ChatGPT 明明这么聪明,为什么不能直接读取我的项目文档?
为什么企业还要折腾什么 RAG、向量数据库、Embedding?
其实,并不是 AI 不够聪明,而是它根本"看不到"你的数据。
今天这篇文章,我们就从整个 AI Agent 的架构出发,彻底讲清楚 RAG(Retrieval-Augmented Generation,检索增强生成) 的工作原理,并用 Node + Ollama + Vectra 从零实现一个本地知识库。
阅读完本文,你将彻底理解:
- 为什么 LLM 需要 RAG?
- Context Engineering(上下文工程)到底是什么?
- 为什么很多企业不用微调,而选择 RAG?
- Embedding(向量)到底是什么?
- Node 如何构建自己的本地向量数据库?
- 面试官最喜欢问哪些问题?
AI Agent 全景架构:RAG 到底属于哪一部分?
很多人学习 RAG 时,一上来就是:
安装 Ollama
安装 Chroma
安装 Milvus
最后工具学了一堆,却不知道为什么要这么做。
其实,我们应该先看看整个 AI Agent 的架构。
markdown
AI Agent
┌────────────────────┐
│ Model(模型) │
└────────┬───────────┘
│
┌────────▼───────────┐
│ Context Engineering│
│ (上下文工程) │
└────────┬───────────┘
│
┌──────────▼───────────┐
│ Memory(记忆) │
└──────────┬───────────┘
│
┌──────────▼───────────┐
│ Tools(工具调用) │
└──────────┬───────────┘
│
┌──────────▼───────────┐
│ Workflow(工作流) │
└──────────────────────┘
而今天要讲的 RAG,其实属于:
Context Engineering(上下文工程)
什么叫上下文工程?
简单来说,就是:
研究如何把最重要的信息,在有限的上下文窗口里,组织给 LLM。
为什么这是一个问题?
因为所有 LLM 都有一个共同特点:
它只能回答自己"看到"的内容。
如果它没见过,就只能猜。
这就是 RAG 出现的原因。
💡 一句话总结:RAG 本质属于 Context Engineering,它解决的是"如何让模型看到正确的信息"。
为什么企业不用微调,而更喜欢 RAG?
假设你现在是一家公司的 AI 负责人。
老板说:
我们有 20 万份财务数据,希望 AI 能回答。
怎么办?
很多人第一反应:
把数据喂给模型训练。
也就是:
Fine-tuning(微调)
实际上,目前企业主要有三种方案。
| 方案 | 效果 | 成本 | 适合场景 |
|---|---|---|---|
| 全量微调 | ★★★★★ | ★★★★★ | 模型训练公司 |
| LoRA 等轻量微调 | ★★★★ | ★★★ | 固定任务 |
| RAG | ★★★★★ | ★★ | 企业知识库 |
为什么越来越多企业选择 RAG?
原因很简单。
原因一:数据天天都在变
例如:
产品文档
接口文档
员工制度
财务报表
合同
每天都可能更新。
如果采用微调:
改一次数据
↓
重新训练
↓
重新部署
成本非常高。
而 RAG:
修改文档
↓
重新生成向量
↓
更新数据库
↓
结束
一分钟就完成。
原因二:企业数据不能上传
很多公司的数据:
- 财务
- 医疗
- 法律
- 银行
都是不能离开公司的。
因此:
diff
LLM(本地)
+
Embedding模型(本地)
+
向量数据库(本地)
=
整个 AI 完全离线
这就是很多企业都在使用的方案。
💡 一句话总结:RAG 不改变模型,而是改变模型看到的信息,因此成本低、更新快。
RAG 到底是什么?
RAG 全称:
Retrieval-Augmented Generation
检索增强生成。
一句话理解:
先查资料,再回答问题。
是不是很像我们考试?
不会
↓
翻书
↓
找到答案
↓
组织语言
↓
回答
RAG 就是在帮 LLM 做这件事情。
完整流程如下:
项目文档
↓
Embedding
↓
向量
↓
存入向量数据库
而用户提问时:
用户问题
↓
Embedding
↓
向量
↓
相似度检索
↓
找到最相关内容
↓
拼接 Prompt
↓
LLM 回答
整个流程如下:
markdown
文档
│
Embedding模型
│
向量数据库
▲
用户提问
│
Embedding模型
│
相似度检索
│
找到最相关内容
│
Prompt 拼接上下文
│
LLM 回答
注意:
LLM 并没有学会这些知识。
只是:
临时把资料放到它面前。
所以叫:
Retrieval(检索)
而不是:
Training(训练)
💡 一句话总结:RAG = 检索 + Prompt + LLM,而不是重新训练模型。
RAG ≠ 向量数据库,很多人第一天就理解错了
刚开始学习 RAG 时,很多人都会有一个误区:
"RAG 不就是把数据存到向量数据库吗?"
其实不是。
向量数据库只是 RAG 整个流程中的一个组件。
我们可以把 RAG 想象成一家图书馆。
markdown
RAG
┌────────────────┐
│ 用户提问题 │
└──────┬─────────┘
│
生成问题向量
│
▼
┌────────────────┐
│ 向量数据库检索 │
└──────┬─────────┘
│
找到最相关文档
│
▼
拼接 Prompt 上下文
│
▼
LLM 回答
其中:
- Embedding 模型:负责把文字转换成向量。
- 向量数据库:负责根据向量找到最相关的内容。
- LLM:负责理解上下文并生成最终答案。
可以发现:
向量数据库只负责"找资料",真正回答问题的是 LLM。
很多同学会把这两者混为一谈,其实它们的职责完全不同。
我们用一个生活中的例子理解:
假设你要写毕业论文。
整个过程其实就是:
图书馆(向量数据库)
↓
找到几本最相关的书
↓
自己阅读
↓
整理语言
↓
完成论文
这里:
- 图书馆不会帮你写论文;
- 它只是负责帮你找到最相关的资料。
RAG 也是一样。
因此:
RAG = 检索(Retrieval)+ 增强(Augmented)+ 生成(Generation)
而向量数据库,只属于其中的 Retrieval(检索) 环节。
RAG 与向量数据库的区别
| 对比项 | RAG | 向量数据库 |
|---|---|---|
| 本质 | 一套完整的解决方案 | 一个存储组件 |
| 是否负责回答问题 | ✅ 是(依赖 LLM) | ❌ 否 |
| 是否包含 Embedding | ✅ 包含 | ❌ 不包含 |
| 是否包含 Prompt 拼接 | ✅ 包含 | ❌ 不包含 |
| 是否需要 LLM | ✅ 需要 | ❌ 不需要 |
💡 一句话总结:RAG 是一条完整的流水线,而向量数据库只是流水线中的"检索工人"。
Chunk(文档切分):真正决定 RAG 效果的关键
很多人觉得:
只要把文档全部存进向量数据库,RAG 就完成了。
实际上,这只是完成了一半。
真正影响 RAG 效果的,不是数据库,而是:
Chunk(文档切分)。
什么是 Chunk?
Chunk 可以理解成:
把一篇很长的文章,拆成很多个小段。
例如一份项目文档:
README.md(5000 行)
如果直接生成一个向量:
整个 README
↓
一个向量
当用户问:
登录接口如何实现?
Embedding 得到的问题向量只能和整个 README 比较。
由于 README 内容太多:
erlang
登录
支付
权限
Docker
部署
数据库
......
最后得到的相似度反而不高。
模型很可能找不到真正需要的内容。
所以正确做法应该是:
erlang
README
↓
Chunk1(项目介绍)
Chunk2(安装)
Chunk3(登录)
Chunk4(支付)
Chunk5(部署)
......
↓
分别生成向量
这样用户提问:
登录接口怎么写?
系统就能精准找到:
Chunk3
而不是整个 README。
这也是为什么很多 RAG 项目都会先做:
文档切分(Chunking)
然后再进行:
Chunk
↓
Embedding
↓
向量数据库
而不是:
整个文档
↓
Embedding
Chunk 切得越小越好吗?
很多新人又会产生第二个误区:
那我是不是一句话切一个 Chunk?
也不是。
Chunk 太小:
登录接口
POST
上下文信息不足。
LLM 根本不知道它属于哪个模块。
Chunk 太大:
整个 README
又会引入大量无关信息。
所以实际项目中需要找到一个平衡。
通常会遵循两个原则:
① 保证语义完整
不要把一个完整的知识点拆开。
例如:
登录流程
↓
参数
↓
返回值
最好放在同一个 Chunk 中。
而不是:
diff
Chunk1
登录接口
--------
Chunk2
请求参数
--------
Chunk3
返回结果
否则检索出来的信息会残缺。
② 相邻 Chunk 保留重叠内容(Overlap)
真实项目里还会使用一种技巧:
Chunk Overlap(重叠切分)
例如:
erlang
Chunk1
......
JWT 登录
Token 生成
-------
Chunk2
Token 生成
权限校验
......
可以看到:
"Token 生成" 同时存在于两个 Chunk 中。
这样即使用户的问题跨越两个知识点,也能提高召回率。
很多成熟框架(如 LangChain、LlamaIndex)都支持自动进行 Chunk 切分和 Overlap 设置。
常见 Chunk 策略
| 策略 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 固定长度切分 | 实现简单 | 容易破坏语义 | 快速验证 Demo |
| 按段落切分 | 保留语义 | 长度不一致 | 技术文档 |
| 按标题切分 | 结构清晰 | 粒度较大 | Markdown 文档 |
| 语义切分(推荐) | 检索效果最好 | 实现复杂 | 企业级 RAG |
⚠️ 易错点:很多人以为 RAG 效果不好,是模型太弱。实际上,很多时候是 Chunk 切分策略设计得不好,导致检索阶段就找错了内容。
💡 一句话总结:RAG 的第一步不是 Embedding,而是合理地切分文档。Chunk 决定了检索的上限,而检索质量决定了最终回答质量。
很多人认为 RAG 的瓶颈在 LLM,其实企业项目中,真正决定效果的往往是数据工程,而不是模型工程。
一个成熟的 RAG 系统,大部分工作其实都花在这些地方:
- 文档清洗(去除广告、目录、重复内容)
- Chunk 切分策略设计
- Embedding 模型选择
- 向量数据库索引优化
- 检索召回(Recall)优化
- 重排序(Rerank)优化
- Prompt 模板设计
而 LLM 只是整个流水线的最后一步。
这也是为什么现在 AI 圈越来越强调 Context Engineering(上下文工程) ------决定 AI 回答质量的,不只是模型本身,更是你提供给它的上下文质量。
Embedding 到底是什么?为什么要"向量化"?
很多新人第一次看到:
Embedding
完全不知道是什么。
其实非常简单。
可以理解成:
把一句话转换成一串数字。
例如:
csharp
今天吃什么?
↓
[0.13,-0.82,0.91...]
另一句话:
csharp
晚上吃火锅?
↓
[0.12,-0.80,0.92...]
虽然文字不同。
但是数字很接近。
说明:
它们语义相近。
于是,我们就可以通过数字计算:
- 欧氏距离
- 点积
- 余弦相似度(最常见)
其中实际项目里使用最多的是:
Cosine Similarity(余弦相似度)
它判断的是:
两个向量方向是否一致。
而不是长度。
因此特别适合文本。
| 算法 | 特点 |
|---|---|
| 欧氏距离 | 计算真实距离 |
| 点积 | 方向+长度 |
| 余弦相似度 | 只比较语义方向(最常用) |
💡 一句话总结:Embedding 是文本的数字身份证,相似语义会拥有相似向量。
Node 实战:构建自己的本地 RAG
整个项目其实只有三步。
第一步:安装 Embedding 模型
bash
ollama pull nomic-embed-text
这个模型只有一个职责:
把文字转换成向量。
并不会聊天。
安装 SDK:
bash
pnpm i ollama
这样 Node 就可以调用本地模型。
安装向量数据库:
bash
pnpm i vectra
Vectra 是 Node 环境下一个非常轻量的向量数据库,它会直接将数据持久化到本地 JSON 文件中,非常适合学习和小型项目。
为什么不用 MySQL?
因为:
MySQL 擅长:
字符串查询
而向量数据库擅长:
yaml
1536维数字检索
这是完全不同的数据结构。
第二步:把项目文档向量化
例如:
README
API 文档
开发规范
数据库设计
全部读取。
然后:
文本
↓
Embedding
↓
向量
↓
Vectra
以后就不用重复计算了。
第三步:用户提问
用户输入:
登录接口怎么写?
系统会:
生成问题向量
↓
搜索数据库
↓
找到最像的文档
↓
放进 Prompt
↓
LLM 输出答案
整个过程不到几百毫秒。
💡 一句话总结:RAG 的核心就是"文档预处理 + 查询时检索 + 拼接上下文"。
⚠️ 初学者最容易踩的坑
❌ 误区一:RAG 会让模型变聪明
不会。
模型能力一点没变。
只是:
给它更多资料。
❌ 误区二:Embedding 模型就是聊天模型
不是。
Embedding:
负责生成向量。
LLM:
负责回答。
职责完全不同。
❌ 误区三:向量数据库可以代替 MySQL
不能。
两者职责完全不同。
MySQL:
管理业务数据。
向量数据库:
管理语义。
面试高频问题
什么是 RAG?
RAG(Retrieval-Augmented Generation)是一种"检索增强生成"技术,它不会重新训练模型,而是在模型回答前,从知识库中检索最相关的内容作为上下文,再交给 LLM 生成答案,从而提升回答的准确性和时效性。
为什么不用微调?
因为:
- 成本低
- 更新快
- 数据无需重新训练
- 企业可完全本地部署
常见向量数据库有哪些?
学习阶段:
- Vectra
- LanceDB
- Chroma
企业项目:
- Milvus
- Weaviate
- Qdrant
- pgvector(PostgreSQL)
RAG 的优缺点?
优点:
✅ 数据实时更新
✅ 无需重新训练
✅ 企业数据安全
✅ 成本低
缺点:
❌ 检索质量直接影响最终答案
❌ 文档切分(Chunk)策略设计不好,会导致召回效果下降
❌ 向量数据库规模较大时,需要考虑索引和性能优化
总结
RAG 的本质,其实只有一句话:
不要试图让模型记住所有知识,而是在回答之前,把它需要的知识找出来。
随着 AI Agent 的发展,Context Engineering(上下文工程) 正逐渐成为比 Prompt Engineering(提示词工程)更重要的能力。而 RAG,正是上下文工程中最核心、最实用的一项技术。
如果你未来想从事 AI 应用开发,那么理解 RAG 的原理和实现,将会是绕不开的一课。
🗂️ 3 分钟复习速查卡
📌 一句话记忆
- LLM:负责推理和生成答案,但知识来源于训练数据。
- Context Engineering:研究如何为 LLM 组织最有价值的上下文。
- RAG:先检索知识,再生成答案,不重新训练模型。
- Embedding:把文本转换为向量,让计算机理解语义相似性。
- 向量数据库:专门存储和检索向量,支持高效语义搜索。
🧠 RAG 工作流程
text
项目文档
│
▼
Embedding
│
▼
向量数据库
▲
│
用户提问
│
▼
Embedding
│
▼
相似度检索
│
▼
拼接 Prompt
│
▼
LLM 输出
🚀 面试口诀
"文档先向量化,查询做召回;拼接 Prompt 给模型,不训练也会答。"