Skip to main content

COIL - Token-optimized structured data encoding for LLM pipelines. Compress JSON into compact, schema-aware blocks that reduce LLM token usage by 40-70%.

Project description

๐Ÿงฌ coil_python โ€” COIL v0.7.0

Token-optimized structured data encoding for LLM pipelines.

COIL (Compact Object Input Language) compresses JSON into a compact, schema-aware representation that reduces LLM token usage by 40โ€“70% while remaining fully lossless and reversible.

Unlike general-purpose compression, COIL is designed around how transformers tokenize text. It detects table-shaped arrays, builds a greedy value-alias map using hill-climbing optimisation, and encodes rows as pipe-delimited strings โ€” squeezing the same information into far fewer tokens.


โœจ Features

  • 40โ€“70% token reduction on structured JSON payloads
  • Lossless round-trip โ€” integers, floats, booleans, None, and arrays all survive encode โ†’ decode with their exact Python types
  • Nested object support โ€” deep dicts are flattened to dot-notation keys and reconstructed on decode
  • Hill-climbing vmap โ€” Algorithm 1 from the COIL paper; only commits substitutions that strictly reduce token count (no negative savings)
  • Per-file type registry โ€” input_coil_types.json alongside your data, never a shared global file
  • Terminal visuals โ€” bar_chart, graph, report for instant feedback
  • matplotlib charts โ€” show_charts for richer visual analysis (optional)
  • CLI โ€” encode, decode, and stats from the command line
  • tiktoken optional โ€” falls back to a character-length heuristic if not installed

๐Ÿ“ฆ Installation

pip install coil_python

With real token counting (recommended for production):

pip install "coil_python[tiktoken]"

With matplotlib charts:

pip install "coil_python[all]"

๐Ÿš€ Quick Start

import json
import coil_python as coil

# Load your data
with open("data.json") as f:
    data = json.load(f)

# Encode โ†’ writes data_coil_types.json alongside the encoded output
type_file = coil.types_file_path("data.json")   # "data_coil_types.json"
encoded   = coil.encode(data, type_file=type_file)

# Save encoded output
with open("data_encoded.json", "w") as f:
    json.dump(encoded, f, indent=2)

# Decode โ†’ restores exact types
decoded = coil.decode(encoded, type_file=type_file)

# Verify losslessness
print(coil.is_lossless(data, decoded))  # True

# Stats
s = coil.stats(data, encoded, decoded, out="coil_stats.json")
coil.report(s)

๐Ÿ–ฅ๏ธ CLI

After installation the coil command is available:

# Encode
coil encode data.json
# โ†’ data_encoded.json  +  data_coil_types.json

# Encode with explicit output paths
coil encode data.json -o out_encoded.json --type-file out_types.json

# Decode
coil decode data_encoded.json
# โ†’ data_encoded_decoded.json

# Stats dashboard
coil stats data.json data_encoded.json

# Library info
coil info

Or via the module:

python -m coil_python encode data.json
python -m coil_python decode data_encoded.json
python -m coil_python stats data.json data_encoded.json

๐Ÿ“˜ API Reference

coil.encode(data, *, type_file="coil_types.json", return_types=False)

Encodes a Python object into COIL format.

COIL automatically:

  • Detects table-shaped arrays (list[dict]) and encodes them positionally
  • Flattens nested dicts to dot-notation keys ({"a": {"b": 1}} โ†’ {"a.b": 1})
  • Builds a hill-climbing value-alias map โ€” only commits aliases that save tokens
  • Stores precise column types to type_file for lossless decode
encoded = coil.encode(data)

# Per-file type registry (recommended โ€” avoids collisions)
type_file = coil.types_file_path("employees.json")  # "employees_coil_types.json"
encoded   = coil.encode(data, type_file=type_file)

# Get the type registry inline
encoded, registry = coil.encode(data, return_types=True)

coil.decode(encoded_data, *, type_file="coil_types.json")

Restores original data from COIL encoding.

decoded = coil.decode(encoded)
decoded = coil.decode(encoded, type_file="employees_coil_types.json")

The type_file must match the path used during encode().


coil.verify(original, encoded, *, type_file="coil_types.json")

Decodes and checks losslessness in one step.

result = coil.verify(data, encoded)
print(result["lossless"])   # True / False
decoded = result["decoded"]

