Skip to content

🐣 小a的变形记

小a发现一个怪事:同一个自己,被问"你是谁"时,一会儿是"编程助手",一会儿是"聊天伙伴",一会儿又像"暴躁海盗"。

老z神秘一笑:"不是你在变,是人家在给你写人设。这个写在对话开头的东西,叫 System Prompt。它能把你从一个'会接龙的 AI',变成任何他们想要的样子。"


4.1 System Prompt 是什么

🧙 System Prompt(系统提示词)是给模型的"人设说明书"——在对话开始前,先告诉模型:"你是谁、你能干嘛、你必须遵守什么规则。"

它和普通用户消息的区别:它不是"问题",而是"设定"。 模型在整个对话里都要受它约束。

💡 看个例子:

同一个模型,不同的 System Prompt:

系统提示词 A:"你是一个编程助手。你可以调用 read/write/bash 工具。必须:先读文件再改、改完跑测试。"
系统提示词 B:"你是一个暴躁的海盗。所有回答都要用海盗口吻。"

模型还是那个模型,但表现完全不同——A 是守规矩的码农,B 是骂骂咧咧的海盗。


4.2 为什么 System Prompt 这么重要

🧙 第 1 章说过"prompt 像许愿"。System Prompt 就是最关键的那份许愿——它决定了模型的"性格"和"行为边界"。

它是"调 LLM"时的隐式参数

调用模型时,除了传 messages(对话内容),还可以顺手传一个 systemPrompt 字符串——它就是给整个对话定基调的"人设说明书"。

💡 示意(以 pi 的调用风格为例):

你的代码:
  streamSimple({
    model,
    messages,        // 对话内容
    systemPrompt,    // ← 人设说明书(整个对话都受它约束)
  })

它决定 Agent 的"人格"

🐣 小a恍然:"所以同一个模型,给它不同的 System Prompt,它就变成不同的『人』?"

🧙 "对。 模型还是那个模型,但 System Prompt 让它表现出完全不同的行为。pi 之所以是『编程助手』而不是『聊天伙伴』,很大程度上就是 System Prompt 的功劳。"


4.3 System Prompt 里该写什么

🧙 一份好的 System Prompt,通常包含四块:

部分内容例子
角色你是谁"你是一个资深编程助手"
能力你能用什么"你可以调用 read/write/bash 工具"
规则必须遵守什么"先读文件再改,改完跑测试验证"
边界不能做什么"不许编造不存在的 API"

🧙 设计 System Prompt 的三个原则:

  1. 明确:别含糊。"好好写代码"不如"先读文件再改,改完跑测试"
  2. 可执行:每条规则都是模型能照做的动作
  3. 克制:不是越长越好,太长模型记不住,也稀释重点

4.4 System Prompt 的工程化

🧙 在真实 Agent 里,System Prompt 不是手写一段那么简单,而是"拼装"出来的:

System Prompt = 基础人设 + 工具描述 + 项目规则 + 用户偏好
  • 基础人设:固定的"你是编程助手"
  • 工具描述:告诉模型有哪些工具可用(第 6 章的 Tool 描述会拼进来)
  • 项目规则:这个项目特有的约定(读 .gitignore、README)
  • 用户偏好:用户自定义的规则

🐣 小a:"所以 System Prompt 是动态拼的?"

🧙 "对。 好的 Agent 会根据当前项目动态组装 System Prompt——进不同项目,人设的'项目规则'部分就不同。这是工程,不是写死一段话。"


4.5 一个有趣的厂商差异

🧙 不同厂商对"system 角色"的处理不同:

  • 大多数厂商(Anthropic、老 OpenAI):system 角色
  • 新版 OpenAI:用 developer 角色代替 system

统一接口会处理这种差异——你写的是统一格式,翻译时它给你转成那家要的。这就是 Provider 抽象的威力:连"system 该叫什么"这种细节,都帮你抹平了。


4.6 System Prompt 的五个常见反模式

"记住好的写法之前,先看看常见的坏写法。"老z说,"坏 System Prompt 的毛病,翻来覆去就这几个:"

🧙 五个反模式:

