在使用Claude API构建应用时,大部分开发者会把精力放在用户消息的构造上,却很少认真打磨System Prompt。实际上,System Prompt是整个对话的基石,它定义了模型的角色、能力边界、输出格式和行为准则,一旦设计不合理,后续无论怎么调整用户提示词,效果都会大打折扣。本文将围绕System Prompt的编写最佳实践和Token计算方法展开,帮助你更规范地使用Claude API。

一、System Prompt在Claude API中的定位与传递方式
在Anthropic的Messages API中,System Prompt并不是消息列表的一部分,而是一个独立的顶层参数。这一点和OpenAI的接口设计有明显区别:OpenAI把system角色放在messages数组里,而Claude API则单独提供了system字段。这样的设计让系统级指令和对话内容彻底分离,结构更清晰。
一个基础的调用示例如下:
import anthropic
client = anthropic.Anthropic(api_key="your-api-key")
response = client.messages.create(
model="claude-3-5-sonnet-latest",
max_tokens=1024,
system="你是一位专业的技术文档工程师,回答必须严谨、简洁,并优先给出可执行的步骤。",
messages=[
{"role": "user", "content": "帮我写一段Python读取CSV文件的示例。"}
]
)
print(response.content[0].text)
需要注意,system参数是一个字符串,它会出现在对话的最前面,优先级高于任何用户消息。当System Prompt与用户消息产生冲突时,模型通常会倾向于遵循System Prompt的指令,这也是我们用它来做安全约束和行为控制的根本原因。不过这种优先级并不是绝对的,如果System Prompt写得含糊其辞,而用户消息非常具体,模型仍可能被带偏,所以指令的明确性非常关键。
System Prompt还支持基于XML标签的结构化写法,例如用<role>、<instructions>、<examples>等标签把不同区块隔开。Anthropic官方也推荐在复杂场景下使用这种方式,因为模型在预训练阶段接触过大量XML结构,对标签边界的识别相当敏感,能有效减少指令之间的相互干扰。
二、System Prompt编写的五条最佳实践
1. 用明确的角色设定代替模糊描述
角色设定不是写一句“你是一个助手”就完事,而是要具体到职责范围和输出偏好。比如“你是一位只回答Python相关问题的工程师,遇到其他语言的问题时礼貌拒绝并建议用户咨询对应方向”,这样的设定既有能力边界,又有兜底行为,模型表现会稳定得多。
2. 明确输出格式约束
如果下游程序需要解析模型输出,一定要在System Prompt中硬性规定格式,甚至给出示例。模糊的“请输出JSON”远不如“输出必须是合法JSON,不要包含markdown代码块标记,不要添加任何解释文字”可靠。经验上,格式类约束放在System Prompt末尾附近效果更好,因为模型对靠近输出位置的指令遵循度更高。
3. 善用XML标签组织长指令
当System Prompt超过几百词时,建议用标签分块,示例如下:
<role>你是一位资深的代码审查专家,擅长Java和Go。</role> <instructions> 1. 只审查用户提交的代码,不主动扩展话题 2. 按严重程度从高到低列出问题 3. 每个问题必须给出修复建议和示例代码 </instructions> <output_format> 以JSON数组输出,字段包括 severity、line、issue、fix </output_format>
这种结构让模型能快速定位每类指令的作用域,尤其在指令数量多、存在条件分支(比如“如果是中文提问则……”)时,标签化能显著降低指令遗漏率。
4. 提供少样本示例而不是空讲规则
规则描述得再详细,也不如给一两个输入输出示例直观。在标签包裹的示例区中给出典型的问答对,模型会模仿示例的风格和结构,这比单纯堆砌形容词有效得多。示例要覆盖边界情况,例如用户输入不合法时应该如何回应,这样模型在异常场景下也有章可循。
5. 控制长度,定期审视冗余
System Prompt的每个Token都是付费的,而且它会在每一次请求中重复计费。一份膨胀到几千Token的System Prompt,在几千次调用后就是一笔不小的成本。建议定期检查是否有互相重复的指令、模型本来就会做的废话(比如“请用中文回答中文问题”),能删则删。
三、Token计算的原理与实战方法
Claude使用的Token roughly对应:英文约100个Token折合75个单词左右,而中文通常一个汉字消耗1到2个Token,具体取决于分词器。更重要的规则是:System Prompt的Token会在每次请求时全部计入输入Token,并且随着多轮对话的进行,历史消息也会累积计入。所以长对话场景下,输入Token会滚雪球式增长。
要精确计算Token,最可靠的方式是调用Anthropic官方提供的计数接口,它会按照线上模型完全一致的分词方式返回结果:
import anthropic
client = anthropic.Anthropic(api_key="your-api-key")
# 统计System Prompt的Token数量
result = client.messages.count_tokens(
model="claude-3-5-sonnet-latest",
system="你是一位专业的技术文档工程师,回答必须严谨、简洁。",
messages=[
{"role": "user", "content": "帮我写一段Python读取CSV文件的示例。"}
]
)
print(result.input_tokens)
这个接口是免费的,不消耗模型调用费用,非常适合在开发调试阶段做上下文预算。一个实用的工程实践是:在发送正式请求前先调用计数接口,估算总输入Token是否接近模型上下文窗口上限,如果超限则先执行历史消息裁剪或摘要压缩,再发起真实请求,避免线上报错。
除了精确计数,日常估算可以记住几个经验值:一段500汉字的中文System Prompt大约消耗700到1000 Token;代码类内容由于包含大量符号和缩进,Token密度通常比自然语言高出百分之三十以上。在做成本测算时,把System Prompt的Token数乘以预估调用次数,就能得到这项固定开销的总量,再结合模型的输入单价即可算出成本。
四、常见问题与排查思路
第一个常见问题是模型不遵守System Prompt。排查时先确认system参数确实传到了顶层而不是误放进了messages数组;其次检查指令之间是否存在冲突,比如前面说“简洁回答”后面又要求“详细解释每个步骤”;最后可以尝试把关键约束用XML标签突出,或调整指令的先后顺序。
第二个问题是Token开销异常偏高。这时候应该打印每次请求的usage字段做对比,响应对象中的input_tokens和output_tokens会给出精确数值。如果发现输入Token随轮次线性甚至超线性增长,说明历史消息没有做截断管理,需要引入滑动窗口或对话摘要机制。另外注意,某些版本的思考类模型会有额外的推理Token消耗,这部分也体现在usage统计中,做成本模型时要一并纳入。
总的来说,System Prompt的质量决定了应用的上限,而Token管理决定了应用的成本下限。把这两件事都做扎实,Claude API的调用效果和稳定性都会有明显提升。
Claude APISystem PromptToken计算修改时间:2026-09-12 17:28:37