Skip to main content

Text compression that uses a local GPT-2 model as a probability source.

Project description

compression-experiments

Stage Idea Best result
1 Brute-force hash inversion (Python) works for ≤3-byte files; ~0.6 M hashes/s
2 Same, in C with CommonCrypto + threads ~45 M H/s
3 NEON SHA-256 hardware intrinsics + threads ~380 M H/s
4 Apple Metal GPU compute shader ~1.0 GH/s
5 CPU + GPU concurrent ~1.4 GH/s (~2300× the Python version)
6 "Deterministic index" version of the hash idea proved the pigeonhole wall
7 Local GPT-2 + arithmetic coding English text → 13% of original (vs gzip's ~57%)
8 OpenAI API + self-extracting HTML page same idea, no local model needed

Stages 1-6 is one idea, proving why arbitrary lossless compression below input size is impossible. Stages 7-8 is another idea, that proved to be much better than well known compression algorithms for english text.

What's in here

The brute-force hash side (stages 1-5)

File What it does
compress.py / decompress.py The original idea: store a file as just SHA-256 + length; "decompress" by trying every possible file until the hash matches.
compress_index.py / decompress_index.py The "deterministic generator" refinement — turns out it's just storing the file as a big integer. Shows the size wall.
brute.c C version of decompression, CommonCrypto, pthreads. ~75× Python.
brute_neon.c C with ARMv8 SHA-2 hardware instructions. ~635× Python.
brute_mb.c 4-way multi-buffer SIMD SHA-256 — interesting failure: slower than hardware SHA on M1.
brute_metal.m Metal compute shader, all 4096 ALU lanes of the M1 Max GPU. ~1.7×10³ × Python.
brute_combined.m CPU NEON-HW + GPU in parallel. ~2.3×10³ × Python.

The actual-compression side (stages 6-8)

File What it does
nnzip/ Python package: local GPT-2 + arithmetic coding. Installs as compress, decompress, and nnzip CLI commands.
pyproject.toml Packaging config: declares the CLI entry points and dependencies.
arithmetic_coder.py Portable bit-level arithmetic coder. Identical output in Python and the JS port (see template.html).
api_compress.py OpenAI API compression (no local model, but slow and pay-per-use). Three modes: compress produces a binary .api file, decompress reverses it, compress-html bakes the payload into a portable HTML self-extractor.
template.html The HTML self-extractor template with the JS arithmetic decoder inline. The Python compressor fills in the __PAYLOAD_B64__ etc. placeholders.

Test data

File Use
sample.txt ~860-byte English paragraph for compression demos.

How to use

Build the C/Metal brute forcers (the hardware showcase)

clang -O3 -Wall -Wno-deprecated-declarations -o brute brute.c
clang -O3 -Wall -Wno-deprecated-declarations -o brute_neon brute_neon.c
clang -O3 -march=native -Wno-deprecated-declarations -o brute_mb brute_mb.c
clang -O3 -fobjc-arc -framework Foundation -framework Metal -o brute_metal brute_metal.m
clang -O3 -fobjc-arc -framework Foundation -framework Metal -o brute_combined brute_combined.m

Then:

printf 'word' > test4.txt
python3 compress.py test4.txt test4.compressed
./brute_combined test4.compressed test4.recovered 8   # ~2 seconds on M1 Max

The full 4-byte search space is 4.3 billion candidates. The Python decompressor would take ~38 minutes. The combined CPU+GPU version finds the right one in ~2 seconds.

Local LLM compression — the nnzip CLI (works on Mac and Windows)

Install the package (one-time, downloads PyTorch + transformers ~600 MB):

python3.12 -m venv venv
./venv/bin/pip install -e .

On Windows, use python -m venv venv and venv\Scripts\pip install -e . — same package, same commands afterward.

Then compress and decompress are available as commands:

./venv/bin/compress sample.txt           # produces sample.txt.nnz
./venv/bin/decompress sample.txt.nnz     # restores sample.txt

Or use the namespaced command:

./venv/bin/nnzip compress sample.txt
./venv/bin/nnzip decompress sample.txt.nnz

First run downloads GPT-2 (~500 MB) and caches it in ~/.cache/huggingface. Expect ~13-20% of original size on English text. Non-English / source code / random binary may not compress (or may grow).

To use a larger model with better compression, set the environment variable:

NNZIP_MODEL=gpt2-medium ./venv/bin/compress sample.txt   # ~1.5 GB download, better ratio

The model name is stored in the .nnz file so the decompressor automatically loads the matching one.

OpenAI API compression (small payloads, portable HTML)

Requires an OpenAI API key. Put it in .env:

OPENAI_API_KEY=sk-...

(.env is in .gitignore — never gets committed.)

./venv/bin/pip install openai tiktoken
./venv/bin/python api_compress.py compress sample.txt sample.api
./venv/bin/python api_compress.py decompress sample.api sample.out

# or, produce a self-extracting HTML page:
./venv/bin/python api_compress.py compress-html sample.txt sample.html
# then open sample.html in any browser, paste your own API key, click Decompress

The HTML file is ~10 KB of template + the compressed payload (tens of bytes for small texts, scaling with input). Best on files at least a few KB; the template overhead is paid once.

Known limitations

  • API determinism risk. OpenAI's logprobs jitter at ~4th decimal across identical calls. mitigate by (a) quantizing logprobs to 2 decimals before sorting and (b) using a fixed rank distribution rather than one derived from per-call probabilities. Natural English text works in testing; pathological inputs could still desync.
  • Speed. API-based decompression is ~1 token/sec (one network round-trip per token). A 1 KB file takes ~6 minutes to extract. This is a demo, not a tool.
  • Cost. Each decompression costs the recipient ~$0.002 per token via the OpenAI API. A 1 KB file costs about 50¢ per extraction.
  • Only English text compresses well. Random binary, source code, non-English get poor ratios (sometimes worse than the original) because GPT-3.5's predictions are weak there.
  • The compressed payload is not encrypted. Anyone with the same OpenAI API access can decompress. If you want privacy too, encrypt before compressing.

Influences and prior art

License

MIT.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nnzip-0.1.0.tar.gz (7.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nnzip-0.1.0-py3-none-any.whl (8.7 kB view details)

Uploaded Python 3

File details

Details for the file nnzip-0.1.0.tar.gz.

File metadata

  • Download URL: nnzip-0.1.0.tar.gz
  • Upload date:
  • Size: 7.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for nnzip-0.1.0.tar.gz
Algorithm Hash digest
SHA256 fd076dd054b61b678ce67858d5e0560481ad1538766db8de397433318f59e5de
MD5 56f9cf1aea2c252c55ce945de054e7e6
BLAKE2b-256 15a0cad633da6e9261744269eb87d3f5734d110a72d6346e782fc629c70db6c6

See more details on using hashes here.

File details

Details for the file nnzip-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: nnzip-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 8.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for nnzip-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 94fa8099e761d468b6c788bc13f716c190a44ad140fedc82d8bd5c10861aee3a
MD5 d5fe7af1cc0f5a1fdc4fdb8f9995580d
BLAKE2b-256 7b2313146042f976b0e7a603bb14fd068831ac71eaa937e37380ecc6a0d0b2b4

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page