Claude Platform Docs
Messages压缩

后台压缩

在对话基于完整历史继续进行的同时按需请求压缩摘要,然后在压缩块到达时将其替换进来。

"Background compaction"(后台压缩),通常也称为"async compaction"(异步压缩),会改变压缩循环中的两件事:压缩请求在对话基于完整历史继续进行的同时运行,而替换操作会等到压缩块到达后才进行。从摘要继续处理缺失的摘要或错误中的内容同样适用,无需更改。

工作继续进行时如何替换

压缩请求及其返回的块与循环中的相同。在发送请求和使用其结果之间,您的历史记录会不断增长,而替换操作必须保留这部分增长的内容。

  1. 使用当前的历史记录发送压缩请求,并记录其中包含的消息数量。
  2. 在该请求运行期间,继续基于完整历史进行对话。追加每个新轮次,不要编辑历史记录中已有的任何内容,并且在此请求被替换进来或失败之前,不要启动另一个压缩请求。
  3. 当响应到达且 stop_reason"compaction" 时,从历史记录开头准确删除您发送的那些消息,并将返回的消息放在它们的位置。自步骤 1 以来追加的每个轮次都保留在其后。
  4. 在块到达后的第一个请求中发送替换后的历史记录,以便在编写摘要期间产生的思考保持有效。

例如,如果压缩请求包含消息 1 到 5,而对话在其运行期间新增了消息 6 到 8,那么替换后您的历史记录就是该块后跟消息 6 到 8。

Request sentmessages 1–512345While it runs6–8 arrive12345678compaction request: 1–5After the swapblock, then 6–8compaction block678

如果响应具有任何其他 stop_reason,则表示未生成摘要,这在步骤 2 中算作失败。请保留完整历史记录;处理缺失的摘要或错误列出了各种原因以及每种情况的处理方法。

在后台请求摘要

与任何其他请求一样,压缩请求也会计入您的"rate limit"(速率限制),并且在其运行期间,您的应用程序会同时有两个请求处于打开状态。在替换之前,对话会基于完整历史持续增长,因此请在"context window"(上下文窗口)仍有空间容纳期间到达的轮次时启动压缩请求。

以下程序是在循环中压缩中的循环,只是将压缩请求从对话的执行路径中移出。它没有 PHP 版本,因为该示例依赖于同时运行两个请求。高亮显示的行表示它与该循环的不同之处,下面的列表按程序运行的顺序逐一说明这些不同之处。

from concurrent.futures import Future, ThreadPoolExecutor

import anthropic
from anthropic.types.beta import BetaMessage, BetaMessageParam

client = anthropic.Anthropic()
executor = ThreadPoolExecutor(max_workers=1)

# 请将此值设为接近您实际的输入预算。此处设得较低,以便简短对话也会触发压缩。
COMPACT_AT_TOKENS = 2500
SYSTEM = "You help design a recipe app's data model. Keep answers short."

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?",
]


def swap_in(history: list[BetaMessageParam], summary: BetaMessage, sent: int) -> None:
    if summary.stop_reason == "compaction":
        # 精确替换压缩请求中包含的那些消息。
        # 后续轮次保留在该块之后。
        history[:sent] = [{"role": "assistant", "content": summary.content}]
        print(f"Swapped {sent} messages")


history: list[BetaMessageParam] = []
pending: Future[BetaMessage] | None = None
sent = 0
for turn, question in enumerate(QUESTIONS, start=1):
    if pending is not None and pending.done():
        swap_in(history, pending.result(), sent)
        pending = None

    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 turn < len(QUESTIONS)
        and pending is None
    ):
        sent = len(history)
        pending = executor.submit(
            client.beta.messages.create,
            model="claude-opus-5-5",
            max_tokens=4096,
            system=SYSTEM,
            betas=["compact-2026-09-04"],
            messages=history.copy(),
            compaction={"type": "summarize"},
        )

# 在保存之前,先换入仍在生成中的摘要
# 或继续对话。
if pending is not None:
    swap_in(history, pending.result(), sent)
executor.shutdown()
  • 决定何时压缩: 大小检查还要求当前没有待处理的压缩请求。
  • 启动请求: 在循环等待压缩响应的地方,此版本会记录历史记录中包含的消息数量,使用每种语言自身的并发工具在历史记录的副本上启动请求,然后不等待结果直接进入下一个轮次。
  • 检查结果: 在每个轮次开始时,程序会检查待处理的请求是否已完成。如果已完成,程序会在发送该轮次的请求之前进行替换。
  • 进行替换: 在循环用返回的消息替换整个历史记录的地方,此版本的替换函数仅替换请求所包含的消息(从开头开始计数),并保留此后追加的所有内容。
  • 结束循环: 如果循环结束时压缩请求仍处于待处理状态,程序会等待它完成并进行替换,这样在您保存或继续对话之前,仍在途中的摘要就不会丢失。

stop_reason 检查与循环中的相同:没有块的响应会使历史记录保持原样。由于不再有待处理的请求,程序随后可以启动新的压缩请求。

在构建摘要期间保持思考有效

在编写摘要期间到达的轮次属于保留的轮次。如果您在支持保留思考的模型上回传思考块,则这些轮次中的思考仅在保留的思考保持有效的条件成立时才保持有效。

Compatibility

Supported models
  • Fable 5 and 5.1
  • Mythos 5, 5.1, and Preview
  • Opus 4.6, 4.7, 4.8, 5, and 5.5
  • Sonnet 4.6 and 5
Supported platforms
  • Claude APIBeta
  • Claude Platform on AWSBeta
  • Google CloudBeta
  • Microsoft FoundryBeta

Was this page helpful?