RAG 检索增强生成
模型不知道你公司的内部文档,也记不住昨天刚更新的数据。RAG(Retrieval-Augmented Generation,检索增强生成)就是解决这个问题的主流方案:先检索相关资料,再让模型基于资料作答。这篇讲清楚它的原理、流程和落地要点。
为什么需要 RAG
直接问大模型私有或最新知识,会遇到两个问题:
- 不知道:训练语料里没有你的内部资料。
- 会瞎编:不知道又被追问时,模型容易「一本正经地胡说」(幻觉)。
RAG 的思路很朴素:把答案的依据先找出来,塞进提示词,再让模型照着资料回答,并要求它只依据给定资料。这样既补上了知识,又能附带引用、降低幻觉。
相比微调(fine-tuning),RAG 的资料可以随时更新、成本低、可溯源,是「让模型用上自有知识」的首选;微调更适合改变模型的风格或能力,而非灌输事实。
整体流程
RAG 分成离线的「建库」和在线的「问答」两段:
建库(离线):
文档 ──切块──► chunks ──向量化──► embeddings ──存入──► 向量数据库
问答(在线):
用户问题 ──向量化──► 在向量库里检索最相似的 chunks
└──► 把 chunks + 问题拼成提示词 ──► 大模型生成带依据的回答核心是用向量表示语义:把文本通过 embedding 模型转成一串数字(向量),语义相近的文本向量距离也近。检索时算「问题向量」和「文档向量」的相似度,取最近的几条。
关键步骤拆解
1. 切块(Chunking)
整篇文档太大,要切成小块再向量化。切块质量直接影响检索效果:
- 块太大:噪声多、容易超出上下文、检索不精准。
- 块太小:语义被切碎、丢失上下文。
- 经验值:每块几百 token,块之间留一点重叠(overlap),避免把一句话从中间切断。
- 尽量按语义边界切(段落、标题、章节),别机械按固定字数。
2. 向量化与存储
用 embedding 模型把每个 chunk 转成向量,连同原文一起存进向量数据库(如 pgvector、Milvus、Qdrant 等),由它负责高效的相似度检索。
3. 检索与拼接提示词
把用户问题也向量化,检索出 Top-K 个最相关的 chunk,拼进提示词。下面用伪代码表示这一步,再调用 Claude 生成:
from anthropic import Anthropic
client = Anthropic()
def answer(question: str) -> str:
# 1) 检索:从向量库取回最相关的若干片段(此处为示意)
chunks = vector_store.search(embed(question), top_k=4)
context = "\n\n---\n\n".join(c.text for c in chunks)
# 2) 把资料作为依据拼进提示词,并约束「只依据资料作答」
system = (
"你是企业知识库助手。只依据 <资料> 中的内容回答;"
"资料里没有的,就明确说「资料中未提及」,不要编造。"
)
user = f"<资料>\n{context}\n</资料>\n\n问题:{question}"
resp = client.messages.create(
model="claude-opus-4-8",
max_tokens=1024,
system=system,
messages=[{"role": "user", "content": user}],
)
return resp.content[0].text务必在
system 里强约束「只依据资料作答、缺失就说没有」,这是 RAG 降低幻觉、获得可信回答的关键一句。落地时的常见坑
- 检索不到 = 答不对:效果差先别怪模型,多半是切块或检索环节没召回正确资料。先单独评估「检索命中率」。
- 重排序(Rerank):向量检索召回后,再用一个更精细的 rerank 模型对 Top-K 排序,能明显提升相关性。
- 评估要分两层:分别评「检索质量」(有没有找到对的资料)和「生成质量」(基于资料答得对不对),别混在一起看。
- 附上引用:让模型标注每条结论来自哪个片段,方便用户核对,也利于排查。
一句话小结
RAG = 先检索、再生成。它让模型用上你的私有与实时知识,且可溯源、易更新。做好它的关键不在调模型,而在切块、检索与「只依据资料作答」这条硬约束。
最后更新于