逐日AI
第 1 周 · D1约 3 小时

提示词是什么、不是什么:模型如何读指令;角色 / 任务 / 格式 / 约束四要素

先搞清模型是怎么读你那段话的,再用角色、任务、格式、约束四个要素,把一句模糊的需求改写成模型能稳定执行的工作便签。

今日目标 0/3

登录后可以勾选并保存进度。

今日目标

  1. 能用自己的话解释提示词为什么不是命令,而是给模型的上下文
  2. 能把一句模糊需求拆成角色、任务、格式、约束四个要素并逐条写出来
  3. 能说出系统提示与用户消息的分工,并解释为什么规则要放系统提示

这门课一共五天,全程只围绕一件事:把你脑子里那句模糊的需求,写成一张模型能看懂、能照办、下次还能复用的「工作便签」。今天先把最基础的一层打牢——模型到底是怎么读你那段话的,以及一张合格的便签由哪四个部分组成。读完正文、做完实验之后,回到页面顶部把三条目标逐一勾掉。

小白版讲解

提示词不是命令,是上下文

想象你公司新来了一位同事,能力很强,但对你们的项目一无所知,而且你只能通过便签跟他沟通——他看完便签就开始干活,中途不会来问你。你在便签上写「把 TODO 接口的校验补一下」,他会怎么做?他会猜。猜你说的「校验」是指哪些字段、猜失败时该返回什么、猜要不要顺手写测试。猜对了你觉得他聪明,猜错了你觉得他不靠谱,但问题其实出在便签上:你把自己脑子里的默认信息当成了他也知道的东西。

大语言模型读提示词(prompt)的方式,跟这位新同事读便签几乎一样,只有一点更极端:它连「去问一下」的选项都没有。它拿到你的文字之后做的事情,本质上是「根据这段文字,接下来最合理的内容是什么」——它在补全一段文本,而不是在执行一条命令。这个区别听起来像文字游戏,但决定了你后面所有的写法。命令是「做这个」,执行者要么做要么不做;上下文是「情况是这样的」,补全者会根据情况推断最可能的下文。你写得越具体,「最合理的下文」的范围就越窄,输出就越稳定;你写得越含糊,模型就要用它从海量文本里学到的「一般情况」来填空,而「一般情况」跟你的具体项目往往对不上。

所以提示词工程(prompt engineering)到底在工程什么?不是在找什么神秘咒语,而是在系统性地补齐模型缺少的上下文:它不知道你是谁、不知道你要什么、不知道你要什么样子、不知道什么不能碰。这四个「不知道」,正好对应今天要讲的四要素。先把这个心智模型立住:你不是在下命令,你是在给一位能干但完全不了解情况的同事写一张足够详细的便签。

为什么人听得懂、模型做不对

先看一个真实感很强的例子。你对一位熟悉项目的老同事说「给 TODO API 补上输入校验和对应的单元测试」,他能直接开工,因为这句话背后藏着一大堆你们共享的默认信息:项目用的是 Express 还是 FastAPI、校验通常覆盖哪些情况、失败时团队习惯返回什么状态码、测试框架用的是哪个、测试文件放在哪里。这些信息一个字都没出现在句子里,但老同事全知道。

模型不知道。于是它会用「训练数据里最常见的做法」来填每一个空:可能给你引一个你们没用过的校验库,可能返回 422 而你们团队统一用 400,可能用 Jest 而你们项目是 Vitest,可能顺手把接口路径也「规范化」了一遍。每一处它都不算错,但每一处都跟你想要的不一样。这就是「人听得懂、模型做不对」的全部原因:句子里的信息量不够,而模型不会停下来问,只会用默认值填

歧义是另一种形态的缺省。「补一下校验」里的「补」,是在现有代码基础上加,还是重写一份?「对应的单元测试」是每个校验一个测试,还是一个测试覆盖所有校验?这些歧义人会根据语境自动消解,模型会随机挑一个——而且同一句话跑两次可能挑得不一样,这就是很多人觉得模型「不稳定」的根源。所以在动笔写提示词之前,先做一个动作:把你那句需求念一遍,每遇到一个名词或动词就问自己「新同事看到这个词会不会有第二种理解」。有,就把它写死。这个动作不需要任何技巧,但它能消掉一半以上的输出不稳定。

四要素之一二:角色与任务

