Skip to main content

prefixcash

Measure, diagnose and fix your LLM prompt-cache hit rate — and see the dollars you save.

A cache-economics layer for LLM applications: library + CLI/TUI + LiteLLM plugin.

License: MIT Python 3.11+ PyPI

Why

LLM providers cache attention states by the exact token prefix of your prompt. Cache hits cost 50–96% less on input tokens (OpenAI ~50%, Anthropic ~90%, DeepSeek ~96%, Gemini ~90% — verified prices in METHODOLOGY.md). Most applications never see those savings:

  • every new chat starts with an expensive cold call;
  • a dynamic {time}, UUID or session id at the start of the system prompt breaks the prefix on every single call;
  • TTLs expire between chats and some providers/upstreams don't cache well;
  • most platforms don't even know their own hit rate.

prefixcash closes the loop: measure it, diagnose what breaks it, fix it safely, prove the dollars.

Features

  • Measure — real hit rate per provider/model/session from provider usage fields (OpenAI, Anthropic, DeepSeek, Gemini, OpenRouter; raw payloads or LiteLLM-normalized), saved USD vs a conservative cold baseline.
  • Diagnose — intra-session prefix-breakage detection (D21): where in the prompt the prefix diverges between consecutive calls and what breaks it (timestamps, UUIDs, reordering, placeholders, high-entropy segments), plus a usage-level check for "shared prefix but no cache hit" (TTL expiry / non-caching provider).
  • Fix (advisory, D18) — the prefix heatmap shows exactly where the cache is lost and proposes assembly fixes (static prefix first, dynamic to the end); cache-aware routing recommendations (pin cache-friendly providers); batch-ordering of calls with shared prefixes — free warm-up from natural traffic, zero extra tokens (no 24/7 keep-alive pings).
  • Provereport produces the «$ saved vs cold baseline» artifact with a public methodology; experiment replays fix variants on a staging sample and gives a cache-economics verdict (quality is validated with your own eval, D25).

Library usage

prefixcash is a library first. The four verbs map to typed functions:

from prefixcash import (
    PrefixCashCallback, iter_calls, measure_log, diagnose_log,
    build_heatmap, lint, suggest_order, run_experiment,
)

# 1. measure — drop-in LiteLLM callback (production)
import litellm
litellm.callbacks = [PrefixCashCallback(file="metrics.jsonl")]
report = measure_log("metrics.jsonl")        # Report: hit rate + $ saved
print(report.totals.hit_rate, report.totals.saved_usd)

# 2. diagnose — where the prefix breaks inside sessions
for session_id, findings in diagnose_log("metrics.jsonl").items():
    for f in findings:
        print(session_id, f.break_words, [c.kind for c in f.causes])

# 3. fix (advisory) — heatmap + assembly suggestions + batch order
calls = list(iter_calls("metrics.jsonl"))
hm = build_heatmap(session_id, calls)
for s in lint(hm):
    print(s.position, s.word, "->", s.suggestion)
order = suggest_order(calls)                 # zero extra tokens

# 4. prove — replay fix variants on a staging sample
report = run_experiment(cases, client, prompt_for=my_prompt_builder)
print(report.verdict)                        # FIX WORKS / NO GAIN

Quick start

pip install prefixcash        # once published on PyPI

From the repo:

uv sync --extra dev --extra examples
uv run prefixcash providers                              # pricing / TTL table
uv run prefixcash report --file examples/sample.jsonl    # $ saved vs cold baseline
uv run prefixcash diagnose --file examples/diagnose.jsonl  # what breaks the prefix + heatmap + fixes
uv run prefixcash tui --file examples/diagnose.jsonl     # interactive heatmap (j/k — sessions)

diagnose on a session whose system prompt embeds a changing timestamp:

s1 — 2 findings, prefix stability 73%
  call 0 -> 1: shared prefix 5 words
    words after the break: 09:05:00. Отвечай коротко и по делу.
    • dynamic_time: word after the break: '09:05:00.'
    • cache_miss_despite_shared_prefix: shared prefix 5 words, but usage.cache_read_tokens == 0
    → fix: move the dynamic time/timestamp to the END of the prompt (after the static block)
  heatmap (color = prefix stability): ...

