---
layout: post
title: 「JS全栈 AI Agent 学习」RAG篇①：先翻书，再答题——RAG 是什么？
date: 2026-03-23
---

> 🗺️ **「全栈 AI Agent 学习」系列**
>
> | 篇                 | 主题                                 | 状态 |
> | ------------------ | ------------------------------------ | ---- |
> | 第一篇             | 提示链 · 路由 · 并行化               | ✅   |
> | 第二篇             | 反思 · 工具使用 · 规划               | ✅   |
> | 第三篇             | 多智能体 · 记忆管理 · 学习适应       | ✅   |
> | **RAG篇①（本篇）** | **RAG 是什么？核心概念与完整流程**   | ✅   |
> | RAG篇②             | RAG 怎么做？从切片到向量检索         | 🔜   |
> | RAG篇③             | RAG 怎么做好？意图、重排序与答案质量 | 🔜   |

---

## 写在前面

学 RAG 之前，我一直有一个困惑——

AI 明明很聪明，为什么问它公司内部的事，它会一本正经地胡说八道？

问它："我们公司的年假政策是什么？"

它回答得条理清晰，自信满满，但你一核对——**完全是编的**。

不是它坏，是它根本没见过你们公司的《员工手册》。
它只能凭训练时见过的"一般公司的年假政策"来猜，
结果就是那种**一本正经的胡说八道**。

RAG 就是为了解决这个问题而生的。

这一篇，我想把 RAG 的核心概念和完整流程说清楚——
不堆术语，从一个具体的例子走一遍，走完你就懂了。

---

## 一、RAG 是什么？

RAG = **Retrieval-Augmented Generation**，检索增强生成。

用大白话说：**先去翻书，再回答问题。**

对比一下两种模式：

```
传统 AI（纯靠记忆）：
用户提问 → AI 凭训练数据回答 → 容易瞎编

RAG（先检索再回答）：
用户提问 → 去知识库里翻相关内容 → 把找到的内容给 AI → AI 根据这些内容回答
```

就像考试：

- 传统 AI = **闭卷考试**，全凭记忆，记不住就瞎编
- RAG = **开卷考试**，可以翻书，答案有依据

这个类比很准，但还不够完整——
开卷考试里，你还需要知道**去哪一页翻**，不能把整本书从头读到尾。

这就是 RAG 有意思的地方：它不只是"给 AI 一本书"，
而是**先精准找到相关的那几段，再给 AI 看**。

---

## 二、为什么需要 RAG？

先说 LLM 的天然局限：

| 问题           | 原因                               |
| -------------- | ---------------------------------- |
| 不知道私有信息 | 你的简历、公司文档，它从没见过     |
| 知识有截止日期 | 训练数据有时间限制，新的事它不知道 |
| 容易"幻觉"     | 不知道的事，它会猜，还猜得很自信   |
| 无法引用来源   | 说不清楚答案从哪来的               |

RAG 解决的，正是这几个问题：

- ✅ 让 AI 能访问私有知识（你的简历、公司文档、产品手册……）
- ✅ 答案有依据，可以显示来源
- ✅ 不会凭空编造，只根据检索到的内容回答
- ✅ 知识库随时可以更新，不需要重新训练模型

---

## 三、RAG 完整流程拆解

我用一个具体例子，带你走一遍完整流程。

### 场景设定

假设公司有一份《员工手册》，里面写着：

- "正式员工每年享有 10 天带薪年假"
- "工龄满 3 年后增加至 15 天"
- "年假有效期为当年 1 月 1 日至 12 月 31 日"

用户问：**"我入职 2 年了，今年还剩几天假？"**

RAG 是怎么处理的？

---

### 第 1 步：用户提问

用户输入一句普通的中文：

```
"我入职 2 年了，今年还剩几天假？"
```

这一步没什么特别的，但它是整个链路的起点。

---

### 第 2 步：问题向量化（Embedding）

**谁在干活？** Embedding 模型（注意：不是 LLM！）

**干什么？** 把文字变成数字坐标。

```
"我入职 2 年了，今年还剩几天假？"
    ↓ Embedding 模型处理
[0.23, 0.81, -0.45, 0.67, ..., 0.52]
```

这串数字就是**向量**，可能有几百个维度。

#### 为什么要变成数字？

计算机不懂"年假"是什么意思，但它会算数。

把文字变成坐标之后，**意思相近的文字，坐标也会靠得很近**。

就像地图：

- "北京"和"天津"的坐标很近（都在华北）
- "北京"和"拉萨"的坐标很远

在语义空间里也一样：

- "年假政策"和"带薪休假"的坐标很近（说的是同一件事）
- "年假政策"和"公司成立时间"的坐标很远（完全不相关）

这个"把文字变成可以计算的坐标"的过程，是整个 RAG 系统的核心。
一旦文字变成了数字，计算机就能计算距离，就能判断相似度。

---

### 第 3 步：向量检索

**谁在干活？** 向量数据库

**干什么？** 在知识库里找**语义最接近**的内容。

#### 知识库是怎么准备的？

《员工手册》早就被切成了很多小块（这个过程叫 **Chunking**），
每块都有自己的坐标：

```
块1："正式员工每年享有10天带薪年假，工龄满3年后增加至15天..."
    → [0.21, 0.79, -0.43, 0.65, ...]

块2："年假有效期为当年1月1日至12月31日，逾期作废..."
    → [0.25, 0.83, -0.47, 0.69, ...]

块3："公司成立于2010年，总部位于北京..."
    → [0.88, 0.12, 0.34, -0.21, ...]
```

#### 计算距离，找出最相关的

向量数据库把用户问题的坐标和每个块的坐标进行比较：

```
用户问题：[0.23, 0.81, -0.45, 0.67, ...]

块1：[0.21, 0.79, -0.43, 0.65, ...] → 距离 0.02 ✅（很近！）
块2：[0.25, 0.83, -0.47, 0.69, ...] → 距离 0.05 ✅（也近）
块3：[0.88, 0.12, 0.34, -0.21, ...] → 距离 0.89 ❌（太远）
```

最终选出 Top 2：块1 和 块2。

#### 关键点：这不是关键词匹配

注意：用户问题里**没有"带薪"这个词**，但依然能检索到"带薪年假"的内容。

为什么？因为 Embedding 模型理解了**语义**：

- "我入职 2 年了，今年还剩几天假"
- "正式员工每年享有 10 天带薪年假"

虽然用词不同，但**在说同一件事**，所以向量距离很近。

这就是 RAG 比传统关键词搜索强的地方——
不是找"有没有这个词"，而是找"说的是不是同一件事"。

---

### 第 4 步：构造增强 Prompt

**谁在干活？** RAG 系统（这一步用户完全看不到）

**干什么？** 把检索结果 + 用户问题，组合成一个新的 Prompt。

实际发给 LLM 的 Prompt 长这样：
