第十一章 向量数据库与RAG¶
导读¶
LLM 有知识截止日期、可能幻觉、不知道企业私有数据。RAG(Retrieval-Augmented Generation,检索增强生成) 是工程上最有效的解决方法:先检索相关文档片段,再让 LLM 基于片段回答。本章解释 embedding 模型、ANN 索引(HNSW/IVF)、RAG 完整流水线、常见失败模式。
11.1 为什么需要 RAG¶
LLM 直接生成有三个问题:
| 问题 | 例子 |
|---|---|
| 知识截止 | "2024 年的财报数据" → 模型预训练截止 2023 |
| 幻觉 | 编造不存在的产品名 / API |
| 私有数据 | "我们公司的报销流程" → 模型从没见过 |
RAG 思路:先检索,再生成——把相关片段塞进 prompt,让模型"看着"答案生成。
11.2 Embedding 模型¶
把文本映射到稠密向量,让"语义相似"="向量相近"。
from sentence_transformers import SentenceTransformer
model = SentenceTransformer('BAAI/bge-m3')
embeddings = model.encode(["你好", "hello", "再见"]) # [3, 1024]
similarity = embeddings @ embeddings.T # 余弦相似度矩阵
主流 embedding 模型:
| 模型 | 维度 | 特点 |
|---|---|---|
| OpenAI text-embedding-3-large | 3072 | 通用强 |
| BAAI bge-m3 | 1024 | 多语言、开源、强 |
| Qwen3-Embedding | 多档 | 阿里出品,中文强 |
| Cohere embed-v3 | 1024 | 商用稳定 |
| nomic-embed-text | 768 | 完全开源 |
关键指标:MTEB(Massive Text Embedding Benchmark)榜单。
11.3 相似度度量¶
| 度量 | 公式 | 用途 |
|---|---|---|
| 余弦相似度 | $\frac{a \cdot b}{ | a |
| 内积(dot product) | \(a \cdot b\) | 已归一化时等价余弦 |
| L2 距离 | \(\sqrt{\sum (a_i - b_i)^2}\) | 归一化后等价余弦 |
Embedding 必须先归一化(L2 norm)——很多模型默认不归一化,需手动 v / v.norm()。
11.4 ANN 索引¶
向量库的核心难题:N 个向量中找 Top-K 最相似——暴力 O(N·d)。当 N = 10M+ 时不可行。
近似最近邻(Approximate Nearest Neighbor, ANN) 用空间结构加速,换取少量召回率损失。
HNSW(Hierarchical Navigable Small World)¶
- 多层图结构,上层稀疏(入口)、下层密集(所有节点);
- 查询从顶层入口贪心走向更近邻居;
- 逐层下钻,最终在底层完成 ef × k 邻域搜索;
- 复杂度 O(log N),召回率 95%+;
- 主流实现:FAISS、HNSWLIB、Milvus、Qdrant、Weaviate、pgvector。
IVF(Inverted File)¶
- 用 K-means 把向量空间聚类;
- 查询时只搜最近的 nprobe 个簇;
- 比 HNSW 简单,但召回率略低;
- 适合超大规模(10亿+ 向量)。
其他¶
| 方法 | 特点 |
|---|---|
| LSH | 早期,质量一般 |
| Annoy | 树结构,静态数据 |
| ScaNN | Google,质量与速度平衡好 |
| DiskANN | 大规模磁盘索引 |
11.5 向量数据库¶
主流向量库:
| 名称 | 类型 | 特点 |
|---|---|---|
| FAISS | 库 | NVIDIA 出品,本地、最快 |
| Milvus | 服务 | 国产、分布式、企业级 |
| Qdrant | 服务 | Rust 写,快 |
| Weaviate | 服务 | 模块化、GraphQL |
| pgvector | PostgreSQL 扩展 | 复用现有 PG |
| Pinecone | SaaS | 全托管 |
| Chroma | 嵌入式 | 原型首选 |
| LanceDB | 嵌入式 | 多模态 |
选型决策:
- 原型 → Chroma 或 LanceDB;
- 已有 PostgreSQL → pgvector;
- 大规模生产 → Milvus / Qdrant;
- 不想运维 → Pinecone。
11.6 RAG 完整流水线¶
离线索引构建¶
- 文档加载:PDF / Word / HTML / Markdown 等,需 OCR / 解析;
- 分块(Chunking):切 500-1000 字符,重叠 50-100;
- Embedding:每块算向量;
- 入库:向量 + 元数据(来源、页码)一起存。
在线查询¶
- 用户问题 Embedding:用同一模型;
- 向量检索 Top-K:K 通常 5-20;
- Rerank(可选):cross-encoder 重排;
- 拼 prompt:
"依据以下片段:{context}\n问题:{question}"; - LLM 生成:要求引用片段;
- 返回答案 + 引用。
11.7 分块策略¶
分块是 RAG 质量的关键变量:
| 策略 | 说明 | 适合 |
|---|---|---|
| 固定长度 | 每 N 字符切 | 简单,通用 |
| 句子级 | NLTK / spacy 切句 | 短文档 |
| 递归切分 | LangChain RecursiveCharacterTextSplitter |
主流默认 |
| 语义切分 | 用 embedding 相似度切 | 长文档,质量高 |
| 文档结构 | 按 Markdown 标题 / 代码函数 | 结构化文档 |
重叠:相邻块重叠 50-100 字符,避免句被切两半。
chunk size trade-off:
- 小(200):精确匹配,但可能丢上下文;
- 大(1000):上下文足,但召回泛化;
- 实践:500-1000 字符 + 100 重叠是常见起点。
11.8 检索质量优化¶
Hybrid 检索¶
向量检索(语义)+ BM25(关键词)取长补短:
适合:含专有名词、产品代码、API 名等关键词的场景。
Rerank¶
检索召回 Top-K(大)后用 cross-encoder 重排:
# Cross-encoder: (query, doc) → score
# 比双塔(query embedding + doc embedding)精确,但慢
# 用法:先向量召回 Top-50, rerank 取 Top-5
主流 rerank 模型:bge-reranker、Cohere rerank-3、Jina rerank。
多查询与查询重写¶
- HyDE:先让 LLM 假设答案,用假设答案做 query 检索;
- Multi-query:LLM 生成多个变体 query,并行检索后融合;
- Step-back:先问更抽象的问题。
11.9 RAG 失败模式¶
| 失败 | 表现 | 对策 |
|---|---|---|
| 检索召回低 | 答非所问 | 调 chunk、加 BM25、调 K |
| 切块切碎语义 | 句被切两半 | 重叠、语义切分 |
| 召回但 LLM 不用 | 仍幻觉 | prompt 强化"依据以下"、Citation |
| 召回错误 | 引用无关片段 | rerank、HyDE |
| 上下文超窗口 | 截断丢信息 | 上下文压缩、长上下文模型 |
| 引用幻觉 | 编造引用 | 强制 cite chunk id |
11.10 评测¶
RAGAS 框架,四个维度:
| 指标 | 含义 |
|---|---|
| Faithfulness | 答案是否忠于检索片段(防幻觉) |
| Answer Relevancy | 答案是否切题 |
| Context Precision | 检索片段是否相关 |
| Context Recall | 是否召回所有需要的片段 |
业务自建评测集:人工标 50-200 个 (question, golden_answer, golden_contexts) 三元组。
11.11 进阶 RAG¶
| 方案 | 思路 |
|---|---|
| GraphRAG | 用知识图谱做检索(Microsoft 提出) |
| Self-RAG | 模型自决定是否检索 |
| Adaptive RAG | 按问题难度动态调整检索策略 |
| Multi-hop RAG | 多次检索 + 推理 |
| RAG-Fusion | 多 query 结果 RRF 融合 |
| Long-context RAG | 用长上下文模型塞所有片段 |
11.12 RAG vs 长上下文 vs 微调¶
| 方案 | 优势 | 劣势 |
|---|---|---|
| RAG | 知识可即时更新、可引用 | 检索可能丢信息 |
| 长上下文(128K+) | 无检索损失 | 成本高、长尾丢失 |
| 微调 | 风格 / 任务适配 | 知识固化、不可即时更新 |
现代趋势:长上下文 + RAG 结合——长上下文塞召回片段,规避两者短板。
工程实战要点¶
- chunk size 是头号超参:业务上一定要调;
- 重叠避免切句:默认 100 字符重叠;
- Embedding 模型与业务对齐:中文用 bge-m3 / Qwen3;
- Hybrid 检索(向量+BM25) 大多数业务比纯向量好;
- Rerank 提升 precision 但加延迟,按业务需求权衡;
- Citation 是工程难点:让 LLM 输出
[chunk_id]引用; - 业务自建评测集必跑:通用 benchmark 不能反映真实质量;
- 长上下文不是万能药:长 ctx 仍有 needle-in-haystack 长尾丢失。
小结¶
- RAG = 检索 + 生成,解决知识截止、幻觉、私有数据三大问题;
- Embedding 模型把文本映射到稠密向量,余弦相似度衡量语义相近;
- ANN 索引(HNSW/IVF)加速近似最近邻搜索;
- 向量库:FAISS(库)、Milvus/Qdrant(服务)、pgvector(PG 扩展)、Chroma(原型);
- RAG 流水线:分块 → embedding → 入库 → 检索 → rerank → 拼 prompt → LLM 生成;
- Hybrid 检索 + Rerank 是质量关键;
- RAGAS 评测:Faithfulness、Answer Relevancy、Context Precision/Recall;
- 长上下文与 RAG 互补,不是替代。
练习题¶
- RAG 解决了 LLM 的哪三个核心问题?
- 解释 HNSW 为什么能做到 O(log N) 检索。
- chunk size 太小或太大各有什么问题?
- Hybrid 检索(向量 + BM25)相对于纯向量的优势是什么?
- Rerank 为什么通常用 cross-encoder 而非双塔?
- 写出 RAGAS 的四个评测维度。
- 一个 RAG 系统 faithfulness 低,可能是什么原因?怎么修?
- 长上下文模型能完全替代 RAG 吗?为什么?
下一章:第十二章 模型服务系统