跳到主要内容

附录 · 实战路线

学完 RAG 的每一个零件,最好的收尾是亲手搭一个。这个附录给你四样东西:一段能跑的最小 RAG、一张选型地图、一份避坑清单,以及中篇的结语。

一、不到 100 行搭一个 RAG(不依赖任何框架)​

中篇反复强调:RAG = 检索 + 增强 + 生成,框架只是把这三步包了层糖。下面这段代码把糖撕掉,让你看清骨头——它把 K0~K5 学的东西全串了起来。

运行前提

需要 Python 3.10+、一个嵌入模型和一个对话模型(把接口换成你自己的即可——各家云服务、本地部署都行)。这段代码用于教学,省略了生产必需的持久化、批处理、错误处理和评测。

"""一个不依赖任何 RAG 框架的最小实现:切块 → 嵌入 → 检索 → 增强 → 生成。"""
import numpy as np
from openai import OpenAI

client = OpenAI(base_url="https://your-endpoint/v1", api_key="YOUR_KEY")
EMBED_MODEL = "your-embedding-model"
CHAT_MODEL = "your-chat-model"

# ---- 0. 你的知识库(真实场景是一堆文档,这里用几段话示意)----
DOCS = [
"本店支持七天无理由退货,需保持包装完好,生鲜类除外。",
"会员退货免运费由本店承担,非会员需自付 10 元退货运费。",
"普通快递 3-5 天送达,偏远地区顺延;付费加急可次日达。",
"黑卡会员享全场 95 折、专属客服和生日礼券。",
]

def embed(texts: list[str]) -> np.ndarray:
"""把文本变成向量(K1 语义检索的地基)。"""
resp = client.embeddings.create(model=EMBED_MODEL, input=texts)
return np.array([d.embedding for d in resp.data])

# ---- 1. 建库:切块 → 嵌入 → 存起来(离线做一次,K2 + K1)----
# 真实场景这里要按 K2 的策略切块;示意起见,一段话就是一个块
CHUNKS = DOCS
CHUNK_VECS = embed(CHUNKS) # 预先算好文档向量,检索时不用重算
CHUNK_VECS /= np.linalg.norm(CHUNK_VECS, axis=1, keepdims=True) # 归一化,点积=余弦

# ---- 2. 检索:把问题变向量,找最相似的 k 段(K1 语义检索)----
def retrieve(question: str, k: int = 2) -> list[str]:
qv = embed([question])[0]
qv /= np.linalg.norm(qv)
sims = CHUNK_VECS @ qv # 余弦相似度(K1 深入层)
top = np.argsort(sims)[::-1][:k] # 取最相似的 k 个
return [CHUNKS[i] for i in top]
# 进阶:这里可换成混合检索(K3)+ 重排(K4),检索质量会明显提升

# ---- 3. 增强 + 生成:拼进提示词,让模型照着答、标出处(K5)----
def rag(question: str) -> str:
chunks = retrieve(question)
context = "\n".join(f"[{i+1}] {c}" for i, c in enumerate(chunks))
prompt = (
f"参考资料:\n{context}\n\n"
f"请仅根据以上资料回答,并在每句话后标注来源编号 [n];"
f"资料未提及的,回答「资料未提及」。\n\n问题:{question}"
)
resp = client.chat.completions.create(
model=CHAT_MODEL,
messages=[{"role": "user", "content": prompt}],
)
return resp.choices[0].message.content

if __name__ == "__main__":
print(rag("退货要自己付运费吗?"))
# 期望:会员免运费、非会员自付 10 元 [2]

它凭什么算一个 RAG? 因为「检索 → 增强 → 生成」三步齐了:retrieve 把问题变向量找最相似的块(K1),rag 把块拼进提示词并要求照资料答、标出处(K5)。你在 K5 全流程动画里看到的一切,就发生在这几十行里。

接下来自己动手加东西,正好对应中篇各章:

  • 把 CHUNKS = DOCS 换成真正的切块逻辑(按标题/滑窗)→ K2 切块;
  • 给 retrieve 加一路 BM25、用 RRF 融合 → K3 混合检索;
  • 召回 20 条、再用重排模型选前 3 → K4 重排;
  • 把 CHUNK_VECS 那个 numpy 数组换成真正的向量库 → K1.2 向量数据库;
  • 写个评测集,跑一遍 RAG 三元组 → K6 评测。

二、向量库与框架地图​

自己手写够学习,生产项目通常会用工具处理持久化、扩展、并发。2026 年的主流选择:

类别选项一句话定位
专用向量库Milvus / Qdrant / Weaviate为向量检索而生,扛得住亿级规模、功能全
数据库的向量扩展pgvector(Postgres)/ Elasticsearch已经在用这些库?加个向量能力,省一套新系统
RAG 框架LangChain / LlamaIndex把切块、检索、生成的胶水都封好,快速起步
一体化/托管各云厂商的知识库服务不想自己搭,上传文档就能问
选型心法

