第 16 期:知识即力量 — RAG 架构原理与 Embedding 基础
为什么 Agent 需要 RAG?
大模型有两个致命缺陷:
- 知识截止日期:GPT-4o 只知道 2024 年 10 月之前的事
- 缺乏私有知识:它不知道你公司的产品文档、内部 Wiki、客户数据
graph TB
subgraph "无 RAG 的 Agent"
Q1["用户: AgentUpdate 的退款政策是什么?"]
Q1 --> LLM1["🤖 GPT-4o"]
LLM1 --> A1["抱歉,我不了解 AgentUpdate 的具体政策 ❌"]
end
subgraph "有 RAG 的 Agent"
Q2["用户: AgentUpdate 的退款政策是什么?"]
Q2 --> Search["🔍 从知识库检索
'退款政策.pdf' → 相关段落"]
Search --> LLM2["🤖 GPT-4o + 检索到的上下文"]
LLM2 --> A2["根据我们的政策,购买 30 天内无条件退款... ✅"]
end
style Search fill:#22c55e,stroke:#16a34a,color:#fff
style A2 fill:#22c55e,stroke:#16a34a,color:#fffRAG 的完整流水线
RAG 分为两个阶段:索引阶段 (离线) 和 检索阶段 (在线)。
graph TB
subgraph "阶段 1: 索引 (Indexing) — 离线预处理"
Doc[📄 原始文档
PDF / Markdown / 网页] --> Chunk[✂️ 文档分块
按段落/标题切割]
Chunk --> Embed[🧮 Embedding 模型
文本 → 向量]
Embed --> Store[💾 向量数据库
Qdrant / Pinecone / Supabase]
end
subgraph "阶段 2: 检索 (Retrieval) — 在线查询"
Query[❓ 用户提问] --> QEmbed[🧮 问题 → 向量]
QEmbed --> Sim[📐 向量相似度搜索
余弦相似度 / 内积]
Sim --> TopK["📑 Top-K 最相关段落
(通常 K=3~5)"]
TopK --> Augment[📝 拼接到 Prompt 中]
Augment --> LLM[🤖 LLM 生成回答]
end
style Embed fill:#8b5cf6,stroke:#7c3aed,color:#fff
style Sim fill:#f59e0b,stroke:#d97706,color:#fff
style LLM fill:#ff6d5b,stroke:#e55a4e,color:#fff1. 什么是 Embedding?
Embedding 是将文本转换为**高维向量(数字数组)**的过程。语义相似的文本,向量距离近;语义不同的文本,向量距离远。
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// Embedding 直觉理解
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// 文本: "如何退款?"
// 向量: [0.023, -0.147, 0.892, ..., 0.034] // 1536 维 (text-embedding-3-small)
// 文本: "退货流程是什么?"
// 向量: [0.021, -0.152, 0.889, ..., 0.031] // 与"退款"向量非常接近!
// 文本: "今天天气怎么样?"
// 向量: [0.567, 0.234, -0.102, ..., 0.891] // 与"退款"向量距离很远
// 📏 余弦相似度计算:
// cos("退款?", "退货流程?") ≈ 0.95 → 非常相似 ✅
// cos("退款?", "天气?") ≈ 0.12 → 完全不相关 ❌
Embedding 模型选型
| 模型 | 维度 | 价格 | 特点 |
|---|---|---|---|
text-embedding-3-small (OpenAI) |
1536 | $0.02/1M tokens | 性价比最高 |
text-embedding-3-large (OpenAI) |
3072 | $0.13/1M tokens | 精度更高 |
text-embedding-004 (Google) |
768 | 免费 | Google 生态集成 |
本地: nomic-embed-text (Ollama) |
768 | 免费 | 数据隔离 |
2. 文档分块策略
分块质量直接决定 RAG 的检索效果。
graph TB
subgraph "分块策略对比"
subgraph "❌ 固定字符分块"
FC["每 500 字切一刀
可能从句子中间切断
破坏语义完整性"]
end
subgraph "✅ 语义分块 (推荐)"
SC["按段落/标题层级切割
保持语义单元完整
每块 200-1000 tokens"]
end
subgraph "✅ 递归字符分块"
RC["先按标题 → 段落 → 句子
逐级尝试切割
保证每块不超 1000 tokens"]
end
end
style SC fill:#22c55e,stroke:#16a34a,color:#fff
style RC fill:#22c55e,stroke:#16a34a,color:#fff// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// n8n 中推荐的分块参数
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// Text Splitter 节点配置:
// - Mode: "Recursive Character" // 递归字符分割 (最通用)
// - Chunk Size: 800 // 每块最多 800 字符
// - Chunk Overlap: 200 // 相邻块重叠 200 字符
// ↑ 重叠是关键! 防止关键信息恰好在分割点被切断
// 例: 块 A 最后 200 字 = 块 B 最前 200 字
// 为什么 Chunk Overlap 很重要?
// 原文: "退款须在购买后 30 天内申请。|切割点| 逾期将不予受理。"
// 无重叠: 块1 = "退款须在购买后 30 天内申请。"
// 块2 = "逾期将不予受理。" ← 缺少上文!
// 有重叠: 块1 = "退款须在购买后 30 天内申请。逾期将不予受理..."
// 块2 = "...购买后 30 天内申请。逾期将不予受理。" ← 上下文连贯!
3. 向量数据库选型
| 向量数据库 | n8n 节点 | 部署方式 | 适用阶段 | 免费额度 |
|---|---|---|---|---|
| Qdrant | Qdrant Vector Store | Docker 自建 | 开发/生产 | 自建免费 |
| Pinecone | Pinecone Vector Store | 云服务 | 生产 | 100K 向量 |
| Supabase | Supabase Vector Store | 云/自建 | 全阶段 | 500MB |
| In-Memory | In-Memory Vector Store | n8n 内置 | 仅开发测试 | — |
| PGVector | Postgres + pgvector | 自建 | 已有 PG 时 | 自建免费 |
4. n8n RAG 技术栈全景
graph TB
subgraph "n8n RAG 完整技术栈"
subgraph "文档加载节点"
PDF[📄 Extract from File
PDF / DOCX / CSV]
Web[🌐 HTML Extract
网页爬取]
GD[📁 Google Drive
云端文件]
end
subgraph "处理节点"
Split[✂️ Text Splitter
递归分块]
Meta[⚙️ Set
添加元数据]
end
subgraph "Embedding 节点"
OAI[🧮 OpenAI Embeddings]
GEM[🧮 Google Embedding]
end
subgraph "存储节点"
QD[💾 Qdrant Vector Store]
PC[💾 Pinecone Vector Store]
SB[💾 Supabase Vector Store]
end
subgraph "检索节点"
RT[🔍 Vector Store Tool
Agent 可调用的检索工具]
QA[📋 QA Chain
问答链]
end
PDF & Web & GD --> Split --> Meta --> OAI & GEM --> QD & PC & SB
QD & PC & SB --> RT & QA
end
style Split fill:#f59e0b,stroke:#d97706,color:#fff
style OAI fill:#8b5cf6,stroke:#7c3aed,color:#fff
style QD fill:#22c55e,stroke:#16a34a,color:#fff下一步
在 Ep 17 中,我们将动手搭建一个完整的 Qdrant 向量数据库 + 文档索引管道,把 PDF/Markdown 文档灌入知识库。