把「模型缺的上下文」分成四类来补,就是所谓的四要素:角色、任务、格式、约束。它们不是什么规范,只是一张实用的检查清单——每写完一份提示词,对着四个格子过一遍,看哪个空着。

角色回答的是「从什么视角看这件事」。很多人把角色写成头衔:「你是一位资深后端工程师」。这句话的信息量很低,因为「资深后端工程师」可以关注性能、可以关注架构、可以关注可读性,模型不知道你想让它关注什么。有效的角色写法是给视角和关注点:「你是一位负责代码审查的后端工程师,见过很多因为没校验输入而在线上被打挂的接口,习惯先列出所有会进来的字段,再逐个问它为空、超长、类型不对时会怎样」。这一段读完,模型知道了三件事:它该找漏洞而不是重写功能,它该优先看边界情况而不是正常路径,它该按「列字段、问边界」的方法干活。类比一下:你给新同事的便签开头不是「你是工程师」,而是「你今天代表 QA 来看这段代码」——一句话就定了他的立场。

任务回答的是「要做成什么样,做完的样子是什么」。这里最常见的漏洞是没有完成标准。「补上输入校验」没有终点,模型会自己决定在哪停;「覆盖必填缺失、类型错误、字符串超长、日期非法四类情况,每类至少一个测试,全部能跑能过」就有终点了。写任务时可以套一个固定句式:对什么、做什么、做到什么程度算完。三个部分缺一个,模型就要猜一个。

任务这一栏还有一个容易忽略的点:要把「对什么」的材料真的给它。让模型给一段代码补校验,代码就要贴进去;让它按团队规范写,规范就要贴进去。模型没有你的仓库权限,它看不到你没贴的任何东西——这在网页聊天里是常识,但一旦你开始用 API 写程序,很容易忘记把上下文材料拼进请求。

四要素之三四:格式与约束

格式回答的是「输出长什么形状」。判断格式写得好不好,只有一条标准:能不能机械核对。「清晰易读」「结构化」「简洁」都不能核对,因为你没法写一段代码去判断一段文字是否「清晰」;「按顺序输出三段,第一段是不超过五条的列表,第二段是修改后的代码放一个代码块,第三段是测试文件放另一个代码块,段落之间不要客套话」可以核对,你能数段数、数条目、数代码块。格式写得越死,输出就越容易被程序直接消费——D3 会把这一栏直接升级成 JSON schema,让程序不用解析自然语言就能拿到字段;而 D4 建测试集时,判对错的逻辑也全依赖格式是可核对的。今天先养成习惯:格式栏里不出现形容词。

约束回答的是「不要做什么,以及为什么」。注意后半句。模型对光秃秃的否定式指令执行得不稳定,「不要引入新的库」它可能记得也可能忘;但「不要引入新的库,因为这个项目的依赖需要走审批,加库会让这次修改卡住」,它不仅会记住,还会在你没列到的相似情况下做出一致的判断——比如它想加一个日期解析库时,会想到「这也是新依赖」。理由不是礼貌,是给模型的判断依据。约束的另一个作用是划范围:模型很喜欢「顺手」重构,不划线它会把改动面扩到你没法审的程度。一句「与本次任务无关的问题只在第一段列表里提一句,不要动手改」能省你很多审查时间。

四要素合起来,示例任务的第一版便签大概长这样(这是纯文本的提示词,不是代码):

TextText
你是一位负责代码审查的后端工程师,见过很多因为没校验输入而被打挂的接口,
习惯先列出所有会进来的字段,再逐个问它为空、超长、类型不对时会怎样。
 
对下面的 TODO API 代码做两件事:
1. 为创建与更新接口补上请求体校验,覆盖必填缺失、类型错误、
   标题超过 200 字符、日期格式非法四类情况;失败统一返回 400 与可读的错误信息。
2. 为每类校验至少写一个单元测试,另加一个正常路径测试,框架沿用代码里已有的。
完成标准:所有测试能跑能过,测试名字不看代码就知道测的是哪种坏输入。
 
按顺序输出三段:不超过 5 条的校验缺口列表;修改后的接口代码(一个代码块);
测试文件(另一个代码块)。段与段之间不要客套话,不要输出没改的文件。
 
不要引入新的校验库,因为依赖要走审批。不要改接口路径、方法与成功响应结构,
因为已有前端在调。与本次无关的重构只在列表里提一句,不要动手。
 