和下篇的框架建议一样:先用上面这段代码把原理跑通,再带着「我到底需要工具替我做哪些活」去选——而不是被某个框架的抽象牵着理解 RAG。所有框架的内核,都是你已经读懂的「检索→增强→生成」。(本表整理于 2026 年,生态演进快,以官方文档为准。)

三、避坑清单​

按中篇的章节顺序,把最常见的坑收成一张速查表:

环节常见坑对策
切块(K2)切太大重点被稀释、切太小事实被切断让每块=一个完整意思;配 overlap;拿真实查询调 chunk size
检索(K1/K3)只用语义,漏掉精确词(型号、编号)上混合检索 + RRF;精确词场景别丢了关键词检索
重排(K4)只信召回第 1 名,被「李鬼」带偏加一层交叉编码器精排;召回宁滥勿缺
生成(K5)模型不照资料答、或复述丢条件提示词说死「只根据资料答」;强制引用;关键条件原样保留
评测(K6)凭手感调参、不知道病根在哪建评测集、跑 RAG 三元组、按失败模式分桶
权限(K8.1)把「不要透露机密」写进提示词当权限控制权限进检索条件(pre-filter),别用检索后过滤
更新(K8.2)以为换嵌入模型可以「新旧混用慢慢过渡」向量必须同源;全库重建用双写切换;删除要同步两套索引
投毒(K8.3)只审入库文档,以为守住入口就安全假设有毒文档会进来:最小权限 + 强制引用 + 固定问答回归测试
源头知识库本身过时/错误(垃圾进垃圾出)数据治理:去重、标时效、定期更新

四、常用默认值起点表​

正文反复说「拿真实查询调参」——但总得有个起点。下面是业界常用的起点值(2024-2026),照着开工、再用 K6 评测往你自己的数据上调:

参数常用起点什么时候调
chunk size(块大小)256512 token(约 300500 汉字)事实密集/短问答→调小;需要长上下文连贯→调大
overlap(重叠)块大小的 10~20%事实常跨块被切断→调大;冗余存储吃紧→调小
召回 top-k(第一阶段)50~200 条召回率不够(真答案没进池)→调大
精排后保留3~10 条上下文预算紧/噪声多→调小
RRF 常数 k60一般不用动,是经验默认值
embedding 维度768 / 1024 / 1536 量级由你选的嵌入模型决定,不是自己拍
相似度阈值视模型而定,常用 0.7 上下宁可先不设阈值、靠 top-k 截断,避免误杀
这些是起点,不是答案

表里每个数字都强依赖你的文档类型、查询类型、嵌入模型——照搬别人的配置往往水土不服。正确用法:以此开工,建一个小评测集(几十条真实问答),跑三元组,看哪个参数拖后腿就调哪个。「评测驱动调参」在 RAG 里不是口号,是唯一靠谱的方法。

五、想继续深入?外部课程索引​

  • CMU 11-642 搜索引擎——从 BM25 到神经检索到 RAG 的学术全景,检索理论最扎实的一门;
  • DeepLearning.AI 的 RAG 系列(Retrieval Augmented Generation、Building and Evaluating Advanced RAG)——动手实现 + 评测,和本篇实践路线互补;
  • RAGAS / TruLens 文档——把 K6 的评测落地到代码。

中篇结语:知识库不是魔法​

还记得 K0 那个「闭卷考试」的比喻吗?走到这里,你已经拆开了一个 RAG 系统的每一个零件:

RAG 不是魔法。它只是给「凭记忆答题」的模型,配了一本可以随时翻的参考书——用检索找到对的那几页(K1~K4),用拼装和引用让它照着答、答必有据(K5),再用三盏灯给整套系统做体检(K6)。

下次你看到一个「能回答公司内部问题」的 AI 助手,你不会再觉得它神秘——你会本能地问:它的知识库怎么切的块?用的语义还是混合检索?有没有重排?答案标不标出处?三元组体检过没有?这些问题,你现在都能自己回答。

三部曲,到此完整​

这也是整套教程的一块拼图归位:

  • 上篇讲清了模型的通用能力从哪来;
  • 中篇讲清了怎么给它接上你的私有知识;
  • 下篇讲清了它怎么自主行动——而其中 A3.3 的 Agentic RAG、K7.2,正是中下两篇交汇的地方:中篇的检索技术 + 下篇的智能体循环 = 会自己查资料、查几轮、边查边想的高阶 RAG。

三卷合起来,是一条从「模型怎么来」到「怎么喂它知识」再到「怎么让它干活」的完整地图。

一起把它变得更好

本教程完全开源。发现错误、有更好的类比、想补一章你熟悉的领域?欢迎到 GitHub 提 Issue 或 PR。愿你带着这份「凡事都想拆开看看」的好奇,用好这个正在被大模型重塑的时代。

——《给 AI 接上你的知识》全篇完