LLM Text Compressor
Remove characters from text while keeping it understandable by LLMs — save on inference costs at scale.
Zero dependencies. Deterministic. Preservation-first.
Why?
LLMs don't need every character to understand language. This text:
Ths fnctn tks a lst of intgrs as inpt and rtrns the mxmm vle fnd in the clctn. If the lst is mpty, it rss a VlError excptn.
Is perfectly understood as:
This function takes a list of integers as input and returns the maximum value found in the collection. If the list is empty, it raises a ValueError exception.
The compressed version is ~20% smaller, which adds up fast when you're feeding large contexts to LLMs.
Use Cases
Agent-to-Agent Communication
In multi-agent architectures, agents constantly pass text to each other — task descriptions, observations, tool outputs, reasoning traces. Compressing these messages reduces token consumption across every hop:
# Orchestrator compresses context before handing off to sub-agents
task_context = gather_observations() # Could be thousands of tokens
compressed_context = compress(task_context, level=3)
sub_agent.run(compressed_context) # Same meaning, fewer tokens
RAG Context Stuffing
When injecting retrieved documents into an LLM prompt, you're often limited by the context window. Compress retrieved chunks to fit more documents into the same budget:
retrieved_docs = vector_search(query, top_k=20)
compressed_docs = [compress(doc, level=2) for doc in retrieved_docs]
# Fit ~20% more context into the same token window
prompt = build_prompt(query, compressed_docs)
Tool Output Compression
Agents calling tools (web search, code execution, API responses) often receive verbose output. Compress before feeding back into the agent loop:
tool_output = web_search("latest Python release notes") # Large HTML/text result
compressed = compress(tool_output, level=4) # Remove filler, trim aggressively
agent.process(compressed) # Agent still understands the content
Chat History / Memory
Long-running conversations accumulate large histories. Compress older messages to keep more context within the window:
for msg in conversation_history[:-5]: # Keep last 5 messages intact
msg["content"] = compress(msg["content"], level=2)
Batch Processing & Cost Reduction
When processing thousands of documents through LLM APIs, even 10% savings per request compounds:
10,000 requests × 2,000 tokens × $0.01/1K tokens = $200
10,000 requests × 1,800 tokens × $0.01/1K tokens = $180 → $20 saved per batch
Multi-Agent Reasoning Chains
In chain-of-thought or tree-of-thought architectures, intermediate reasoning is passed between steps. Compress intermediate outputs without losing semantic content:
# Each reasoning step compresses its output before passing forward
step1_result = compress(agent_step_1(problem), level=2)
step2_result = compress(agent_step_2(step1_result), level=2)
final_answer = agent_step_3(step2_result)
Features
- 4 compression levels — from light (doubled letters) to maximum (sentence pruning)
- Smart preservation — URLs, emails, phone numbers, UUIDs, IDs, proper nouns, and acronyms are never touched
- Structured data detection — code blocks, JSON, XML pass through verbatim
- Opt-out regions — wrap text in
[COMPRESSOR_OFF]...[/COMPRESSOR_OFF]to skip compression - Markdown-aware mode — preserves headings, lists, links, blockquotes
- Locale support — French, Spanish, German, Portuguese, Italian stop words
- Streaming API — compress files of arbitrary size without loading into memory
- Compression stats — get detailed metrics and preserved span positions
- Custom patterns & words — extend preservation with your own regex or word sets
Installation
pip install llm-text-compressor
Requires Python 3.10+. No dependencies.
Quick Start
from llm_text_compressor import compress
text = "This function takes a list of integers as input and returns the maximum value."
print(compress(text))
# "Ths fnctn tks a lst of intgrs as inpt and rtrns the mxmm vle."
Compression Levels
| Level | Strategy | Description |
|---|---|---|
| 1 | Light | Remove doubled letters (letter → leter) |
| 2 | Medium | + Remove interior vowels (letter → ltr) |
| 3 | Heavy | + Truncate long words (understanding → undrsg) |
| 4 | Maximum | + Remove filler phrases & deduplicate lines, then apply level 3 |
compress("understanding artificial intelligence", level=1)
# "understaning artificial inteligence"
compress("understanding artificial intelligence", level=2)
# "undrstndng artfcl intlgnce"
compress("understanding artificial intelligence", level=3)
# "undrsg artfl intle"
Preservation
Structured data is automatically detected and preserved:
text = "Contact user@example.com or visit https://docs.example.com for ID abc-123-def"
print(compress(text, level=3))
# "Cntct user@example.com or vist https://docs.example.com for ID abc-123-def"
Auto-preserved types: URLs, emails, phone numbers, UUIDs, hex IDs, alphanumeric IDs, proper nouns, acronyms, code blocks, JSON objects, XML blocks.
Custom Preservation
# Preserve specific words
compress(text, preserve_words={"kubernetes", "nginx"})
# Preserve regex patterns (e.g. Jira tickets)
compress(text, preserve_patterns=[r"[A-Z]+-\d+"])
Opt-Out Regions
text = """
This will be compressed.
[COMPRESSOR_OFF]
This exact text will NOT be compressed.
[/COMPRESSOR_OFF]
This will be compressed too.
"""
compress(text)
Markdown Mode
Preserves markdown syntax while compressing content:
text = "## Introduction\n\nThis is an important paragraph about machine learning."
compress(text, markdown=True)
# "## Introduction\n\nThs is an imprtnt pargrph abt mchn lrnng."
Headings markers, list markers, link URLs, blockquote markers, and horizontal rules are kept intact.
Locale Support
Preserve language-specific stop words for better readability:
compress("Le développement de l'intelligence artificielle", locale="fr")
# Preserves "le", "de" and other French stop words
Supported locales: fr (French), es (Spanish), de (German), pt (Portuguese), it (Italian).
Compression Stats
Get detailed metrics about the compression:
from llm_text_compressor import compress_with_stats
result = compress_with_stats("Hello world, this is a test.", level=2)
print(f"Ratio: {result.ratio:.2f}") # 0.85
print(f"Saved: {result.savings_pct:.1f}%") # 15.0%
print(f"Preserved spans: {len(result.preserved_spans)}")
Returns a CompressionResult with: text, original_length, compressed_length, ratio, savings_pct, level, and preserved_spans.
Streaming
Compress large files without loading them into memory:
from llm_text_compressor import compress_stream, compress_file
# From chunks
chunks = ["This is a ", "test of streaming ", "compression."]
for compressed_chunk in compress_stream(chunks, level=2):
print(compressed_chunk, end="")
# From a file
for chunk in compress_file("large_document.txt", level=2):
output.write(chunk)
Benchmarks
Run the included benchmark suite:
python benchmarks/run_benchmark.py
python benchmarks/run_benchmark.py --markdown # test markdown mode
python benchmarks/run_benchmark.py --tokens # token counts (requires tiktoken)
python benchmarks/run_benchmark.py -o results.json # save JSON report
Typical results across the included corpus (~14 KB of mixed content):
| Level | Character Savings |
|---|---|
| L1 | ~1% |
| L2 | ~10% |
| L3 | ~13% |
| L4 | ~14% |
API Reference
# Core compression
compress(text, level=3, normalize=True, preserve_patterns=None,
preserve_words=None, markdown=False, locale=None) -> str
# With statistics
compress_with_stats(...) -> CompressionResult
# Streaming
compress_stream(chunks, level=3, buffer_size=4096, ...) -> Generator[str]
compress_file(file_path, level=3, chunk_size=8192, encoding="utf-8", ...) -> Generator[str]
See SPECS.md for full technical specifications.
REST API
A production-ready FastAPI REST API is included with Redis caching support:
# Using Docker Compose (includes Redis)
docker compose up --build
# API available at http://localhost:8000
# Interactive docs at http://localhost:8000/docs
API Features
- Redis caching with configurable TTL for improved performance
- Batch compression endpoint for processing multiple texts
- Streaming compression for large documents
- Cache statistics and monitoring endpoints
- Health checks with Redis status
- OpenAPI/Swagger documentation
Endpoints:
POST /compress— Compress text with cachingPOST /compress/stats— Compress with detailed statisticsPOST /compress/batch— Compress multiple texts in one requestPOST /compress/stream— Stream-compress large chunksGET /cache/stats— View Redis cache statisticsGET /health— Health check with cache status
See api/README.md for full API documentation.
Development
# Clone and install
git clone https://github.com/avatsaev/llm-text-compressor.git
cd llm-text-compressor
pip install -e ".[dev]"
# Run tests (124 tests)
pytest
# Lint & type check
ruff check src/ tests/
mypy src/
License
MIT
Metadata
Release files for llm-text-compressor 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| llm_text_compressor-0.1.2.tar.gz | 57.1 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| llm_text_compressor-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 73.9 kB
Release files / llm_text_compressor-0.1.2.tar.gz
| Download URL | llm_text_compressor-0.1.2.tar.gz |
|---|---|
| Size | 57.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f4784ca7cc3d3142e1bcea0a4db63c41f2dc120713e26673070f2c28c6cf0136
|
|
BLAKE2b-256 checksum How to use checksums |
649574b2c7f5b49cf56fc09e5315f9e15460985c0fa7477d0653eba845ae5fc1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.14
|
Release files / llm_text_compressor-0.1.2-py3-none-any.whl
| Download URL | llm_text_compressor-0.1.2-py3-none-any.whl |
|---|---|
| Size | 16.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5234dee5de244c7293686eec61d91d4c8631c91bf5d5505103178bf7b3926332
|
|
BLAKE2b-256 checksum How to use checksums |
6e7c01323ae3684f88c593f7678a177ed06d5f935ff496515f2181258c5fe9aa
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.14
|
Security for llm-text-compressor 0.1.2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.