Compactação em segundo plano
Solicite um resumo de compactação sob demanda enquanto a conversa continua com o histórico completo e, em seguida, insira o bloco no lugar quando ele chegar.
A "background compaction" (compactação em segundo plano), frequentemente chamada de "async compaction" (compactação assíncrona), muda duas coisas no loop de compactação: a solicitação de compactação é executada enquanto a conversa continua com o histórico completo, e a substituição aguarda até que o bloco chegue. Continuar a partir do resumo e Lidar com um resumo ausente ou um erro se aplicam sem alterações.
Como a substituição funciona enquanto o trabalho continua
A solicitação de compactação e o bloco que ela retorna são os mesmos do loop. Seu histórico cresce entre o envio da solicitação e o uso do resultado, e a substituição deve manter esse crescimento no lugar.
- Envie a solicitação de compactação com o histórico como está e registre quantas mensagens ele continha.
- Enquanto essa solicitação é executada, continue a conversa com o histórico completo. Acrescente cada novo turno, não edite nada que já esteja no histórico e não inicie outra solicitação de compactação até que esta tenha sido inserida no lugar ou tenha falhado.
- Quando a resposta chegar com
stop_reason"compaction", remova exatamente as mensagens que você enviou do início do histórico e coloque a mensagem retornada no lugar delas. Todos os turnos acrescentados desde a etapa 1 permanecem depois dela. - Envie o histórico substituído na primeira solicitação após a chegada do bloco, para que o pensamento produzido enquanto o resumo estava sendo escrito continue válido.
Por exemplo, se a solicitação de compactação continha as mensagens 1 a 5 e a conversa ganhou as mensagens 6 a 8 enquanto ela era executada, após a substituição seu histórico será o bloco seguido das mensagens 6 a 8.
Se a resposta tiver qualquer outro stop_reason, nenhum resumo foi produzido, o que conta como uma falha na etapa 2. Mantenha o histórico completo; Lidar com um resumo ausente ou um erro lista as causas e o que fazer em cada caso.
Solicitar o resumo em segundo plano
A solicitação de compactação conta para seus "rate limits" (limites de taxa) como qualquer outra solicitação e, enquanto ela é executada, sua aplicação tem duas solicitações abertas ao mesmo tempo. A conversa continua crescendo com o histórico completo até a substituição, então inicie a solicitação de compactação enquanto a "context window" (janela de contexto) ainda tiver espaço para os turnos que chegarem nesse meio-tempo.
O programa a seguir é o loop de Compactar em um loop com a solicitação de compactação retirada do caminho da conversa. Ele não tem versão em PHP, porque o exemplo depende da execução de duas solicitações ao mesmo tempo. As linhas destacadas mostram onde ele difere do loop, e a lista a seguir as aborda na ordem em que o programa as executa.
from concurrent.futures import Future, ThreadPoolExecutor
import anthropic
from anthropic.types.beta import BetaMessage, BetaMessageParam
client = anthropic.Anthropic()
executor = ThreadPoolExecutor(max_workers=1)
# Defina isto perto do seu orçamento real de entrada. Aqui está baixo para que uma conversa curta seja compactada.
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":
# Substitua exatamente as mensagens que a solicitação de compactação continha.
# Os turnos posteriores ficam depois do bloco.
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})
# A próxima solicitação também envia esta resposta, então conte-a.
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"},
)
# Troque por um resumo que ainda está a caminho antes de salvar
# ou continuar a conversa.
if pending is not None:
swap_in(history, pending.result(), sent)
executor.shutdown()- Decidir quando compactar: A verificação de tamanho também exige que nenhuma solicitação de compactação esteja pendente.
- Iniciar a solicitação: Onde o loop aguarda a resposta de compactação, esta versão registra quantas mensagens o histórico contém, inicia a solicitação em uma cópia do histórico com a ferramenta de concorrência própria de cada linguagem e segue para o próximo turno sem esperar.
- Verificar o resultado: No início de cada turno, o programa verifica se a solicitação pendente foi concluída. Se tiver sido, o programa faz a substituição antes de enviar a solicitação desse turno.
- Fazer a substituição: Onde o loop substitui todo o histórico pela mensagem retornada, a função de substituição desta versão substitui apenas as mensagens que a solicitação continha, contadas a partir do início, e mantém tudo o que foi acrescentado desde então.
- Encerrar o loop: Se a solicitação de compactação ainda estiver pendente quando o loop terminar, o programa aguarda por ela e faz a substituição, para que um resumo que ainda está a caminho não seja perdido antes de você salvar ou continuar a conversa.
A verificação de stop_reason não muda em relação ao loop: uma resposta sem bloco deixa o histórico como estava. Como não há mais nada pendente, o programa pode então iniciar uma nova solicitação de compactação.
Manter o pensamento válido enquanto o resumo é construído
Os turnos que chegam enquanto o resumo está sendo escrito são turnos mantidos. Se você enviar blocos de pensamento de volta em um modelo com "preserved thinking" (pensamento preservado), o pensamento nesses turnos permanece válido apenas enquanto as condições para o pensamento mantido forem atendidas.
Compatibility
| Supported models |
|
|---|---|
| Supported platforms |
|
Was this page helpful?