headroom-ai 0.2.13__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- headroom/__init__.py +212 -0
- headroom/cache/__init__.py +76 -0
- headroom/cache/anthropic.py +517 -0
- headroom/cache/base.py +342 -0
- headroom/cache/compression_feedback.py +613 -0
- headroom/cache/compression_store.py +814 -0
- headroom/cache/dynamic_detector.py +1026 -0
- headroom/cache/google.py +884 -0
- headroom/cache/openai.py +584 -0
- headroom/cache/registry.py +175 -0
- headroom/cache/semantic.py +451 -0
- headroom/ccr/__init__.py +77 -0
- headroom/ccr/context_tracker.py +582 -0
- headroom/ccr/mcp_server.py +319 -0
- headroom/ccr/response_handler.py +772 -0
- headroom/ccr/tool_injection.py +415 -0
- headroom/cli.py +219 -0
- headroom/client.py +977 -0
- headroom/compression/__init__.py +42 -0
- headroom/compression/detector.py +424 -0
- headroom/compression/handlers/__init__.py +22 -0
- headroom/compression/handlers/base.py +219 -0
- headroom/compression/handlers/code_handler.py +506 -0
- headroom/compression/handlers/json_handler.py +418 -0
- headroom/compression/masks.py +345 -0
- headroom/compression/universal.py +465 -0
- headroom/config.py +474 -0
- headroom/exceptions.py +192 -0
- headroom/integrations/__init__.py +159 -0
- headroom/integrations/agno/__init__.py +53 -0
- headroom/integrations/agno/hooks.py +345 -0
- headroom/integrations/agno/model.py +625 -0
- headroom/integrations/agno/providers.py +154 -0
- headroom/integrations/langchain/__init__.py +106 -0
- headroom/integrations/langchain/agents.py +326 -0
- headroom/integrations/langchain/chat_model.py +1002 -0
- headroom/integrations/langchain/langsmith.py +324 -0
- headroom/integrations/langchain/memory.py +319 -0
- headroom/integrations/langchain/providers.py +200 -0
- headroom/integrations/langchain/retriever.py +371 -0
- headroom/integrations/langchain/streaming.py +341 -0
- headroom/integrations/mcp/__init__.py +37 -0
- headroom/integrations/mcp/server.py +533 -0
- headroom/memory/__init__.py +37 -0
- headroom/memory/extractor.py +390 -0
- headroom/memory/fast_store.py +621 -0
- headroom/memory/fast_wrapper.py +311 -0
- headroom/memory/inline_extractor.py +229 -0
- headroom/memory/store.py +434 -0
- headroom/memory/worker.py +260 -0
- headroom/memory/wrapper.py +321 -0
- headroom/models/__init__.py +39 -0
- headroom/models/registry.py +687 -0
- headroom/parser.py +293 -0
- headroom/pricing/__init__.py +51 -0
- headroom/pricing/anthropic_prices.py +81 -0
- headroom/pricing/litellm_pricing.py +113 -0
- headroom/pricing/openai_prices.py +91 -0
- headroom/pricing/registry.py +188 -0
- headroom/providers/__init__.py +61 -0
- headroom/providers/anthropic.py +621 -0
- headroom/providers/base.py +131 -0
- headroom/providers/cohere.py +362 -0
- headroom/providers/google.py +427 -0
- headroom/providers/litellm.py +297 -0
- headroom/providers/openai.py +566 -0
- headroom/providers/openai_compatible.py +521 -0
- headroom/proxy/__init__.py +19 -0
- headroom/proxy/server.py +2683 -0
- headroom/py.typed +0 -0
- headroom/relevance/__init__.py +124 -0
- headroom/relevance/base.py +106 -0
- headroom/relevance/bm25.py +255 -0
- headroom/relevance/embedding.py +255 -0
- headroom/relevance/hybrid.py +259 -0
- headroom/reporting/__init__.py +5 -0
- headroom/reporting/generator.py +549 -0
- headroom/storage/__init__.py +41 -0
- headroom/storage/base.py +125 -0
- headroom/storage/jsonl.py +220 -0
- headroom/storage/sqlite.py +289 -0
- headroom/telemetry/__init__.py +91 -0
- headroom/telemetry/collector.py +764 -0
- headroom/telemetry/models.py +880 -0
- headroom/telemetry/toin.py +1579 -0
- headroom/tokenizer.py +80 -0
- headroom/tokenizers/__init__.py +75 -0
- headroom/tokenizers/base.py +210 -0
- headroom/tokenizers/estimator.py +198 -0
- headroom/tokenizers/huggingface.py +317 -0
- headroom/tokenizers/mistral.py +245 -0
- headroom/tokenizers/registry.py +398 -0
- headroom/tokenizers/tiktoken_counter.py +248 -0
- headroom/transforms/__init__.py +106 -0
- headroom/transforms/base.py +57 -0
- headroom/transforms/cache_aligner.py +357 -0
- headroom/transforms/code_compressor.py +1313 -0
- headroom/transforms/content_detector.py +335 -0
- headroom/transforms/content_router.py +1158 -0
- headroom/transforms/llmlingua_compressor.py +638 -0
- headroom/transforms/log_compressor.py +529 -0
- headroom/transforms/pipeline.py +297 -0
- headroom/transforms/rolling_window.py +350 -0
- headroom/transforms/search_compressor.py +365 -0
- headroom/transforms/smart_crusher.py +2682 -0
- headroom/transforms/text_compressor.py +259 -0
- headroom/transforms/tool_crusher.py +338 -0
- headroom/utils.py +215 -0
- headroom_ai-0.2.13.dist-info/METADATA +315 -0
- headroom_ai-0.2.13.dist-info/RECORD +114 -0
- headroom_ai-0.2.13.dist-info/WHEEL +4 -0
- headroom_ai-0.2.13.dist-info/entry_points.txt +2 -0
- headroom_ai-0.2.13.dist-info/licenses/LICENSE +190 -0
- headroom_ai-0.2.13.dist-info/licenses/NOTICE +43 -0
headroom/utils.py
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
"""Shared utilities for Headroom SDK."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import hashlib
|
|
6
|
+
import json
|
|
7
|
+
import re
|
|
8
|
+
import uuid
|
|
9
|
+
from datetime import datetime
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
# Marker format for Headroom modifications
|
|
13
|
+
MARKER_PREFIX = "<headroom:"
|
|
14
|
+
MARKER_SUFFIX = ">"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def generate_request_id() -> str:
|
|
18
|
+
"""Generate a unique request ID."""
|
|
19
|
+
return str(uuid.uuid4())
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def compute_hash(data: str | bytes) -> str:
|
|
23
|
+
"""Compute SHA256 hash, returning hex string."""
|
|
24
|
+
if isinstance(data, str):
|
|
25
|
+
data = data.encode("utf-8")
|
|
26
|
+
return hashlib.sha256(data).hexdigest()
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def compute_short_hash(data: str | bytes, length: int = 16) -> str:
|
|
30
|
+
"""Compute truncated SHA256 hash."""
|
|
31
|
+
return compute_hash(data)[:length]
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def compute_messages_hash(messages: list[dict[str, Any]]) -> str:
|
|
35
|
+
"""Compute hash of messages list for deduplication."""
|
|
36
|
+
# Serialize deterministically
|
|
37
|
+
serialized = json.dumps(messages, sort_keys=True, separators=(",", ":"))
|
|
38
|
+
return compute_short_hash(serialized)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def compute_prefix_hash(messages: list[dict[str, Any]], prefix_count: int | None = None) -> str:
|
|
42
|
+
"""
|
|
43
|
+
Compute hash of message prefix for cache alignment.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
messages: List of messages.
|
|
47
|
+
prefix_count: Number of messages to include (default: all system messages + 1).
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
Hash of the prefix content.
|
|
51
|
+
"""
|
|
52
|
+
if not messages:
|
|
53
|
+
return compute_short_hash("")
|
|
54
|
+
|
|
55
|
+
if prefix_count is None:
|
|
56
|
+
# Default: system messages + first non-system
|
|
57
|
+
prefix_count = 1
|
|
58
|
+
for i, msg in enumerate(messages):
|
|
59
|
+
if msg.get("role") == "system":
|
|
60
|
+
prefix_count = i + 2
|
|
61
|
+
else:
|
|
62
|
+
break
|
|
63
|
+
|
|
64
|
+
prefix_messages = messages[:prefix_count]
|
|
65
|
+
serialized = json.dumps(prefix_messages, sort_keys=True, separators=(",", ":"))
|
|
66
|
+
return compute_short_hash(serialized)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def format_timestamp(dt: datetime | None = None) -> str:
|
|
70
|
+
"""Format datetime as ISO8601 string."""
|
|
71
|
+
if dt is None:
|
|
72
|
+
dt = datetime.utcnow()
|
|
73
|
+
return dt.isoformat() + "Z"
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def parse_timestamp(ts: str) -> datetime:
|
|
77
|
+
"""Parse ISO8601 timestamp string."""
|
|
78
|
+
# Handle both with and without Z suffix
|
|
79
|
+
ts = ts.rstrip("Z")
|
|
80
|
+
return datetime.fromisoformat(ts)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def create_marker(marker_type: str, **kwargs: Any) -> str:
|
|
84
|
+
"""
|
|
85
|
+
Create a Headroom marker string.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
marker_type: Type of marker (e.g., "tool_digest", "dropped_context").
|
|
89
|
+
**kwargs: Attributes to include in the marker.
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
Formatted marker string.
|
|
93
|
+
"""
|
|
94
|
+
attrs = " ".join(f'{k}="{v}"' for k, v in kwargs.items())
|
|
95
|
+
if attrs:
|
|
96
|
+
return f"{MARKER_PREFIX}{marker_type} {attrs}{MARKER_SUFFIX}"
|
|
97
|
+
return f"{MARKER_PREFIX}{marker_type}{MARKER_SUFFIX}"
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def create_tool_digest_marker(original_hash: str) -> str:
|
|
101
|
+
"""Create marker for crushed tool output."""
|
|
102
|
+
return create_marker("tool_digest", sha256=original_hash)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def create_dropped_context_marker(reason: str, count: int | None = None) -> str:
|
|
106
|
+
"""Create marker for dropped context."""
|
|
107
|
+
if count is not None:
|
|
108
|
+
return create_marker("dropped_context", reason=reason, count=str(count))
|
|
109
|
+
return create_marker("dropped_context", reason=reason)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def create_truncated_marker(original_length: int, truncated_to: int) -> str:
|
|
113
|
+
"""Create marker for truncated content."""
|
|
114
|
+
return create_marker(
|
|
115
|
+
"truncated",
|
|
116
|
+
original=str(original_length),
|
|
117
|
+
truncated_to=str(truncated_to),
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def extract_markers(text: str) -> list[dict[str, Any]]:
|
|
122
|
+
"""
|
|
123
|
+
Extract Headroom markers from text.
|
|
124
|
+
|
|
125
|
+
Returns:
|
|
126
|
+
List of dicts with marker_type and attributes.
|
|
127
|
+
"""
|
|
128
|
+
pattern = re.compile(r"<headroom:(\w+)([^>]*)>")
|
|
129
|
+
markers = []
|
|
130
|
+
|
|
131
|
+
for match in pattern.finditer(text):
|
|
132
|
+
marker_type = match.group(1)
|
|
133
|
+
attrs_str = match.group(2).strip()
|
|
134
|
+
|
|
135
|
+
# Parse attributes
|
|
136
|
+
attrs: dict[str, str] = {}
|
|
137
|
+
if attrs_str:
|
|
138
|
+
attr_pattern = re.compile(r'(\w+)="([^"]*)"')
|
|
139
|
+
for attr_match in attr_pattern.finditer(attrs_str):
|
|
140
|
+
attrs[attr_match.group(1)] = attr_match.group(2)
|
|
141
|
+
|
|
142
|
+
markers.append({"type": marker_type, "attributes": attrs})
|
|
143
|
+
|
|
144
|
+
return markers
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def safe_json_loads(text: str) -> tuple[Any | None, bool]:
|
|
148
|
+
"""
|
|
149
|
+
Safely parse JSON, returning (result, success).
|
|
150
|
+
|
|
151
|
+
Args:
|
|
152
|
+
text: JSON string to parse.
|
|
153
|
+
|
|
154
|
+
Returns:
|
|
155
|
+
Tuple of (parsed_result or None, success_bool).
|
|
156
|
+
"""
|
|
157
|
+
try:
|
|
158
|
+
return json.loads(text), True
|
|
159
|
+
except (json.JSONDecodeError, ValueError):
|
|
160
|
+
return None, False
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def safe_json_dumps(obj: Any, **kwargs: Any) -> str:
|
|
164
|
+
"""
|
|
165
|
+
Safely serialize to JSON with defaults.
|
|
166
|
+
|
|
167
|
+
Args:
|
|
168
|
+
obj: Object to serialize.
|
|
169
|
+
**kwargs: Additional json.dumps arguments.
|
|
170
|
+
|
|
171
|
+
Returns:
|
|
172
|
+
JSON string.
|
|
173
|
+
"""
|
|
174
|
+
kwargs.setdefault("ensure_ascii", False)
|
|
175
|
+
kwargs.setdefault("separators", (",", ":")) # Compact by default
|
|
176
|
+
return json.dumps(obj, **kwargs)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def estimate_cost(
|
|
180
|
+
input_tokens: int,
|
|
181
|
+
output_tokens: int,
|
|
182
|
+
model: str,
|
|
183
|
+
cached_tokens: int = 0,
|
|
184
|
+
provider: Any = None,
|
|
185
|
+
) -> float | None:
|
|
186
|
+
"""
|
|
187
|
+
Estimate API cost in USD using provider.
|
|
188
|
+
|
|
189
|
+
Args:
|
|
190
|
+
input_tokens: Number of input tokens.
|
|
191
|
+
output_tokens: Number of output tokens.
|
|
192
|
+
model: Model name.
|
|
193
|
+
cached_tokens: Number of cached input tokens.
|
|
194
|
+
provider: Provider instance for cost estimation.
|
|
195
|
+
|
|
196
|
+
Returns:
|
|
197
|
+
Estimated cost in USD, or None if not available.
|
|
198
|
+
"""
|
|
199
|
+
if provider is None:
|
|
200
|
+
return None
|
|
201
|
+
result = provider.estimate_cost(input_tokens, output_tokens, model, cached_tokens)
|
|
202
|
+
return float(result) if result is not None else None
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
def format_cost(cost: float) -> str:
|
|
206
|
+
"""Format cost as human-readable string."""
|
|
207
|
+
if cost < 0.01:
|
|
208
|
+
return f"${cost:.4f}"
|
|
209
|
+
return f"${cost:.2f}"
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def deep_copy_messages(messages: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
|
213
|
+
"""Create a deep copy of messages list."""
|
|
214
|
+
result: list[dict[str, Any]] = json.loads(json.dumps(messages))
|
|
215
|
+
return result
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: headroom-ai
|
|
3
|
+
Version: 0.2.13
|
|
4
|
+
Summary: The Context Optimization Layer for LLM Applications - Cut costs by 50-90%
|
|
5
|
+
Project-URL: Homepage, https://github.com/chopratejas/headroom
|
|
6
|
+
Project-URL: Documentation, https://github.com/chopratejas/headroom#readme
|
|
7
|
+
Project-URL: Repository, https://github.com/chopratejas/headroom
|
|
8
|
+
Project-URL: Issues, https://github.com/chopratejas/headroom/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/chopratejas/headroom/blob/main/CHANGELOG.md
|
|
10
|
+
Author: Headroom Contributors
|
|
11
|
+
Maintainer: Headroom Contributors
|
|
12
|
+
License-Expression: Apache-2.0
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
License-File: NOTICE
|
|
15
|
+
Keywords: ai,anthropic,caching,claude,compression,context,gpt,llm,machine-learning,openai,optimization,proxy,token
|
|
16
|
+
Classifier: Development Status :: 4 - Beta
|
|
17
|
+
Classifier: Intended Audience :: Developers
|
|
18
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
19
|
+
Classifier: Operating System :: OS Independent
|
|
20
|
+
Classifier: Programming Language :: Python :: 3
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
24
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
25
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
26
|
+
Classifier: Typing :: Typed
|
|
27
|
+
Requires-Python: >=3.10
|
|
28
|
+
Requires-Dist: litellm>=1.0.0
|
|
29
|
+
Requires-Dist: openai>=2.14.0
|
|
30
|
+
Requires-Dist: pydantic>=2.0.0
|
|
31
|
+
Requires-Dist: sentence-transformers>=5.2.0
|
|
32
|
+
Requires-Dist: tiktoken>=0.5.0
|
|
33
|
+
Provides-Extra: agno
|
|
34
|
+
Requires-Dist: agno>=1.0.0; extra == 'agno'
|
|
35
|
+
Provides-Extra: all
|
|
36
|
+
Requires-Dist: fastapi>=0.100.0; extra == 'all'
|
|
37
|
+
Requires-Dist: httpx>=0.24.0; extra == 'all'
|
|
38
|
+
Requires-Dist: jinja2>=3.0.0; extra == 'all'
|
|
39
|
+
Requires-Dist: llmlingua>=0.2.0; extra == 'all'
|
|
40
|
+
Requires-Dist: numpy>=1.24.0; extra == 'all'
|
|
41
|
+
Requires-Dist: sentence-transformers>=2.2.0; extra == 'all'
|
|
42
|
+
Requires-Dist: torch>=2.0.0; extra == 'all'
|
|
43
|
+
Requires-Dist: transformers>=4.30.0; extra == 'all'
|
|
44
|
+
Requires-Dist: tree-sitter-language-pack>=0.10.0; extra == 'all'
|
|
45
|
+
Requires-Dist: uvicorn>=0.23.0; extra == 'all'
|
|
46
|
+
Provides-Extra: code
|
|
47
|
+
Requires-Dist: tree-sitter-language-pack>=0.10.0; extra == 'code'
|
|
48
|
+
Provides-Extra: dev
|
|
49
|
+
Requires-Dist: anthropic>=0.18.0; extra == 'dev'
|
|
50
|
+
Requires-Dist: langchain-ollama>=0.2.0; extra == 'dev'
|
|
51
|
+
Requires-Dist: mypy>=1.0.0; extra == 'dev'
|
|
52
|
+
Requires-Dist: ollama>=0.4.0; extra == 'dev'
|
|
53
|
+
Requires-Dist: openai>=1.0.0; extra == 'dev'
|
|
54
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
|
|
55
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
|
|
56
|
+
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
57
|
+
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
58
|
+
Provides-Extra: llmlingua
|
|
59
|
+
Requires-Dist: llmlingua>=0.2.0; extra == 'llmlingua'
|
|
60
|
+
Requires-Dist: torch>=2.0.0; extra == 'llmlingua'
|
|
61
|
+
Requires-Dist: transformers>=4.30.0; extra == 'llmlingua'
|
|
62
|
+
Provides-Extra: proxy
|
|
63
|
+
Requires-Dist: fastapi>=0.100.0; extra == 'proxy'
|
|
64
|
+
Requires-Dist: httpx>=0.24.0; extra == 'proxy'
|
|
65
|
+
Requires-Dist: uvicorn>=0.23.0; extra == 'proxy'
|
|
66
|
+
Provides-Extra: relevance
|
|
67
|
+
Requires-Dist: numpy>=1.24.0; extra == 'relevance'
|
|
68
|
+
Requires-Dist: sentence-transformers>=2.2.0; extra == 'relevance'
|
|
69
|
+
Provides-Extra: reports
|
|
70
|
+
Requires-Dist: jinja2>=3.0.0; extra == 'reports'
|
|
71
|
+
Description-Content-Type: text/markdown
|
|
72
|
+
|
|
73
|
+
<p align="center">
|
|
74
|
+
<h1 align="center">Headroom</h1>
|
|
75
|
+
<p align="center">
|
|
76
|
+
<strong>The Context Optimization Layer for LLM Applications</strong>
|
|
77
|
+
</p>
|
|
78
|
+
<p align="center">
|
|
79
|
+
Cut your LLM costs by 50-90% without losing accuracy
|
|
80
|
+
</p>
|
|
81
|
+
</p>
|
|
82
|
+
|
|
83
|
+
<p align="center">
|
|
84
|
+
<a href="https://github.com/chopratejas/headroom/actions/workflows/ci.yml">
|
|
85
|
+
<img src="https://github.com/chopratejas/headroom/actions/workflows/ci.yml/badge.svg" alt="CI">
|
|
86
|
+
</a>
|
|
87
|
+
<a href="https://pypi.org/project/headroom-ai/">
|
|
88
|
+
<img src="https://img.shields.io/pypi/v/headroom-ai.svg" alt="PyPI">
|
|
89
|
+
</a>
|
|
90
|
+
<a href="https://pypi.org/project/headroom-ai/">
|
|
91
|
+
<img src="https://img.shields.io/pypi/pyversions/headroom-ai.svg" alt="Python">
|
|
92
|
+
</a>
|
|
93
|
+
<a href="https://github.com/chopratejas/headroom/blob/main/LICENSE">
|
|
94
|
+
<img src="https://img.shields.io/badge/license-Apache%202.0-blue.svg" alt="License">
|
|
95
|
+
</a>
|
|
96
|
+
</p>
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Why Headroom?
|
|
102
|
+
|
|
103
|
+
- **Zero code changes** - works as a transparent proxy
|
|
104
|
+
- **50-90% cost savings** - verified on real workloads
|
|
105
|
+
- **Reversible compression** - LLM retrieves original data via CCR
|
|
106
|
+
- **Content-aware** - code, logs, JSON each handled optimally
|
|
107
|
+
- **Provider caching** - automatic prefix optimization for cache hits
|
|
108
|
+
- **Persistent memory** - remember across conversations with zero-latency extraction
|
|
109
|
+
- **Framework native** - LangChain, Agno, MCP, agents supported
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Headroom vs Alternatives
|
|
114
|
+
|
|
115
|
+
| Approach | Token Reduction | Accuracy | Reversible | Latency |
|
|
116
|
+
|----------|-----------------|----------|------------|---------|
|
|
117
|
+
| **Headroom** | 50-90% | No loss | Yes (CCR) | ~1-5ms |
|
|
118
|
+
| Truncation | Variable | Data loss | No | ~0ms |
|
|
119
|
+
| Summarization | 60-80% | Lossy | No | ~500ms+ |
|
|
120
|
+
| No optimization | 0% | Full | N/A | 0ms |
|
|
121
|
+
|
|
122
|
+
**Headroom wins** because it intelligently selects relevant content while keeping a retrieval path to the original data.
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## 30-Second Quickstart
|
|
127
|
+
|
|
128
|
+
### Option 1: Proxy (Zero Code Changes)
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
pip install "headroom-ai[proxy]"
|
|
132
|
+
headroom proxy --port 8787
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Point your tools at the proxy:
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
# Claude Code
|
|
139
|
+
ANTHROPIC_BASE_URL=http://localhost:8787 claude
|
|
140
|
+
|
|
141
|
+
# Any OpenAI-compatible client
|
|
142
|
+
OPENAI_BASE_URL=http://localhost:8787/v1 cursor
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Option 2: LangChain Integration
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
pip install "headroom-ai[langchain]"
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
from langchain_openai import ChatOpenAI
|
|
153
|
+
from headroom.integrations import HeadroomChatModel
|
|
154
|
+
|
|
155
|
+
# Wrap your model - that's it!
|
|
156
|
+
llm = HeadroomChatModel(ChatOpenAI(model="gpt-4o"))
|
|
157
|
+
|
|
158
|
+
# Use exactly like before
|
|
159
|
+
response = llm.invoke("Hello!")
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
See the full [LangChain Integration Guide](docs/langchain.md) for memory, retrievers, agents, and more.
|
|
163
|
+
|
|
164
|
+
### Option 3: Agno Integration
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
pip install "headroom-ai[agno]"
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
```python
|
|
171
|
+
from agno.agent import Agent
|
|
172
|
+
from agno.models.openai import OpenAIChat
|
|
173
|
+
from headroom.integrations.agno import HeadroomAgnoModel
|
|
174
|
+
|
|
175
|
+
# Wrap your model - that's it!
|
|
176
|
+
model = HeadroomAgnoModel(OpenAIChat(id="gpt-4o"))
|
|
177
|
+
agent = Agent(model=model)
|
|
178
|
+
|
|
179
|
+
# Use exactly like before
|
|
180
|
+
response = agent.run("Hello!")
|
|
181
|
+
|
|
182
|
+
# Check savings
|
|
183
|
+
print(f"Tokens saved: {model.total_tokens_saved}")
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
See the full [Agno Integration Guide](docs/agno.md) for hooks, multi-provider support, and more.
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## Framework Integrations
|
|
191
|
+
|
|
192
|
+
| Framework | Integration | Docs |
|
|
193
|
+
|-----------|-------------|------|
|
|
194
|
+
| **LangChain** | `HeadroomChatModel`, memory, retrievers, agents | [Guide](docs/langchain.md) |
|
|
195
|
+
| **Agno** | `HeadroomAgnoModel`, hooks, multi-provider | [Guide](docs/agno.md) |
|
|
196
|
+
| **MCP** | Tool output compression for Claude | [Guide](docs/ccr.md) |
|
|
197
|
+
| **Any OpenAI Client** | Proxy server | [Guide](docs/proxy.md) |
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## Features
|
|
202
|
+
|
|
203
|
+
| Feature | Description | Docs |
|
|
204
|
+
|---------|-------------|------|
|
|
205
|
+
| **Memory** | Persistent memory across conversations (zero-latency inline extraction) | [Memory](docs/memory.md) |
|
|
206
|
+
| **Universal Compression** | ML-based content detection + structure-preserving compression | [Compression](docs/compression.md) |
|
|
207
|
+
| **SmartCrusher** | Compresses JSON tool outputs statistically | [Transforms](docs/transforms.md) |
|
|
208
|
+
| **CacheAligner** | Stabilizes prefixes for provider caching | [Transforms](docs/transforms.md) |
|
|
209
|
+
| **RollingWindow** | Manages context limits without breaking tools | [Transforms](docs/transforms.md) |
|
|
210
|
+
| **CCR** | Reversible compression with automatic retrieval | [CCR Guide](docs/ccr.md) |
|
|
211
|
+
| **LangChain** | Memory, retrievers, agents, streaming | [LangChain](docs/langchain.md) |
|
|
212
|
+
| **Agno** | Agent framework integration with hooks | [Agno](docs/agno.md) |
|
|
213
|
+
| **Text Utilities** | Opt-in compression for search/logs | [Text Compression](docs/text-compression.md) |
|
|
214
|
+
| **LLMLingua-2** | ML-based 20x compression (opt-in) | [LLMLingua](docs/llmlingua.md) |
|
|
215
|
+
| **Code-Aware** | AST-based code compression (tree-sitter) | [Transforms](docs/transforms.md) |
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## Performance
|
|
220
|
+
|
|
221
|
+
| Scenario | Before | After | Savings |
|
|
222
|
+
|----------|--------|-------|---------|
|
|
223
|
+
| Search results (1000 items) | 45,000 tokens | 4,500 tokens | 90% |
|
|
224
|
+
| Log analysis (500 entries) | 22,000 tokens | 3,300 tokens | 85% |
|
|
225
|
+
| Long conversation (50 turns) | 80,000 tokens | 32,000 tokens | 60% |
|
|
226
|
+
| Agent with tools (10 calls) | 100,000 tokens | 15,000 tokens | 85% |
|
|
227
|
+
|
|
228
|
+
**Overhead**: ~1-5ms per request
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## Providers
|
|
233
|
+
|
|
234
|
+
| Provider | Token Counting | Cache Optimization |
|
|
235
|
+
|----------|----------------|-------------------|
|
|
236
|
+
| OpenAI | tiktoken (exact) | Automatic prefix caching |
|
|
237
|
+
| Anthropic | Official API | cache_control blocks |
|
|
238
|
+
| Google | Official API | Context caching |
|
|
239
|
+
| Cohere | Official API | - |
|
|
240
|
+
| Mistral | Official tokenizer | - |
|
|
241
|
+
|
|
242
|
+
New models auto-supported via naming pattern detection.
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## Safety Guarantees
|
|
247
|
+
|
|
248
|
+
- **Never removes human content** - user/assistant messages preserved
|
|
249
|
+
- **Never breaks tool ordering** - tool calls and responses stay paired
|
|
250
|
+
- **Parse failures are no-ops** - malformed content passes through unchanged
|
|
251
|
+
- **Compression is reversible** - LLM retrieves original data via CCR
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## Installation
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
pip install headroom-ai # SDK only
|
|
259
|
+
pip install "headroom-ai[proxy]" # Proxy server
|
|
260
|
+
pip install "headroom-ai[langchain]" # LangChain integration
|
|
261
|
+
pip install "headroom-ai[agno]" # Agno agent framework
|
|
262
|
+
pip install "headroom-ai[code]" # AST-based code compression
|
|
263
|
+
pip install "headroom-ai[llmlingua]" # ML-based compression
|
|
264
|
+
pip install "headroom-ai[all]" # Everything
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
**Requirements**: Python 3.10+
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
## Documentation
|
|
272
|
+
|
|
273
|
+
| Guide | Description |
|
|
274
|
+
|-------|-------------|
|
|
275
|
+
| [Memory Guide](docs/memory.md) | Persistent memory for LLMs |
|
|
276
|
+
| [Compression Guide](docs/compression.md) | Universal compression with ML detection |
|
|
277
|
+
| [LangChain Integration](docs/langchain.md) | Full LangChain support |
|
|
278
|
+
| [Agno Integration](docs/agno.md) | Full Agno agent framework support |
|
|
279
|
+
| [SDK Guide](docs/sdk.md) | Fine-grained control |
|
|
280
|
+
| [Proxy Guide](docs/proxy.md) | Production deployment |
|
|
281
|
+
| [Configuration](docs/configuration.md) | All options |
|
|
282
|
+
| [CCR Guide](docs/ccr.md) | Reversible compression |
|
|
283
|
+
| [Metrics](docs/metrics.md) | Monitoring |
|
|
284
|
+
| [Troubleshooting](docs/troubleshooting.md) | Common issues |
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## Who's Using Headroom?
|
|
289
|
+
|
|
290
|
+
> Add your project here! [Open a PR](https://github.com/chopratejas/headroom/pulls) or [start a discussion](https://github.com/chopratejas/headroom/discussions).
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
## Contributing
|
|
295
|
+
|
|
296
|
+
```bash
|
|
297
|
+
git clone https://github.com/chopratejas/headroom.git
|
|
298
|
+
cd headroom
|
|
299
|
+
pip install -e ".[dev]"
|
|
300
|
+
pytest
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for details.
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
## License
|
|
308
|
+
|
|
309
|
+
Apache License 2.0 - see [LICENSE](LICENSE).
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
313
|
+
<p align="center">
|
|
314
|
+
<sub>Built for the AI developer community</sub>
|
|
315
|
+
</p>
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
headroom/__init__.py,sha256=xpDRSbZmqivOrMN_dU7YAD4d5-E9_0ybAbwn3HR8Ieo,5091
|
|
2
|
+
headroom/cli.py,sha256=vqy5qd2J4A0DKRsFs4ceWQgfY6ttTR--H9f179XtiVg,6571
|
|
3
|
+
headroom/client.py,sha256=ow8Jg4pZQz25D2YnsMgk79BzvnsyUjFwGhPp_dcgEBk,36058
|
|
4
|
+
headroom/config.py,sha256=OU4DmOaLZnsio9CC8wfJuwwpQpOJjQJ_SSyAhOk3WYM,18099
|
|
5
|
+
headroom/exceptions.py,sha256=5vKZLgra36R4zOPrCl272iAaoNh4hAYr7q85kAhHs0c,4431
|
|
6
|
+
headroom/parser.py,sha256=wMY4_tZYgTrZCuI-XwNiORRlT-LJyie5s7QOa1q17b4,9097
|
|
7
|
+
headroom/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
+
headroom/tokenizer.py,sha256=CKwqJWt7o7AO8DsCrGvR7zzK3_yb-2YvgA2FUhMPSBE,2149
|
|
9
|
+
headroom/utils.py,sha256=DZLbBaI7E5nE_7nr0SYEwVX0ANo45D-MD9YkAPHT0r4,6087
|
|
10
|
+
headroom/cache/__init__.py,sha256=858lq533p9NrRdnq7ZXNloumXqCpumGOod-YT5tcPAY,2111
|
|
11
|
+
headroom/cache/anthropic.py,sha256=hbn1ijxx8JaSP3k0tQitZ0_gfC7R14hIqMQj4vuHP68,19039
|
|
12
|
+
headroom/cache/base.py,sha256=_pZ5p7FVK_DFa24CtoJ6KnUwQqICNBiCmWGonecq7vA,9581
|
|
13
|
+
headroom/cache/compression_feedback.py,sha256=4NpnGCrfkJoIDwdBNZVFXuZJTo7PLWyBBd-C4Q_I1sY,22519
|
|
14
|
+
headroom/cache/compression_store.py,sha256=-C0x40x2UEJHXVJcW_sfWzF5ekFyJ0LdcjDMmHxwW8M,31372
|
|
15
|
+
headroom/cache/dynamic_detector.py,sha256=7YZc8BFT1q9J-wX6D2ITkFV6pZnICfEe8yxYrDB7lE0,33517
|
|
16
|
+
headroom/cache/google.py,sha256=PyIG6StV_VRQvKdyfwX-CTkTrSCabx6VtEOJ03Bc1Wo,28910
|
|
17
|
+
headroom/cache/openai.py,sha256=bSZ2qZLr5wXVgcCdCX107ao5cOmYRI6hi0kwYVw3cao,21108
|
|
18
|
+
headroom/cache/registry.py,sha256=NrSGyv-WdzUcR24WzPw28nVdF-FFe65fGXXI4JnFW3E,5238
|
|
19
|
+
headroom/cache/semantic.py,sha256=iaSd44SQ-n7ajDgDqNuq_ZuYwgTD11meB6JHTuwlICA,13320
|
|
20
|
+
headroom/ccr/__init__.py,sha256=8Ii9-t0R9KcVKOucYDpWMO0LAe55oPKIVaLdG-mQgik,2182
|
|
21
|
+
headroom/ccr/context_tracker.py,sha256=Obq9gmbRaUYlk5a-I0oaGDUWn9PVySciUGRyrfXiz2A,18318
|
|
22
|
+
headroom/ccr/mcp_server.py,sha256=-ID1nRvEX7jyCdn1-iE2r6vwaNZGvPqJHjjWU0_6tDo,9893
|
|
23
|
+
headroom/ccr/response_handler.py,sha256=KpXC2wAEL8KkuThosjefg1bzuxbIDM1z-3QTU4_5mpc,26917
|
|
24
|
+
headroom/ccr/tool_injection.py,sha256=wSro_HSEwxbQ-Q7gS1pUdiS5LK3jU81HRot_kCFU57I,14527
|
|
25
|
+
headroom/compression/__init__.py,sha256=1_E_SyKnrcsuVqYQjVt10oZRWicv40zH6wSAnpSWCtI,1174
|
|
26
|
+
headroom/compression/detector.py,sha256=33GRUi8PZQrGyCIC-eDXB4YeA1I4sPE1OhylqXycjWA,11426
|
|
27
|
+
headroom/compression/masks.py,sha256=nkWAFhlYnIKw5P1DF76v-CO3MyMfxWmja2X73PVwtnM,10746
|
|
28
|
+
headroom/compression/universal.py,sha256=akYpmNoirw99RDf_RCiJfiZ5hLE8nTmhxmClbWcweKw,15052
|
|
29
|
+
headroom/compression/handlers/__init__.py,sha256=j7JdxabNfC1Ew9exuQaDwp25j95t6cVtu-qbIjnUdww,694
|
|
30
|
+
headroom/compression/handlers/base.py,sha256=pZ8rl4G1P02bm82CWJ0cPKqebIIgp6BnP4N1u1OlkKc,6173
|
|
31
|
+
headroom/compression/handlers/code_handler.py,sha256=CFf9JVzL6fyDZFuSZqdtvfyS-3QYe9nwxjtXyyHdH1k,16401
|
|
32
|
+
headroom/compression/handlers/json_handler.py,sha256=emevNLyBY3PDscsq_Rf5OtRiLr-dpU5-Z6jRwaM5r9Y,14057
|
|
33
|
+
headroom/integrations/__init__.py,sha256=Djgvi9XKkzKNhlVZw9LBH_Mc4fMLozQgFEmY2A3pXH4,4599
|
|
34
|
+
headroom/integrations/agno/__init__.py,sha256=mbVIm6DE28bjr3XeXg2clMIXOu5Tr1Qf52D1XbH_S2w,1372
|
|
35
|
+
headroom/integrations/agno/hooks.py,sha256=LG8TS6PFofI5OCzhqf4bYmEelV1lmexYdFWIwteKhsg,11451
|
|
36
|
+
headroom/integrations/agno/model.py,sha256=4IsXB_Hkm1gscMfr3lJOZLUJafqkO31vzQpj5togNRk,24076
|
|
37
|
+
headroom/integrations/agno/providers.py,sha256=1L9ub4PuHJJlaZObGjPV8AaZtq-Ht_EyKqjhqW2Mp10,5603
|
|
38
|
+
headroom/integrations/langchain/__init__.py,sha256=8jJBq0vx7TFvRppph-sbsupZR4WYyFXM5fsaC6GXpYI,2785
|
|
39
|
+
headroom/integrations/langchain/agents.py,sha256=e09sQKJoa2BRuNukoUeiv6ONT2nlbZ6C3o6GQQwosPI,10353
|
|
40
|
+
headroom/integrations/langchain/chat_model.py,sha256=enFdd-ZxMCOWbwgS2-3Hxk5EMH5S0ekfGLbjPk0MRwM,35822
|
|
41
|
+
headroom/integrations/langchain/langsmith.py,sha256=fbfDQ6bG2psB7D56PXr3kp6sAoNmV5B6jWUq5dsUg8Y,10183
|
|
42
|
+
headroom/integrations/langchain/memory.py,sha256=PwjuFoP6PVJ8w6V1Ige8GmPCzmlD3QDLCYyhC13qZUI,10972
|
|
43
|
+
headroom/integrations/langchain/providers.py,sha256=1XEShnlqnhawJ2_S8kXsEW7bdRnI9uYveVxcTP3Xt-E,6655
|
|
44
|
+
headroom/integrations/langchain/retriever.py,sha256=8nqSVJzoE8qg5fTmEr3rIhfgpgz6QKUF70xru9HWUTw,12545
|
|
45
|
+
headroom/integrations/langchain/streaming.py,sha256=G24xbopZIQo7d_mLJ9U40Q4DIzYCuamYERC1VpGzSsI,10092
|
|
46
|
+
headroom/integrations/mcp/__init__.py,sha256=aVVYXRR5PGo-2xI2sRAVnEuvqX1EchiPavVUTnzaIbE,931
|
|
47
|
+
headroom/integrations/mcp/server.py,sha256=sFiSzy1GhhyRlpzsodLqwogZfIWP-Osrn-jGHF1rO_g,17525
|
|
48
|
+
headroom/memory/__init__.py,sha256=puPyG1afrnUQP2wA9cGx5mCLqcutRrbrDc5RgYbGDXI,1123
|
|
49
|
+
headroom/memory/extractor.py,sha256=T2juKQiUTuYQo14Ag6dlZwmm0k8NCaTmB6UcFY579yU,12281
|
|
50
|
+
headroom/memory/fast_store.py,sha256=WnQvYLTizqYRvuTGPBjVTa75XJxsrmf_0TmwxxPyWrk,20153
|
|
51
|
+
headroom/memory/fast_wrapper.py,sha256=JYp7TPVoWGyJqXuRGoFn_L2Sp4Fu0JEs34PR2KdOofE,10119
|
|
52
|
+
headroom/memory/inline_extractor.py,sha256=GAyrBTKkiqtyEaZlcK0foenMBOsMlC7FYqGOSG226VY,6833
|
|
53
|
+
headroom/memory/store.py,sha256=rAAUBOsJIGvIRwu-hRag01Np5plPlQRtiPa-frc2r2k,13883
|
|
54
|
+
headroom/memory/worker.py,sha256=keHNw0tx3feU29HH0ckBnNeSd8oL2fIfAkRUgAyQD70,8480
|
|
55
|
+
headroom/memory/wrapper.py,sha256=lJFZxytrKR1GX5qmYUET9AmHosR_odHOgJ7041IJ9x0,9817
|
|
56
|
+
headroom/models/__init__.py,sha256=3rVSXirBE6PMW0Al3JkCNF2Wj8pPvIhyWlYd_kySdKs,873
|
|
57
|
+
headroom/models/registry.py,sha256=59f40DlSohYzYfciEgAfMuft2GnMvXurtrbamxB8aD4,20350
|
|
58
|
+
headroom/pricing/__init__.py,sha256=CZO-2VFXArMlQBance_rS6MOWV2zu0PjWmxoxkfIqF8,1359
|
|
59
|
+
headroom/pricing/anthropic_prices.py,sha256=Xu39m-ui4AVNt4IT9tJkEvbbe5ED9xi7NSe5AHGDr7I,2526
|
|
60
|
+
headroom/pricing/litellm_pricing.py,sha256=ldVEYG8FecRir9TFjfnGsgcdAf1YsMrjfmtWhjpTI_Y,3232
|
|
61
|
+
headroom/pricing/openai_prices.py,sha256=bseLDWG-fnad_Kp2LVtizKsThWQ475M6y7ilM6cFtV0,2573
|
|
62
|
+
headroom/pricing/registry.py,sha256=wCLKpzapRNrYKhnzgdm5vH6n7gQb1A16YvqXN4qz6rA,6344
|
|
63
|
+
headroom/providers/__init__.py,sha256=L66dA13RcxjpEoj9-2iautoJHBK6AYpqcES1gw3qK6w,1707
|
|
64
|
+
headroom/providers/anthropic.py,sha256=c4yT86mzZ9_eJq6RzNz2_obIdconV11cW1fRr33L8bE,23820
|
|
65
|
+
headroom/providers/base.py,sha256=R_BmRjeNZcPaY2in7f5fqKXqQz059eLfU5yjHzFrzm8,3195
|
|
66
|
+
headroom/providers/cohere.py,sha256=TIxn7Dnjr8Wmref6V9pjl1D7GqEh8-lrgcxPd37eTu4,11368
|
|
67
|
+
headroom/providers/google.py,sha256=2M8YXswMaUp5E6e07svnwQpbuY83Pkk2eT3XGXzj83E,14643
|
|
68
|
+
headroom/providers/litellm.py,sha256=JIsAcYUpg12QfJhQKkRKmNcjcwOgtU_AjIjwQaB0NFc,9398
|
|
69
|
+
headroom/providers/openai.py,sha256=-scxYB1nNFzhkqnEG2jRAt6zfo1p9zMRknuyYh4GyBg,19807
|
|
70
|
+
headroom/providers/openai_compatible.py,sha256=xki1h6lJU7EvkcJ0tDUoUGwH3JXN_eoFJtzB5UlINQ0,14154
|
|
71
|
+
headroom/proxy/__init__.py,sha256=4YsySyHYWD5UgpJtTnFOHBiNrE-VaKrz32nBlk84FWk,511
|
|
72
|
+
headroom/proxy/server.py,sha256=WIQELkFA8oMV5jGixYiscdjuTWMdIilYMLE5P_wKDOg,105249
|
|
73
|
+
headroom/relevance/__init__.py,sha256=yCTJAgzWHjDCHfj5-lmRMPaskJ5_lPsLZ4JxwH3P6e8,3784
|
|
74
|
+
headroom/relevance/base.py,sha256=ZQNM_Qrjf4H9rt3xiyB4LEyies6FGmUNd6VxJrgflAA,3198
|
|
75
|
+
headroom/relevance/bm25.py,sha256=-C0svaUTPvNZWMicZWh3BWnxyboUS2ueS9IsPHnRhLU,7976
|
|
76
|
+
headroom/relevance/embedding.py,sha256=PNg2CMrzq_A9zuAV-1lHmSatEJ2xGIg0GA5KM_-dDFk,7603
|
|
77
|
+
headroom/relevance/hybrid.py,sha256=PMmWGzqhpqM7cftiwJ1EcV23tT52UJ-u5bmknvbj_kA,9306
|
|
78
|
+
headroom/reporting/__init__.py,sha256=xsv9DswXQeYw7UuX8V8joIHI5dbhHNVTMDYKYtJ_naw,112
|
|
79
|
+
headroom/reporting/generator.py,sha256=d9S1Kcz1zUamdKonLBvzslK7PvNxarWIg72gE-nvs0M,17469
|
|
80
|
+
headroom/storage/__init__.py,sha256=Cp3wbeesr_BTn0d27urJlotySYvv5KsqM70buJZJCpE,1002
|
|
81
|
+
headroom/storage/base.py,sha256=wJZ5Q71XNbYEc9nknkOEdTJZ8riesA0rIuvNONj74pA,3090
|
|
82
|
+
headroom/storage/jsonl.py,sha256=bzrvZ4_ACIn9aagG6whByU9aCEy3HBmpvL5ejE-_mcg,7787
|
|
83
|
+
headroom/storage/sqlite.py,sha256=ilb3x_1zrenPNYRuKzRGdVM_APTDLnlQqsi4DK5Bv5E,10015
|
|
84
|
+
headroom/telemetry/__init__.py,sha256=Bn_BS-q13Tp3S-XXhqXGcE-W11HCOxY9jKZcgWQT_dc,2184
|
|
85
|
+
headroom/telemetry/collector.py,sha256=DEZqRmtQloTmPVSC43LXScS4xiXgTJMT3GD0NPCKFl8,28606
|
|
86
|
+
headroom/telemetry/models.py,sha256=eMyE1QXEXJ9M58EFcWrBMkKERBYDrmDc2LUjd_0-z1A,34651
|
|
87
|
+
headroom/telemetry/toin.py,sha256=xTcJ-k9x7WJ4MnwntfPyFSb78SObkDv0OsHHLj3IkfE,67905
|
|
88
|
+
headroom/tokenizers/__init__.py,sha256=20Enzr5VjhyHho7k4jigCadKxeeRQcqLBRJ282mfvh8,2030
|
|
89
|
+
headroom/tokenizers/base.py,sha256=yKEX5wLGYmY_p8lU80bgfXSOjcQBD1CA97zSHzlcw9Y,6752
|
|
90
|
+
headroom/tokenizers/estimator.py,sha256=7My8MiULg2xNAHiKdg3ZiFUagNIH7tIBIoe4MyaO8K0,6010
|
|
91
|
+
headroom/tokenizers/huggingface.py,sha256=qhJ0sHEfo-tdmFD2Yi9cN4d2RCaCngW4vYxWOxqMIe4,9838
|
|
92
|
+
headroom/tokenizers/mistral.py,sha256=alLAIAhGYm4uT43UaVE3Y1j5Tp2pCn5XtRKRI9L7BEE,7155
|
|
93
|
+
headroom/tokenizers/registry.py,sha256=G5TiaFhkqFehf9G3WLLzu8Z9RKFvwW06j-yGlagY6og,12314
|
|
94
|
+
headroom/tokenizers/tiktoken_counter.py,sha256=GSdRV-KB1ThFz49xOATfNIm7BwrE8sURaj9I_VCnKII,8283
|
|
95
|
+
headroom/transforms/__init__.py,sha256=v6PANKEreOPSUvIJfe1ZRI2tjmwneNfusL2pojDeJxg,2839
|
|
96
|
+
headroom/transforms/base.py,sha256=5QTe-O3Db8NgVWMU9B8L152QE3ImOg1-mZRkeDglmSM,1418
|
|
97
|
+
headroom/transforms/cache_aligner.py,sha256=138I-ikdvOJ4fDGf7nqpy7ZfcBJsgpD0DvvrGqSWaWM,12369
|
|
98
|
+
headroom/transforms/code_compressor.py,sha256=z9RHj6L0nocAiINf2Swu7_gke26bmy0KuclOxCrcbpI,47525
|
|
99
|
+
headroom/transforms/content_detector.py,sha256=H9jtV3nOqcePR_FZt2Bcf-fMWMrADgImQlIRiCNU8lM,10421
|
|
100
|
+
headroom/transforms/content_router.py,sha256=O4HxpnBRg1VRwnV5oswH8dv_OFt0ZtjFdCBnhslQqMc,40733
|
|
101
|
+
headroom/transforms/llmlingua_compressor.py,sha256=kwYpbKjpm3SAQy4fY5y4Nb3r0nyfQpbFor3Y_PKkxHI,22530
|
|
102
|
+
headroom/transforms/log_compressor.py,sha256=I1741IoafdEQ9DPPS5hBpSnQa7n3aQlzi1th2WQgXqU,17152
|
|
103
|
+
headroom/transforms/pipeline.py,sha256=U877fTvcMA8lAKHgJvDn6krd474QU2Qit2vDnBa4l7g,10391
|
|
104
|
+
headroom/transforms/rolling_window.py,sha256=alunXwaUgqT7np-QNvE531qglrvLn9I94zC8naJUZJw,11345
|
|
105
|
+
headroom/transforms/search_compressor.py,sha256=3ZeBZMlpuvCpeZtQpBqSRlQcIiPrG6vwuIJobgENtHY,11679
|
|
106
|
+
headroom/transforms/smart_crusher.py,sha256=BnLXyqO-_gPOw5s8N7S3QqxHltVqLrpnax6ZSHvQX8Q,107390
|
|
107
|
+
headroom/transforms/text_compressor.py,sha256=vJcjv-7hQlR_KPSyU_m0xgpTnyYRfTglCwmhdG50V9c,8438
|
|
108
|
+
headroom/transforms/tool_crusher.py,sha256=yA9wUHy9Zs1RxVJq4ldeIBGW_nG_0tNwR-IKaN-qxcM,11210
|
|
109
|
+
headroom_ai-0.2.13.dist-info/METADATA,sha256=ik1K3AfrCZcW_HWphLs3Noly7Kw75ESTxgdOoMVSC0U,10853
|
|
110
|
+
headroom_ai-0.2.13.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
111
|
+
headroom_ai-0.2.13.dist-info/entry_points.txt,sha256=aJkYI5-izD3UFi07BK4FgQXmPaMftTTDSsta8LxeA9o,47
|
|
112
|
+
headroom_ai-0.2.13.dist-info/licenses/LICENSE,sha256=8U3UQMjjFStNTTJGFd6CUd2wEdyB9ITarQtpAgk1Ocw,10770
|
|
113
|
+
headroom_ai-0.2.13.dist-info/licenses/NOTICE,sha256=i_mkOhEsx5Z3tI4kbQ6KYOBbYC30-FHxxMeS5b5RhBs,1237
|
|
114
|
+
headroom_ai-0.2.13.dist-info/RECORD,,
|