AI开发-RAG:让模型回答时先查资料
前言
RAG 是 Retrieval-Augmented Generation 的缩写,直译就是检索增强生成。这个概念这些年很火,但它的基本想法并不复杂:不要让大模型只凭训练参数回答,而是在生成之前先去知识库里检索相关资料,再把资料一起交给模型。
很多企业内部问答、文档助手、代码库问答,本质上都是 RAG。因为这些知识经常更新,而且不一定出现在模型训练数据里。与其每次重新训练模型,不如维护一套可更新的外部知识库。
为什么需要 RAG
大模型擅长语言组织和模式归纳,但它不擅长保证知识一定最新、一定来自某个指定来源。RAG 把外部文档引入生成过程,可以缓解幻觉问题,也能让答案带上出处。
原始 RAG 论文把模型参数里的知识称为 parametric memory,把外部索引里的知识称为 non-parametric memory。这个区分很有用:模型负责理解和表达,知识库负责提供可更新、可追溯的信息。
基本流程
最常见的流程是四步:文档切分、向量化入库、问题检索、带上下文生成。文档切分不要太粗也不要太碎,太粗会把无关内容塞进上下文,太碎又容易丢失完整语义。
检索阶段通常先用向量相似度召回,再用关键词、rerank 或业务规则二次排序。最后把最相关的片段放进 prompt,让模型基于这些片段回答。
开发时容易踩的坑
第一个坑是只关注 embedding 模型,忽略了文档清洗。脏数据、重复段落、标题丢失,会让检索结果很飘。第二个坑是 chunk 设计过于随意,导致召回片段缺上下文。第三个坑是 prompt 没约束好,模型拿不到资料时仍然硬答。
我一般会在 prompt 里明确写:如果资料中没有答案,就回答不知道,并说明缺少什么资料。同时把引用片段 ID 保留下来,方便前端展示出处,也方便调试检索质量。
切片不是随便切
很多 RAG 系统一开始效果差,问题不一定在 embedding 模型,而在文档切片。比如 Markdown 标题丢了,只留下正文,检索结果就会缺少上下文;又比如按固定字数硬切,把一个完整步骤拆成两半,模型拿到的片段自然答不完整。
更稳的做法是保留层级标题,把标题、来源、更新时间一起放进 metadata。技术文档可以按标题、段落和代码块切;制度文档可以按条款切;FAQ 可以一问一答作为最小单元。
{
"id": "blog-rag-001",
"title": "AI开发-RAG:让模型回答时先查资料",
"section": "开发时容易踩的坑",
"content": "第一个坑是只关注 embedding 模型,忽略了文档清洗...",
"metadata": {
"source": "blog",
"url": "/2026/06/20/AI开发-RAG/",
"updated_at": "2026-06-20"
}
}
metadata 不只是附属信息,它会参与过滤和展示。比如用户只想查博客,就用 source 过滤;前端展示答案出处,就用 title 和 url;评估召回质量,也可以根据 section 判断命中的片段是否正确。
一个最小 RAG 示例
下面用 Python 写一个最小流程,省略具体 embedding 服务,只展示工程结构。真正上线时,可以把向量库换成 Milvus、pgvector、Qdrant、Elasticsearch 或云服务。
def retrieve(question, top_k=4):
query_vector = embed(question)
return vector_store.search(query_vector, top_k=top_k)
def build_prompt(question, chunks):
context = "\n\n".join(
f"[{c['id']}] {c['text']}" for c in chunks
)
return f"""你只能根据下面资料回答问题。
如果资料里没有答案,请直接说不知道,并说明缺少什么资料。
资料:
{context}
问题:{question}
回答时请标注引用片段 ID。
"""
def answer(question):
chunks = retrieve(question)
prompt = build_prompt(question, chunks)
return llm.generate(prompt)
这个版本很朴素,但它把关键点放进去了:先检索,再拼上下文,再约束模型必须基于资料回答。很多问题不是靠复杂框架解决的,而是靠这些基础约束一点点收紧。
怎么评估 RAG 好不好
我会把 RAG 评估拆成两层:检索层和生成层。检索层看 top_k 里有没有命中正确片段,常用指标有 recall@k、MRR、nDCG;生成层看答案是否准确、是否忠实于资料、引用是否正确。
cases:
- question: "报销单最晚什么时候提交?"
gold_chunks: ["policy-2026-03"]
expected_keywords: ["7天", "出差结束"]
- question: "博客 Gitalk 初始化脚本做了什么?"
gold_chunks: ["blog-gitalk-init"]
expected_keywords: ["自动初始化", "issue"]
最开始不一定要搭复杂平台,先做几十个手工样本就很有用。改切片、换 embedding、调 rerank 时都跑一遍,系统变好还是变差就不会只靠感觉。
小结
RAG 不是万能补丁,它更像一个工程化套路:把可变知识交给外部检索,把语言生成交给模型。一个好用的 RAG 系统,核心不是“接上向量数据库”这么简单,而是资料质量、召回质量、上下文组织和答案约束共同作用。
参考资料:Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks。