Experiments (staging)

Validate fix variants before production: replay a sample against your provider, measure hit rate + saved USD, get a verdict. Quality is checked with your own eval (D25).

export DEEPSEEK_API_KEY=sk-...        # or: cp examples/.env.example examples/.env
uv sync --extra dev --extra examples
uv run python -m examples.sales_agent            # LangChain agent (one turn)
uv run python -m examples.run_experiment         # broken vs fixed: hit rate + savings
uv run python -m benchmark.verify_diagnose       # offline diagnose check (no network)
uv run python -m benchmark.run_benchmark         # live run -> benchmark/RESULTS.md

Benchmark (live run, DeepSeek)

Diagnosis finds every breakage pattern; replay confirms the fix economics:

scenario diagnosis hit% baseline hit% fixed Δ verdict
sales-timestamp dynamic_iso_datetime 65% 87% +22% FIX WORKS
sales-uuid dynamic_uuid 66% 98% +33% FIX WORKS
kb-reorder content_change 49% 99% +49% FIX WORKS
short-prompt 0% 0% 0% NO GAIN (honest)
real-framework (claude-quant L2) dynamic_iso_datetime 50% 75% +24% FIX WORKS

Details and per-sample $: benchmark/RESULTS.md.

Architecture

src/prefixcash/
├── core/         # CacheMetrics, provider usage parsers, pricing tables
├── diagnose/     # intra-session breakage detection, prefix heatmap, assembly-lint
├── optimize/     # batch ordering by prefix, cache-aware routing, staging experiments
├── integrations/ # LiteLLM callback, JSONL importers
└── cli/          # report / monitor / diagnose / providers / import / tui

Measurement methodology (baseline, pricing policy, TTL, limitations): METHODOLOGY.md.

Roadmap

  • P0 (measure) ✅ — parsers (OpenAI/DeepSeek), CacheMetrics, report/monitor CLI, LiteLLM callback.
  • P1 (diagnose) ✅ — parsers (Anthropic/Gemini/OpenRouter), intra-session breakage detection, heatmap.
  • P2 (optimize + launch) 🚧 — heatmap ✅, batch-order ✅, routing ✅, Textual TUI ✅, experiments ✅, benchmark ✅; next: PyPI + GitHub release, benchmark blog post, Show HN.

Contributing

PRs are welcome — especially new provider parsers and benchmark scenarios. Open an issue first for design discussions.

License

MIT — see LICENSE.

Download files

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

Source Distribution

prefixcash-0.2.0.tar.gz (276.2 kB view details)

Uploaded Source

Built Distribution

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

prefixcash-0.2.0-py3-none-any.whl (39.8 kB view details)

Uploaded Python 3

File details

Details for the file prefixcash-0.2.0.tar.gz.

File metadata

  • Download URL: prefixcash-0.2.0.tar.gz
  • Upload date:
  • Size: 276.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.27 {"installer":{"name":"uv","version":"0.9.27","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for prefixcash-0.2.0.tar.gz
Algorithm Hash digest
SHA256 4e99b0a48ffb416839268a6d19b7f53ee7d6cfdc75b38dbd1d4e32a92f0978ad
MD5 faf8334360f5735bc6442663a9b38347
BLAKE2b-256 b9168202035317c2faf9731f734a87ec6f220f234101ab192817fe1c66d28d5f

See more details on using hashes here.

File details

Details for the file prefixcash-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: prefixcash-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 39.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.27 {"installer":{"name":"uv","version":"0.9.27","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for prefixcash-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f6c3271f06e6a476a859faa4f05bfd4648a1dc950e92981b6e942727fb4c5385
MD5 fe9b2ce471020ec0599b95a057935158
BLAKE2b-256 6785b2aafb50e7da83925cbaf1bd5b28efdcbf5059839a22807d5b6e548316c3

See more details on using hashes here.

Release history Release notifications | RSS feed

0.2.1

2 files

This release

0.2.0 This release

2 files

Supported by

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