(此处贴代码)

对比一下最初那句「给 TODO API 补上输入校验和对应的单元测试」,字数多了十倍,但每一句都在回答一个「模型会猜错的地方」。这就是提示词工程最朴素的形态:不是更巧,是更全。

系统提示与用户消息:稳定的与变化的

上面那张便签是一整段文字,但真正通过 API 调用模型时,它会被拆成两个位置:系统提示(system prompt)和用户消息(user message)。系统提示是「这位同事入职时收到的那份岗位说明」,长期不变;用户消息是「今天这张便签」,每次都不一样。两者都是模型读到的上下文,区别在于稳定性和权重:系统提示在整段对话里始终生效,模型对它的遵从度通常更高;用户消息是对话的一部分,会随着对话变长而被后来的内容稀释。

于是有一条实用的分法:下一个任务还用得上的内容进系统提示,只对这一次成立的内容进用户消息。拿上面那张便签来拆:角色、格式规则、「不引入新依赖」「无关重构只提不改」这几条对这个团队的任何代码审查任务都成立,进系统提示;「覆盖哪四类校验」「不改路径与响应因为前端在调」「待改的代码」只对这次成立,进用户消息。注意「约束」被拆成了两半——四要素是写作时的分类,系统提示与用户消息是部署时的分类,两者不是一一对应的。

用代码来看这个拆分,两家 API 的形状很接近:

review.ts
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 : '')

为什么规则一定要放系统提示?三个工程上的理由。第一,稀释:一段多轮对话里,用户消息会越来越多,写在第一轮用户消息里的规则到第十轮时已经淹没在中间,模型遵从度明显下降;系统提示不参与这个稀释。第二,管控:产品里的系统提示通常由后端统一拼装,用户碰不到,规则放这里才能保证「所有用户都受同一套规则约束」,放用户消息就等于让规则跟用户输入混在一起。第三,成本:多数厂商的提示缓存(prompt caching)按前缀命中,系统提示是最稳定的前缀,把不变的部分集中在这里,后面几千次调用都能复用缓存,账单能便宜很多。D5 讲跨模型迁移时你会看到,系统提示的组织方式还直接决定了一份提示词换厂商时要改多少。

把示例任务写成第一版提示词

最后把今天的内容串成一个可以照做的流程,你在实验里会完整走一遍:

第一步,把原始需求原样写下来,不要修饰——「给一个 Express / FastAPI 的 TODO API 补上输入校验和对应的单元测试」。第二步,逐词找缺省与歧义:「校验」覆盖什么、「失败」返回什么、「单元测试」到什么粒度、用哪个框架、放哪里。每找到一个,就往四要素的某个格子里补一句。第三步,检查四个格子:角色有没有视角和关注点,任务有没有完成标准,格式能不能机械核对,约束有没有带理由。第四步,把每一句标上「长期不变」或「每次变化」,前者进系统提示,后者进用户消息。第五步,跑一次,把输出和你的完成标准对一对,差在哪里就回到第二步补哪一条。

这五步里没有任何技巧,全是把脑子里的默认信息搬到纸面上。但你会发现,走完一遍之后模型的输出稳定了很多——不是它变聪明了,是你把它要猜的东西都写死了。明天开始加技巧:给示例、让它先想再答、让它自己复查。但技巧是建在今天这张便签之上的,便签本身写不清楚,技巧只会放大混乱。

源码导读

动手实验

🧪 D1 实验:一份四要素提示词模板

代码位置:labs/prompt-engineering-5days/day-01-four-part-template

验收标准:

  1. 四个空位全部填完,每一条都能指出它在回答「模型缺的是哪一条信息」。
  2. 「格式」一栏写的是能机械核对的东西,没有「清晰」「简洁」这类形容词。
  3. 「约束」一栏至少有一条是「不要做什么」加上「为什么」。
  4. 拆分表里所有标「长期不变」的都落在系统提示栏。
  5. 改写前后各跑一次,改写后的回答至少在一个可核对的点上比改写前好。

