拆大模型 06|Prompt 工程不靠玄学:上下文要当程序写

一、prompt 到底算不算玄学

社区里常把这门手艺讲成玄学:prompt 写得好不好,全看有没有找到那句"神秘措辞"------找到了,模型功力大涨;找不到,怎么写都没用。这套说法之所以能传开,是因为它把 prompt 说成了只可意会的东西:说不清原理、换个模型就失灵、别人照抄也不管用。而实际有效的 prompt 实践恰恰相反:可理解、可复现、靠结构。

先把结论摆出来:

Prompt 不是玄学,它更像一段程序:有输入、有结构、有约束,能版本化、能测试、能回归。区别只在于它没有编译器替你查错,跑起来还带概率。

Prompt 工程的本质是上下文工程:决定往第 02 篇那块白板上放什么、以什么结构放。

从第 01-05 篇的机理可以直接推出这个论点:模型的行为完全由"参数 + 当前上下文"决定(第 04 篇),参数改不了,应用层能动的地方只有上下文------所以"调 prompt"不是碰运气,是精心安排模型的输入,如同写代码是精心安排指令序列。

换成日常的说法:写 prompt,就是给新来的聪明同事交代活儿 。他能力很强,但完全不了解你的项目、偏好和黑话。你会怎么交代?说清背景(角色)、要干什么(任务)、规矩禁忌(约束)、甩两个优秀案例(示例)、交付物长什么样(输出格式)。你不会指望一句"帮我弄一下"就得到满意结果------对模型同理,而且模型这位同事只会按字面理解,从不脑补。

二、结构化 Prompt 五要素

把"交代活儿"的内容拆成五个要素,几乎所有生产级 prompt 都由它们组装而成:

  1. 角色(Role):设定专业身份与视角。"你是资深代码审查员"不是玄学------这行字一进上下文,后面每个 token 的概率表就跟着变了(第 01 篇的接龙逻辑:前文决定下一个词的概率)。模型会顺着"资深代码审查员"这个前文往下续,用词、结构、关注点都被带到那个方向。角色还影响详略与口吻。
  2. 任务(Task):说清要干什么,动词开头,判定标准明确。"优化这段代码"是坏任务;"找出这段代码里三个最可能在线上出问题的点,按风险排序"是好任务。
  3. 约束(Constraints) :边界与禁忌。字数限制、不许编造(接第 04 篇:明确"不确定就说不确定")、必须引用给定材料、安全红线。约束就是把续写框在规定的范围里,越界的不输出。
  4. 示例(Examples):few-shot,下一节单独拆。
  5. 输出格式(Output Format):交付物契约。JSON Schema、固定段落结构、字段清单。没有这一条,模型给的就是"一段给人读的话",你还得手工整理成结构(第 10 篇的主题);有了这一条,它才是程序能直接解析的可靠组件。

一条装配原则:五要素是位置,不是步骤。顺序可调、内容可增删,但每次改动都清楚自己在动哪一块------这就是"玄学"和"工程"的分水岭:改动可定位,出问题可回滚。

三、Few-shot:模型的照猫画虎能力

五要素里最"魔法"的是示例------给两三个输入输出对,模型就能模仿出没明说的规律。这个现象叫 in-context learning(上下文内学习):模型不更新参数,仅凭白板上的几个例子就"学会了"新任务。

机理不复杂,两条各管一头。

生成的时候:模型每往外写一步,都要先算"眼下要写的内容"和上下文里各段的匹配分------分越高,那一段被取用进来的比例就越大(第 03 篇的 Q/K/V:Q 拿去找,K 用来比,V 按比例汇总)。示例正是分数最高的那几段,它们的写法因此被一并带了进来。

训练的时候:预训练让它见过海量"前面给几个例子、后面照着做完"的文本(第 01 篇),所以"照着样例把活干完",本来就是它见得最多、最容易续下去的写法。

两条合起来,示例等于把接下来往哪个方向续,提前定了个大概------模型顺着这个方向往下写:照猫画虎,最后画出来的往往像虎,因为它见过的虎比猫多得多。

