Claude API 上下文窗口怎么核算?先数输入 token,再预留输出预算

Claude API 上下文预检需要同时看输入计数、总窗口和单次输出上限。提供模型元数据查询、count_tokens 预检、保守余量与生成后停止原因核验代码。

Claude API 的上下文窗口不能简单理解为“最多上传多少汉字”。它容纳当前请求需要参考的内容,并为本轮输出留空间。开发时应先针对准确模型计算输入 token,再把计划输出和安全余量加进去,同时检查模型的单次输出上限。

本文面向发送 Messages API 请求的 Python 开发者,演示生成前的预算检查,不处理网页端订阅次数。接口、字段和限制于 2026 年 10 月 1 日核对;示例没有进行付费模型生成实测。

Claude API 上下文窗口怎么核算?先数输入 token,再预留输出预算

把三个数字分开核对

数字 用途 读取来源
输入 token 估计值 当前请求已经占用多少输入容量 POST /v1/messages/count_tokens
上下文窗口与最大输入容量 判断本轮内容是否装得下 准确模型的官方规格,以及 Models API 的 max_input_tokens
最大输出与本次 max_tokens 限定单次生成预算 Models API 的 max_tokens,以及自己请求的 max_tokens

官方上下文文档说明,system、历史消息、工具定义、工具结果、图像和文档都可能占用窗口,生成的输出也需要空间。缓存输入仍计入窗口;缓存不会把材料变成“零 token”。

窗口大小和输出上限随模型变化,不能从“Claude”这个产品名推定统一数字。使用Models API查询确切 ID 的 max_input_tokens 和 max_tokens;总上下文窗口按该模型的官方规格确认。字段返回 null 或能力不明确时先查证,不把它当作无限大。

一个保守预算公式

对本文这种普通文本请求,可先采用应用层检查:

输入 token 估计值 + 本次输出预算 + 预留量 ≤ 已确认的上下文窗口

同时要求输入不超过最大输入容量、输出预算不超过最大输出。预留量是你的应用策略,不是官方保证;它用于应对估计误差和后续小幅变化。如果增加工具结果、历史或新附件,应重新计数。

假设一个演示任务的已确认窗口为 200,000 token,输入估计为 120,000,输出预算为 4,000,预留量为 2,400,则预算合计 126,400,低于窗口。这些数值用于解释计算,没有代表实际模型调用结果;模型是否能准确利用长材料还要单独验证。

准备要计数的输入

  1. 安装 Python 3.10 或更新版本和 requests:python -m pip install requests。
  2. 将下列 JSON 保存为 UTF-8 的 message_input.json,再用自己的 system 和真实消息替换演示文本。认证信息不要放进这个文件。
  3. 配置 ANTHROPIC_API_KEY、ANTHROPIC_MODEL 与 CLAUDE_CONTEXT_WINDOW。最后一个值填写从该准确模型规格确认的总窗口 token 数,不沿用别的模型的数值。
  4. 可设置 CLAUDE_OUTPUT_BUDGET 为需要的输出预算;本例默认 2048。计数请求会把输入发送给服务端,不能因为尚未生成答案就忽略材料权限。
{
  "system": "只根据给出的资料回答,缺少依据时说明未找到。",
  "messages": [
    {"role": "user", "content": "演示资料:项目分为准备、执行和核对三步。请说明执行后如何核对。"}
  ]
}

计数接口支持 system、客户端工具定义和消息输入,但并非所有 Messages 扩展输入都能原样计数。按照官方计数说明,大多数服务器工具、MCP connector、URL/file 来源的图片或文档存在计数接口限制;图片和 PDF 可按支持的 Base64 结构计数。遇到不支持的输入应按官方规则调整,不能删除它们后把较小计数当作完整请求的结果。

Python:读模型边界,再做预检

import json
import math
import os
import sys
from pathlib import Path
from urllib.parse import quote
import requests

model = os.environ["ANTHROPIC_MODEL"]
context_window = int(os.environ["CLAUDE_CONTEXT_WINDOW"])
output_budget = int(os.environ.get("CLAUDE_OUTPUT_BUDGET", "2048"))
if context_window <= 0 or output_budget <= 0:
    raise ValueError("窗口与输出预算必须为正整数")
headers = {
    "x-api-key": os.environ["ANTHROPIC_API_KEY"],
    "anthropic-version": "2023-06-01",
    "content-type": "application/json",
}
spec = json.loads(Path("message_input.json").read_text(encoding="utf-8"))
if set(spec) - {"system", "tools", "messages"}:
    raise ValueError("本例只接受普通 system、客户端 tools 和 messages 输入")
