RAG 检索增强生成

前两篇是"检索"侧的原理,这一篇把 RAG 全流程串起来——这是向量数据库目前最大的应用场景。附一个照官方文档写的最小可跑示例(我没有实际跑过,跑的时候按报错修)。

RAG 到底在解决什么问题

大模型两个硬伤:知识有截止日期没见过你的私有数据;硬问它就编(幻觉)。RAG 的思路很朴素:回答之前,先去向量库里把相关资料检索出来,塞进 prompt 让模型"开卷考试"

好处:知识随时可更新(重新入库即可)、答案可溯源(能给引用)、私有数据不出库。

完整流水线

离线入库:加载文档 → 清洗 → 切块 → embedding 模型转向量 → 存入向量库(元数据一起存)
在线查询:用户提问 → 同一模型转向量 → ANN 检索 top K → (rerank 精排) → 拼进 prompt → LLM 生成答案

对应到工程组件:加载/切块用 LangChain 的 splitter 或自己写;embedding 用 bge 系或 API;向量库按概览篇的选型直觉(学习用 Chroma);编排 LangChain / LlamaIndex,或干脆手写——书里的观点是:最小 RAG 手写百来行就够,先跑通再上框架,框架的黑盒会掩盖原理。

最小可跑示例(照官方文档写的,未实测)

目标:Chroma(内嵌模式,零部署)+ bge 中文模型,存三条笔记然后按语义检索。

pip install chromadb sentence-transformers
from chromadb import PersistentClient
from sentence_transformers import SentenceTransformer

# bge 中文模型,首次运行会自动下载(约 1.3GB)
model = SentenceTransformer("BAAI/bge-large-zh-v1.5")

# 内嵌模式:数据落在本地目录,零部署;持久化后重启可读回
client = PersistentClient(path="./chroma_data")

# 建集合:显式指定余弦度量(Chroma 默认 L2,归一化向量下两者等价,但显式更稳)
col = client.get_or_create_collection("notes", metadata={"hnsw:space": "cosine"})

docs = [
    "SQLite 的 WAL 模式解决 database is locked 问题",
    "Redis 的 SET 命令加 NX 和 EX 可以做简易分布式锁",
    "MySQL 的 InnoDB 用 B+ 树组织索引",
]
emb = model.encode(docs, normalize_embeddings=True)
col.add(ids=["n1", "n2", "n3"], embeddings=emb.tolist(), documents=docs)

# 查询:语义找,字面完全不同也能命中
q = model.encode(["redis 怎么实现锁"], normalize_embeddings=True)
res = col.query(query_embeddings=q.tolist(), n_results=2)
print(res["ids"], res["documents"])   # 期望 n2 排第一

我标注过的两个核对点:①Chroma 新版 API 建集合的参数写法有变动,以当时官方文档为准;②模型首次下载需要网络,离线环境要提前缓存。

检索不准的排查清单(书里观点的汇总)

效果差时按顺序查,从数据侧往参数侧

  1. 切块:是不是把主题切碎了/块太大稀释了语义?(最大嫌疑,回 02 篇)
  2. 模型域匹配:query 和文档是否同一模型?中文场景有没有用中文榜上像样的模型?bge 的指令前缀加了没?
  3. 度量与归一化:建库时的度量方式、向量有没有归一化、是否不同批次模型混库
  4. 检索参数:top_K 给多少(先 50 再 rerank 到 5)、ef_search/nprobe 是否给得太小
  5. query 本身:口语化问句是否需要改写(把"这玩意咋弄"改写成关键词式)——进阶做法叫 query rewriting

还有一个反直觉的忠告:库查不到就拒答,比检索分数垫底还硬塞给模型编答案强——给检索结果设个相似度阈值,低于阈值直接回"资料里没有"。

进阶名词速记(知道是什么,不展开)

  • 混合检索:BM25 关键词检索 + 向量语义检索各跑一路,RRF 融合——专有名词、型号、代码类查询关键词路线反而强
  • 父子块:小块检索、大块喂模型(02 篇提过)
  • GraphRAG:把实体关系抽成图谱再检索,适合"多跳关联"的问题——名词先记着
  • 评估:构造一组"问题 → 期望命中的文档"测试集,算命中率(hit rate)和 MRR——朴素起步够用,别上来就上 RAGAS

⬅️ 02-Embedding 模型与文本切块 🏠 00-数据库 ➡️ Alembic