展开目录(7 节)
先说结论:适合谁,不适合谁
这篇记录的是把 Claude Sonnet 5.5 通过 API 接进日常开发流程的过程,包括接入配置、三个不同类型的项目,以及每一步遇到的问题。先给判断:
- 适合:跨文件重构、从需求直接生成前端页面、拿报错日志和相关代码去定位问题。这三类任务都靠”读得多、改得准”。
- 不建议:拿它批量做”一行注释、一个小函数”这类碎活。单次调用的固定开销不划算,用更小的模型就够。
- 前提:你得能把上下文喂对。上下文给得乱,再强的模型也会改出一堆”看起来合理”的错误代码。
接入:三分钟跑通,先避开这几个坑
走的是 Anthropic Messages 格式。必填项就这几个:请求头 x-api-key、anthropic-version,请求体里的 model、max_tokens、messages。其中最容易漏的是 max_tokens,漏了会直接报 max_tokens: Field required。
- 拿到 Key 和 base URL。在控制台创建 Key,同时复制网关的 base URL。不要把官方域名和网关域名混着用。
- 确认模型 ID。去模型列表复制 Sonnet 5.5 的准确 ID,别手敲,少一个连字符就是 404。
- 用 curl 发一条最小请求。先确认鉴权和路由没问题,再接 SDK。
- 换成 SDK 并开启流式。写代码任务输出长,不开 stream 很容易在中间层超时。
- 把 Key 放环境变量。不要写进仓库,也不要放前端代码里。
curl https://YOUR_GATEWAY_BASE/v1/messages \
-H "x-api-key: $API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "claude-sonnet-5-5",
"max_tokens": 1024,
"messages": [{"role": "user", "content": "用一句话解释 event loop"}]
}'
Python 里用官方 SDK 时,只需要改 base_url:
import os
from anthropic import Anthropic
client = Anthropic(
api_key=os.environ["API_KEY"],
base_url="https://YOUR_GATEWAY_BASE", # SDK 会自己拼 /v1/messages
)
with client.messages.stream(
model="claude-sonnet-5-5",
max_tokens=8192,
temperature=0.2,
system="你是资深后端工程师。只输出 unified diff,不要解释。",
messages=[{"role": "user", "content": prompt}],
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)
base_url 末尾不要再带 /v1,否则会拼成 /v1/v1/messages 并返回 404。这是接入阶段最常见的错误。参数怎么配:写代码场景的取值
写代码不需要”创意”,参数往保守的方向调。下面是这几个项目里实际用的取值:
| 场景 | temperature | max_tokens | 说明 |
|---|---|---|---|
| 跨文件重构(输出 diff) | 0 ~ 0.2 | 8000 ~ 16000 | 要稳定、可复现,输出长度按改动文件数估算 |
| 前端页面生成 | 0.3 ~ 0.5 | 6000 ~ 10000 | 允许一点布局变化,单文件组件通常不超过这个量 |
| 调试排错 | 0 ~ 0.2 | 2000 ~ 4000 | 要求先给判断,再给最小修复,输出不用长 |
| 代码审查 | 0.2 | 3000 ~ 6000 | 让它按”严重/一般/建议”分级输出 |
费用方面,Sonnet 这个档位过去的定价大致在每百万输入 token 约 3 美元、输出约 15 美元的区间。5.5 的实际价格请看价目表。写代码场景的特点是输入远大于输出,所以成本主要在你喂了多少上下文,不在它写了多少。
项目一:长上下文重构,把 Express 旧项目迁到 TypeScript
仓库约 60 个 JS 文件,路由、中间件、数据库访问层混在一起。我把相关目录拼成一个大提示词,量级约 8 万 token,要求它输出每个文件的 unified diff。
表现好的地方:它能记住前面定义的类型,并在后面文件里保持一致。比如 UserDTO 在 controller、service、repository 三层的字段名没有各写各的。表现不好的地方:当改动文件超过十几个时,后面的 diff 偶尔会出现行号偏移,git apply 报 patch does not apply。
我的处理办法是按目录分批,每批 8~12 个文件,并把上一批产出的类型文件放进下一批的上下文。这样既稳,也省钱,因为每批只带必要的依赖。
tsc --noEmit,类型错误基本能一次暴露。如果一次塞入过多内容,会收到类似 prompt is too long: xxx tokens > xxx maximum 的报错。不要靠删注释硬凑,直接分批。
项目二:前端页面生成,一个后台管理列表页
需求是 React + Tailwind 的订单管理页:筛选栏、表格、分页、批量操作。我给的是接口返回的 JSON 示例和一张线框图的文字描述,而不是一句”做个后台页面”。
第一版就能跑,结构也合理:筛选状态用 useReducer 收口,表格列用配置数组驱动。问题集中在三处:
- 请求竞态没处理,快速切换筛选条件时,旧请求的结果会覆盖新的。需要明确要求加
AbortController。 - 空状态、加载态、错误态默认只做了加载态,要在提示词里列清楚。
- 偶尔会引用项目里没装的包,比如多引一个日期库。提示词里写明”只能使用 package.json 里已有依赖”。
模糊提示词
- “做一个订单管理页面”
- 风格、依赖、状态都靠猜
- 返工 3~4 轮才能用
结构化提示词
- 给 JSON 示例、依赖清单、状态清单
- 明确竞态、空态、错误态
- 通常 1~2 轮可合入
结论很明确:前端生成要用第二种写法。在这类任务上,提示词的写法对结果的影响,比换模型还大。
项目三:调试排错,一个偶发超时的 asyncio 服务
现象是 Python 服务每隔几小时出现一批 asyncio.TimeoutError,重启后恢复。我给它的材料是:错误日志前后各 50 行、连接池初始化代码、调用方的 async with 片段,没有贴整个仓库。
它的第一个判断是连接池耗尽,原因是某个分支里拿到连接后异常路径没有释放。这个判断对了。我把它给出的修复和自己的排查对照,改动只有几行,包在 try/finally 里。
需要提醒的是:它会给出多个可能原因,并且语气都很笃定。我后来固定在提示词里加一句”按可能性排序,并给出每个假设对应的验证方法(日志或命令)”,这样拿到的是可验证的清单,而不是一个结论。
常见报错与费用控制
| 现象 / 报错 | 常见原因 | 处理 |
|---|---|---|
| 401 authentication_error | Key 错误,或把网关 Key 发给了官方域名 | 核对 base URL 与 Key 是否配套 |
| 404 not_found_error | 模型 ID 拼错,或 base URL 多了 /v1 | 从模型列表复制 ID,检查路径拼接 |
| 429 rate_limit_error | 并发或每分钟 token 超限 | 指数退避重试,批量任务限制并发为 2~4 |
| 529 overloaded_error | 上游临时过载 | 重试,仍失败则降级到备用模型 |
| 输出在代码中途截断 | max_tokens 偏小,stop_reason 为 max_tokens |
调大,或拆分任务 |
费用上有三个实际有效的做法:
- 只传必要文件。把整个
node_modules旁边的目录也扫进去是最常见的浪费。 - 重复使用的长前缀(代码规范、类型定义)如果网关支持 prompt caching,就打开,能明显压低重复输入的成本。
- 小任务分流给更小的模型,Sonnet 5.5 只留给跨文件和排错。
我的判断是:如果你每天的调用大多是单文件小改动,不必上 Sonnet 5.5;如果你经常处理多文件重构和棘手的线上问题,它值这个钱,但要配合分批和脱敏的流程。