做提示工程这件事,我前后折腾了一年多。最开始我以为它就是“把需求说清楚”,后来以为是“结构化的文字艺术”,再后来看了各种教程,开始研究角色、思维链、few-shot……直到某个晚上,我把一大堆 prompt 实验结果摊在表格里,突然发现一件事:整个过程中我做的事,跟控制论里描述的“黑箱辨识”几乎没有区别。大模型是一个打开不了的系统,我只能从外部设计输入、观察输出、修正假设,再试验。所谓 prompt tuning,本质上就是给一台内部不透明的机器做系统辨识。
这篇文章我想把这个视角写清楚:为什么提示工程其实是一门黑箱辨识术,以及这个认知能在实操层面给你带来什么。适合所有正在跟大模型打交道的人——不管是做应用开发的程序员、天天画交互稿的产品经理,还是自己折腾 AI 工具的独立开发者。你不需要懂控制论公式,但我会尽量把控制论最核心的那几个思想用大白话讲透。
1. 黑箱辨识:提示工程被我低估的那一层
1.1 控制论里的“黑箱”到底指什么
控制论在中文互联网里一直是个带点神秘色彩的词,但它提出的“黑箱”概念其实特别朴素。所谓黑箱,就是指一个系统,你无法直接观察到它的内部结构或内部状态,只能通过输入和输出来了解它。你按下一个按钮(输入),它亮灯或者发出声音(输出),你根据这些行为变化去推测里面可能是什么机制。
举一个让我印象很深的例子。我之前拿到一个完全陌生的小设备,没有说明书,也没办法拆开。我要做的第一件事不是什么高深操作,而是“玩”:按不同顺序按键、拨动开关、观察指示灯变化、记录响应。反复几十次之后,我虽然仍然不知道设备内部是继电器还是单片机,但我已经能预测哪几个操作会导致哪几个输出,甚至能总结出一套使用规则。这就是最原始的黑箱辨识。
这套方法论在系统控制里有个正式名字,叫系统辨识。工程师不去拆解系统的内部结构,而是通过给系统加激励信号、记录响应曲线,然后拟合出一个等价的输入输出模型。辨识出来的模型不一定等价于系统内部的真实机制,但只要它能预测系统行为,它就有用。
你发现没有,这套描述放到今天的大模型上,几乎是完美的贴合。
1.2 大模型为什么是终极黑箱
大模型跟普通软件有个本质区别:你没法用调试器设置断点、没法查看变量内存、没法把某个层单独摘出来改逻辑。你面对的是一个参数量在千亿甚至万亿级别的网络,即便你把某一个权重捞出来看,它也不会告诉你它“代表什么”。
更麻烦的是,大模型对外只有一个自然语言接口。你所有想表达的信息都要编码成文字,它所有返回的信息也都是文字。这也意味着,黑箱的输入空间和输出空间都非常特殊——它们不是数字信号、不是结构化参数,而是充满歧义、多义、上下文依赖的人类语言。
我经常用一个比喻:普通基础软件是一个打开机箱的电脑,你能看到主板、内存、硬盘;传统机器学习模型是带着透明外壳的机器,能看到权重但不太好理解;大模型是一台焊死的智能设备,只剩下一个文本输入框。你所有的辨识努力,都必须从那个文本输入框开始。
所以说,控制论里的黑箱思想,在大模型时代不是过时了,反而是被低估了。我们做提示工程的时候,本质上就是在对一个黑箱系统做外部观测,并且试图通过反复实验来逼近一个“等效模型”。
1.3 黑箱辨识三环节:输入、输出、反馈
把提示工程还原成黑箱辨识之后,你会发现所有工作都能拆成三个环节:
- 输入设计:写提示词时,选择角色、任务、背景、示例、输出格式、约束条件等各个维度,这相当于给黑箱施加的“激励信号”。
- 输出观察:分析模型回复里的内容、结构、逻辑、语气、错误模式,这相当于读取黑箱的“响应信号”。
- 反馈更新:把实际输出和期望输出做对比,找出差异,修改下一轮输入,再观测,直到系统行为逼近你的目标。
很多新手做提示工程只停留在第一个环节——拼命改输入,但不仔细看输出的细节,也不做系统的对比与反馈更新。结果就是同样的问题反复出现,改了七八个版本也不知道是哪个修改起了作用。真正的黑箱辨识术,是把这三个环节形成一个闭环,每一步都有记录、有分析、有假设检验。
说到记录,我一直建议至少用一个简单的表格来管理你的实验,哪怕只是记几行。列上实验编号、日期、prompt版本、修改点、测试用例、模型名称、参数设置、输出评价。有了记录你才能回答“到底是哪次改动带来的效果”。
2. 拆解输入空间:让每次调试都变成可复现实验
2.1 一次只动一个变量,其他全锁死
做黑箱辨识的第一铁律,是控制变量。这个道理听着简单,操作的时候特别容易被忽略。我在刚开始调 prompt 的时候就干过这种事:为了提升分类效果,同时改了角色设定、加了few-shot示例、还把输出格式从纯文本换成了JSON,最后效果变好了,但我完全不知道是哪一个改动在起作用。下一轮换一个场景,改动的技巧失效了,我手里没有任何可复用的经验。
正确做法是每次实验只改一个维度。这一次你想验证“加示例是否有用”,那就保持角色、格式、背景全部不变,只在提示词里增加两个示例,然后跑同一个测试集,对比输出差异。测试完得出“示例有效”或“示例无效”的结论,再进入下一步。
这个流程看起来慢,实际上最省时间。因为黑箱系统里各个因素之间有强耦合,你同时动两个变量,得到的结果根本无法归因。一次实验一个结论,五个实验之后你就积累了五个确定有效的修改项,这比一晚上乱试二十个版本要可靠得多。
2.2 把 Prompt 拆成四个可分离的层
大多数提示词可以拆成四个功能层,分清楚能让你的输入设计变得非常系统。这四个层是:
- 指令层:定义任务目标和角色身份,比如“你是一名客服工单分析助手,请将用户反馈分类”。
- 信息层:提供背景资料、业务规则、约束条件、待处理的数据等。
- 示例层:给几个输入输出样例,告诉模型“我要的答案长这样”。
- 格式层:指定输出的结构、字段类型、长度或编码方式,比如“输出JSON,字段包括category、confidence、reason”。
我通常建议所有改动都落到某一个层里,不要跨层混改。当你发现模型输出内容不对,先检查信息层,是不是业务规则没讲清楚;当你发现输出格式不对,直接动格式层;当你发现答案风格不符合预期,去改指令层或示例层。分层之后,问题定位会快很多。
举个例子。我一次做工单分类任务,模型偶尔会在 JSON 之外输出一句“注意:本结果基于规则判断”,直接把下游解析搞崩了。我当时很生气,以为是幻觉,后来冷静下来一看,问题出在格式层——我根本没有告诉模型“只允许输出JSON,不要输出其他任何文字”。加上这一条约束之后,问题彻底消失。很多看似玄学的模型失控,其实就是某一层的信息缺失。
2.3 用可观测指标替代“感觉”
黑箱辨识里,输出观测必须量化,否则你很难判断“这次改好了”还是“只是这次运气好”。我见过很多人在 prompt 调试时只用“感觉这版更顺了”来评价,这其实是在浪费黑箱实验的数据。
我一般会至少选三到五个可观测指标,给每次输出打分。比如做内容生成任务,我会看完整性、合规性、流畅度、幻觉率;做分类任务,我看准确率、召回率、格式命中率。每个指标要有明确的观测方式,而不是让印象说了算。
举个例子,我给自己制定过一个简化评分表,在调试阶段很有用:
| 评估维度 | 观测方式 | 判定标准 |
|---|---|---|
| 任务完成度 | 需求点覆盖个数 | 遗漏需求点≤1 |
| 格式合规性 | JSON/字段解析是否成功 | 解析通过率100% |
| 逻辑一致性 | 抓取关键推理链段落 | 无矛盾即可 |
| 事实正确性 | 随机抽检3个具体事实 | 错误数0 |
| 稳定性 | 同一prompt跑10次 | 有效输出≥8次 |
每次实验记录不足的指标,下一轮就针对最差的那个指标改对应的层。这样你的提示工程就从“感觉艺术”变成了“实验科学”。过程也许更枯燥,但结果非常可靠。
3. 输出空间解读:看懂黑箱给你的信号
3.1 模型不是“错”,而是“没被约束”
调试 prompt 时,最经常出现的一种心态是“模型又答错了”。但从黑箱辨识的视角看,所谓“错”,大多数情况下不是模型随机出错,而是你的输入没有把合法输出空间约束清楚。
举个例子。你让模型“分析一条用户反馈”,它除了分析还加了一段背景科普,这时候它并不是不懂你的任务,而是你的指令层和格式层没有给出“只需要输出分析,不需要解释”的边界。模型在概率上倾向于延续上下文,如果你没有画终止线,它就会沿着惯性继续生成。
所以在看输出的时候,我建议先区分两类信号:内容信号和结构信号。内容信号指的是它实际说了什么事实、什么结论;结构信号指的是输出是否按照你希望的框架组织,有没有多余段落、多余字段、多余声明。很多时候模型内容是对的,只是结构信号异常,你只需要补格式层约束,而不是把整个任务定义重写一遍。
3.2 探针式提问和消融实验:把模型当作被测系统
黑箱辨识少不了“测试”,放在 prompt 工程里,你可以设计几种探针。
第一种是边界探针。你问模型“你的回答到哪个程度为止”,比如一次让它生成内容时,看它在什么情况下会开始自由发挥;或者设计一个明显超出训练数据分布的问题,看它如何表现。
第二种是反事实探针。你人为改变某个输入前提,看输出是否跟着变化。比如在做工单分类时,故意把“用户投诉快递太慢”改成“用户表扬快递很快”,看模型能不能正确切换分类。这能帮你确认模型是否真的在按你给的规则推理,还是纯粹靠字面联想。
第三种是消融实验。这是控制论和机器学习里很常见的做法——拿掉输入里的某个部分,观察输出变化。如果你去掉某段业务背景后,输出质量明显下降,说明背景信息起到了关键作用;如果输出几乎没有变化,说明该段信息可能被指令层覆盖,或者根本没有被模型有效利用。消融实验能帮你做“归因分析”,知道哪些输入必须保留,哪些可以精简。
我把这些探针统称为“给黑箱编一套考试卷”。设计得好的考试卷,比随便扔十个需求调用模型更说明问题。
3.3 幻觉问题:从辨识视角看,它是外推误差
很多人把幻觉看成大模型一个不可解释的毛病,但从黑箱辨识角度来看,幻觉是系统辨识里一个经典误差类型——你让模型预测它没有足够依据的区域,它就从邻近区域外推。既然你没有提供可靠信息,它只能用语言概率填补空白。
处理幻觉不能完全靠“告诉它不要瞎编”,因为负面指令往往不够具体。更有效的办法是改变辨识条件:
- 让输出锚定在你提供的信息上:在信息层加入“只基于以下材料回答,不要使用材料外的知识”。
- 缩小输出范围:给出固定答案模板,让它填空而不是自由生成。
- 降低外推压力:设置低采样温度,或者要求它先输出依据再给出结论,让模型把推理过程显性化。
我记得有一个知识库问答场景,模型总爱把文档里没有的信息当成科普补充进去。我后来把提示改成“只允许回答文档中出现的知识点,如果问题不在文档范围内,直接回答‘未在资料中找到’”,效果立竿见影。这就是把黑箱的输出空间刻意压缩到你能控制的范围内。
4. 反馈闭环:从单轮问答到持续辨识
4.1 单轮实验和多轮闭环的区别
很多提示词模板只考虑“一次性问答”——用户发一句话,模型回一段话,结束。但在真实业务里,你需要的往往是一个持续逼近目标的闭环:先给一个初步输出,分析它,发现缺陷,针对缺陷继续追问或修正,直到输出满足要求。
控制论最核心的思想之一就是反馈。没有反馈的系统,只能盲飞;有反馈的系统,才能在干扰和偏差中自我校正。大模型交互也一样:你可以让模型“先输出初稿,然后自己检查是否符合约束,再输出修订稿”,这本质上是在做一个内部反馈回路。
我通常会区分两种反馈方式。一种叫外部反馈,你作为观察者去修改下一轮输入;另一种叫内部反馈,你在 prompt 里让模型自己扮演“审稿人”,先产出结果,再对照检查清单自评,然后修正。两种方式在很多任务里可以组合使用,效率会明显提升。
4.2 一套标准的迭代动作:对比、假设、修改、复测
日常调试我把迭代过程固定成四个动作,每次循环都严格照做:
- 对比:把当前输出跟目标要求、跟上一版输出放在一起看差异。这个差异就是黑箱给你的反馈信号。
- 假设:基于差异提出假设,比如“是不是格式层缺少约束”“是不是示例太少导致模式识别不准”。
- 修改:只修改假设指向的那一个层,其他保持不变。
- 复测:用同一批测试用例重新跑,记录结果的变化趋势。
听上去很像软件测试里的最小化复现。确实,提示工程做到最后,跟调试程序没有本质区别,只是你的“代码”是自然语言,你的“运行环境”是个黑箱大模型。
我建议在迭代时至少保留上一版 prompt 的完整快照。有时候你改了三个版本之后,会发现第三版比第一版还差,如果没有快照,你回退的凭据都没有。我就是靠这个习惯避免过很多次“改坏了但找不回来”的尴尬。
4.3 模型自我修正:给黑箱引入内部反馈
内部反馈的做法我已经提过了,这里展开说一下。所谓自我修正,最简单的方式是在同一个对话里分两步走:第一步让模型输出初稿;第二步输入“请重新检查你的输出,确认是否符合以下要求:要求列表”,让它自己找问题并修订。
这种方式并不是在所有任务上都有效,但它特别适合那些需要“准确性和严谨性”的场景,比如长文写作、代码生成、规则推理。模型自检能力有时候会比外部修改更细腻,因为它能看到自己的整体输出,而你在外部往往只能盯住几个局部指标。
我做过一个测试,让模型生成一段带具体数据的总结,不加任何自检步骤时,错误率较高;加了自检后,错误率大幅下降。原因也好理解:第一轮生成时模型在自由联想,第二轮自检时它面对的是自己的既成输出,更容易发现不一致的地方。这就是反馈回路带来的增益。
4.4 什么时候该收手:辨识成本与收益递减
黑箱辨识不是无限迭代的。到一定阶段,你会发现输出质量的提升开始变得不明显,或者改了 A 指标 B 指标就掉下来,这是典型的收益递减。
我现在的习惯是,在开始调 prompt 前先定一个“达标线”。比如分类准确率到 90% 以上、格式解析 100%、幻觉错误低于 5%,达到线就收手,把时间花在更重要的事情上。如果迭代到第五轮仍无明显提升,我会停下重新审查假设,而不是继续无脑调整措辞。这也是一种辨识策略——你知道什么时候该停止给黑箱加激励,否则你只是在跟随机噪声较劲。
5. 实战流程:把“用户反馈分类”提示调到 90% 准确率
这一节我拿一个真实做过的任务当例子,完整走一遍黑箱辨识流程。任务是把用户反馈自动分成几类:问题反馈、功能建议、表扬鼓励、其他无关内容。目标不只是分类,还要输出一句话原因,方便下游团队处理。
5.1 明确辨识目标与准备测试集
动手之前我先定义“什么算成功”:一是分类准确率不低于设定阈值;二是JSON格式可以被程序稳定解析;三是不漏掉明显的边界情况。为了避免口径不一致,我抽了几十条覆盖各类场景的真实反馈作为测试集,其中一部分用于观察,固定几条作为回归,最终以固定回归结果为准。
这一步常被省略,但它是整个工程的地基。没有固定测试集,你永远无法回答“这版是不是比上版好”。
5.2 第一版基线提示设计
第一版提示我只放了一个核心指令和输出格式,不堆花活,目的是拿到一个真实的“基准行为”。
prompt_template = """ 你是客服工单分析助手。 请将下面的用户反馈分类为:问题、建议、表扬、其他。 只输出JSON,不要输出其他文字。 输出格式: {"category": "类别", "reason": "一句话原因"} 用户反馈: {feedback} """用同一批测试集跑下来,基线效果不太理想,但错误很典型:一是“建议”和“问题”互相混淆,比如“希望你们增加夜间客服”被分到了问题;二是“表扬”和“其他”边界不清,有些语气正常的反馈被当成了其他;三是少数输出里 JSON 格式不稳,多了引号或换行。
这一步的意义不是得到一个好结果,而是拿到黑箱的“响应基线”。接下来所有的调整,都是在这个基线之上打的。
5.3 错误模式分析与分层修改
我对照错误样例做了归因。最主要的错误出在信息层:模型的分类判别标准不明确。于是我决定只动信息层,加了一段分类定义和两条典型示例,其他层完全不动。改进后我在同一批测试集上重新测,分类准确率明显提升,这个提升基本可归因于信息层的补充。
紧接着我又发现新问题:模型偶尔在未要求的字段上自创输出。于是我再动一次格式层,写明“只允许输出 category 和 reason 两个字段,不得包含其他字段”。这一步修正之后,解析错率基本归零。
分层的威力就在这里。如果我把信息层和格式层混在一起改,根本分不清准确率提升是来自分类定义还是格式约束,后续换场景迁移时也没法判断哪些部分是可复用的。
5.4 回归测试与方差控制
最后一步是回归测试和稳定性验证。我把最终版 prompt 放在固定回归测试集上多次运行,看准确率的波动范围,确认它不是某一次随机好运气。如果某一次分类结果波动很大,我还会尝试把采样温度调低,或者进一步收紧格式层约束。
多轮迭代之后,这套分类 prompt 基本稳定在目标阈值以上,满足上线要求。我把整个过程中的关键改动记录成一张小表:
| 实验版本 | 修改内容 | 准确率 | 格式解析成功率 |
|---|---|---|---|
| v1 基线 | 仅基础指令+格式 | 约64% | 96% |
| v2 信息层 | 增加分类定义与示例 | 约83% | 97% |
| v3 格式层 | 限定字段,禁止额外输出 | 约86% | 100% |
| v4 指令层 | 加强判定优先级说明 | 约89% | 100% |
从表格里能清楚看到哪一层的修改贡献了哪一项指标,这种可回放、可归因的实验记录,就是黑箱辨识术带来的最大回报。
6. 高频翻车现场与排查清单
6.1 常见问题速查表
我整理了一些最常见的翻车场景,方便你在调试时快速对照:
| 现象 | 原因判断 | 建议操作 |
|---|---|---|
| 改了 prompt 结果反而更差 | 可能动到了多个层,或新增信息与旧规则冲突 | 回退快照,一次只改一个层 |
| 同样的 prompt 结果时好时坏 | 采样噪声大,或在测试集上没固定 | 降低温度,固定测试集多跑几次看分布 |
| 模型不按格式输出 | 格式层约束缺失或被示例层带偏 | 单独强化格式层,写死“只允许输出” |
| 加了很多示例还是不行 | 示例与目标任务分布不一致 | 换与真实场景更贴近的示例,或精简示例数量 |
| 输出格式正确但内容不对 | 判定标准不明确,信息层缺业务规则 | 补充分类定义、边界案例、否定条件 |
| 长文本任务漏掉关键点 | 指令太多且无优先级 | 把需求列表化,在指令层标注顺序 |
| 换了模型或场景后效果崩掉 | 黑箱状态变了,原辨识模型失效 | 重新做一轮基线测试,不直接沿用旧 prompt |
6.2 这类问题最容易踩的几个坑
先说“示例陷阱”。我一度以为 few-shot 示例越多越好,结果模型开始模仿示例的措辞和长度,甚至把示例里的无关细节也当成了硬性格式。示例不是越多越好,它更像给黑箱一个“概率锚点”,少量、高代表性、覆盖边界情况的示例比一堆相似案例更有辨识价值。
再说“过度约束”。提示词不是写法律条文,你把所有可能性都塞进格式层,模型反而更容易在边缘情况里自相矛盾。我见过把输出规则写了一大段,结果模型为了满足规则开始编造字段。更好的做法是:把少数几条必须满足的硬规则写清楚,其余用温和的倾向性描述去引导。
还有一个特别容易出错的是“参数乱动”。很多人一看到输出不好就调 temperature 或 top_p,其实在大多数业务场景里,采样温度对我们的可复现性和稳定性影响非常大,调高温度往往只是让输出看起来多样,并不解决语义上的错。我自己的经验是:先通过 prompt 内容修问题,有必要时再考虑低温度采样,而且两种设置都要做回归测试。
7. 这种辨识思维还能用在哪里
7.1 换模型、换场景时的“辨识迁移”
黑箱辨识术最容易被忽略的价值,是迁移。你在一套模型上调好的提示词,换到另一个模型,或者换到一个新的业务场景,效果大概率会退化。这不是因为你当初的提示写得不好,而是因为黑箱变了——内部参数、训练分布、对齐方式都不同,你原来辨识出来的“等效模型”已经不再适用。
正确的做法是重新启动一轮轻量级辨识:先拿旧 prompt 做基线,跑少量代表性用例,看哪些地方退化,再针对退化点做分层修改。很多团队做模型升级时最怕的就是“业务表现忽好忽坏”,本质上就是没做辨识迁移。
我还会给每个场景维护一张“行为特征卡”,记录这个模型在这个场景下容易犯什么错、哪一层约束最敏感、什么语气指令最有效。换模型时,这张卡就是迁移的起点,而不是从零开始猜。
7.2 团队协作和经验沉淀
提示工程在团队里最难的是评审。你说“这版 prompt 很好”,同事问“好在哪里”,你答不上来,这就没法协作。如果用黑箱辨识的框架,评审就有了共同语言:定义可观测指标、固定测试集、记录分层改动、对比实验数据。每个人都能看懂,每个建议都能被验证。
我曾经在一个小团队里试过这套方法,把全员测试 prompt 的过程统一成一张表格,后面做复盘和交接都变得非常顺畅。新同学接手时,不需要靠“悟性”,只要照着表格里的实验记录就能理解为什么某句话要那样写。
7.3 “控制论的幽灵”到底在指什么
标题里的“控制论的幽灵”不是文学修辞。控制论最关注的是反馈、目标、辨识、自校正这些概念,它们从系统科学里诞生,后来飘到人工智能领域,又以“提示工程”这个完全意料之外的方式重新出现。你越想越会发现,很多今天看起来新鲜的东西,底层的骨架其实是老前辈早就搭好的。
这种跨越几十年仍然能指导实践的思维方式,我觉得就是“幽灵”让人着迷的地方。它不强迫你打开黑箱,而是教你通过输入输出与反馈去理解一个复杂系统。只要你还跟不可观测的系统打交道,这套思路就永远不过时。
结尾:我个人的一点体会
写到这里,再说几句私人的感受。做提示工程这一年,我最大的变化就是不再把模型当成“神奇的答题机器”,而是当成一台可以被辨识、被预测、被校准的系统。你用控制变量的方式去碰它,它就会给你可复现的反馈;你靠感觉乱试,它就回报你更多的随机和不可控。
如果你现在刚开始接触提示工程,我建议不要先学更多技巧,而是先建立自己的实验小表格,从一条基线 prompt 开始,一次改一个变量,把每次输出记录下来。这个习惯比任何提示词模板都值钱。黑箱永远会在那里,但你能不能辨识它,取决于你有没有一套稳定、可积累的观测方法。