此功能符合零数据保留(ZDR)的条件。当您的组织签订了 ZDR 协议时,通过此功能发送的数据在 API 响应返回后不会被存储。
服务器端压缩是在长时间运行的对话和智能体工作流中管理上下文的推荐策略。它能以最少的集成工作自动处理上下文管理。
"Compaction"(压缩)通过在接近上下文窗口限制时自动总结较早的上下文,从而延长长时间运行的对话和任务的有效上下文长度。这不仅仅是为了保持在令牌上限以下。随着对话变长,模型难以在整个历史记录中保持专注。压缩通过用简洁的摘要替换过时的内容,使活动上下文保持专注和高效。
如需深入了解长上下文为何会退化以及压缩如何提供帮助,请参阅 有效的上下文工程。
这非常适合以下场景:
压缩功能目前处于测试阶段。请在您的 API 请求中包含 beta header(测试版标头)compact-2026-01-12 以使用此功能。
以下模型支持压缩功能:
claude-fable-5)claude-mythos-5)启用压缩后,当对话接近配置的令牌阈值时,Claude 会自动对其进行总结。API 会:
compaction 块。在后续请求中,将响应追加到您的消息中。API 会自动丢弃 compaction 块之前的所有消息块,从摘要处继续对话。
通过在 Messages API 请求的 context_management.edits 中添加 compact_20260112 策略来启用压缩。
client = anthropic.Anthropic()
messages = [{"role": "user", "content": "Help me build a website"}]
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-4-8",
max_tokens=4096,
messages=messages,
context_management={"edits": [{"type": "compact_20260112"}]},
)
# 将响应(包括任何压缩块)追加到对话中以继续对话
messages.append({"role": "assistant", "content": response.content})| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
type | string | 必填 | 必须为 "compact_20260112" |
trigger | object | 150,000 个令牌 | 触发压缩的时机。必须至少为 50,000 个令牌。 |
pause_after_compaction | boolean | false | 是否在生成压缩摘要后暂停 |
instructions | string | null | 自定义摘要提示。提供时会完全替换默认提示。 |
使用 trigger 参数配置压缩的触发时机:
client = anthropic.Anthropic()
messages = [{"role": "user", "content": "Hello, Claude"}]
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-4-8",
max_tokens=4096,
messages=messages,
context_management={
"edits": [
{
"type": "compact_20260112",
"trigger": {"type": "input_tokens", "value": 150000},
}
]
},
)默认情况下,压缩使用以下摘要提示:
You have written a partial transcript for the initial task above. Please write a summary of the transcript. The purpose of this summary is to provide continuity so you can continue to make progress towards solving the task in a future context, where the raw history above may not be accessible and will be replaced with this summary. Write down anything that would be helpful, including the state, next steps, learnings etc. You must wrap your summary in a <summary></summary> block.您可以通过 instructions 参数提供自定义指令来完全替换此提示。自定义指令不是对默认提示的补充,而是完全替换它:
client = anthropic.Anthropic()
messages = [{"role": "user", "content": "Hello, Claude"}]
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-4-8",
max_tokens=4096,
messages=messages,
context_management={
"edits": [
{
"type": "compact_20260112",
"instructions": "Focus on preserving code snippets, variable names, and technical decisions.",
}
]
},
)使用 pause_after_compaction 可在生成压缩摘要后暂停 API。这允许您在 API 继续生成响应之前添加额外的内容块(例如保留最近的消息或特定的指令性消息)。
启用后,API 会在生成压缩块后返回一条带有 compaction 停止原因的消息:
client = anthropic.Anthropic()
messages = [{"role": "user", "content": "Hello, Claude"}]
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-4-8",
max_tokens=4096,
messages=messages,
context_management={
"edits": [{"type": "compact_20260112", "pause_after_compaction": True}]
},
)
# 检查压缩是否触发了暂停
if response.stop_reason == "compaction":
# 响应仅包含压缩块
messages.append({"role": "assistant", "content": response.content})
# 继续该请求
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-4-8",
max_tokens=4096,
messages=messages,
context_management={"edits": [{"type": "compact_20260112"}]},
)当模型处理包含大量工具使用迭代的长任务时,总令牌消耗可能会显著增长。您可以将 pause_after_compaction 与压缩计数器结合使用,以估算累计使用量,并在达到预算后优雅地结束任务:
client = anthropic.Anthropic()
messages = [{"role": "user", "content": "Hello, Claude"}]
TRIGGER_THRESHOLD = 100_000
TOTAL_TOKEN_BUDGET = 3_000_000
n_compactions = 0
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-4-8",
max_tokens=4096,
messages=messages,
context_management={
"edits": [
{
"type": "compact_20260112",
"trigger": {"type": "input_tokens", "value": TRIGGER_THRESHOLD},
"pause_after_compaction": True,
}
]
},
)
if response.stop_reason == "compaction":
n_compactions += 1
messages.append({"role": "assistant", "content": response.content})
# 估算已消耗的总令牌数;若超出预算则提示收尾
if n_compactions * TRIGGER_THRESHOLD >= TOTAL_TOKEN_BUDGET:
messages.append(
{
"role": "user",
"content": "Please wrap up your current work and summarize the final state.",
}
)当触发压缩时,API 会在助手响应的开头返回一个 compaction 块。
长时间运行的对话可能会产生多次压缩。最后一个压缩块反映了提示的最终状态,用生成的摘要替换其之前的内容。
{
"content": [
{
"type": "compaction",
"content": "Summary of the conversation: The user requested help building a web scraper..."
},
{
"type": "text",
"text": "Based on our conversation so far..."
}
]
}您必须在后续请求中将 compaction 块传回 API,以便使用缩短后的提示继续对话。最简单的方法是将整个响应内容追加到您的消息中:
client = anthropic.Anthropic()
messages = [{"role": "user", "content": "Hello, Claude"}]
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-4-8",
max_tokens=4096,
messages=messages,
context_management={"edits": [{"type": "compact_20260112"}]},
)
# 收到包含压缩块的响应后
messages.append({"role": "assistant", "content": response.content})
# 继续对话
messages.append({"role": "user", "content": "Now add error handling"})
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-4-8",
max_tokens=4096,
messages=messages,
context_management={"edits": [{"type": "compact_20260112"}]},
)当 API 接收到 compaction 块时,其之前的所有内容块都会被忽略。您可以选择:
在启用压缩的情况下进行流式传输响应时,当压缩开始时您会收到一个 content_block_start 事件。压缩块的流式传输方式与文本块不同。您会收到一个 content_block_start 事件,随后是一个包含完整摘要内容的单个 content_block_delta(没有中间流式传输),然后是一个 content_block_stop 事件。
client = anthropic.Anthropic()
messages = [{"role": "user", "content": "Hello, Claude"}]
with client.beta.messages.stream(
betas=["compact-2026-01-12"],
model="claude-opus-4-8",
max_tokens=4096,
messages=messages,
context_management={"edits": [{"type": "compact_20260112"}]},
) as stream:
for event in stream:
if event.type == "content_block_start":
if event.content_block.type == "compaction":
print("Compaction started...")
elif event.content_block.type == "text":
print("Text response started...")
elif event.type == "content_block_delta":
if event.delta.type == "compaction_delta":
print(f"Compaction complete: {len(event.delta.content or '')} chars")
elif event.delta.type == "text_delta":
print(event.delta.text, end="", flush=True)
# 获取最终累积的消息
message = stream.get_final_message()
messages.append({"role": "assistant", "content": message.content})压缩与提示缓存配合良好。您可以在压缩块上添加 cache_control 断点来缓存摘要内容。原始的已压缩内容会被忽略。
{
"role": "assistant",
"content": [
{
"type": "compaction",
"content": "[summary text]",
"cache_control": { "type": "ephemeral" }
},
{
"type": "text",
"text": "Based on our conversation..."
}
]
}当压缩发生时,摘要会成为需要写入缓存的新内容。如果没有额外的缓存断点,这也会使任何已缓存的系统提示失效,需要将其与压缩摘要一起重新缓存。
为了最大化缓存命中率,请在系统提示的末尾添加一个 cache_control 断点。这样可以使系统提示与对话分开缓存,因此当压缩发生时:
client = anthropic.Anthropic()
messages = [{"role": "user", "content": "Hello, Claude"}]
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-4-8",
max_tokens=4096,
system=[
{
"type": "text",
"text": "You are a helpful coding assistant...",
"cache_control": {
"type": "ephemeral"
}, # Cache the system prompt separately
}
],
messages=messages,
context_management={"edits": [{"type": "compact_20260112"}]},
)这种方法对于较长的系统提示特别有益,因为即使在对话过程中发生多次压缩事件,它们仍能保持缓存状态。
压缩需要额外的采样步骤,这会计入速率限制和计费。API 会在响应中返回详细的使用量信息:
{
"usage": {
"input_tokens": 23000,
"output_tokens": 1000,
"iterations": [
{
"type": "compaction",
"input_tokens": 180000,
"output_tokens": 3500
},
{
"type": "message",
"input_tokens": 23000,
"output_tokens": 1000
}
]
}
}iterations 数组显示每次采样迭代的使用量。当压缩发生时,您会看到一个 compaction 迭代,后跟主 message 迭代。在此示例中,顶层的 input_tokens 和 output_tokens 与 message 迭代完全匹配,因为只有一个非压缩迭代。最后一次迭代的令牌计数反映了压缩后的有效上下文大小。
顶层的 input_tokens 和 output_tokens 不包括压缩迭代的使用量。它们反映的是所有非压缩迭代的总和。要计算请求消耗和计费的总令牌数,请对 usage.iterations 数组中的所有条目求和。
如果您之前依赖 usage.input_tokens 和 usage.output_tokens 进行成本跟踪或审计,则在启用压缩时需要更新跟踪逻辑,以对 usage.iterations 进行汇总。只有在请求期间触发新的压缩时,iterations 数组才会被填充。重新应用之前的 compaction 块不会产生额外的压缩成本,在这种情况下,顶层使用量字段仍然准确。
使用服务器工具(如网络搜索)时,会在每次采样迭代开始时检查压缩触发器。根据您的触发阈值和生成的输出量,单个请求中可能会发生多次压缩。
令牌计数端点(/v1/messages/count_tokens)会应用提示中现有的 compaction 块,但不会触发新的压缩。使用它来检查之前压缩后的有效令牌计数:
client = anthropic.Anthropic()
messages = [{"role": "user", "content": "Hello, Claude"}]
count_response = client.beta.messages.count_tokens(
betas=["compact-2026-01-12"],
model="claude-opus-4-8",
messages=messages,
context_management={"edits": [{"type": "compact_20260112"}]},
)
print(f"Current tokens: {count_response.input_tokens}")
print(f"Original tokens: {count_response.context_management.original_input_tokens}")以下是一个使用压缩的长时间运行对话的完整示例:
client = anthropic.Anthropic()
messages: list[dict] = []
def chat(user_message: str) -> str:
messages.append({"role": "user", "content": user_message})
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-4-8",
max_tokens=4096,
messages=messages,
context_management={
"edits": [
{
"type": "compact_20260112",
"trigger": {"type": "input_tokens", "value": 100000},
}
]
},
)
# 追加响应(压缩块会自动包含在内)
messages.append({"role": "assistant", "content": response.content})
# 返回文本内容
return next(block.text for block in response.content if block.type == "text")
# 运行长对话
print(chat("Help me build a Python web scraper"))
print(chat("Add support for JavaScript-rendered pages"))
print(chat("Now add rate limiting and error handling"))
# ……根据需要继续以下示例使用 pause_after_compaction 来逐字保留上一轮交互和当前用户消息(共三条消息),而不是对它们进行总结:
from typing import Any
client = anthropic.Anthropic()
messages: list[dict[str, Any]] = []
def chat(user_message: str) -> str:
messages.append({"role": "user", "content": user_message})
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-4-8",
max_tokens=4096,
messages=messages,
context_management={
"edits": [
{
"type": "compact_20260112",
"trigger": {"type": "input_tokens", "value": 100000},
"pause_after_compaction": True,
}
]
},
)
# 检查是否发生了压缩并暂停
if response.stop_reason == "compaction":
# 从响应中获取压缩块
compaction_block = response.content[0]
# 保留之前的对话交换 + 当前用户消息(共 3 条消息)
# 方法是将它们包含在压缩块之后
preserved_messages = messages[-3:] if len(messages) >= 3 else messages
# 构建新的消息列表:压缩块 + 保留的消息
new_assistant_content = [compaction_block]
messages_after_compaction = [
{"role": "assistant", "content": new_assistant_content}
] + preserved_messages
# 使用压缩后的上下文 + 保留的消息继续请求
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-4-8",
max_tokens=4096,
messages=messages_after_compaction,
context_management={"edits": [{"type": "compact_20260112"}]},
)
# 更新我们的消息列表以反映压缩结果
messages.clear()
messages.extend(messages_after_compaction)
# 追加最终响应
messages.append({"role": "assistant", "content": response.content})
# 返回文本内容
return next(block.text for block in response.content if block.type == "text")
# 运行一个长对话
print(chat("Help me build a Python web scraper"))
print(chat("Add support for JavaScript-rendered pages"))
print(chat("Now add rate limiting and error handling"))
# ... 根据需要继续使用相同模型进行摘要: 您请求中指定的模型将用于生成摘要。无法选择使用不同的(例如更便宜的)模型来生成摘要。
定义工具时压缩可能失败: 当您的请求包含 tools 时,模型偶尔会在内部摘要步骤中调用工具,而不是编写摘要。发生这种情况时,响应会包含一个 content: null 的 compaction 块。为防止这种情况,请将 instructions 设置为明确告知模型不要调用工具的提示,例如:
Summarize the transcript inside <summary></summary> tags. Include relevant information in the summary for continuing the task in the next context window. Do not call any tools while writing this summary; respond with text only.探索一个实用的实现方案,使用后台线程和提示缓存,通过即时会话记忆压缩来管理长时间运行的对话。
了解上下文窗口大小和管理策略。
探索管理对话上下文的其他策略,如工具结果清除和思考块清除。
Was this page helpful?