what is rag based prompt

接入与开发

讲清基于 RAG 的提示词到底是什么,以及在生产环境里怎么拼上下文、控长度、做降级和排查,让检索结果真的被模型用上。

你接好了检索,文档也召回了,可模型答的还是没边儿——问题多半出在提示词怎么把检索结果喂进去这一步。这篇不讲 RAG 原理,只讲落地:检索结果怎么拼进提示词、放哪个位置、太长怎么裁、没召回时怎么兜底、出问题从哪儿开始查。

你接好了检索,文档也召回了,可模型答的还是没边儿——问题多半出在提示词怎么把检索结果喂进去这一步。检索链路再漂亮,最后都是要落成一段文本塞进模型上下文里,这段文本怎么组织,直接决定模型用不用得上召回的内容。

这篇不讲 RAG 的原理和架构,只讲落地:检索结果怎么拼进提示词、放哪个位置、太长怎么裁、没召回时怎么兜底、出问题从哪儿开始查。看完你至少能自己动手改一版提示词,并且知道改完该盯哪几个指标。

基于 RAG 的提示词和普通提示词差在哪

普通提示词靠模型自己脑子里的知识;基于 RAG 的提示词里多了一段运行时才拿到的检索内容,每次请求都可能不一样。也就是说,同一句用户问题,今天拼进去的是这份资料,明天可能是另一份,输出自然会变。

  1. 拆成三段写任务说明与约束、检索到的资料块、用户当前问题,三段分开写,别混成一段自然语言。约束和资料块混在一起,模型很容易把资料里的句子当成指令执行。
  2. 把资料块当变量看资料块是拼进去的,所以能审计、能替换、能截断。模型答错了,先看拼进去的那段资料对不对,而不是先怀疑模型能力——十次里有七八次是进料环节的问题。
  3. 标记来源每块资料带上来源标识(文件名、小节号、更新时间),让模型在回答里能引用,也方便你事后核对它有没有编。没有来源标识,你就没法判断它是在引用还是在编。

拼装顺序与资料块格式:几个不折腾的默认做法

顺序这件事没有玄学,把固定指令放最前、用户问题放最后、检索资料夹在中间,这是多数接口下最稳的顺序;反过来把资料放最后容易盖住指令,模型会顺着资料跑。

  • 每块资料带上来源标识,并明确要求模型引用;引用格式在指令里写死,别让它自由发挥
  • 块与块之间用明确分隔标记,别指望模型靠空行区分,空行在长上下文里会被吃干净
  • 同一份资料别重复拼两遍,重复会稀释注意力,还会让模型误以为这件事特别重要
  • 资料块里塞进整篇原文是最常见的浪费:先裁剪成相关段落再拼,原文留在你自己的存储里

切块、嵌入、检索这条链路的选型,站内有两处可以对照:嵌入模型看 嵌入模型(/embeddings),向量库看 向量数据库目录(/stacks/vector-dbs)。换掉其中任何一环,拼装策略都可能要跟着调。

长度预算:怎么保证不爆上下文也不丢关键信息

先定死三块预算:指令占多少、资料占多少、留给回答和思考的余量占多少。按当时模型的上下文窗口换算,具体数字去 基础概念词典(/ai-dict/category/basics) 对 Token 与上下文的定义,别凭感觉拍。

预算块给多少超了怎么办
指令与约束固定一小段,尽量不动精简措辞,拆成模板变量
检索资料按相关度从高到低填,填满即停丢掉低分块,或对长文先摘要
对话历史只带最近几轮,旧轮次压成一句指代不清时再补一轮原文
回答与思考余量留出稳定余量余量不足时先砍资料,别砍指令

召回多不等于该全拼。宁可少给几块高质量的,也别把低分块凑数——低分块最大的危害不是占长度,而是给模型提供了编造的素材。超长文档先摘要再拼,但摘要要保留实体名、编号、时间这类可检索的硬信息,否则模型答得顺却对不上事实。

没召回到、召回错了、超时了分别怎么办

零召回时,不要让提示词里出现空的资料块。明确告诉模型「本次没有检索到相关资料」,并要求它直说不知道,而不是凭记忆编。空资料块比没有资料块更危险,模型会默认无事发生然后自由发挥。

  • 召回质量差:先看切片和召回条数,再动提示词;调提示词解决不了进料问题
  • 检索超时或报错:设一个降级分支,直接走无检索的普通回答并在返回里标记来源为空
  • 回答与资料不符:在提示词里加硬约束,只依据资料块作答、不得引入外部事实,并要求标注引用来源
  • 始终兜底的:把上面几类异常样本记下来做回归,别每次都靠人肉复现

进料本身脏的话,提示词再怎么改都是白改。清洗和切片的清单参考 PDF 和扫描件清洗(/guides/pdf-ocr-doc-cleaning),先把文档质量这一层过了再回头看拼装。

上线后看什么、怎么改才不白改

至少记这几个字段:检索命中条数、拼进提示词的字符量、最终 Token 消耗、是否走了降级、回答是否带引用。按天扫一遍异常比例,成本异常先查拼装——多数「突然变贵」是资料块变长或历史轮次没裁,而不是模型涨价。

  1. 攒固定用例覆盖命中、零召回、超长文档、多轮指代四类场景,每类几条,写成能一键重跑的脚本
  2. 先跑基线改之前先跑一遍记录结果,不然你根本不知道改动是变好还是变坏
  3. 一次只改一处拼装顺序、分隔标记、约束措辞分开改,混在一起改出了问题定位不到
  4. 重跑对比改完重跑同一批用例,重点看零召回和超长文档这两类有没有退化,方法参考 提示词回归测试(/guides/prompt-version-regression-testing)
下一步想省掉自己搭套件的功夫,可以先去站内工具目录看看现成的评测与成本核算工具,再决定哪些自己写、哪些直接用。

常见问题

基于 RAG 的提示词和提示词工程是一回事吗?

不是。提示词工程管的是怎么把指令写清楚,模型本身就能回答;基于 RAG 的提示词多了一层运行时拼装——每问一次都要先检索、再决定拼什么进去。所以它一半是写法问题,一半是链路问题,光把措辞打磨漂亮解决不了召回到的内容根本不对。

检索结果是不是越长越好?

不是。长度受限于上下文窗口和成本,而且低相关度的块会稀释注意力,把真正有用的那段淹掉。默认做法是按相关度排序填到预算上限就停,宁可少给几块。资料太长时先摘出相关段落,硬信息(名称、编号、时间)要留在里面。

模型没按资料回答、开始自己编,先从哪查?

按这个顺序:一看拼进去的资料是否真的包含答案,二看资料块有没有被截断在关键句中间,三看指令里有没有明确禁止编造和允许说不知道,四看资料块的位置是不是被放到了用户问题后面。绝大多数情况问题在前两步,不在模型。

本文依据各平台公开文档与官方公告整理,只做中文归纳;具体做法、参数与限制以官方文档为准。