Client-side digest tool: tokenizes LLM logs locally on the shared ruler and emits metrics-only JSON. No text ever leaves the machine.
Project description
tokenfair-digest
Client-side digest tool for LLM API billing audits. Captures SDK responses, recounts tokens locally on a shared cl100k_base ruler, and emits metrics-only JSON. No prompt or completion text ever leaves your machine — only token counts are written.
Install
pip install tokenfair-digest
Capture (drop-in, one line)
Add a single line where you create your client, and every response is logged to a local JSONL file.
OpenAI
from openai import OpenAI
from tokenfair_digest.capture import capture_openai
client = capture_openai(OpenAI(), "openai_logs.jsonl")
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "Hello!"}],
)
# openai_logs.jsonl now has one record per response
Anthropic
from anthropic import Anthropic
from tokenfair_digest.capture import capture_anthropic
client = capture_anthropic(Anthropic(), "anthropic_logs.jsonl")
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello!"}],
)
Generate a digest
Once you have a JSONL log file, convert it to a metrics-only digest:
tokenfair-digest openai_logs.jsonl -f openai -o digest.json
Supported formats: openai, anthropic, gemini, atap
The digest JSON can be opened in the TokenFair web app or VS Code extension to audit where your tokens went.
Programmatic usage
from tokenfair_digest import build_digest, count_tokens, CaptureWriter
# Count tokens on the shared ruler
n = count_tokens("Hello, world!")
# Build a digest from parsed records
from tokenfair_digest.parsers import parse_openai_export
with open("openai_logs.jsonl") as fh:
digest = build_digest(parse_openai_export(fh))
Guarantees
- No text on disk. Only metric fields are written (
record_id,provider,model, token counts). Prompt and completion text stay in memory only. - Never breaks your call. The capture tee swallows any logging error — your API call is unaffected.
- Thread-safe. Writes are serialized with a lock.
- Streaming is skipped, not corrupted. Streamed responses have no
usageto record. - Matches the JS side. Uses the same
cl100k_basetokenizer as@garzillion-labs/capture, so counts line up.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tokenfair_digest-0.1.0.tar.gz.
File metadata
- Download URL: tokenfair_digest-0.1.0.tar.gz
- Upload date:
- Size: 12.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6316adeb3c34a212ce14ee7c3c01a53a91ed3dbfca4cb9e097a35b61f5a5895a
|
|
| MD5 |
835dbc0c460995d920ccb6fe0d41f03c
|
|
| BLAKE2b-256 |
1a0c18c32974391d894466cc03cc9759ef8dce4bba2c98608ef65e8dbac31754
|
File details
Details for the file tokenfair_digest-0.1.0-py3-none-any.whl.
File metadata
- Download URL: tokenfair_digest-0.1.0-py3-none-any.whl
- Upload date:
- Size: 13.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4f572a86985997935c73df9caac4dadd3b30282372c9849aca5c8dbcee2d5d88
|
|
| MD5 |
0cacc543e51f35f5df831b4e0c423643
|
|
| BLAKE2b-256 |
e8128ae8765ec6588db19ed92ba4b6bf3c7a74ad9873d2b4656b62d66071aadf
|