Compact
Gestion de la mémoireThree-Layer Compression
Context will fill up; three-layer compression strategy enables infinite sessions
s01 > s02 > s03 > s04 > s05 > [ s06 ] | s07 > s08 > s09 > s10 > s11 > s12
"Le contexte se remplira ; vous avez besoin d'un moyen de faire de la place" -- stratégie de compression en trois couches pour des sessions infinies.
Problème
La fenêtre de contexte est finie. Un simple read_file sur un fichier de 1000 lignes coûte ~4000 tokens. Après avoir lu 30 fichiers et exécuté 20 commandes bash, vous atteignez 100 000+ tokens. L'agent ne peut pas travailler sur de grandes bases de code sans compression.
Solution
Trois couches, croissant en agressivité :
À chaque tour:
+------------------+
| Tool call result |
+------------------+
|
v
[Layer 1: micro_compact] (silencieux, à chaque tour)
Remplacer tool_result > 3 tours vieux
avec "[Previous: used {tool_name}]"
|
v
[Check: tokens > 50000?]
| |
no yes
| |
v v
continue [Layer 2: auto_compact]
Sauvegarder transcript dans .transcripts/
LLM résume la conversation.
Remplacer tous les messages par [summary].
|
v
[Layer 3: compact tool]
Le modèle appelle compact explicitement.
Même résumé que auto_compact.
Comment Ça Marche
- Layer 1 -- micro_compact : Avant chaque appel LLM, remplacer les vieux résultats d'outils par des placeholders.
def micro_compact(messages: list) -> list:
tool_results = []
for i, msg in enumerate(messages):
if msg["role"] == "user" and isinstance(msg.get("content"), list):
for j, part in enumerate(msg["content"]):
if isinstance(part, dict) and part.get("type") == "tool_result":
tool_results.append((i, j, part))
if len(tool_results) <= KEEP_RECENT:
return messages
for _, _, part in tool_results[:-KEEP_RECENT]:
if len(part.get("content", "")) > 100:
part["content"] = f"[Previous: used {tool_name}]"
return messages
- Layer 2 -- auto_compact : Quand les tokens dépassent le seuil, sauvegarder le transcript complet sur disque, puis demander au LLM de résumer.
def auto_compact(messages: list) -> list:
# Save transcript for recovery
transcript_path = TRANSCRIPT_DIR / f"transcript_{int(time.time())}.jsonl"
with open(transcript_path, "w") as f:
for msg in messages:
f.write(json.dumps(msg, default=str) + "\n")
# LLM summarizes
response = client.messages.create(
model=MODEL,
messages=[{"role": "user", "content":
"Summarize this conversation for continuity..."
+ json.dumps(messages, default=str)[:80000]}],
max_tokens=2000,
)
return [
{"role": "user", "content": f"[Compressed]\n\n{response.content[0].text}"},
{"role": "assistant", "content": "Understood. Continuing."},
]
-
Layer 3 -- manual compact : L'outil
compactdéclenche le même résumé à la demande. -
La boucle intègre les trois :
def agent_loop(messages: list):
while True:
micro_compact(messages) # Layer 1
if estimate_tokens(messages) > THRESHOLD:
messages[:] = auto_compact(messages) # Layer 2
response = client.messages.create(...)
# ... tool execution ...
if manual_compact:
messages[:] = auto_compact(messages) # Layer 3
Les transcripts préservent l'historique complet sur disque. Rien n'est vraiment perdu -- juste déplacé hors du contexte actif.
Qu'est-ce qui a Changé par Rapport à s05
| Composant | Avant (s05) | Après (s06) |
|---|---|---|
| Outils | 5 | 5 (base + compact) |
| Gestion contexte | None | Compression en trois couches |
| Micro-compact | None | Anciens résultats -> placeholders |
| Auto-compact | None | Déclencheur de seuil de tokens |
| Transcripts | None | Sauvegardés dans .transcripts/ |
Essayer
python agents/s06_context_compact.py
Lire chaque fichier Python dans le répertoire agents/ un par un(regarder micro-compact remplacer les anciens résultats)Continuer à lire des fichiers jusqu'à ce que la compression se déclenche automatiquementUtiliser l'outil compact pour compresser manuellement la conversation
