lkd0001头像

Claude API 长输出请求:用 stream + get_final_message() 拿完整结果,以及几个容易漏的地方

把 max_tokens 调大以后,直接用 client.messages.create() 发非流式请求,Python SDK 可能会直接拒绝。官方文档的说法是:SDK 会校验非流式 Messages 请求,预计会超过 10 分钟超时的不让发;对 max_tokens 很大的请求,SDK 要求走流式,避免 HTTP 超时。

很多场景其实并不需要逐字显示,只想要一个完整结果。SDK 为这种情况留了一个现成的办法。

最小写法

import anthropic

client = anthropic.Anthropic()

with client.messages.stream(
    model="claude-opus-5-5",
    max_tokens=128000,
    messages=[{"role": "user", "content": "Write a detailed analysis..."}],
) as stream:
    message = stream.get_final_message()

for block in message.content:
    if block.type == "text":
        print(block.text)

.stream() 用 SSE 保持连接,get_final_message() 把所有事件汇总成一个完整的 Message 对象,结构和 messages.create() 返回的一样。业务代码不用自己拼 delta。

返回后别只取第一个文本块

message.content 是一个数组,可能同时有 thinking、text、tool_use 等块。上面示例按 block.type == "text" 过滤,比直接取 content[0].text 稳。用了工具的话,stop_reason 是 tool_use,这时要去执行工具,不能把文本当最终答案。

自己处理事件时要注意的三点

如果不用 SDK 的汇总,而是自己解析 SSE:

  1. 错误可能出现在 200 之后。 流式响应先返回 HTTP 200,中途仍可能收到 event: error,例如高峰期的 overloaded_error(非流式时对应 529)。只看状态码判断成功是不够的。
  2. 工具参数是分片的 JSON 字符串。 input_json_delta 里的 partial_json 要累积起来,等到 content_block_stop 再解析;最终的 tool_use.input 才是对象。
  3. 未知事件类型要能跳过。 流里会穿插 ping,官方也说明以后可能新增事件类型,解析器不要遇到不认识的类型就抛异常。另外 message_delta 里 usage 的 Token 数是累计值,不要再自己相加。

中途断了怎么办

SDK 默认对连接错误、限流和 5xx 自动重试 2 次(指数退避,有 retry-after 时按它来),可以用 max_retries 调整或关闭。如果你的任务队列也会重试,最好只留一层,避免同一请求被重复提交。

想接着断点继续生成,官方给的做法分模型:

  • Claude 4.5 及更早:把已收到的部分放进 assistant 消息,作为新请求的开头继续生成。
  • Claude 4.6 及之后:这些模型不支持 assistant 预填,改成加一条 user 消息,把已收到的内容带上,让模型从断开处继续。

tool_use 和 thinking 块不能部分恢复,只能从最近的文本块接着来。

不需要实时结果时

官方建议超过 10 分钟的长请求考虑流式或 Message Batches。如果调用方可以稍后再取结果,Batches 不需要一直保持连接,按轮询拿结果即可。

参考资料

转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/lkd0001/article/details/170334288

文章来源转载

评论

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--