保留最近轮次的压缩
通过按需压缩总结对话中较早的轮次,并在摘要之后逐字发送最近的轮次。
"Keep-tail compaction"(保留尾部压缩)会在摘要之后逐字保留对话的最后几个轮次。它改变了压缩循环中的两件事:哪些消息进入压缩请求,以及您在压缩块之后发送什么。从摘要继续中的所有内容均原样适用。
选择要保留的轮次
没有任何参数用于设置保留哪些轮次。您需要在历史记录中选择一个切分点:切分点之前的消息进入压缩请求,从切分点开始的消息则被保留。
保留的轮次会以完整长度发回给 Claude,因此您保留得越多,压缩释放的空间就越少。
请将切分点放在没有未完成工具调用的位置,使每个工具调用及其结果位于同一侧。如果您发送的消息以一个 assistant 轮次结尾,且该轮次中的工具调用尚无结果,API 会拒绝该压缩请求。
压缩较早的轮次,并在压缩块之后发送其余轮次
要逐字保留最近轮次组成的尾部,请将这些轮次排除在压缩请求之外。API 会总结发送给它的每一条消息,因此请只发送较早的轮次,然后将压缩块放在您保留的轮次前面。
请按照历史记录中的原样发送保留的轮次,包括思考块。两个请求都携带 beta 标头,如请求摘要中所述。
在以下示例中,历史记录包含两个轮次,切分点保留第二个轮次。压缩请求携带第一个轮次:
{
"model": "claude-opus-5-5",
"max_tokens": 4096,
"messages": [
{
"role": "user",
"content": "I am building a recipe app. Help me name the main entities in the data model."
},
{
"role": "assistant",
"content": "Start with Recipe, Ingredient, and Step. Add a RecipeIngredient entry that holds the quantity and unit for each ingredient in a recipe."
}
],
"compaction": { "type": "summarize" }
}下一个请求首先发送返回的压缩块,然后是原样的保留轮次,最后是新的 user 消息。从摘要继续展示了一个以压缩块开头的请求。
以下程序是在循环中压缩中的循环,经过修改以保留最后两个轮次。高亮显示的行表示它与原循环的不同之处。
from anthropic.types.beta import BetaMessageParam
client = anthropic.Anthropic()
# 请将此值设为接近您实际的输入预算。此处设得较低,以便短对话也会触发压缩。
COMPACT_AT_TOKENS = 2500
SYSTEM = "You help design a recipe app's data model. Keep answers short."
KEEP_TURNS = 2
QUESTIONS = [
"What are the main entities in the data model?",
"Which fields should Recipe have?",
"Which fields should Ingredient have?",
"Which fields should RecipeIngredient have?",
"Which fields should Step have?",
"Which indexes should these tables have?",
"Which fields should be required?",
"Which fields should have default values?",
]
history: list[BetaMessageParam] = []
for turn, question in enumerate(QUESTIONS, start=1):
history.append({"role": "user", "content": question})
response = client.beta.messages.create(
model="claude-opus-5-5",
max_tokens=8192,
system=SYSTEM,
betas=["compact-2026-09-04"],
messages=history,
)
history.append({"role": "assistant", "content": response.content})
# 下一个请求也会发送此回复,因此需将其计入。
conversation_tokens = response.usage.input_tokens + response.usage.output_tokens
if conversation_tokens > COMPACT_AT_TOKENS and KEEP_TURNS < turn < len(QUESTIONS):
# 一个轮次包含一条用户消息和一条助手回复,
# 因此保留的轮次以用户消息开头。
split = -2 * KEEP_TURNS
older, recent = history[:split], history[split:]
summary = client.beta.messages.create(
model="claude-opus-5-5",
max_tokens=4096,
system=SYSTEM,
betas=["compact-2026-09-04"],
messages=older,
compaction={"type": "summarize"},
)
if summary.stop_reason == "compaction":
history = [{"role": "assistant", "content": summary.content}, *recent]
print(f"Kept {len(recent) // 2} turns after the block")- 选择切分点: 该程序保留最后两个轮次,其中一个轮次是指一条
user消息及对它的回复。程序在距末尾四条消息处拆分历史记录,因此保留的轮次以一条user消息开头。 - 决定何时压缩: 大小检查还要求对话的轮次多于程序保留的轮次,因此较早的部分永远不会为空。
- 压缩请求: 原循环发送整个历史记录,而此版本只发送较早的消息。
- 替换: 原循环用返回的消息替换整个历史记录,而此版本的新历史记录是返回的消息后跟保留的轮次。
stop_reason 检查以及替换之后的每个请求都与原循环相同。
保持保留轮次中的思考有效
如果您在支持保留思考的模型上发回思考块,则保留轮次中的思考仅在保留的思考保持有效的条件成立时才保持有效,其中一个条件限制了切分点可以落在的位置。
该程序的切分点位于一条回复与下一条 user 消息之间,满足该条件。在您已发出的某个请求的末尾进行切分同样满足该条件:精确压缩该请求的 messages,并保留您的历史记录自那以后新增的所有内容。
Compatibility
| Supported models |
|
|---|---|
| Supported platforms |
|
Was this page helpful?