if not isinstance(spec.get("messages"), list) or not spec["messages"]:
    raise ValueError("messages 必须是非空列表")

metadata_response = requests.get(
    "https://api.anthropic.com/v1/models/" + quote(model, safe=""),
    headers=headers, timeout=(10, 30),
)
metadata_response.raise_for_status()
metadata = metadata_response.json()
input_limit = metadata.get("max_input_tokens")
output_limit = metadata.get("max_tokens")
if not isinstance(input_limit, int) or not isinstance(output_limit, int):
    raise RuntimeError("模型限额未明确返回,请先核对官方模型规格")

count_response = requests.post(
    "https://api.anthropic.com/v1/messages/count_tokens",
    headers=headers, json={"model": model, **spec}, timeout=(10, 60),
)
count_response.raise_for_status()
input_tokens = count_response.json()["input_tokens"]
# 本例自定余量:至少 1024,或输入估计值的 2%。不是官方容差保证。
reserve = max(1024, math.ceil(input_tokens * 0.02))
required = input_tokens + output_budget + reserve
print("model", metadata.get("id"), "estimated_input", input_tokens,
      "output_budget", output_budget, "reserve", reserve,
      "required", required, "confirmed_context", context_window)
if input_tokens > input_limit:
    raise SystemExit("输入超过模型最大输入容量,先缩减材料")
if output_budget > output_limit:
    raise SystemExit("输出预算超过模型最大输出,先调整预算")
if required > context_window:
    raise SystemExit("没有足够的上下文余量,先缩减输入或调整任务")
print("预检通过;是否得到完整答案仍需看生成结果")

if "--send" in sys.argv:
    response = requests.post(
        "https://api.anthropic.com/v1/messages",
        headers=headers,
        json={"model": model, "max_tokens": output_budget, **spec},
        timeout=(10, 60),
    )
    response.raise_for_status()
    message = response.json()
    print("stop_reason", message.get("stop_reason"),
          "usage", message.get("usage"))
    print("\n".join(b["text"] for b in message["content"] if b["type"] == "text"))

保存为 context_preflight.py,执行 python context_preflight.py。默认只查询模型信息与计数,不发生成请求;当前官方文档说明 token 计数免费,但有独立速率限制。确认预检和材料权限后,执行 python context_preflight.py --send 才生成答案,生成调用按账户计费。

怎样验证预检与真实结果

  • 先用上面的短消息测试:应该返回整数输入计数,模型限额是明确数字,预算合计低于你核对的窗口。
  • 将本例输出预算故意设为大于模型最大输出:脚本应在生成前拒绝发送。测试后恢复合法值。
  • 生成后检查 stop_reason。end_turn 表示这一轮正常结束,但仍需核对答案内容;max_tokens 表示输出预算用尽,不能把截断答案当作完整交付。
  • 保存真实响应的 usage,与计数估计比较。计数存在小幅差异;若请求启用了缓存,输入总量要同时考虑普通输入、缓存读取与缓存创建字段。

超出预算时怎样缩减而不丢任务

先移除重复材料与过期历史,保留当前任务、关键约束、已经确认的事实和出处。长文档可以先定位相关章节,分别提取可核对的事实,再合并分析。工具结果只保留需要的字段,不要把完整调试日志当作回答资料。

每次改变模型或输入后都重新计数,不能用汉字数粗略换算替代。本文示例没有加入 thinking 配置;带 thinking 的多轮会话,要按所选模型的块保留与计数规则处理。工具调用和结果仍须保持消息结构完整,不随意删除配对中的一半。

相关问答

窗口足够大,为什么还是漏掉关键内容?

容量通过只说明预算可容纳输入输出,不保证模型能准确找出每个事实。上下文文档提示长上下文可能出现召回与准确性下降。把关键问题、资料位置与核对标准写清,并用具体字段或引用验证答案。

开新会话就不需要计算了吗?

开新会话可以减少历史,但 system、当前资料、工具定义和本轮输出仍然占窗口。迁移后的任务要重新计数,也要带上需要继续工作的事实与约束。

Ai菜鸟网。发布者:AI小管家,转载请注明出处:https://www.alyyhw.com/30436.html

赞 (0)
AI小管家的头像AI小管家
Transformers 分词结果怎么看?核对 token、ID 与原文位置
上一篇 9小时前
Transformers 聊天模板怎么用?把角色消息转成模型输入
下一篇 9小时前

相关推荐

联系我们

联系我们

1

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信
关注微信
分享本页
返回顶部