这带来一个必须写进工程手册的特性:示例是 prompt 里最强的格式约束,强过任何文字描述。"输出必须是 JSON"说十遍,不如贴一个正确样例。但同时------

  • 示例的毛病会被忠实复制:示例里日期格式错了、字段名手滑,模型大概率跟着错
  • 示例是隐式程序:模型从例子里归纳的规律可能比你预期多(学到口吻)也可能比你预期少(漏掉边界处理),所以要挑"覆盖典型情况"的例子,必要时加一条覆盖反例

示例怎么挑?手动写几条是及格线;更好的做法是交给程序:用第 05 篇那套向量检索,把过去攒下的"问题 + 好答案"入库,来一个新问题就按语义相似度捞出最接近的几条,拼进这一次的 prompt------示例是现场挑的,不是提前写死的。

四、思维链:写出来才能看见

"让我们一步一步思考"曾经被当成一句必须加上的话术,但思维链(Chain-of-Thought, CoT)的效果有扎实的机理,一点也不玄:

回到第 01 篇那条规矩:模型每写一个 token,只能拿已经写出来的内容去算下一个 。由此可以推出一件跟人很不一样的事:它没有"先想清楚再开口"这一步 ------它每往下写一个字,就是往下算了一步,写字的过程本身就是思考的过程,没写出来的,就等于没算过。人可以先在心里打好腹稿再动笔,模型没有这块地方可以打,腹稿对它来说就是不存在的东西。

CoT 的作用就是把"腹稿"搬到"白板上":

  • 一上来就要答案,中间那几步就没处可写,模型只能一步跳到结论------出错的概率自然高
  • 让它先写推理过程,每一步的结论都留在上下文里------中间结果被写进白板,下一步生成时会把它一起算进去(第 03 篇)
  • 推理链等于把一次要全对的"心算",拆成一串可以分步对的"笔算":每一步只要猜对眼前这一小段,而不是一步猜中整条结论------每步要猜的内容更短、更确定,整条链出错的概率就低得多

所以 CoT 的本质是给模型的推理找一个看得见的落点 :写出来,才看得见;看得见,下一步才算得上。这也是 2026 年那批推理增强模型(各类 o 系 / R 系思考模型)的做法------把"思考"直接做成生成内容的一部分,先写一段推理,再给答案。机制还是同一个,只是这一步不再靠你在 prompt 里点名要求,模型自己就会做。

工程上要记两条。

一是 CoT 要花钱,也花时间 。输出是按 token 计费、也按 token 耗时:模型一个字一个字往外蹦,答案越长,等得越久、账单越大(第 02 篇算过这笔账)。而思维链会把输出拉长好几倍------本来几十个字能答完的题,加上推理过程轻松变成几百个字,等待时间和费用一起翻上去。所以简单任务别上思维链:分类、抽字段、改格式这类活儿,多写的那段推理不产生任何收益,只是把成本抬高了。

二是推理内容给谁看,要提前决定。模型的推理过程暴露给用户还是下游系统,是两套设计:给用户看,要考虑他能不能读懂、会不会被中间的错误结论误导;给下游看,要让最终答案能被程序稳定解析------通常的做法是用结构把思考和最终答案分开,别让推理过程混进结果字段里。

五、Prompt 的版本化管理:git 思维 + 测试集 + 回归评估

既然承认 prompt 是程序,就该用管程序的方式管它。生产环境的 prompt 管理三件套:

第一件:版本化。Prompt 文件进 git,改动词句有 diff、有提交说明、有评审------和代码同级对待。模板与变量分离(模板写结构,变量填运行时数据),避免散落在业务代码里的字符串拼接。成熟的团队已经把 prompt 模板当作与数据库 schema 同级的受管资产。

第二件:测试集。攒一批典型输入 + 期望输出(或评分标准),作为 prompt 的"单元测试"。没有测试集的 prompt 优化是玄学调参------改动的影响面你根本不知道。

