Compaction Strategies¶
Intelligent memory management through advanced compaction strategies.
Overview¶
Compaction is the process of reducing memory storage by summarizing or merging related entries. Axon provides multiple compaction strategies to intelligently manage memory lifecycle based on your application's needs.
Key Features: - ✓ Multiple compaction strategies - ✓ Semantic similarity grouping - ✓ Importance-based prioritization - ✓ Time-based aging - ✓ Hybrid approaches - ✓ Customizable thresholds
Why Compaction?¶
The Problem¶
# Memory grows unbounded
for i in range(100000):
await memory.store(f"Entry {i}")
# Eventually: OutOfMemory or slow queries
The Solution¶
# Automatic compaction keeps memory manageable
config = MemoryConfig(
persistent=PersistentPolicy(
compaction_threshold=10000, # Compact when > 10K entries
compaction_strategy="semantic" # Group similar entries
)
)
# System automatically compacts
# 100K entries → 10K summaries
# Storage reduced 10x, key information preserved
Compaction Strategies¶
1. Semantic Compaction¶
Groups semantically similar entries:
from axon.core.compaction_strategies import SemanticCompactionStrategy
strategy = SemanticCompactionStrategy(
similarity_threshold=0.85, # 85% similarity to group
min_cluster_size=2 # Min 2 entries per cluster
)
# Groups similar entries into clusters
# Example: All entries about "Python programming" → 1 summary
Best For: - Reducing redundancy - Knowledge bases with similar content - Long-term memory consolidation
Example:
# Before compaction: 100 similar entries
entries = [
"Python is a programming language",
"Python is used for data science",
"Python is great for beginners",
# ... 97 more similar entries
]
# After compaction: 1 summary
summary = "Python is a versatile programming language widely used for data science, web development, and automation. It's beginner-friendly and has a rich ecosystem."
2. Importance Compaction¶
Prioritizes low-importance entries:
from axon.core.compaction_strategies import ImportanceCompactionStrategy
strategy = ImportanceCompactionStrategy(
importance_threshold=0.5 # Compact entries below 0.5 importance
)
# Selects low-importance entries first
# Preserves high-value memories
Best For: - Preserving critical information - User-prioritized memories - Tiered storage systems
Example:
# High importance (0.9) - KEPT
"Critical business decision: Approved $1M budget"
# Medium importance (0.5) - KEPT
"Team meeting notes from Q4 review"
# Low importance (0.2) - COMPACTED
"Coffee machine is on 3rd floor"
"Lunch menu for Tuesday"
3. Time-Based Compaction¶
Compacts older entries first:
from axon.core.compaction_strategies import TimeBasedCompactionStrategy
strategy = TimeBasedCompactionStrategy(
age_threshold_days=30 # Compact entries older than 30 days
)
# Prioritizes older entries
# Recent memories stay detailed
Best For: - Recency-focused applications - Conversation history - Event logs
Example:
# Recent (2 days old) - KEPT DETAILED
"User reported bug in payment flow"
# Old (60 days) - COMPACTED
"Daily standup notes from January" → "January standup summary"
4. Hybrid Compaction¶
Combines multiple strategies:
from axon.core.compaction_strategies import HybridCompactionStrategy
strategy = HybridCompactionStrategy(
strategies=[
SemanticCompactionStrategy(similarity_threshold=0.85),
ImportanceCompactionStrategy(importance_threshold=0.5),
TimeBasedCompactionStrategy(age_threshold_days=30)
],
weights=[0.4, 0.4, 0.2] # 40% semantic, 40% importance, 20% time
)
# Best of all strategies combined
Best For: - Production applications - Balanced approach - Complex memory management needs
Configuration¶
Policy-Level Configuration¶
from axon.core.config import MemoryConfig
from axon.core.policies import PersistentPolicy
config = MemoryConfig(
persistent=PersistentPolicy(
adapter_type="qdrant",
compaction_threshold=10000, # Compact when > 10K entries
compaction_batch_size=100, # Summarize 100 entries at a time
compaction_strategy="semantic" # Use semantic clustering
)
)
Strategy-Specific Configuration¶
# Semantic with custom parameters
config = MemoryConfig(
persistent=PersistentPolicy(
compaction_strategy="semantic",
compaction_config={
"similarity_threshold": 0.90, # Stricter similarity
"min_cluster_size": 3 # Larger clusters
}
)
)
# Importance with custom threshold
config = MemoryConfig(
persistent=PersistentPolicy(
compaction_strategy="importance",
compaction_config={
"importance_threshold": 0.6 # Higher threshold
}
)
)
Manual Compaction¶
Trigger Compaction¶
# Manual compaction trigger
await memory.compact(tier="persistent")
# Or compact all tiers
await memory.compact_all()
Scheduled Compaction¶
import schedule
import asyncio
async def scheduled_compaction():
"""Run compaction daily at 2 AM."""
await memory.compact(tier="persistent")
print(f"Compaction complete at {datetime.now()}")
# Schedule daily
schedule.every().day.at("02:00").do(lambda: asyncio.create_task(scheduled_compaction()))
Examples¶
Semantic Compaction in Action¶
from axon.core.compaction_strategies import SemanticCompactionStrategy
# Setup
strategy = SemanticCompactionStrategy(similarity_threshold=0.85)
config = MemoryConfig(
persistent=PersistentPolicy(
compaction_threshold=1000,
compaction_strategy=strategy
)
)
memory = MemorySystem(config)
# Store related entries
await memory.store("Python is great for data science", importance=0.7)
await memory.store("Python has excellent data science libraries", importance=0.7)
await memory.store("NumPy and Pandas make Python ideal for data", importance=0.7)
# After threshold reached, these get compacted into:
# "Python is a popular language for data science, with powerful libraries like NumPy and Pandas."
Importance-Based Preservation¶
# High-importance entries are preserved
await memory.store("Quarterly revenue: $10M", importance=0.95) # PRESERVED
await memory.store("Sales target: $12M", importance=0.90) # PRESERVED
# Low-importance entries are compacted
for i in range(100):
await memory.store(f"Daily log entry {i}", importance=0.3) # COMPACTED
# After compaction:
# - 2 high-importance entries stay detailed
# - 100 low-importance → 1 summary: "Daily activity logs from Q1"
Time-Based Memory Management¶
# Recent entries (last 7 days) - high detail
recent_entries = [...] # Kept as-is
# Older entries (30+ days) - compacted
old_entries = [...] # Summarized by month
# Example output after compaction:
# "January 2025: 500 entries about project planning, team meetings, and code reviews"
Monitoring Compaction¶
Track Compaction Events¶
# Compaction is logged to audit trail
audit_logger = AuditLogger()
memory = MemorySystem(config, audit_logger=audit_logger)
# After compaction
events = audit_logger.query_events(operation=OperationType.COMPACT)
for event in events:
print(f"Compacted {len(event.entry_ids)} entries")
print(f"Duration: {event.duration_ms}ms")
print(f"Tier: {event.metadata['tier']}")
Compaction Metrics¶
# Get compaction statistics
stats = memory.get_compaction_stats(tier="persistent")
print(f"Total compactions: {stats['total_compactions']}")
print(f"Entries compacted: {stats['entries_compacted']}")
print(f"Space saved: {stats['space_saved_mb']}MB")
print(f"Average compression: {stats['avg_compression_ratio']}x")
Performance¶
Compaction Overhead¶
| Strategy | Selection Cost | Grouping Cost | Best For |
|---|---|---|---|
| Semantic | O(n) | O(n²) | < 10K entries |
| Importance | O(n log n) | O(n) | Any scale |
| Time-Based | O(n log n) | O(n) | Any scale |
| Hybrid | O(n log n) | O(n²) | Balanced |
Optimization Tips¶
# 1. Adjust batch size for your workload
config = MemoryConfig(
persistent=PersistentPolicy(
compaction_batch_size=50 # Smaller batches = more frequent summarization
)
)
# 2. Use background compaction
async def background_compaction():
while True:
await asyncio.sleep(3600) # Every hour
await memory.compact(tier="persistent")
# 3. Monitor and adjust thresholds
stats = memory.get_tier_stats("persistent")
if stats["entry_count"] > 20000:
# Adjust threshold
memory.update_policy(
tier="persistent",
compaction_threshold=15000
)
Best Practices¶
1. Choose the Right Strategy¶
# ✓ Good: Match strategy to use case
# Knowledge base → Semantic
config = MemoryConfig(
persistent=PersistentPolicy(compaction_strategy="semantic")
)
# User preferences → Importance
config = MemoryConfig(
session=SessionPolicy(compaction_strategy="importance")
)
# Event logs → Time-based
config = MemoryConfig(
ephemeral=EphemeralPolicy(compaction_strategy="time_based")
)
2. Set Appropriate Thresholds¶
# ✓ Good: Based on actual usage
# Small app: 1K threshold
config = MemoryConfig(
persistent=PersistentPolicy(compaction_threshold=1000)
)
# Large app: 100K threshold
config = MemoryConfig(
persistent=PersistentPolicy(compaction_threshold=100000)
)
3. Monitor Compaction Quality¶
# Check if compaction is preserving important information
before_count = len(await memory.export(tier="persistent"))
await memory.compact(tier="persistent")
after_count = len(await memory.export(tier="persistent"))
compression_ratio = before_count / after_count
print(f"Compression: {compression_ratio}x")
if compression_ratio > 100:
logger.warning("Very high compression - may be losing information")
Custom Strategies¶
Implement Custom Strategy¶
from axon.core.compaction_strategies import CompactionStrategy
class CustomCompactionStrategy(CompactionStrategy):
"""Custom strategy for domain-specific needs."""
def select_entries_to_compact(
self,
entries: list[MemoryEntry],
threshold: int,
**kwargs
) -> list[MemoryEntry]:
"""Select entries based on custom logic."""
# Your selection logic here
# e.g., select entries with specific tags
return [e for e in entries if "compact_me" in e.tags]
def group_entries(
self,
entries: list[MemoryEntry],
batch_size: int = 100,
**kwargs
) -> list[list[MemoryEntry]]:
"""Group entries for summarization."""
# Your grouping logic here
# e.g., group by date ranges
return self._group_by_month(entries)
@property
def name(self) -> str:
return "custom"
# Use custom strategy
config = MemoryConfig(
persistent=PersistentPolicy(
compaction_strategy=CustomCompactionStrategy()
)
)
Next Steps¶
-
Logging
Monitor compaction with structured logging.
-
Performance
Optimize compaction performance.
-
Adapters
Compaction support by adapter.