mirror of
https://github.com/headroomlabs-ai/headroom.git
synced 2026-08-27 14:17:10 -04:00
This commit prepares Headroom for public open source release with comprehensive documentation, licensing, and community infrastructure. License & Legal: - Add Apache 2.0 LICENSE file - Add NOTICE file with third-party attributions - Add SECURITY.md for vulnerability reporting Community: - Add CONTRIBUTING.md with contribution guidelines - Add CODE_OF_CONDUCT.md (Contributor Covenant) - Add GitHub issue templates (bug report, feature request) - Add pull request template Documentation: - Update README.md with compelling value proposition - Add docs/getting-started.md - Add docs/proxy.md for proxy server documentation - Add docs/transforms.md for transform reference - Add docs/api.md for API reference - Add examples/README.md Package Infrastructure: - Add headroom/py.typed for PEP 561 compliance - Add headroom/cli.py for CLI entry point - Add .github/workflows/ci.yml for CI pipeline - Add .github/workflows/publish.yml for PyPI publishing - Update pyproject.toml with proper metadata New Features: - Add multi-provider support (Google, Cohere, LiteLLM, OpenAI-compatible) - Add universal tokenizer registry with multiple backends - Add model registry with pricing and context limits - Add production proxy server with caching and rate limiting Code Quality: - Fix 83 lint issues via ruff auto-fix - Fix version consistency (benchmarks 0.1.0 → 0.2.0) - Add skip decorators for optional dependency tests
4.9 KiB
4.9 KiB
Transform Reference
Headroom provides three core transforms that work together to optimize LLM context.
SmartCrusher
Statistical compression for JSON tool outputs.
How It Works
SmartCrusher analyzes JSON arrays and selectively keeps important items:
- First/Last items - Context for pagination and recency
- Error items - 100% preservation of error states
- Anomalies - Statistical outliers (> 2 std dev from mean)
- Relevant items - Matches to user's query via BM25/embeddings
- Change points - Significant transitions in data
Configuration
from headroom import SmartCrusherConfig
config = SmartCrusherConfig(
min_tokens_to_crush=200, # Only compress if > 200 tokens
max_items_after_crush=50, # Keep at most 50 items
keep_first=3, # Always keep first 3 items
keep_last=2, # Always keep last 2 items
relevance_threshold=0.3, # Keep items with relevance > 0.3
anomaly_std_threshold=2.0, # Keep items > 2 std dev from mean
preserve_errors=True, # Always keep error items
)
Example
from headroom import SmartCrusher
crusher = SmartCrusher(config)
# Before: 1000 search results (45,000 tokens)
tool_output = {"results": [...1000 items...]}
# After: ~50 important items (4,500 tokens) - 90% reduction
compressed = crusher.crush(tool_output, query="user's question")
What Gets Preserved
| Category | Preserved | Why |
|---|---|---|
| Errors | 100% | Critical for debugging |
| First N | 100% | Context/pagination |
| Last N | 100% | Recency |
| Anomalies | All | Unusual values matter |
| Relevant | Top K | Match user's query |
| Others | Sampled | Statistical representation |
CacheAligner
Prefix stabilization for improved cache hit rates.
The Problem
LLM providers cache request prefixes. But dynamic content breaks caching:
"You are helpful. Today is January 7, 2025." # Changes daily = no cache
The Solution
CacheAligner extracts dynamic content to stabilize the prefix:
from headroom import CacheAligner
aligner = CacheAligner()
result = aligner.align(messages)
# Static prefix (cacheable):
# "You are helpful."
# Dynamic content moved to end:
# [Current date context]
Configuration
from headroom import CacheAlignerConfig
config = CacheAlignerConfig(
extract_dates=True, # Move dates to dynamic section
normalize_whitespace=True, # Consistent spacing
stable_prefix_min_tokens=100, # Min prefix size for alignment
)
Cache Hit Improvement
| Scenario | Before | After |
|---|---|---|
| Daily date in prompt | 0% hits | ~95% hits |
| Dynamic user context | ~10% hits | ~80% hits |
| Consistent prompts | ~90% hits | ~95% hits |
RollingWindow
Context management within token limits.
The Problem
Long conversations exceed context limits. Naive truncation breaks tool calls:
[tool_call: search] # Kept
[tool_result: ...] # Dropped = orphaned call!
The Solution
RollingWindow drops complete tool units, preserving pairs:
from headroom import RollingWindow
window = RollingWindow(config)
result = window.apply(messages, max_tokens=100000)
# Guarantees:
# 1. Tool calls paired with results
# 2. System prompt preserved
# 3. Recent turns kept
# 4. Oldest tool outputs dropped first
Configuration
from headroom import RollingWindowConfig
config = RollingWindowConfig(
max_tokens=100000, # Target token limit
preserve_system=True, # Always keep system prompt
preserve_recent_turns=5, # Keep last 5 user/assistant turns
drop_oldest_first=True, # Remove oldest tool outputs
)
Drop Priority
- Oldest tool outputs - First to go
- Old assistant messages - Summary preserved
- Old user messages - Only if necessary
- Never dropped: System prompt, recent turns, active tool pairs
TransformPipeline
Combine transforms for optimal results.
from headroom import TransformPipeline, SmartCrusher, CacheAligner, RollingWindow
pipeline = TransformPipeline([
SmartCrusher(), # First: compress tool outputs
CacheAligner(), # Then: stabilize prefix
RollingWindow(), # Finally: fit in context
])
result = pipeline.transform(messages)
print(f"Saved {result.tokens_saved} tokens")
Recommended Order
- SmartCrusher - Reduce individual messages
- CacheAligner - Optimize for caching
- RollingWindow - Final size constraint
Safety Guarantees
All transforms follow strict safety rules:
- Never remove human content - User/assistant text is sacred
- Never break tool ordering - Calls and results stay paired
- Parse failures are no-ops - Malformed content passes through
- Preserves recency - Last N turns always kept
- 100% error preservation - Error items never dropped