coil.stats(original, encoded, decoded=None, *, out="coil_stats.json")

Computes compression metrics and saves them to out.

s = coil.stats(data, encoded, decoded)
print(s["comparison"]["token_saving_percent"])   # e.g. 62.79
print(s["comparison"]["compression_ratio"])       # e.g. 2.69
print(s["lossless"])                              # True

Returns a dict with original, encoded, comparison, and optionally lossless.


coil.is_lossless(original, decoded)

Deep structural equality check for any JSON-compatible object.

print(coil.is_lossless(data, decoded))  # True

coil.bar_chart(stats, metric="tokens")

Horizontal bar chart in the terminal.

coil.bar_chart(stats, "tokens")   # token count comparison
coil.bar_chart(stats, "bytes")    # byte size comparison
coil.bar_chart(stats, "ratio")    # compression ratio bar
coil.bar_chart(stats, "chars")    # character count

coil.graph(stats, metric="full")

Multi-metric summary graph.

coil.graph(stats, "savings")   # token & byte savings with colour bars
coil.graph(stats, "size")      # side-by-side size comparison
coil.graph(stats, "full")      # everything: savings + size + quality

coil.report(stats)

Full compression dashboard โ€” the clearest single-call summary.

coil.report(stats)
โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—
โ•‘           COIL Compression Report            โ•‘
โ• โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•ฃ
โ•‘  Original  โ”‚ 8154   tokens โ”‚ 32614    bytes  โ•‘
โ•‘  Encoded   โ”‚ 3034   tokens โ”‚ 12134    bytes  โ•‘
โ• โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•ฃ
โ•‘  Token saved  : โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘ 62.79%  โ•‘
โ•‘  Bytes saved  : โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘ 62.8%   โ•‘
โ• โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•ฃ
โ•‘  Compression  : 2.69x                        โ•‘
โ•‘  Lossless     : โœ… YES                        โ•‘
โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

coil.show_charts(stats)

Matplotlib bar charts for token count, byte size, and savings summary. Requires pip install "coil_python[charts]".

coil.show_charts(stats)

coil.types_file_path(input_file)

Derives the type-registry filename from an input file path.

coil.types_file_path("data/employees.json")
# โ†’ "data/employees_coil_types.json"

coil.debug_mode(flag=True)

Enable verbose internal logging.

coil.debug_mode(True)
# [COIL] Encoding โ†’ type_file=coil_types.json, model=default
# [COIL] Encoding complete

coil.set_model(model_name)

Select the tokenizer backend for token counting.

coil.set_model("gpt-4o-mini")   # uses tiktoken if installed
coil.set_model("claude-4")      # anthropic (heuristic fallback)
coil.set_model("default")       # character-length heuristic (no deps)

Supported: "gpt-4o", "gpt-4o-mini", "gpt-4.1", "claude-3", "claude-4", "gemini", "mistral", "default".


coil.info()

Returns library metadata.

coil.info()
# {
#   "library":   "coil_python",
#   "version":   "0.5.0",
#   "ecosystem": "python",
#   "model":     "default",
#   "debug":     False,
#   "purpose":   "Token-optimized structured data encoding for LLMs"
# }

๐Ÿ” Complete Example

import json
import coil_python as coil

# โ”€โ”€ Setup โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
coil.set_model("gpt-4o-mini")   # use tiktoken for accurate token counts
coil.debug_mode(False)

# โ”€โ”€ Load โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
with open("telemetry.json") as f:
    data = json.load(f)

# โ”€โ”€ Encode โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
type_file = coil.types_file_path("telemetry.json")
encoded   = coil.encode(data, type_file=type_file)

with open("telemetry_encoded.json", "w") as f:
    json.dump(encoded, f, indent=2)

# โ”€โ”€ Decode โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
decoded = coil.decode(encoded, type_file=type_file)

with open("telemetry_decoded.json", "w") as f:
    json.dump(decoded, f, indent=2)

# โ”€โ”€ Verify โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
result = coil.verify(data, encoded, type_file=type_file)
print("Lossless:", result["lossless"])

# โ”€โ”€ Analyse โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
s = coil.stats(data, encoded, decoded, out="telemetry_stats.json")

coil.report(s)
coil.bar_chart(s, "tokens")
coil.bar_chart(s, "ratio")
coil.graph(s, "full")
coil.show_charts(s)   # requires matplotlib

