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.1.tar.gz (9.3 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.1-py3-none-any.whl (9.2 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: nnzip-0.1.1.tar.gz
  • Upload date:
  • Size: 9.3 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.1.tar.gz
Algorithm Hash digest
SHA256 07a545545c89becbe0c199f110fba703d247a481055dbe6f49373cdb656e012e
MD5 b85aec8207b4b2ed1daa4dcebeec7c9d
BLAKE2b-256 4ac7118830a1823099d347d136bcafa2c200a610356c29cd4f3795af33fd25c4

See more details on using hashes here.

File details

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

File metadata

  • Download URL: nnzip-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 9.2 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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 7b22b1211584a212b43e0f3afc689c5d234e250c18962453f16c1c1882f709dc
MD5 241e172ff58bc2428c464764c4f9bc80
BLAKE2b-256 db4d566f477dd8ba2be4d6340671125be5f8d90e223bee2cf6d297dbbdf05697

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