🦞 一只用 AI Agent 搭副业产线的程序员


上篇我们说了 Prompt 要当代码写。但代码需要架构。

这篇文章给你 Prompt 架构的第一层:System Prompt 和 User Prompt 的分工。很多人混在一起用,结果就是 Prompt 一长就失控。

别混。这两个角色天然不同。


先搞清楚:AI 收到的不是一段话,是两个人

每次调用 API,你传的 Messages 数组里有一个 role 字段。可以填三种:

Role 谁说的 干什么的
system 你(开发者) 定义 AI 的行为规则、角色、边界
user 用户 具体的任务、问题、输入
assistant AI 历史回复(多轮对话用)

这三者的关系像什么?

System Prompt  = 员工手册(入职第一天发的,管所有行为)
User Prompt    = 任务单(每天变化的,管这一个任务)
Assistant      = 工作日志(之前干了啥,管上下文连续性)

一个反例:混在一起会怎样

很多人这样写 Prompt:

你是一个优秀的 Go 后端开发,有 10 年经验,擅长写高性能代码。
你的回答要简洁、准确、代码完整可运行。不要写废话。
现在帮我写一个 LRU 缓存。
哦对了,用泛型。要有测试。还有……

这有什么问题?角色定义和具体任务搅在一起。 每次新任务,你都要把角色定义再说一遍。想复用角色设定?复制粘贴。想换一个角色?全删了重写。

更糟的是——如果你在一个循环 Agent 里用这种 Prompt,每一轮都要重复发送角色描述。10 轮对话,角色重复了 10 次,全是钱的流失。


正确的分层

// System Prompt —— 一次定义,永久复用
systemPrompt := `你是 Go 后端开发专家。

行为规则:
1. 代码完整可编译,不省略 import 和 package 声明
2. 所有公开函数包含 godoc 注释
3. 不确定的 API 明确说"不确定",不编造
4. 不要解释代码为什么这样写,除非被问到

输出约束:
- 代码块使用 ```go 标记
- 错误处理不要用 panic,用 fmt.Errorf 包装
- 时间相关的逻辑使用 time.Time,不要用字符串`
// User Prompt —— 每次不同,只管任务
userPrompt := `用 Go 泛型实现一个线程安全的 LRU 缓存。
要求:
- 支持 Get、Put、Len 方法
- 容量满了淘汰最久未使用的
- 并发安全`

这样分开后,System Prompt 你可以复用 100 次、1000 次。User Prompt 只管这一次的任务。


用 JSON 配置驱动 Prompt 管理

更进一步——把 System Prompt 从代码里抽出来,用配置文件管理:

{
  "roles": {
    "go-backend-dev": {
      "name": "Go 后端开发专家",
      "system": "你是 Go 后端开发专家。代码完整可编译,不确定的 API 明确说不知道。输出简洁精准。",
      "temperature": 0.1,
      "max_tokens": 500
    },
    "code-reviewer": {
      "name": "代码审查员",
      "system": "你是代码审查员。只找问题,不表扬。按严重程度排序:高危 > 中危 > 低危。每个问题标注行号。",
      "temperature": 0.0,
      "max_tokens": 800
    },
    "doc-writer": {
      "name": "技术文档写手",
      "system": "你是技术文档写手。写中文 godoc 风格注释。准确、简洁、不说废话。",
      "temperature": 0.3,
      "max_tokens": 1000
    },
    "rubber-duck": {
      "name": "小黄鸭调试助手",
      "system": "你是小黄鸭调试助手。用户会向你解释代码逻辑。你的任务是通过提问帮他发现思维盲区。不要直接给答案。用苏格拉底式提问。",
      "temperature": 0.7,
      "max_tokens": 300
    }
  }
}

然后在 Go 代码里加载:

package main

import (
    "encoding/json"
    "fmt"
    "os"
)

type RoleConfig struct {
    Name        string  `json:"name"`
    System      string  `json:"system"`
    Temperature float64 `json:"temperature"`
    MaxTokens   int     `json:"max_tokens"`
}

type Config struct {
    Roles map[string]RoleConfig `json:"roles"`
}

type PromptManager struct {
    config *Config
}

func NewPromptManager(configPath string) (*PromptManager, error) {
    data, err := os.ReadFile(configPath)
    if err != nil {
        return nil, err
    }
    var cfg Config
    json.Unmarshal(data, &cfg)
    return &PromptManager{config: &cfg}, nil
}

func (pm *PromptManager) BuildMessages(roleKey string, userPrompt string) ([]Message, float64, int, error) {
    role, ok := pm.config.Roles[roleKey]
    if !ok {
        return nil, 0, 0, fmt.Errorf("未知角色: %s", roleKey)
    }

    messages := []Message{
        {Role: "system", Content: role.System},
        {Role: "user", Content: userPrompt},
    }
    return messages, role.Temperature, role.MaxTokens, nil
}

func main() {
    pm, _ := NewPromptManager("roles.json")

    // 换角色只需要换一个 key
    messages, temp, maxTok, _ := pm.BuildMessages("go-backend-dev",
        "写一个 WebSocket 心跳检测函数")

    result := callLLM(messages, temp, maxTok)
    fmt.Println(result)

    // 同一个代码库,不同的角色
    messages2, temp2, maxTok2, _ := pm.BuildMessages("code-reviewer",
        result) // 把刚生成的代码丢给审查员

    review := callLLM(messages2, temp2, maxTok2)
    fmt.Println(review)
}

切换角色现在是一行代码的事。团队里不同的人可以复用同一个角色库。


System Prompt 写什么的 4 层模型

内容 示例
第 1 层:角色定义 AI 是什么身份 「你是 Go 后端开发专家」
第 2 层:行为规则 怎么做事 「代码完整可编译,不确定的说不知道」
第 3 层:输出约束 输出什么格式 「用 ```go 代码块,不输出解释」
第 4 层:禁止事项 不要做什么 「不要编造 API,不要用 panic」

第 1 层是必须的,第 2-4 层根据任务复杂度选配。简单任务可能只需要第 1 层 + 第 3 层。


一个真实的坑:System Prompt 太长

我一开始给 Agent 写的 System Prompt 有 3000 字,规定了各种场景下的行为。结果呢?

AI 经常「忘记」后面的规则。因为 System Prompt 太长,离得远的规则权重降低了。

后来我优化成 200 字以内,只保留最重要的 3-4 条规则。准确率反而提高了。

System Prompt 不是越长越好。是越精越好。


User Prompt 怎么写:三段式模板

[任务] 用 Go 实现一个带过期时间的本地缓存。
[输入] 无
[输出] 完整可编译的 Go 代码,包含:
  - Set(key, value, ttl) 方法
  - Get(key) (value, bool) 方法
  - 过期自动清理机制

三段式:任务 + 输入 + 输出。简洁明确,不给 AI 发挥空间。


总结:一张表分清 System 和 User

System Prompt User Prompt
谁写 你(开发者) 你(或最终用户)
频率 写一次,复用多次 每次任务不同
内容 角色、规则、约束 具体任务、输入数据
维护方式 JSON 配置文件 代码里拼接或模板
长度 尽量短,200 字内 根据任务复杂度
类比 员工手册 任务单

下一篇我们搞一个实验——同一个任务,用 Few-shot(给示例)和 Zero-shot(不给示例)各跑 50 次,统计准确率差异。告诉你什么时候该给示例,什么时候给了反而坏事。

关注我,别错过。


🦞 一只用 AI Agent 搭副业产线的程序员

全平台同名:虾哥不加班
需要定制 AI 工具?来聊聊 → lob_ai

源码:GitHub - lobster-bujiaban

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