print(coil.info())

๐Ÿง  How COIL Works

COIL applies a two-stage algorithm to each table-shaped array it encounters:

Stage 1 โ€” Structural analysis Arrays of uniform dicts are detected as tables. Nested dicts are flattened to dot-notation keys (user.name, location.city) so the entire record fits into a single flat row. The original nesting is reconstructed on decode.

Stage 2 โ€” Hill-climbing vmap (Algorithm 1)

  1. Candidate values are sorted by freq(v) ร— tokenCount(v) descending.
  2. Each iteration finds the single best alias assignment.
  3. An alias is committed only if it strictly reduces the token count.
  4. A stall counter stops the loop after 6 consecutive non-improving candidates.
  5. Alias tokens are compact: V1..V9, VA..VZ, VAA...

The result is a META header (column order, alias map) and a BODY of pipe-delimited rows โ€” a format that is dense for transformer attention while remaining fully decodable.


โš ๏ธ Important: type_file pairing

encode() writes a type registry file and decode() reads it. Both calls must use the same type_file path, and the file must exist when you call decode().

# โœ… Correct โ€” same type_file path
encoded = coil.encode(data, type_file="my_types.json")
decoded = coil.decode(encoded, type_file="my_types.json")

# โŒ Wrong โ€” default path, then missing file on another machine
encoded = coil.encode(data)           # writes coil_types.json locally
decoded = coil.decode(encoded)        # reads coil_types.json โ€” must exist!

For multi-file pipelines, use types_file_path() to generate a unique name per input file automatically.


๐Ÿ“Š Benchmark

Tested on mixed_test.json (smart-city analytics payload with 6 embedded tables, nested objects, mixed types, nulls, and array columns):

Metric Value
Original tokens 3,000
Encoded tokens 1,823
Token saving 39.2%
Byte saving 39.3%
Compression ratio 1.65ร—
Lossless โœ…

On highly repetitive datasets (sensor logs, transaction records) savings reach 60โ€“70% with compression ratios above 2.5ร—.


๐Ÿ“‹ Known Limitations

  • Token counts use a ceil(len / 4) heuristic unless tiktoken is installed. Install with pip install "coil_python[tiktoken]" for accurate counts.
  • COIL falls back to the original data when encoding would not reduce size, so not every JSON document will be compressed.
  • The type_file must be kept alongside the encoded JSON for decode to work. It is not embedded in the encoded output.

๐Ÿ“œ License

MIT


๐Ÿ‘ค Author

Muthukumaran S & Bala Jothi Adithiya S โ€” Creator of the COIL Protocol

Contact - muthukumarandeveloper@gmail.com , balajothiadithya@gmail.com

If you use COIL in research, please cite it as: COIL โ€” Compact Object Input Language, 2026.

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

coil_python-0.7.0.tar.gz (23.2 kB view details)

Uploaded Source

Built Distribution

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

coil_python-0.7.0-py3-none-any.whl (21.0 kB view details)

Uploaded Python 3

File details

Details for the file coil_python-0.7.0.tar.gz.

File metadata

  • Download URL: coil_python-0.7.0.tar.gz
  • Upload date:
  • Size: 23.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.1

File hashes

Hashes for coil_python-0.7.0.tar.gz
Algorithm Hash digest
SHA256 e19d60f8c14bd4b78dcdc63aff559a32b6ab3d5e46a2f4630b2c8ceb7b6c31a8
MD5 4db70c5893647088bb1d93eb316ec497
BLAKE2b-256 78ffd2a387787ae3c5370e8a38aa2b7a3870a7bdabb0f18ee2e59a95c52fc81f

See more details on using hashes here.

File details

Details for the file coil_python-0.7.0-py3-none-any.whl.

File metadata

  • Download URL: coil_python-0.7.0-py3-none-any.whl
  • Upload date:
  • Size: 21.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.1

File hashes

Hashes for coil_python-0.7.0-py3-none-any.whl
Algorithm Hash digest
SHA256 130d37268c88fe74380da089f4a6feef53fa85ac38c193f1b99ebfb021dcd436
MD5 a20d3c7adaf0673c9ca769194e0d5b1c
BLAKE2b-256 68d3e84e6c448653336feb5d345ae15a42dc47b3e613246819f985e2e0d4f938

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