Skip to main content

🔥 prompt-flamegraph

See where your LLM prompt tokens actually go.

Interactive flamegraphs · waste detection · prompt diffs — all local, zero-dependency.

PyPI version Python versions License: LGPL v3 Website

Interactive HTML flamegraph Terminal demo

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

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-aggregate / aggregate=False to 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 --demo                            # try it instantly
cat openai_request.json | prompt-flamegraph -       # stdin works too
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)

Without aggregation (--no-aggregate) — every sliver drawn, hover still shows each one's real name and tokens:

Flamegraph without aggregation

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):

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=..., cost_per_token=None, waste_report=None,
        width=1200, height=720, max_depth=8, aggregate=True)
to_svg(tree, title=..., width=1200, row_height=34, max_depth=8,
       aggregate=True)
to_markdown(tree, title=..., cost_per_token=None)
to_json(tree, title=..., 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

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.3.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for prompt-flamegraph 0.3.1
File Size Uploaded
prompt_flamegraph-0.3.1.tar.gz 62.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for prompt-flamegraph 0.3.1
File Interpreter ABI Platform
prompt_flamegraph-0.3.1-py3-none-any.whl Python 3 none any Details

Total release size: 119.7 kB

Release files / prompt_flamegraph-0.3.1.tar.gz

Download URL prompt_flamegraph-0.3.1.tar.gz
Size 62.5 kB
Tags Source
SHA-256 checksum
How to use checksums
54e53ea0f14cababdec2054b37c834ac9ec01173f1d9382adc837c79a621cf51
BLAKE2b-256 checksum
How to use checksums
e3825ec98c52a607142ae343616b5dc497ce1bddb53a44dc7cc5b58e098d0181
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

Release files / prompt_flamegraph-0.3.1-py3-none-any.whl

Download URL prompt_flamegraph-0.3.1-py3-none-any.whl
Size 57.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e47db7f920e8886ea42cebbae3b478b73cd158514cdc8f418802bdcbefb3b552
BLAKE2b-256 checksum
How to use checksums
f2949a92041d0f36a290e73cd75566b08f7894b318c94334927f236de6d9229a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

Release history Release notifications | RSS feed

0.4.1

2 release files

0.4.0

2 release files

0.3.3

2 release files

0.3.2

2 release files

This release

0.3.1 This release

2 release files

0.3.0

2 release files

0.2.4

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page