提示词是什么、不是什么:模型如何读指令;角色 / 任务 / 格式 / 约束四要素
先搞清模型是怎么读你那段话的,再用角色、任务、格式、约束四个要素,把一句模糊的需求改写成模型能稳定执行的工作便签。
今日目标
- 能用自己的话解释提示词为什么不是命令,而是给模型的上下文
- 能把一句模糊需求拆成角色、任务、格式、约束四个要素并逐条写出来
- 能说出系统提示与用户消息的分工,并解释为什么规则要放系统提示
这门课一共五天,全程只围绕一件事:把你脑子里那句模糊的需求,写成一张模型能看懂、能照办、下次还能复用的「工作便签」。今天先把最基础的一层打牢——模型到底是怎么读你那段话的,以及一张合格的便签由哪四个部分组成。读完正文、做完实验之后,回到页面顶部把三条目标逐一勾掉。
小白版讲解
提示词不是命令,是上下文
想象你公司新来了一位同事,能力很强,但对你们的项目一无所知,而且你只能通过便签跟他沟通——他看完便签就开始干活,中途不会来问你。你在便签上写「把 TODO 接口的校验补一下」,他会怎么做?他会猜。猜你说的「校验」是指哪些字段、猜失败时该返回什么、猜要不要顺手写测试。猜对了你觉得他聪明,猜错了你觉得他不靠谱,但问题其实出在便签上:你把自己脑子里的默认信息当成了他也知道的东西。
大语言模型读提示词(prompt)的方式,跟这位新同事读便签几乎一样,只有一点更极端:它连「去问一下」的选项都没有。它拿到你的文字之后做的事情,本质上是「根据这段文字,接下来最合理的内容是什么」——它在补全一段文本,而不是在执行一条命令。这个区别听起来像文字游戏,但决定了你后面所有的写法。命令是「做这个」,执行者要么做要么不做;上下文是「情况是这样的」,补全者会根据情况推断最可能的下文。你写得越具体,「最合理的下文」的范围就越窄,输出就越稳定;你写得越含糊,模型就要用它从海量文本里学到的「一般情况」来填空,而「一般情况」跟你的具体项目往往对不上。
所以提示词工程(prompt engineering)到底在工程什么?不是在找什么神秘咒语,而是在系统性地补齐模型缺少的上下文:它不知道你是谁、不知道你要什么、不知道你要什么样子、不知道什么不能碰。这四个「不知道」,正好对应今天要讲的四要素。先把这个心智模型立住:你不是在下命令,你是在给一位能干但完全不了解情况的同事写一张足够详细的便签。
为什么人听得懂、模型做不对
先看一个真实感很强的例子。你对一位熟悉项目的老同事说「给 TODO API 补上输入校验和对应的单元测试」,他能直接开工,因为这句话背后藏着一大堆你们共享的默认信息:项目用的是 Express 还是 FastAPI、校验通常覆盖哪些情况、失败时团队习惯返回什么状态码、测试框架用的是哪个、测试文件放在哪里。这些信息一个字都没出现在句子里,但老同事全知道。
模型不知道。于是它会用「训练数据里最常见的做法」来填每一个空:可能给你引一个你们没用过的校验库,可能返回 422 而你们团队统一用 400,可能用 Jest 而你们项目是 Vitest,可能顺手把接口路径也「规范化」了一遍。每一处它都不算错,但每一处都跟你想要的不一样。这就是「人听得懂、模型做不对」的全部原因:句子里的信息量不够,而模型不会停下来问,只会用默认值填。
歧义是另一种形态的缺省。「补一下校验」里的「补」,是在现有代码基础上加,还是重写一份?「对应的单元测试」是每个校验一个测试,还是一个测试覆盖所有校验?这些歧义人会根据语境自动消解,模型会随机挑一个——而且同一句话跑两次可能挑得不一样,这就是很多人觉得模型「不稳定」的根源。所以在动笔写提示词之前,先做一个动作:把你那句需求念一遍,每遇到一个名词或动词就问自己「新同事看到这个词会不会有第二种理解」。有,就把它写死。这个动作不需要任何技巧,但它能消掉一半以上的输出不稳定。
四要素之一二:角色与任务
把「模型缺的上下文」分成四类来补,就是所谓的四要素:角色、任务、格式、约束。它们不是什么规范,只是一张实用的检查清单——每写完一份提示词,对着四个格子过一遍,看哪个空着。
角色回答的是「从什么视角看这件事」。很多人把角色写成头衔:「你是一位资深后端工程师」。这句话的信息量很低,因为「资深后端工程师」可以关注性能、可以关注架构、可以关注可读性,模型不知道你想让它关注什么。有效的角色写法是给视角和关注点:「你是一位负责代码审查的后端工程师,见过很多因为没校验输入而在线上被打挂的接口,习惯先列出所有会进来的字段,再逐个问它为空、超长、类型不对时会怎样」。这一段读完,模型知道了三件事:它该找漏洞而不是重写功能,它该优先看边界情况而不是正常路径,它该按「列字段、问边界」的方法干活。类比一下:你给新同事的便签开头不是「你是工程师」,而是「你今天代表 QA 来看这段代码」——一句话就定了他的立场。
任务回答的是「要做成什么样,做完的样子是什么」。这里最常见的漏洞是没有完成标准。「补上输入校验」没有终点,模型会自己决定在哪停;「覆盖必填缺失、类型错误、字符串超长、日期非法四类情况,每类至少一个测试,全部能跑能过」就有终点了。写任务时可以套一个固定句式:对什么、做什么、做到什么程度算完。三个部分缺一个,模型就要猜一个。
任务这一栏还有一个容易忽略的点:要把「对什么」的材料真的给它。让模型给一段代码补校验,代码就要贴进去;让它按团队规范写,规范就要贴进去。模型没有你的仓库权限,它看不到你没贴的任何东西——这在网页聊天里是常识,但一旦你开始用 API 写程序,很容易忘记把上下文材料拼进请求。
四要素之三四:格式与约束
格式回答的是「输出长什么形状」。判断格式写得好不好,只有一条标准:能不能机械核对。「清晰易读」「结构化」「简洁」都不能核对,因为你没法写一段代码去判断一段文字是否「清晰」;「按顺序输出三段,第一段是不超过五条的列表,第二段是修改后的代码放一个代码块,第三段是测试文件放另一个代码块,段落之间不要客套话」可以核对,你能数段数、数条目、数代码块。格式写得越死,输出就越容易被程序直接消费——D3 会把这一栏直接升级成 JSON schema,让程序不用解析自然语言就能拿到字段;而 D4 建测试集时,判对错的逻辑也全依赖格式是可核对的。今天先养成习惯:格式栏里不出现形容词。
约束回答的是「不要做什么,以及为什么」。注意后半句。模型对光秃秃的否定式指令执行得不稳定,「不要引入新的库」它可能记得也可能忘;但「不要引入新的库,因为这个项目的依赖需要走审批,加库会让这次修改卡住」,它不仅会记住,还会在你没列到的相似情况下做出一致的判断——比如它想加一个日期解析库时,会想到「这也是新依赖」。理由不是礼貌,是给模型的判断依据。约束的另一个作用是划范围:模型很喜欢「顺手」重构,不划线它会把改动面扩到你没法审的程度。一句「与本次任务无关的问题只在第一段列表里提一句,不要动手改」能省你很多审查时间。
四要素合起来,示例任务的第一版便签大概长这样(这是纯文本的提示词,不是代码):
你是一位负责代码审查的后端工程师,见过很多因为没校验输入而被打挂的接口,
习惯先列出所有会进来的字段,再逐个问它为空、超长、类型不对时会怎样。
对下面的 TODO API 代码做两件事:
1. 为创建与更新接口补上请求体校验,覆盖必填缺失、类型错误、
标题超过 200 字符、日期格式非法四类情况;失败统一返回 400 与可读的错误信息。
2. 为每类校验至少写一个单元测试,另加一个正常路径测试,框架沿用代码里已有的。
完成标准:所有测试能跑能过,测试名字不看代码就知道测的是哪种坏输入。
按顺序输出三段:不超过 5 条的校验缺口列表;修改后的接口代码(一个代码块);
测试文件(另一个代码块)。段与段之间不要客套话,不要输出没改的文件。
不要引入新的校验库,因为依赖要走审批。不要改接口路径、方法与成功响应结构,
因为已有前端在调。与本次无关的重构只在列表里提一句,不要动手。
(此处贴代码)对比一下最初那句「给 TODO API 补上输入校验和对应的单元测试」,字数多了十倍,但每一句都在回答一个「模型会猜错的地方」。这就是提示词工程最朴素的形态:不是更巧,是更全。
系统提示与用户消息:稳定的与变化的
上面那张便签是一整段文字,但真正通过 API 调用模型时,它会被拆成两个位置:系统提示(system prompt)和用户消息(user message)。系统提示是「这位同事入职时收到的那份岗位说明」,长期不变;用户消息是「今天这张便签」,每次都不一样。两者都是模型读到的上下文,区别在于稳定性和权重:系统提示在整段对话里始终生效,模型对它的遵从度通常更高;用户消息是对话的一部分,会随着对话变长而被后来的内容稀释。
于是有一条实用的分法:下一个任务还用得上的内容进系统提示,只对这一次成立的内容进用户消息。拿上面那张便签来拆:角色、格式规则、「不引入新依赖」「无关重构只提不改」这几条对这个团队的任何代码审查任务都成立,进系统提示;「覆盖哪四类校验」「不改路径与响应因为前端在调」「待改的代码」只对这次成立,进用户消息。注意「约束」被拆成了两半——四要素是写作时的分类,系统提示与用户消息是部署时的分类,两者不是一一对应的。
用代码来看这个拆分,两家 API 的形状很接近:
import Anthropic from '@anthropic-ai/sdk'
const client = new Anthropic() // 自动读 ANTHROPIC_API_KEY
// 系统提示:岗位说明,下一个任务还用得上的都放这里
const SYSTEM = [
'你是一位负责代码审查的后端工程师,习惯先列出所有会进来的字段,再逐个问边界情况。',
'输出按顺序三段:校验缺口列表(不超过 5 条)、修改后的代码(一个代码块)、测试文件(另一个代码块)。',
'不要引入新的依赖,因为依赖需要走审批。与本次任务无关的重构只提一句,不要动手改。',
].join('\n')
// 用户消息:今天这张便签,只对这一次成立
const task = [
'为创建与更新接口补上请求体校验,覆盖必填缺失、类型错误、标题超 200 字符、日期非法四类。',
'不要改接口路径、方法与成功响应,因为已有前端在调。',
'代码如下:',
code,
].join('\n')
const res = await client.messages.create({
model: 'claude-sonnet-5',
max_tokens: 4096,
system: SYSTEM,
messages: [{ role: 'user', content: task }],
})
console.log(res.content[0].type === 'text' ? res.content[0].text : '')from anthropic import Anthropic
client = Anthropic() # 自动读 ANTHROPIC_API_KEY
# 系统提示:岗位说明,下一个任务还用得上的都放这里
SYSTEM = "\n".join([
"你是一位负责代码审查的后端工程师,习惯先列出所有会进来的字段,再逐个问边界情况。",
"输出按顺序三段:校验缺口列表(不超过 5 条)、修改后的代码(一个代码块)、测试文件(另一个代码块)。",
"不要引入新的依赖,因为依赖需要走审批。与本次任务无关的重构只提一句,不要动手改。",
])
# 用户消息:今天这张便签,只对这一次成立
task = "\n".join([
"为创建与更新接口补上请求体校验,覆盖必填缺失、类型错误、标题超 200 字符、日期非法四类。",
"不要改接口路径、方法与成功响应,因为已有前端在调。",
"代码如下:",
code,
])
res = client.messages.create(
model="claude-sonnet-5",
max_tokens=4096,
system=SYSTEM,
messages=[{"role": "user", "content": task}],
)
print(res.content[0].text)为什么规则一定要放系统提示?三个工程上的理由。第一,稀释:一段多轮对话里,用户消息会越来越多,写在第一轮用户消息里的规则到第十轮时已经淹没在中间,模型遵从度明显下降;系统提示不参与这个稀释。第二,管控:产品里的系统提示通常由后端统一拼装,用户碰不到,规则放这里才能保证「所有用户都受同一套规则约束」,放用户消息就等于让规则跟用户输入混在一起。第三,成本:多数厂商的提示缓存(prompt caching)按前缀命中,系统提示是最稳定的前缀,把不变的部分集中在这里,后面几千次调用都能复用缓存,账单能便宜很多。D5 讲跨模型迁移时你会看到,系统提示的组织方式还直接决定了一份提示词换厂商时要改多少。
把示例任务写成第一版提示词
最后把今天的内容串成一个可以照做的流程,你在实验里会完整走一遍:
第一步,把原始需求原样写下来,不要修饰——「给一个 Express / FastAPI 的 TODO API 补上输入校验和对应的单元测试」。第二步,逐词找缺省与歧义:「校验」覆盖什么、「失败」返回什么、「单元测试」到什么粒度、用哪个框架、放哪里。每找到一个,就往四要素的某个格子里补一句。第三步,检查四个格子:角色有没有视角和关注点,任务有没有完成标准,格式能不能机械核对,约束有没有带理由。第四步,把每一句标上「长期不变」或「每次变化」,前者进系统提示,后者进用户消息。第五步,跑一次,把输出和你的完成标准对一对,差在哪里就回到第二步补哪一条。
这五步里没有任何技巧,全是把脑子里的默认信息搬到纸面上。但你会发现,走完一遍之后模型的输出稳定了很多——不是它变聪明了,是你把它要猜的东西都写死了。明天开始加技巧:给示例、让它先想再答、让它自己复查。但技巧是建在今天这张便签之上的,便签本身写不清楚,技巧只会放大混乱。
源码导读
动手实验
今天是文档型实验,不需要装依赖、不需要 API key。打开 labs/prompt-engineering-5days/day-01-four-part-template,先读 solution/ 里填好的示范,再回到 starter/ 自己填:
- 通读
solution/four-part-template.md,重点看每个要素后面「为什么这么写」那一行,理解每一句在补哪条模型缺的信息。 - 在
starter/four-part-template.md的第一部分为示例任务填写角色、任务、格式、约束四个空位,填完对着验收标准第 1–3 条自检。 - 填第二部分:把四要素逐条拆进系统提示与用户消息两栏,每条标上「长期不变」或「每次变化」,确认所有不变的都在系统提示栏。
- 填第三部分:找一个你最近真的问过 AI 且答得不好的问题,用同一张模板改写,改写前后各跑一次,写下改写后好在哪个可核对的点上。
面试题
今天 3 道题在下方题库区,围绕「提示词的本质」「四要素的分工」「系统提示为什么放规则」三个方向。每道题先看「分析过程」再看要点——分析过程教的是怎么推导,要点只是推导的落点。三道题都标了国内与海外通用。
检查清单与明日预告
- 能用自己的话解释提示词为什么不是命令,而是给模型的上下文
- 能把一句模糊需求拆成角色、任务、格式、约束四个要素并逐条写出来
- 能说出系统提示与用户消息的分工,并解释为什么规则要放系统提示
- 四要素模板的 5 条验收标准全部通过
- 3 道面试题不看要点也能答出至少 2 道
明天(D2)我们在这张便签上加技巧:给模型看几份「做好的活」(少样本示例)、让它先想再答(思维链)、把大任务拆成几张小便签再让它自己复查(分步与自检)。这些技巧网上到处都有,但我们会多讲一件几乎没人讲的事——每一种技巧各自的代价,以及在什么情况下它们一个都救不了你。先知道边界,再学技巧,才不会遇到问题时把所有技巧都往上堆。
面试题库
提示词工程到底在工程什么?它和写需求文档、写技术方案有什么本质区别?What exactly is being engineered in prompt engineering, and how does it differ from writing a requirements doc or a design spec?
国内高频海外高频基础#prompt-basics#mental-model分析过程 · 先想清楚再作答
- 这题在筛「有没有理解模型是在补全而不是执行」。答成「用巧妙的措辞让模型听话」会被判为只会用聊天产品;答出「系统性补齐模型缺少的上下文」才算入门。
- 拆法:先问自己「读者是谁」。需求文档的读者是有项目背景的人,可以依赖共享默认;提示词的读者是一个没有任何项目背景、也不会停下来提问的补全器,所有默认信息都得显式写出。
- 再落到「工程」二字:可复现、可测试、可版本化。提示词写完要能跑测试集、要进仓库、要能对比两版差异——这才是它区别于「写一段话」的地方。
- 结论:提示词工程是把隐性上下文显式化、并把这段文本当代码一样管理的工程活动;措辞技巧只是其中很小的一部分。
- 可预期的追问:那和写给外包团队的需求说明有什么区别?答案是外包会反问,模型不会,所以提示词对完整性的要求更高,且要在没有反馈回路的前提下自带完成标准。
How to reason about it · think before answering
- The screen here is whether the candidate knows the model completes text rather than executes commands. 'Clever wording that makes the model obey' signals chat-app experience only.
- Start from the reader: a spec is read by people who share project context; a prompt is read by a completer with zero context that never asks a clarifying question, so every implicit default must be spelled out.
- Then justify the word engineering: reproducibility, testability, versioning. A prompt should run against a test set, live in the repo, and diff cleanly between versions.
- Conclusion: prompt engineering is making implicit context explicit and managing that text like code; phrasing tricks are a small part.
- Likely follow-up: how is that different from a brief for an outsourced team? The team pushes back with questions; the model does not, so a prompt must carry its own completion criteria.
答题要点
- 模型在补全一段文本而不是执行命令,提示词是给它的上下文,写得越具体可能的下文越窄、输出越稳
- 工程的对象是「模型缺的信息」:视角、完成标准、输出形状、边界与理由,也就是四要素
- 区别于需求文档:读者没有共享背景、不会反问,所以完整性要求更高、必须自带完成标准
- 「工程」意味着可测试、可版本化、可对比,而不是一次性的巧妙措辞
Key points
- The model completes text rather than executing commands; a prompt is context, and specificity narrows the plausible continuations
- What gets engineered is the missing information: perspective, completion criteria, output shape, boundaries with reasons
- Unlike a spec, the reader shares no background and never asks back, so completeness and explicit done-criteria matter more
- Engineering implies testable, versioned, comparable artifacts, not one-off clever phrasing
角色、任务、格式、约束四要素各解决什么问题?如果只能保留三个,你会砍掉哪个,为什么?What problem does each of the four prompt elements — role, task, format, constraints — solve? If you could keep only three, which would you drop and why?
国内高频海外高频进阶#prompt-basics#four-elements分析过程 · 先想清楚再作答
- 前半句是送分,后半句才有区分度:它在考你是否知道每个要素对应模型的哪一种「猜」,以及哪种猜错的代价最小。
- 拆法:把每个要素映射到一个「模型会猜错的地方」——角色对应视角与关注点,任务对应终点在哪,格式对应输出能否被程序消费,约束对应改动范围与不可碰的边界。
- 判断哪个可砍:看缺了之后是「结果不稳定」还是「结果不可用」。缺角色多半是关注点偏了但仍可用;缺任务的完成标准会让模型不知何时停;缺格式会让下游解析失败;缺约束会让改动面失控。
- 结论:多数工程场景下角色最可砍,因为任务与格式写得足够具体时视角已经被隐含;但要说明前提是任务里已经写清了关注点。
- 追问几乎必然是「那为什么大家还都写角色」——答案是它便宜且能一句话压缩大量隐性偏好,在任务没法写得很细的对话场景里性价比最高。
How to reason about it · think before answering
- The first half is a warm-up; the second half tests whether you can map each element to a specific way the model would otherwise guess, and rank the cost of each wrong guess.
- Map them: role fixes perspective and focus, task fixes the finish line, format decides whether downstream code can consume the output, constraints bound the change surface.
- To pick the one to drop, ask whether its absence makes results unstable or unusable. Missing role skews focus but stays usable; missing done-criteria means the model never knows when to stop; missing format breaks parsers; missing constraints lets edits sprawl.
- Conclusion: in most engineering settings role is the most droppable, because a specific task plus a strict format already imply the perspective — provided the task states what to care about.
- Expect the follow-up 'then why does everyone write a role?' Because it is cheap and compresses many implicit preferences into one line, which pays off in chat-style use where the task cannot be fully specified.
答题要点
- 角色定视角与关注点;任务定做什么与完成标准;格式定输出形状是否可机械核对;约束定不可碰的边界与理由
- 每个要素对应模型的一种「猜」,缺哪个就多一种不稳定
- 可砍的是角色:任务与格式足够具体时视角已隐含,但前提是任务里写清了关注点
- 任务的完成标准与格式的可核对性最不能省,因为它们直接决定输出能不能被程序消费
Key points
- Role sets perspective; task sets the goal and done-criteria; format makes output mechanically checkable; constraints bound scope with reasons
- Each element removes one kind of guess the model would otherwise make
- Role is the most droppable once task and format are specific enough to imply the perspective
- Done-criteria and checkable format are the least negotiable because downstream code depends on them
为什么规则要放系统提示而不是用户消息?请从遵从度、管控和成本三个角度说明,并指出系统提示做不到什么。Why do rules belong in the system prompt rather than the user message? Cover adherence, control, and cost, and name what the system prompt cannot guarantee.
国内高频海外高频进阶#system-prompt#prompt-basics分析过程 · 先想清楚再作答
- 题眼在「三个角度」和「做不到什么」。只答「系统提示权重高」是背概念,面试官要看的是你有没有在生产里拼过系统提示。
- 拆法:遵从度看多轮稀释——用户消息会被后续对话淹没,系统提示全程生效;管控看谁能改——系统提示由后端统一拼装、用户碰不到,规则放这里才能对所有用户一致;成本看缓存——提示缓存按前缀命中,系统提示是最稳定的前缀。
- 「做不到什么」是区分度所在:系统提示遵从度高不等于绝对,提示注入可以让模型跑偏,所以安全边界不能只靠系统提示,要在模型外用代码兜底。
- 结论:规则进系统提示是为了稳定、一致、省钱;但它是「强建议」不是「硬约束」,硬约束必须在代码层实现。
- 追问方向:系统提示可以放在对话末尾吗?可以但不推荐——多数模型对靠前指令更敏感,且会破坏缓存前缀;另一个追问是「哪些内容不该进系统提示」,答案是每次都变的任务细节,放进去会让缓存失效且难以复用。
How to reason about it · think before answering
- The tell is whether you cover all three angles and name a limitation. 'System prompts carry more weight' alone reads as memorized.
- Adherence: user turns get diluted as the conversation grows, the system prompt stays in force. Control: the backend assembles the system prompt and users cannot touch it, so rules apply uniformly. Cost: prompt caching matches on prefixes, and the system prompt is the most stable prefix.
- The limitation is the differentiator: higher adherence is not a guarantee, prompt injection can still steer the model, so security boundaries need code-level enforcement outside the model.
- Conclusion: rules go in the system prompt for stability, consistency and cost, but it is a strong suggestion, not a hard constraint.
- Follow-ups: can the system prompt go last? Possible but unwise — models weight early instructions more and it breaks the cache prefix. What should stay out? Per-request task details, which would bust the cache and hurt reuse.
答题要点
- 遵从度:用户消息会被多轮对话稀释,系统提示全程生效
- 管控:系统提示由后端统一拼装,用户碰不到,规则才能对所有人一致
- 成本:提示缓存按前缀命中,系统提示是最稳定的前缀,不变的内容集中在这里最省钱
- 做不到的:它不是安全边界,提示注入可以绕过,硬约束必须在代码层兜底
Key points
- Adherence: user turns get diluted over a long conversation, the system prompt stays in force
- Control: the backend assembles it and users cannot edit it, so rules apply to everyone
- Cost: prompt caching matches prefixes, so stable content in the system prompt maximizes cache hits
- Limit: it is not a security boundary; prompt injection can bypass it, so enforce hard rules in code
评论
登录后即可参与讨论
还没有评论,来说第一句。