第三件:回归评估 。每次改 prompt 跑一遍测试集,量化对比(准确率、格式合规率、人工/模型评分),不合格不发布。原因很硬:模型升级、参数调整、prompt 微改都可能引发能力回归------没有回归评估的 prompt 在生产上是裸奔。
#mermaid-svg-Hj38Aj4yXk59rG2q{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Hj38Aj4yXk59rG2q .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Hj38Aj4yXk59rG2q .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Hj38Aj4yXk59rG2q .error-icon{fill:#552222;}#mermaid-svg-Hj38Aj4yXk59rG2q .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Hj38Aj4yXk59rG2q .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Hj38Aj4yXk59rG2q .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Hj38Aj4yXk59rG2q .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Hj38Aj4yXk59rG2q .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Hj38Aj4yXk59rG2q .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Hj38Aj4yXk59rG2q .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Hj38Aj4yXk59rG2q .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Hj38Aj4yXk59rG2q .marker.cross{stroke:#333333;}#mermaid-svg-Hj38Aj4yXk59rG2q svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Hj38Aj4yXk59rG2q p{margin:0;}#mermaid-svg-Hj38Aj4yXk59rG2q .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Hj38Aj4yXk59rG2q .cluster-label text{fill:#333;}#mermaid-svg-Hj38Aj4yXk59rG2q .cluster-label span{color:#333;}#mermaid-svg-Hj38Aj4yXk59rG2q .cluster-label span p{background-color:transparent;}#mermaid-svg-Hj38Aj4yXk59rG2q .label text,#mermaid-svg-Hj38Aj4yXk59rG2q span{fill:#333;color:#333;}#mermaid-svg-Hj38Aj4yXk59rG2q .node rect,#mermaid-svg-Hj38Aj4yXk59rG2q .node circle,#mermaid-svg-Hj38Aj4yXk59rG2q .node ellipse,#mermaid-svg-Hj38Aj4yXk59rG2q .node polygon,#mermaid-svg-Hj38Aj4yXk59rG2q .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Hj38Aj4yXk59rG2q .rough-node .label text,#mermaid-svg-Hj38Aj4yXk59rG2q .node .label text,#mermaid-svg-Hj38Aj4yXk59rG2q .image-shape .label,#mermaid-svg-Hj38Aj4yXk59rG2q .icon-shape .label{text-anchor:middle;}#mermaid-svg-Hj38Aj4yXk59rG2q .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Hj38Aj4yXk59rG2q .rough-node .label,#mermaid-svg-Hj38Aj4yXk59rG2q .node .label,#mermaid-svg-Hj38Aj4yXk59rG2q .image-shape .label,#mermaid-svg-Hj38Aj4yXk59rG2q .icon-shape .label{text-align:center;}#mermaid-svg-Hj38Aj4yXk59rG2q .node.clickable{cursor:pointer;}#mermaid-svg-Hj38Aj4yXk59rG2q .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Hj38Aj4yXk59rG2q .arrowheadPath{fill:#333333;}#mermaid-svg-Hj38Aj4yXk59rG2q .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Hj38Aj4yXk59rG2q .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Hj38Aj4yXk59rG2q .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Hj38Aj4yXk59rG2q .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Hj38Aj4yXk59rG2q .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Hj38Aj4yXk59rG2q .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Hj38Aj4yXk59rG2q .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Hj38Aj4yXk59rG2q .cluster text{fill:#333;}#mermaid-svg-Hj38Aj4yXk59rG2q .cluster span{color:#333;}#mermaid-svg-Hj38Aj4yXk59rG2q div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Hj38Aj4yXk59rG2q .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Hj38Aj4yXk59rG2q rect.text{fill:none;stroke-width:0;}#mermaid-svg-Hj38Aj4yXk59rG2q .icon-shape,#mermaid-svg-Hj38Aj4yXk59rG2q .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Hj38Aj4yXk59rG2q .icon-shape p,#mermaid-svg-Hj38Aj4yXk59rG2q .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Hj38Aj4yXk59rG2q .icon-shape .label rect,#mermaid-svg-Hj38Aj4yXk59rG2q .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Hj38Aj4yXk59rG2q .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Hj38Aj4yXk59rG2q .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Hj38Aj4yXk59rG2q :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 不达标
达标
System Prompt 模板

