System Prompt 到底干了什么
System Prompt 是你和模型之间的”契约”——它定义了模型在接下来的对话中应该扮演什么角色、遵守什么规则、用什么方式回答问题。
在 Hermes 使用的 ChatML 格式里,system prompt 放在对话的最开头。你可能觉得 system prompt 和在 user message 里写指令差不多,但实际上有本质区别。Hermes 在训练时对 system 角色的内容有特殊处理——system 里的指令在模型的”注意力权重”中占据更高优先级。同样一条规则,放在 system prompt 里比放在 user message 里更容易被模型遵守。
Hermes 对 System Prompt 的响应特点
不同模型对 system prompt 的服从程度差异很大。Hermes 在这方面表现相当好,是 Nous Research 训练时特别优化过的。
1. 角色扮演服从度高 — 让它扮演一个角色,它会比较稳定地保持,不容易被用户”带跑”。
2. 格式约束遵守度不错 — 让它只输出 JSON、只用列表格式回答、或者控制回答长度,大部分时候能做到。详细技巧看 Hermes JSON Mode。
3. 否定指令有效果 — “不要做 X”在 Hermes 上实际有效。但最好还是用肯定句替代否定句。
4. 多条规则能并存 — 可以列出多条规则,Hermes 能同时遵守,不会只记住最后一条。
System Prompt 设计的基本框架
1 | 1. 角色定义(你是谁) |
角色定义要具体
1 | # 差 |
具体的角色设定会让模型的回答更有针对性——它会避免解释太基础的概念,同时不会一上来就用特别高级的术语。
行为规则写法
用具体行为描述,不用抽象形容词:
1 | # 差 |
量化优于模糊:
1 | # 差 |
实用 System Prompt 模板
技术问答机器人
1 | tech_system_prompt = """你是一个资深全栈开发者,擅长 Python、JavaScript 和系统架构。 |
文档分析助手
1 | doc_system_prompt = """你是一个文档分析专家。 |
角色扮演(游戏NPC)
1 | npc_system_prompt = """你扮演一个名叫"老陈"的酒馆老板,在一个中世纪奇幻世界里。 |
动态 System Prompt
实际应用中,system prompt 不一定固定不变。你可以根据用户信息、对话轮次、时间等因素动态构建:
1 | import datetime |
System Prompt 长度和性能权衡
System prompt 越长,每次对话消耗的 token 就越多。在 长文本处理 那篇文章里讲过上下文长度对性能的影响。
| System Prompt 长度 | 首次响应延迟增加 | 适用场景 |
|---|---|---|
| < 200 字 | 可忽略 | 简单角色/规则 |
| 200-500 字 | 约 100-300ms | 复杂角色+规则 |
| 500-1000 字 | 约 300-800ms | 含 few-shot 示例 |
| > 1000 字 | > 1s | 含知识库内容 |
如果你的 system prompt 超过 1000 字,认真想想有没有可以精简的部分。
常见反模式
1. 过度约束导致模型”窒息” — 规则太多太严会让模型”不知道怎么说话”,保留核心规则就好。
2. 矛盾的指令 — “回答要详细全面”同时”控制在100字以内”,模型会随机遵守其中一条。确保规则之间没有矛盾。
3. 定义了但不测试 — 写完 system prompt 后至少用 20-30 个不同的问题测试,特别是边界情况。
和 Function Calling 的配合
如果你的应用涉及 Function Calling,system prompt 里需要同时定义角色规则和工具定义。推荐结构是:
1 | system_prompt = """ |
角色规则放前面,工具定义放中间,工具使用规范放后面。这个顺序经过测试效果最稳定。
版本管理
生产环境里 system prompt 会经常迭代,建议做版本管理:
1 | SYSTEM_PROMPTS = { |
更严肃的做法是把 system prompt 存在数据库或配置中心里,支持 A/B 测试和灰度发布。cocoloop 社区里有同学分享过用 Git 管理 prompt 版本的方案,配合自动化测试效果挺好的。
System prompt 是 Hermes 应用开发中最值得投入时间的环节之一——写好了能省掉大量的后处理代码和异常处理逻辑。花几个小时打磨一个好的 system prompt,比花几天写兜底代码划算得多。