对话的最小形式
{
"model": "claude-sonnet-4-6",
"max_tokens": 1024,
"system": "你是严谨的技术编辑。",
"messages": [
{ "role": "user", "content": "帮我润色这段:..." }
]
}
System Prompt 的正确位置
Claude 的 system prompt 是 顶层独立字段,不是 messages 数组里的一项。这和 OpenAI 的习惯不同。
const msg = await client.messages.create({ model: "claude-sonnet-4-6", max_tokens: 1024, // ✅ 正确:system 是顶层 system: "你是资深的 iOS 工程师。回答简洁、准确、带代码示例。", messages: [ { role: "user", content: "SwiftData 怎么做多线程?" }, ], }); // ❌ 错误:把 system 塞进 messages const bad = { messages: [ { role: "system", content: "..." }, // 400 Error { role: "user", content: "..." }, ] };
Structured System Prompt
system 不只是一段字符串,也可以是 结构化数组——为 Prompt Caching 打点用(第 6 章):
system: [
{
type: "text",
text: "你是金融数据分析师。必须用 markdown 表格呈现。",
},
{
type: "text",
text: readFileSync("company_knowledge.md", "utf-8"), // 长上下文
cache_control: { type: "ephemeral" }, // 缓存这一大块
},
],
多轮对话
把历史对话堆到 messages 数组里,role 必须 user / assistant 交替:
{
"messages": [
{ "role": "user", "content": "帮我起个域名。" },
{ "role": "assistant", "content": "你的项目做什么?" },
{ "role": "user", "content": "个人博客。" },
{ "role": "assistant", "content": "三个候选:..." },
{ "role": "user", "content": "第二个不错,再给三个类似风格。" }
]
}
· 必须以
user 开头· user / assistant 必须交替,不能 user→user 或 assistant→assistant
· 不允许 role=system(要用顶层 system 字段)
违反 → 400 错误,Claude 不接受就是不接受
续写 assistant 消息
一个巧妙用法:messages 最后一条是 assistant,Claude 会从那里接着写(适合"让 Claude 按固定开头输出"):
{
"messages": [
{ "role": "user", "content": "用 JSON 返回人名和年龄。" },
{ "role": "assistant", "content": "{" }
]
}
Claude 会从 { 开始续写,几乎保证是合法 JSON。配合 stop_sequences 可以精确截断。(工具调用更推荐用 Tool Use,第 4 章)
content 不只是 string
单条消息的 content 可以是字符串,也可以是 block 数组——存在多模态/工具/缓存需求时必须用数组:
{
role: "user",
content: [
{ type: "text", text: "这张图是什么?" },
{ type: "image", source: { type: "base64", media_type: "image/png", data: "..." } },
],
}
Block 类型包括:text / image / document(PDF) / tool_use / tool_result / thinking。后续各章讲。
temperature 和 top_p
推荐:调一个就够,别同时调两个。典型设置:
- 严谨/分类/抽取:
temperature=0 - 写作/对话:
temperature=0.7 - 创意/brainstorm:
temperature=1.0
max_tokens 是硬上限
不是"目标长度",而是"生成多了就截断"。被截断时 stop_reason = "max_tokens",这是 bug 信号,要么调大,要么让 Claude 在 prompt 里更短。
各模型上限不同,Sonnet 4.x 可达 64K output tokens,Opus 可更高;写 system prompt 的时候也要算进 context window(input + output 总和)。
stop_sequences 停止词
const msg = await client.messages.create({ model: "claude-sonnet-4-6", max_tokens: 500, stop_sequences: ["###", "END_ANSWER"], messages: [{ role: "user", content: "只到 ### 为止" }], }); // 命中时 stop_reason = "stop_sequence",stop_sequence 字段告诉你命中了哪个
经典用途:定界符裹住 JSON(<JSON> 开始、</JSON> 停止),解析更稳。
Token Counting:发请求前先算
长文档场景,想提前知道一个 prompt 要花多少钱/会不会超上下文——SDK 有 count_tokens:
const count = await client.messages.countTokens({ model: "claude-sonnet-4-6", system: "...", messages: [{ role: "user", content: veryLongDoc }], }); console.log(count.input_tokens); // 比如 84732
这不消耗任何模型推理费用,只是计算——生产 RAG 流程里常用来做"截断策略的参考线"。
上下文窗口是多少
Claude 4.x 系列普遍支持 200K input tokens。超长时有两种处理:
- 提前截断:文档检索后只放相关段 + 对话最近 N 轮
- 摘要滚动:当对话越过某阈值,让 Claude 总结前半段,再把总结塞回 messages
关于请求的幂等性
同一个 prompt 两次调用,即使 temperature=0,也不保证字节相同——模型浮点运算、采样实现都有细微抖动。要做回放测试,用快照比对 + LLM as judge,别指望字符串 equality。
元数据 metadata
const msg = await client.messages.create({ model: "claude-sonnet-4-6", max_tokens: 500, metadata: { user_id: "user_abc123", // 用于 Anthropic 侧滥用检测 }, messages: [...], });
metadata.user_id 非必填,但生产环境推荐带上——Anthropic 可以基于此做异常检测和问题排查(这字段不计入 prompt、不影响模型输出)。
错误处理模板
import Anthropic from "@anthropic-ai/sdk"; try { const msg = await client.messages.create({...}); } catch (err) { if (err instanceof Anthropic.APIConnectionError) { // 网络问题,重试 } else if (err instanceof Anthropic.RateLimitError) { // 429,指数退避 } else if (err instanceof Anthropic.APIStatusError) { console.error(err.status, err.error); throw err; } }
请求超时
const client = new Anthropic({ timeout: 120 * 1000, // 2 分钟,长输出情况够用 maxRetries: 3, // SDK 默认 2 });
常见错误 Top 5
claude-sonnet-4.6(错,用点) vs claude-sonnet-4-6(对,用短横)最佳实践
① 用 XML 标签分段:
<context>、<question>、<example> —— Claude 天然对 XML 有良好理解② 说明输出格式:"以 JSON 返回,包含字段 a、b、c" 比"返回 JSON" 可靠 10 倍
③ 先定位角色再发问:system 里讲清楚"你是谁",比在 user 里反复强调有效
本章小结
system是顶层字段,不进 messages- messages 必须 user / assistant 交替,以 user 起头
- content 可以是 string,也可以是 block 数组(text/image/tool_use/...)
max_tokens必填,被截断 → 调大或压缩 prompt- 想估算 token 用
messages.countTokens,不花钱 - 生产配上 metadata.user_id、timeout、maxRetries、指数退避