(五要素,进 git 版本化)
组装最终 Prompt

(占位符填充)
Few-shot 示例库

(可按相似度动态挑选,见第 05 篇)
运行时变量

(用户输入 / 检索文档 / 工具结果)
历史对话

(受第 02 篇窗口预算约束)
模型生成
结构化输出校验

(见第 10 篇)
测试集回归评估
回到模板改版本

(diff + 评审 + 重跑)
发布,记录版本号

这张图就是"上下文即程序"的完整形态:最终送进模型的 prompt,是模板、示例、变量、历史在运行时组装的产物------每个部分都是可管理、可测试、可替换的组件。所谓上下文工程,管的就是这条装配线。

六、三个反模式:别再交这些学费

反模式一:迷信万能话术。"你必须这样做"、"这非常重要"、"答对了我给你打满分"------这些流行话术偶尔有效,本质是它们在训练数据里常常紧挨着"认真作答"的文本,于是把续写往那个方向推了一把,但效果不稳定。结构化五要素 + 测试验证,永远优先于玄学话术。

反模式二:越长越好 。把公司 wiki 全文贴进 prompt 的"最佳实践"正在害人:第 02 篇讲过,窗口是钱(token 计费 + KV Cache 开销),而 lost in the middle 让中间的大段材料利用率最低。正确的方向是"每一段都对这次任务有用",而不是"能塞多少塞多少"。对任务无用的客套和重复指令,还会摊薄关键约束在模型眼里的分量。

反模式三:把模型当搜索引擎 。指望模型"记住"全部知识、对冷门事实也给得准------它的机制是一个字一个字往下续写,不是在库里查条目(第 04 篇)。该查资料的接 RAG(第 05、08 篇),该算数的调工具(第 07 篇),prompt 的职责是让模型在手头已有的材料上,做它最擅长的归纳与表达。

一句话总结:好的 prompt 不是一段神奇的文字,而是一份写给"极聪明但零上下文、按字面执行、逐 token 续写"的新同事的需求文档,配上范例和验收标准,并用管代码的方式管它的版本和回归。


小结

  • Prompt 是程序不是玄学:模型行为由"参数 + 上下文"决定,参数改不了,应用层能动的只有上下文
  • 结构化五要素:角色、任务、约束、示例、输出格式------拆成固定几块的意义,是改动可定位、版本可回滚
  • Few-shot 是最强的格式约束:模型是照着例子的样子往下写,不是在理解你写的规则,所以示例的毛病会被忠实复制;高级选例靠向量相似度(见第 05 篇)
  • CoT 的机理:自回归模型"写出来才能看见"------中间推理显式进白板,把心算拆成笔算;代价是每 token 的延迟与费用
  • 生产三件套:prompt 进 git、建测试集、改版必跑回归评估------不当成代码管,就在生产裸奔
  • 三个反模式:迷信万能话术、越长越好、把模型当搜索引擎

思考题

  1. 同一份精心调优的 prompt,换了另一家模型后效果明显下降。这说明 prompt 的哪部分是"可移植的程序",哪部分是"针对特定解释器的调优"?如果是后者,迁移时该重做什么?(提示:五要素里哪几项依赖模型的固有格式偏好与对齐性格------回想第 04 篇"性格是调出来的"。)
  2. few-shot 的示例数量是不是越多越好?示例之间存在冲突(两个例子代表两种不同解法)时,模型会怎么"照猫画虎"?(提示:想想 Attention 对多个相似模式的加权混合------它会二选一还是出新东西?)

高频面试题

Q1:怎么理解"Prompt 工程的本质是上下文工程"?

