当前位置: 首页 > news >正文

System Prompt vs User Prompt:一个管「你是谁」,一个管「你要什么」

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


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

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

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


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

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

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

这三者的关系像什么?

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 代码里加载:

packagemainimport("encoding/json""fmt""os")typeRoleConfigstruct{Namestring`json:"name"`Systemstring`json:"system"`Temperaturefloat64`json:"temperature"`MaxTokensint`json:"max_tokens"`}typeConfigstruct{Rolesmap[string]RoleConfig`json:"roles"`}typePromptManagerstruct{config*Config}funcNewPromptManager(configPathstring)(*PromptManager,error){data,err:=os.ReadFile(configPath)iferr!=nil{returnnil,err}varcfg Config json.Unmarshal(data,&cfg)return&PromptManager{config:&cfg},nil}func(pm*PromptManager)BuildMessages(roleKeystring,userPromptstring)([]Message,float64,int,error){role,ok:=pm.config.Roles[roleKey]if!ok{returnnil,0,0,fmt.Errorf("未知角色: %s",roleKey)}messages:=[]Message{{Role:"system",Content:role.System},{Role:"user",Content:userPrompt},}returnmessages,role.Temperature,role.MaxTokens,nil}funcmain(){pm,_:=NewPromptManager("roles.json")// 换角色只需要换一个 keymessages,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 PromptUser Prompt
谁写你(开发者)你(或最终用户)
频率写一次,复用多次每次任务不同
内容角色、规则、约束具体任务、输入数据
维护方式JSON 配置文件代码里拼接或模板
长度尽量短,200 字内根据任务复杂度
类比员工手册任务单

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

关注我,别错过。


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

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

源码:GitHub - lobster-bujiaban

http://www.jsqmd.com/news/929135/

相关文章:

  • 如何轻松解锁中兴光猫完整权限:智能网络管理工具实战指南
  • 如何快速安装APA第7版参考文献格式:3分钟搞定Microsoft Word学术排版
  • 图形化编程入门嵌入式:用Visuino与Seeeduino XIAO实现LED闪烁
  • 普定县26年最新奢侈品名包名表专业回收权威店铺推荐 - 莘州文化
  • 猫抓插件完全指南:浏览器视频下载的终极解决方案
  • DIY便携焊接工作站:利用Makita电池改造烙铁,集成照明功能
  • Granite-3B-Code-Base-2K进阶技巧:如何优化提示工程获得最佳代码生成效果
  • 鸣潮游戏自动化工具:如何用智能脚本告别重复操作
  • 终极免费QQ音乐QMC解码器:3分钟实现音乐跨平台播放自由
  • 鹿寨县26年最新奢侈品名包名表专业回收权威店铺推荐 - 莘州文化
  • 七星关区26年最新奢侈品名包名表专业回收权威店铺推荐 - 莘州文化
  • 基于双卡尔曼滤波(DEKF)的soc估计,在线更新模型参数,还可以估计本周期内soh的小幅度变化166 附赠对应的参考文档。
  • 德江县26年最新奢侈品名包名表专业回收权威店铺推荐 - 莘州文化
  • 用74HCT逻辑门搭建多谐振荡器:从RC定时原理到非稳态/单稳态电路实践
  • 为什么你的Sora 2复杂场景总“穿模”或“失重”?4个被官方文档隐藏的物理引擎参数必须手动校准
  • Video2X终极指南:零基础实现AI视频画质增强与超分辨率
  • 解放双手的智能战斗伴侣:炉石佣兵战记自动化脚本完全指南
  • 亚洲EMBA特色盘点:五大顶尖项目差异化优势与择校指南
  • 显示器黑屏故障维修:从电容失效原理到焊接更换全流程详解
  • 仁怀市26年最新奢侈品名包名表专业回收权威店铺推荐 - 莘州文化
  • MI-UKF多新息无迹卡尔曼滤波电池电量SOC估算MIUKF,无迹卡尔曼滤波中加入多新息方法。 具体包含有 UKF 和 EKF 的代码和仿真及对比,端电压误差等,
  • 赫章县26年最新奢侈品名包名表专业回收权威店铺推荐 - 莘州文化
  • Veo 2分辨率设置终极校准协议:色深/时序/EDID欺骗三重握手失败诊断流程(含HDMI 2.1b认证设备清单)
  • 智慧教育平台电子课本批量下载:5分钟快速上手的高效工具
  • Legado开源阅读鸿蒙版:打造您的专属无广告数字图书馆
  • 【2024生成式AI语音可视化终极指南】:Sora 2口型同步如何将LipSync误差压缩至±2帧内——附可复现训练pipeline
  • RealRestorer安全使用指南:许可证限制与合规建议
  • AI芯片分布式系统DLOS v2.7: 迈向自重写AI操作系统内核
  • 实测JoyAI-LLM-Flash-GGUF:MMLU 89.5分超越Qwen3-30B,数学推理能力惊艳![特殊字符]
  • 威宁彝族回族苗族自治县26年最新奢侈品名包名表专业回收权威店铺推荐 - 莘州文化