RAG 检索增强生成实战:让大模型"读懂你的私有数据"
RAG 检索增强生成实战:让大模型“读懂你的私有数据”
大模型的知识有截止日期,也看不到你的公司内部文档、代码仓库、客服记录。直接问它“我们产品的退款政策是什么”,它只能瞎编。RAG(Retrieval-Augmented Generation,检索增强生成) 就是解决这个问题的标准方案:先去知识库里“查”,再把查到的内容“喂”给模型去“答”。
一、RAG 全链路
知识库文档
│
▼
切分 Chunking ──▶ Embedding 向量化 ──▶ 存入向量库
│ ▲
│ │ 检索
用户提问 ──▶ Embedding ──▶ 相似度召回 TopK ─┘
│
▼
重排 Rerank(可选)
│
▼
拼成 Prompt:上下文 + 问题 ──▶ 大模型生成答案
一句话:离线建库,在线检索,检索结果当上下文。
二、四个关键环节
1. 切分(Chunking)
把长文档切成片段。常见策略:
- 固定长度(如 500 字 + 50 字重叠):简单,但可能切断语义。
- 递归切分(按段落→句子→词逐级切):最常用,尽量保留结构。
- 语义切分(按标题/分隔符):对技术文档最友好。
重叠(overlap)很关键——避免一句话被切两半导致检索不到。
2. Embedding
把文本变成高维向量。选型要点:
- 维度:768 / 1024 / 1536 不等,维度越高通常越准但也越占空间。
- 中英文:优先选在中文语料上训练过的模型(如 bge、m3e、智源系列),别用纯英文模型硬上中文。
- 查询与文档用同一模型:否则向量空间不一致,相似度没有意义。
3. 向量库
| 方案 | 特点 | 适合 |
|---|---|---|
| pgvector | 复用 PostgreSQL,运维简单 | 已有 PG、数据量中小的团队 |
| Milvus | 专为向量设计,分布式 | 海量、高并发 |
| Chroma | 轻量、嵌入式 | 原型、单机 |
4. 重排(Rerank)
向量召回是“粗筛”,经常把字面相近但语义无关的排前面。加一层交叉编码器重排(如 bge-reranker)能显著提升精度——先用向量召回 Top50,再重排取 Top5。
三、最小可运行实现
下面用伪向量库演示核心逻辑(真实项目换成 pgvector 即可):
import numpy as np
# 用随机向量假装是 Embedding(真实用 bge/m3e 模型)
def embed(text: str) -> np.ndarray:
np.random.seed(hash(text) % (2**32))
return np.random.rand(768)
chunks = [
"退款政策:购买后 7 天内未拆封可申请全额退款。",
"公司 WiFi 密码是 aibycode-2026,请勿外传。",
"Agent 是能自主调工具完成任务的系统。",
]
index = [(c, embed(c)) for c in chunks]
def retrieve(query: str, top_k=1):
q = embed(query)
scored = [(c, float(np.dot(q, v))) for c, v in index]
scored.sort(key=lambda x: x[1], reverse=True)
return [c for c, _ in scored[:top_k]]
answer_ctx = retrieve("怎么退款?")[0]
print("召回片段:", answer_ctx)
# 把 answer_ctx 拼进 Prompt 交给大模型即可
四、常见陷阱
- Chunk 太大:一个 chunk 塞进整篇文档,检索命中但噪声太多,模型反而答不准。
- 召回率低:Embedding 模型与语料不匹配(英文模型上中文),或没做重排。
- 上下文污染:把 20 个不相关 chunk 全塞进 Prompt,稀释了真正相关的信息。
- 知识过期:建库后文档更新了,索引没重建,模型仍引用旧内容。
- 过度依赖检索:RAG 不保证 100% 准确,关键业务必须让模型标注“来源片段”以便人审。
经验法则:RAG 的上限 = 检索质量。检索做不好,模型再强也白搭。
下一篇我们聊如何把“工具”喂给模型——Function Calling 的工程化封装。