🔥 prompt-flamegraph
See where your LLM prompt tokens actually go.
Interactive flamegraphs · waste detection · prompt diffs — all local, zero-dependency.
No proxy, no server, no dashboard, no telemetry — one function call, one output file. Feed it a structured prompt or a raw OpenAI/Anthropic payload and get an interactive flamegraph of your token usage, with waste findings and cost estimates.
Contents
- Install
- Quick start
- Works with your payloads
- CI budget gate
- Waste detection
- CLI
- Model pricing
- API
- Resources
Install
pip install prompt-flamegraph
| Extra | Why |
|---|---|
pip install prompt-flamegraph[tiktoken] |
accurate OpenAI-style token counts |
pip install prompt-flamegraph[rich] |
prettier terminal output |
Quick start
from prompt_flamegraph import profile_prompt
prompt = {
"system_prompt": "You are a helpful coding assistant.",
"tools": ["..."],
"rag_context": {"doc_1": "..."},
"chat_history": ["..."],
}
profile_prompt(prompt, output="context.html", model="gpt-4o")
Open context.html in your browser. Done.
Reading the flamegraph — bar width = token share. Hover any bar (even a sub-pixel sliver) for its real name, token count and text. Nodes too thin to draw (<2% of their parent or <26px, or deeper than
max_depth=8) fold into striped· N more ·buckets; pass--no-aggregateon the CLI oraggregate=Falsetoto_html/to_svgto draw every node.
Works with your payloads
No restructuring needed — the CLI and normalize() auto-detect common shapes.
Raw OpenAI / Anthropic request bodies:
from prompt_flamegraph import normalize, profile_prompt
payload = {
"system": "You are a helpful assistant.",
"messages": [{"role": "user", "content": "Hello!"}],
}
profile_prompt(normalize(payload), output="context.html")
LangChain / LiteLLM objects — duck-typed, the framework is never imported:
from prompt_flamegraph import profile_any
# ChatPromptValue, rendered templates, BaseMessage lists...
profile_any(chat_prompt_value, output="context.html", model="gpt-4o")
CI budget gate
Fail a pipeline when a prompt outgrows its token budget — exit code 3 when exceeded, report still written:
prompt-flamegraph prompt.json --budget 100000 --format json -o report.json
Copy-paste GitHub Actions workflow: .github/workflows/prompt-budget.yml.example.
Waste detection
Find token waste before paying for it — duplicates, near-duplicates, oversized RAG, long histories, too many tools, context-window pressure:
from prompt_flamegraph import build_tree, detect_waste
tree = build_tree(prompt)
report = detect_waste(tree)
for finding in report.findings:
print(f"- {finding.kind}: {finding.message}")
- duplicate: 3× duplicate text ("def helper(): …") — keep only one
- duplicate: 10× duplicate text ('Hi!') — keep only one
- too_many_tools: 6 tools defined — only declare the ones the model actually calls
- long_history: chat history is 33.3% of the total context — consider truncation
Findings are also embedded in the HTML report (detect_waste=True by default).
CLI
prompt-flamegraph prompt.json -o context.html # HTML flamegraph
prompt-flamegraph prompt.json --terminal # terminal bar chart
prompt-flamegraph v1.json --diff v2.json -o d.html # diff (green/red/orange)
prompt-flamegraph prompt.json --format svg|md|json # other exports
prompt-flamegraph prompt.json --model gpt-4o # tokenizer + price + window
prompt-flamegraph prompt.json --no-aggregate # draw every single node
prompt-flamegraph prompt.json --budget 100000 # CI gate (exit 3 if over)
prompt-flamegraph --list-models # supported models
prompt-flamegraph prompt.json --theme dark # force dark mode
prompt-flamegraph --demo # try it instantly
cat openai_request.json | prompt-flamegraph - # stdin works too
Input files may be UTF-8 or UTF-16 — BOMs from Notepad and PowerShell redirection are handled transparently.
Terminal output
────────────────────────────── Prompt Flamegraph ───────────────────────────────
Total: 102 tokens
Category Tokens % of total Visual
system_prompt 18 17.6% █████
tools 41 40.2% ████████████
read_file 21 20.6% ██████
run_command 20 19.6% █████
rag_context 22 21.6% ██████
doc_1.py 11 10.8% ███
doc_2.py 11 10.8% ███
chat_history 21 20.6% ██████
… (nested rows truncated)
On non-UTF-8 streams (redirected output on Windows, LC_ALL=C) bars
degrade to ASCII # instead of crashing.
Without aggregation (--no-aggregate) — every sliver drawn, hover still shows each one's real name and tokens:
Model pricing
--model prices and context windows ship as a bundled snapshot — everything works offline. To refresh, fetch LiteLLM's crowd-updated pricing table into your user cache ($XDG_CACHE_HOME/prompt-flamegraph/models.json, or %LOCALAPPDATA%\prompt-flamegraph on Windows):
prompt-flamegraph --update-models
The cache extends --model/--list-models to hundreds of models — bundled entries win on conflicts, --list-models shows cache age. Normal runs never touch the network; only --update-models does. Use --offline or PROMPT_FLAMEGRAPH_OFFLINE=1 for bundled-only mode.
Prices — bundled and cached — are community-sourced estimates (LiteLLM's table), not official provider quotes. Check your provider's pricing page for billing-grade numbers.
Features at a glance
| 🪶 Zero dependencies | pure stdlib; tiktoken/rich optional |
| 📊 5 output formats | HTML · SVG · Markdown · JSON · terminal |
| 🔍 Waste detection | duplicates, near-dups, oversized RAG, long history, tool bloat |
| 🆚 Prompt diffs | before/after comparison with color-coded changes |
| 🔌 Payload adapters | OpenAI, Anthropic, LangChain, LiteLLM — no imports needed |
| 💰 Live pricing | bundled snapshot + LiteLLM refresh + offline mode |
| 🚦 CI gate | --budget N exits 3 when the prompt is too big |
| 🎛️ Pluggable tokenizers | tiktoken encodings, words, or any str -> int callable |
API
from prompt_flamegraph import (
profile_prompt, # dict → HTML flamegraph file
profile_any, # any payload/framework object → flamegraph
normalize, # OpenAI/Anthropic payload → structured dict
from_messages, # message list → structured dict
from_langchain, # LangChain-style object → structured dict
build_tree, # → internal Node tree
detect_waste, # tree → WasteReport
diff_prompts, # two prompts → diff HTML
to_html, to_svg, to_markdown, to_json, # tree → string
resolve_model, list_models, # model registry
count_tokens, get_tokenizer, # tokenizer utilities
)
Full signatures
profile_prompt(data, output="prompt_flamegraph.html", title=None,
tokenizer=None, model=None, cost_per_token=None,
detect_waste=True, context_window=None,
width=1200, height=720)
# model= auto-derives tokenizer, pricing and context window
# (mutually exclusive with tokenizer=; falls back to the
# estimator with a warning when the encoding needs tiktoken)
build_tree(data, name="prompt", tokenizer=None, model=None)
detect_waste(tree, context_window=None)
diff_prompts(v1, v2, output="prompt_diff.html", ...)
to_html(tree, title="Prompt Flamegraph", cost_per_token=None, waste_report=None,
width=1200, height=720, max_depth=8, aggregate=True)
to_svg(tree, title="Prompt Flamegraph", width=1200, row_height=34, max_depth=8,
aggregate=True)
to_markdown(tree, title="Prompt Flamegraph", cost_per_token=None)
to_json(tree, title="Prompt Flamegraph", cost_per_token=None, waste_report=None)
profile_any(obj, output=None, model=None, **profile_kwargs)
from_messages(messages, tools=None, system_prompt=None)
# roles "system"/"developer" merge into system_prompt
normalize(data) # extra top-level keys preserved; "model" dropped
Resources
- 🌐 Website / docs — https://fjjjuv.github.io/prompt-flamegraph/index.html
- 📦 PyPI — https://pypi.org/project/prompt-flamegraph/
- ✂️ prompt-optimizer — companion tool that trims the waste you find: https://github.com/fjjjuv/prompt-optimizer
- ✍️ Dev.to walkthrough — Stop Guessing Where Your LLM Prompt Tokens Go
Source
https://github.com/fjjjuv/prompt-flamegraph
License
LGPL-3.0-or-later — free to import into proprietary code; modifications to the library itself stay open. See LICENSE (full GPLv3 it builds on: LICENSE.GPL).
Metadata
Release files for prompt-flamegraph 0.4.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| prompt_flamegraph-0.4.1.tar.gz | 84.7 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| prompt_flamegraph-0.4.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 153.7 kB
Release files / prompt_flamegraph-0.4.1.tar.gz
| Download URL | prompt_flamegraph-0.4.1.tar.gz |
|---|---|
| Size | 84.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7cf2c8726fe544e6e50f5eacd42315b8a2b2503e83f396bfd0a27baaf6ed582d
|
|
BLAKE2b-256 checksum How to use checksums |
ac09e1ab94b9532877a054c2ba8b84c440243fb9b5701adfeeffbd7dc03fb7cc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.10
|
Release files / prompt_flamegraph-0.4.1-py3-none-any.whl
| Download URL | prompt_flamegraph-0.4.1-py3-none-any.whl |
|---|---|
| Size | 69.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
106e88331f2391e930ff5ba4cac7a592755f2124f6b8e181c49f9553f832adf7
|
|
BLAKE2b-256 checksum How to use checksums |
71ee4031c8b1792143364e1216e3d368f9cf4a003b96ade61571caa07dfddef1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.10
|
Security for prompt-flamegraph 0.4.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.