今天是文档型实验,不需要装依赖、不需要 API key。打开 labs/prompt-engineering-5days/day-01-four-part-template,先读 solution/ 里填好的示范,再回到 starter/ 自己填:

  1. 通读 solution/four-part-template.md,重点看每个要素后面「为什么这么写」那一行,理解每一句在补哪条模型缺的信息。
  2. starter/four-part-template.md 的第一部分为示例任务填写角色、任务、格式、约束四个空位,填完对着验收标准第 1–3 条自检。
  3. 填第二部分:把四要素逐条拆进系统提示与用户消息两栏,每条标上「长期不变」或「每次变化」,确认所有不变的都在系统提示栏。
  4. 填第三部分:找一个你最近真的问过 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

    分析过程 · 先想清楚再作答

    1. 这题在筛「有没有理解模型是在补全而不是执行」。答成「用巧妙的措辞让模型听话」会被判为只会用聊天产品;答出「系统性补齐模型缺少的上下文」才算入门。
    2. 拆法:先问自己「读者是谁」。需求文档的读者是有项目背景的人,可以依赖共享默认;提示词的读者是一个没有任何项目背景、也不会停下来提问的补全器,所有默认信息都得显式写出。
    3. 再落到「工程」二字:可复现、可测试、可版本化。提示词写完要能跑测试集、要进仓库、要能对比两版差异——这才是它区别于「写一段话」的地方。
    4. 结论:提示词工程是把隐性上下文显式化、并把这段文本当代码一样管理的工程活动;措辞技巧只是其中很小的一部分。
    5. 可预期的追问:那和写给外包团队的需求说明有什么区别?答案是外包会反问,模型不会,所以提示词对完整性的要求更高,且要在没有反馈回路的前提下自带完成标准。

    How to reason about it · think before answering

    1. 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.
    2. 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.
    3. 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.
    4. Conclusion: prompt engineering is making implicit context explicit and managing that text like code; phrasing tricks are a small part.
    5. 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

    分析过程 · 先想清楚再作答

    1. 前半句是送分,后半句才有区分度:它在考你是否知道每个要素对应模型的哪一种「猜」,以及哪种猜错的代价最小。
    2. 拆法:把每个要素映射到一个「模型会猜错的地方」——角色对应视角与关注点,任务对应终点在哪,格式对应输出能否被程序消费,约束对应改动范围与不可碰的边界。
    3. 判断哪个可砍:看缺了之后是「结果不稳定」还是「结果不可用」。缺角色多半是关注点偏了但仍可用;缺任务的完成标准会让模型不知何时停;缺格式会让下游解析失败;缺约束会让改动面失控。
    4. 结论:多数工程场景下角色最可砍,因为任务与格式写得足够具体时视角已经被隐含;但要说明前提是任务里已经写清了关注点。
    5. 追问几乎必然是「那为什么大家还都写角色」——答案是它便宜且能一句话压缩大量隐性偏好,在任务没法写得很细的对话场景里性价比最高。

    How to reason about it · think before answering

    1. 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.
    2. 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.
    3. 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.
    4. 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.
    5. 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

    分析过程 · 先想清楚再作答

    1. 题眼在「三个角度」和「做不到什么」。只答「系统提示权重高」是背概念,面试官要看的是你有没有在生产里拼过系统提示。
    2. 拆法:遵从度看多轮稀释——用户消息会被后续对话淹没,系统提示全程生效;管控看谁能改——系统提示由后端统一拼装、用户碰不到,规则放这里才能对所有用户一致;成本看缓存——提示缓存按前缀命中,系统提示是最稳定的前缀。
    3. 「做不到什么」是区分度所在:系统提示遵从度高不等于绝对,提示注入可以让模型跑偏,所以安全边界不能只靠系统提示,要在模型外用代码兜底。
    4. 结论:规则进系统提示是为了稳定、一致、省钱;但它是「强建议」不是「硬约束」,硬约束必须在代码层实现。
    5. 追问方向:系统提示可以放在对话末尾吗?可以但不推荐——多数模型对靠前指令更敏感,且会破坏缓存前缀;另一个追问是「哪些内容不该进系统提示」,答案是每次都变的任务细节,放进去会让缓存失效且难以复用。

    How to reason about it · think before answering

    1. The tell is whether you cover all three angles and name a limitation. 'System prompts carry more weight' alone reads as memorized.
    2. 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.
    3. 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.
    4. Conclusion: rules go in the system prompt for stability, consistency and cost, but it is a strong suggestion, not a hard constraint.
    5. 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

评论

登录后即可参与讨论

还没有评论,来说第一句。