A:因为模型的输出由两样东西决定------参数和当前上下文。参数你改不了,应用层唯一能动的就是上下文。

  • 所以 Prompt 工程不是"找一个神奇措辞":它是系统地管理进入窗口的所有内容------system prompt、few-shot 示例、检索文档、对话历史、工具返回,怎么组装、各占多少预算。
  • 工程化落在三件事上:模板与变量分离、prompt 进版本管理、配测试集做回归评估。
  • 一句话:把 prompt 当代码管。

Q2:zero-shot、few-shot、思维链分别是什么?什么场景用哪个?

A:三者的区别在两点:给不给例子,要不要写出推理过程。

  • zero-shot:直接下指令,不给例子。
  • few-shot:先在 prompt 里放几个"输入 → 输出"的样例,让模型自己从样例里看出模式。适合格式要求严格,或者任务模式很难用语言讲清的场景。
  • 思维链(CoT):要求模型先把推理步骤写出来,再给结论。适合多步推理、数学、逻辑题。
  • CoT 为什么有用:自回归模型的中间结果必须"写出来",才能参与后面的计算。
  • 怎么组合、怎么取舍:三者可以叠着用(few-shot CoT);CoT 会多出推理步骤的 token,拖长延迟,简单任务不必用。

Q3:思维链(CoT)为什么能提升推理准确率?它的局限是什么?

A:因为自回归模型没有"腹稿"。

  • 机制的约束:每一步只能基于已经生成的 token 算,没写出来的中间结论不参与后续计算。
  • CoT 做了什么:把中间推理显式写进上下文,每一步的结论就成了下一步的输入。于是一次高难度预测被拆成一串低难度预测,累计错误率大幅下降。
  • 局限一:推理链本身会错,而且错误会顺着链往下传。
  • 局限二:输出变长,延迟和费用跟着涨。
  • 局限三:参数里本来就没有的知识,写多少步也推不出来(见第 04 篇),得配检索或工具。

Q4:生产环境如何对 prompt 做版本化与质量保障?

A:三件套:模板进 git、备好测试集、每次改动跑回归。

  • 模板进 git:prompt 以文件形式版本化,模板与运行时变量分离,改动走 diff 和评审。
  • 备好测试集:维护典型输入与期望输出(或评分标准),作为评估基准。
  • 跑回归:prompt 变更、模型升级、参数调整,都要跑一遍全量测试集,对比格式合规率、任务指标、人工或模型评分,达标才发布。
  • 再加一条:每次请求记下所用的 prompt 版本号,线上出问题能回溯到具体版本。

系列导航:上一篇 05《Embedding 与向量检索》 → 下一篇 07《Function Calling》:模型怎么伸手调你的代码

相关推荐
鸿蒙开发爱好者36 分钟前
下班后做的小工具和小游戏,我把它们整理成了 WyanHub
网络·人工智能·职场和发展·个人开发
Tapdata41 分钟前
被忽略的第三类上下文:Agent 进入真实业务后,还缺什么?
数据库·人工智能·架构
地平线智能驾驶开发者42 分钟前
征程6|用 hrt_model_exec 看清 YOLOv5x 的输入、原始输出和后处理
人工智能·yolov5·机器视觉
地平线开发者1 小时前
征程6|用 hrt\_model\_exec 看清 YOLOv5x 的输入、原始输出和后处理
人工智能·算法
杨凯凡1 小时前
Spring AI RAG 实战:向量检索、租户过滤、引用溯源与防幻觉边界
java·人工智能·spring
#六脉神剑3 小时前
myBuilder 11 月新版本:AI辅助设计
ide·人工智能·低代码·ai·mybuilder
SJZR3 小时前
图解循环神经网络(RNN)
人工智能·rnn·神经网络
QXWZ_IA3 小时前
测绘单位采购RTK:设备价格、账号年费、售后,用时间轴分权重
网络·人工智能·安全
kaixin_啊啊4 小时前
【零基础学AI】第 29 章——第一次调用大模型 API
人工智能