128K 输出实战:不上 streaming 就等着 HTTP 超时
Opus 4.6 把最大输出 token 从 64K 提到了 128K。翻了一倍。
这意味着你可以让模型一次生成一个完整的长文件——一整个 React 组件库、一份 50 页的分析报告、或者一大段数据处理脚本——不用再拆成多次请求拼接。
但 128K 输出有一个硬性前提:必须用 streaming。不用 streaming 的话,HTTP 连接大概率会超时,请求直接失败。这不是建议,是现实。
为什么必须 streaming
一个 128K token 的输出,模型大概要生成 30-90 秒(取决于复杂度和 effort 设置)。普通的 HTTP 请求有超时时间——客户端、负载均衡器、API 网关都有各自的超时配置。大部分默认值在 30-60 秒。
不用 streaming 时,客户端发出请求后干等。服务端在后台生成,生成完才一次性返回。如果生成时间超过任何一层的超时配置,连接断开,你什么都拿不到。
Streaming 模式下,服务端边生成边发——每生成一小段就推送一个 event。HTTP 连接保持活跃,不会被超时机制杀掉。
Anthropic 的 SDK 文档里也明确说了:当 max_tokens 设得很大时,必须用 streaming。
基本用法
import anthropic
client = anthropic.Anthropic()
# 方式一:用 stream() 处理每个 event
with client.messages.stream(
model="claude-opus-4-6",
max_tokens=128000,
thinking={"type": "adaptive"},
messages=[{
"role": "user",
"content": "生成一个完整的 Express.js REST API 项目,包含用户认证、CRUD 操作、错误处理和测试文件。"
}]
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)
# 方式二:不想逐块处理,只要最终结果
with client.messages.stream(
model="claude-opus-4-6",
max_tokens=128000,
thinking={"type": "adaptive"},
messages=[{"role": "user", "content": "..."}]
) as stream:
message = stream.get_final_message()
print(message.content[0].text)
第二种方式用 get_final_message(),虽然你不逐块处理输出,但底层仍然是 streaming 接收,HTTP 连接不会超时。
成本估算
128K 输出 token,按 Opus 4.6 的 $25/MTok 计算:128K × $25 = $3.20 纯输出成本。
加上输入成本(假设 5K token 的 prompt):5K × $5 = $0.025。
再加上 adaptive thinking 的成本(这是 output token,high effort 下可能有 20K-50K 的思考 token):假设 30K × $25 = $0.75。
一次完整的 128K 输出请求,总成本大约 $4.00。不便宜。
如果你用 max effort,思考 token 可能更多,总成本轻松到 $5-6。
什么时候值得用 128K 输出
128K token 大约对应 8-10 万字中文、或 5-7 万字英文。这个量足够生成:
- 一个中等复杂度的完整项目骨架(多个文件)
- 一份详细的技术方案文档
- 一个包含几十个函数的工具库
- 一份对长文档的逐段分析报告
值得用的判断标准:你之前需要拆成 3-5 次请求、每次生成一部分、然后手动拼接。现在一次搞定,省了多次请求的 token 浪费(每次请求都要重复发 system prompt 和上下文),也避免了拼接时的上下文不连贯。
不值得用的判断标准:你的输出本来就不长(几千 token),没必要把 max_tokens 设到 128K。max_tokens 只是上限,不是"一定要生成这么多"。设大了不会多花钱(按实际输出计费),但可能影响模型的行为——有时候模型知道自己有很大的输出空间,会倾向于写更多。
处理"输出半截"的问题
即使用了 streaming,也有可能遇到输出被截断。看 stop_reason:
end_turn:正常结束。max_tokens:输出达到了 max_tokens 上限,被截断了。如果你设了 128K 而且真的用满了,说明内容确实太长,考虑拆分任务。model_context_window_exceeded:输入 + 输出一起撞了上下文窗口上限(200K 或 1M)。输入太多,留给输出的空间不够了。
with client.messages.stream(
model="claude-opus-4-6",
max_tokens=128000,
messages=[{"role": "user", "content": "..."}]
) as stream:
message = stream.get_final_message()
if message.stop_reason == "max_tokens":
print("输出被截断了,考虑拆分任务")
elif message.stop_reason == "model_context_window_exceeded":
print("上下文满了,减少输入或开 1M beta")
一个经验:如果你的输入已经有 150K token,留给输出的空间只有 50K(200K 窗口下)。想要 128K 输出,输入得控制在 72K 以内。用 1M 窗口的话就不用这么纠结,但要承受长上下文溢价。
实际开发中的建议
1. 不要盲目设 128K
# 别这样——除非你真的需要超长输出
max_tokens=128000
# 按任务估一下够用的值
max_tokens=16000 # 一般的代码生成/分析
max_tokens=32000 # 较长的文档/多文件生成
max_tokens=64000 # 大型项目骨架
max_tokens=128000 # 确认需要极长输出时才用
2. streaming 的错误处理
长时间的 streaming 连接更容易遇到网络中断。加重试逻辑:
import time
def generate_with_retry(messages, max_retries=3):
for attempt in range(max_retries):
try:
with client.messages.stream(
model="claude-opus-4-6",
max_tokens=128000,
messages=messages
) as stream:
return stream.get_final_message()
except anthropic.APIConnectionError:
if attempt < max_retries - 1:
time.sleep(2 ** attempt) # 指数退避
else:
raise
3. 前端展示
如果你在做用户可见的产品,128K 输出会持续几十秒甚至几分钟。streaming 模式下用户能看到内容逐步出现,体验远好于干等。但要注意前端渲染的性能——几万字的实时渲染可能卡顿,做好虚拟滚动或分段渲染。
4. 输出的 token 计费包括思考
adaptive thinking 产生的思考 token 算 output token,从 max_tokens 里扣。如果你设了 max_tokens=128000,模型花了 30K 在思考上,实际可用于回答的只有 98K。
如果你发现输出总是比预期短,检查一下响应里的 thinking token 消耗——可能不是模型"偷懒",是思考占了太多空间。降低 effort 可以减少思考 token,留更多空间给实际输出。
参考链接
- Streaming 文档:
https://platform.claude.com/docs/en/build-with-claude/streaming - What's New in Claude 4.6(128K 输出说明):
https://platform.claude.com/docs/en/about-claude/models/whats-new-claude-4-6