백그라운드 압축
대화가 전체 기록을 유지한 채로 계속되는 동안 온디맨드 압축 요약을 요청한 다음, 블록이 도착하면 교체하세요.
"Background compaction"(백그라운드 압축)은 흔히 "async compaction"(비동기 압축)이라고도 불리며, 압축 루프에서 두 가지를 변경합니다: 압축 요청은 대화가 전체 기록을 유지한 채로 계속되는 동안 실행되며, 교체는 블록이 도착할 때까지 대기합니다. 요약에서 이어서 진행하기와 요약 누락 또는 오류 처리하기는 변경 없이 그대로 적용됩니다.
작업이 계속되는 동안 교체가 작동하는 방식
압축 요청과 그것이 반환하는 블록은 루프에서와 동일합니다. 요청을 보내는 시점과 그 결과를 사용하는 시점 사이에 기록이 늘어나며, 교체는 이렇게 늘어난 부분을 그대로 유지해야 합니다.
- 현재 상태의 기록으로 압축 요청을 보내고, 그 기록에 포함된 메시지 수를 기록해 두세요.
- 해당 요청이 실행되는 동안 전체 기록으로 대화를 계속 진행하세요. 새로운 턴마다 추가하고, 이미 기록에 있는 내용은 수정하지 말며, 이번 요청이 교체되거나 실패하기 전까지는 다른 압축 요청을 시작하지 마세요.
stop_reason이"compaction"인 응답이 도착하면, 보냈던 메시지를 기록의 앞부분에서 정확히 제거하고 그 자리에 반환된 메시지를 넣으세요. 1단계 이후 추가된 모든 턴은 그 뒤에 그대로 유지됩니다.- 블록이 도착한 후 첫 번째 요청에서는 교체된 기록을 보내세요. 그러면 요약이 작성되는 동안 생성된 사고(thinking)가 유효하게 유지됩니다.
예를 들어, 압축 요청이 메시지 1부터 5까지를 포함했고 그 요청이 실행되는 동안 대화에 메시지 6부터 8까지가 추가되었다면, 교체 후 기록은 블록 다음에 메시지 6부터 8까지가 이어지는 형태가 됩니다.
응답에 다른 stop_reason이 있다면 요약이 생성되지 않은 것이며, 이는 2단계에서의 실패로 간주됩니다. 전체 기록을 그대로 유지하세요. 요약 누락 또는 오류 처리하기에서 원인과 각각에 대한 대처 방법을 확인할 수 있습니다.
백그라운드에서 요약 요청하기
압축 요청은 다른 요청과 마찬가지로 속도 제한에 포함되며, 요청이 실행되는 동안 애플리케이션은 동시에 두 개의 요청을 열어 두게 됩니다. 대화는 교체가 이루어지기 전까지 전체 기록을 기준으로 계속 늘어나므로, 그 사이에 도착하는 턴을 위한 여유가 컨텍스트 윈도우에 남아 있을 때 압축 요청을 시작하세요.
다음 프로그램은 루프에서 압축하기의 루프에서 압축 요청을 대화의 경로에서 분리한 것입니다. 이 예제는 두 개의 요청을 동시에 실행하는 것에 의존하기 때문에 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 |
|
|---|---|
| Supported platforms |
|
Was this page helpful?