直接把问题抛给大模型,它给出的答案未必可靠。模型的知识来自训练语料,一旦涉及企业内部文档、产品手册或者最新资讯,要么答不上来,要么编造一段看似合理的内容,也就是常说的幻觉。RAG(Retrieval-Augmented Generation,检索增强生成)的思路很直接:先从外部知识库里检索出与问题相关的资料,再把这些资料注入提示词上下文,让模型对照着资料回答。本文围绕RAG的完整落地流程展开,涵盖文档切分、向量化、检索策略以及提示词模板设计这几个核心环节。

RAG的核心工作流程是怎样的
一套典型的RAG系统分为离线和在线两部分。离线部分负责把知识库准备好:加载原始文档,切分成合适大小的文本块,用Embedding模型将每个文本块转换成向量,最后存入向量数据库。在线部分处理用户的每次提问:把问题同样转成向量,在向量库里做相似度检索,取出最相关的若干文本块,把这些文本块和用户问题一起组装成提示词,交给大模型生成最终回答。
可以看出,RAG本质上是一种提示词工程手段——它不改变模型本身,而是通过控制输入上下文的内容来影响输出质量。检索环节决定了模型能“看到”什么,提示词模板决定了模型如何“使用”这些内容。两者任何一环出问题,最终回答都会受影响。理解这一点非常重要,因为很多团队把注意力全放在模型选型上,忽略了检索质量才是RAG系统的瓶颈所在。
一个最小可用的RAG调用流程,用Python伪代码表示大致如下:
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.vectorstores import FAISS
from langchain.embeddings import HuggingFaceEmbeddings
# 1. 文档切分
splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
chunks = splitter.split_documents(docs)
# 2. 向量化并入库
embeddings = HuggingFaceEmbeddings(model_name="BAAI/bge-small-zh-v1.5")
vectorstore = FAISS.from_documents(chunks, embeddings)
# 3. 检索相关内容
retrieved = vectorstore.similarity_search("产品退货政策是什么", k=4)
# 4. 组装提示词
context = "\n\n".join([doc.page_content for doc in retrieved])
prompt = f"请根据以下参考资料回答问题,若资料中没有答案请直接说明。\n\n参考资料:\n{context}\n\n问题:产品退货政策是什么"
文档切分与向量化:决定检索质量的第一道关口
切分策略直接影响检索精度。块切得太大,一个块里混杂多个主题,向量表达会被稀释,检索时匹配不精准;切得太小,语义不完整,模型拿到的上下文支离破碎。实践中常用的做法是按段落和句子边界递归切分,块大小控制在300到800字符之间,并保留10%到20%的重叠,避免关键信息恰好被切断在两个块的边界上。
对于结构化文档,比如技术手册、API文档,还可以利用标题层级做切分,让每个块自带章节路径信息。这样检索命中的块不仅包含正文,还携带了它所属的上下文,模型能更准确地理解内容位置关系。另外,中文文档在切分前最好先做清洗,去掉页眉页脚、乱码和多余的空白符,这些噪声会污染向量表示。
Embedding模型的选择同样关键。通用的英文模型在中文语料上表现通常不佳,建议选用针对中文优化过的模型,例如bge系列、m3e等。如果知识库覆盖多个业务领域,还可以考虑定期评估检索的召回率,用标注好的问答对做验证,及时调整模型或切分参数,而不是凭感觉调优。
检索策略与提示词模板设计
基础的相似度检索未必够用。可以引入混合检索,把向量检索和关键词检索(如BM25)的结果融合,兼顾语义匹配和精确匹配:用户问的是某个报错码或专有名词时,关键词检索往往比语义检索更可靠;而描述模糊的自然语言提问则更依赖向量检索。两者结合通常能明显提升召回效果。此外,重排序(Rerank)也是常见手段——先用向量检索粗筛出二三十个候选块,再用专门的重排序模型精排,取前几个注入提示词,既保证质量又控制了上下文长度。
提示词模板的设计容易被轻视,但它直接决定模型如何使用检索结果。一个实用的模板需要包含几个要素:明确指示模型只能依据参考资料作答、要求在资料不足以回答时坦白承认、规定回答格式。示例如下:
你是一个企业知识库助手。请严格根据下面的参考资料回答用户问题。
要求:
1. 只使用参考资料中的信息,不要编造内容
2. 如果参考资料不足以回答问题,请回复"根据现有资料无法回答"
3. 回答末尾注明引用了哪几条资料
参考资料:
{context}
用户问题:{question}
关于注入内容的组织方式,建议给每个检索块加上编号和来源标注,方便模型引用,也方便后续做溯源审计。当检索结果较多时,按相关性从高到低排列,因为很多模型对上下文开头和结尾的内容更敏感,中间部分容易被忽略。如果单次检索的内容超过模型上下文窗口,不要硬塞,应当压缩摘要或者减少注入块数,宁可让模型回答“资料不足”,也不要让它基于被截断的信息给出误导性结论。
常见问题与优化方向
RAG系统上线后常见三类问题。第一类是检索不准,用户问A却检索回B,这时要检查切分粒度、Embedding模型适配性,并考虑引入查询改写——先让大模型把口语化的问题重写成适合检索的规范表述,再执行检索。第二类是幻觉残留,模型无视参考资料自说自话,多数情况是提示词约束不够强,或者注入的资料与问题相关性太低,模型宁可编造也不愿承认不知道。第三类是上下文膨胀,知识库一大,检索回来的内容又多又杂,token成本直线上升,回答质量反而下降,控制注入块数、做重排序筛选是有效对策。
评估环节建议尽早建立。构造一批测试问答对,从检索召回率、答案准确率两个维度打分,每次调整切分参数或更换模型后跑一遍回归测试,用数据说话。否则调优就变成玄学,改了参数也不知道是好是坏。进阶方向还可以探索GraphRAG(基于知识图谱的检索)、多轮对话中的查询改写与历史压缩等,这些都是在基础RAG跑通之后值得投入的优化点。
总的来说,RAG把大模型从“闭卷考试”变成了“开卷考试”,它的价值不在于模型变聪明了,而在于模型获得了可控、可更新的外部知识来源。把切分、检索、提示词这三件事做扎实,一套够用的知识库问答系统就已经成型了大半。