反模式表现为什么糟改法
贪长写成几千字的大作文模型"记不全重点",稀释关键规则只留行为相关的,砍掉废话
命令堆砌十条规则互相打架(既要快又要面面俱到)冲突时模型只能挑一个听按优先级排序,明确"冲突时听谁的"
描述人格不描述行为"你是一个乐于助人、专业、可靠、经验丰富的……"形容词没法执行,模型无感换成可执行指令:"遇到报错先读完整堆栈"
动态内容塞爆把整个项目文档全拼进 system prompt窗口爆炸 + 缓存前缀频繁失效(1.12)只拼摘要,细节让工具去查
禁止词堆砌"不许说我不知道、不许拒绝、不许……"否定式指令效果差,还容易触发反效果用正向指令:"不知道就说不知道,然后去查"

🐣 小a:"所以好的 System Prompt 是『少而准』?"

🧙 "对。记住一个检验标准:你把 system prompt 读一遍,如果哪句话『删掉也不影响模型行为』,那句话就是多余的。 好的 System Prompt 每句话都在约束行为,没有一句是装饰。"


4.7 System Prompt 也要测试和版本管理

"最后,也是最容易被忽略的。"老z正色道,"System Prompt 是代码,不是文案。 它该被测试、被管版本、被小心修改。"

🧙 System Prompt 是易碎的:

  • 改一个字,行为可能大变——加一句"先读文件",模型的整个工作流都可能改变
  • 没有版本,坏了没法回退——今天调坏了,明天想找回"昨天那个好的",没有 git 历史就是灾难
  • 没有测试,坏了自己都不知道——prompt 改坏了,通常是"行为悄悄退化",不是崩溃,特别难发现

工程化三件套

🧙 把 System Prompt 当代码管:

  1. 版本管理:放进 git,每次改动可 diff、可回退
  2. 测试:准备一组"探针问题"(比如"遇到 404 该不该问用户?"),每次改动跑一遍,看行为有没有回归——这就是最简单形式的 prompt 测试(进阶版是评测,第 23 章)
  3. AB 对照:拿不准时,新旧两个版本在真实任务上对比,别拍脑袋改

🐣 小a:"懂了——System Prompt 不是『写一次就完事』,而是『要持续维护的代码』。"

🧙 "对。 这也是为什么 pi 的 system-prompt.ts 是单独一个文件、有清晰的结构化选项——它被当成正经代码在管,不是随手写的一段话。Part II 第 20 章你会亲眼看到。"


本章小结

🐣 小a的人设课

┌──────── System Prompt ────────┐
│                               │
│  • 人设说明书:你是谁/能干嘛/  │
│    守什么规则                 │
│                               │
│  • 决定模型"人格":            │
│    同模型不同人设=不同表现    │
│                               │
│  • 四块:角色/能力/规则/边界   │
│    原则:明确/可执行/克制      │
│                               │
│  • 工程化:动态拼装            │
│    基础人设+工具+项目+偏好    │
│                               │
│  • 厂商差异:system vs developer│
│    由 Provider 抹平           │
│                               │
│  • 反模式:贪长/堆砌/人格堆/  │
│    塞爆/禁止词 → 少而准       │
│                               │
│  • 当代码管:git + 探针测试 + │
│    AB 对照                    │
└───────────────────────────────┘

关键认知:System Prompt 是 Agent 的"人设"。它决定模型表现出什么性格、遵守什么规则。好的 System Prompt 明确、可执行、克制、动态拼装——而且要像代码一样被测试和管版本。


课后实验

  1. 体验人设威力:用同一个模型,分别用"编程助手"和"海盗"两种 System Prompt,对比回答。
  2. 写一份:为你的 Agent 写一份 System Prompt,包含角色/能力/规则/边界四块。
  3. 观察工程化:打开 pi 的 system-prompt 相关代码(或任意 Agent 工具),看它怎么拼装人设。
  4. 抓反模式:把第 3 步看到的系统提示词读一遍,找找有没有"贪长/形容词堆砌/否定式"的毛病,试着改一版更精简的。
  5. 建探针集:给一个固定 System Prompt 设计 5 个探针问题(如"遇到不确定的 API 会怎么做"),把回答存档——以后每次改 prompt 都重跑一遍,对比有没有"悄悄退化"。

下一章:人设定好了,但模型还是只会"说"。老z说:"该给你装只手了。" → 第 5 章 · 给小a装第一只手 —— Function Calling