Compare LLM prompts side by side — no config, no dashboard, just a table
Project description
promptdiff
Compare LLM prompts side by side. No config files. No dashboards. No signup.
pip install compare-prompts
The problem
You have two (or more) prompts. You changed one word. Did it actually change anything? Right now:
- Running them manually and eyeballing outputs takes 30 minutes
- Setting up promptfoo requires YAML config and predefined "correct" answers
- Platforms like Braintrust/LangSmith require signup and send data to a dashboard
promptdiff is the missing middle ground — run it in your script, get a table in your terminal.
Quickstart
Step 1 — Install
pip install compare-prompts
Step 2 — Generate a starter file (optional)
compare-prompts init
This creates a test_prompts.py file you can edit immediately.
Step 3 — Or write your own comparison
from compare_prompts import compare
compare(
prompts={
"original": "You are a helpful assistant.",
"concise": "You are a concise helpful assistant.",
},
inputs=[
"Explain what a database is.",
"What is recursion?",
"Write a short poem about coding.",
],
model="gpt-4o-mini"
)
Step 4 — Run it
python test_prompts.py
Step 5 — See results
Running 2 prompts x 3 inputs = 6 calls... done
Prompt Comparison Results
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
avg length (tokens) 187 61 (-67%)
tone warm neutral
uses lists 67% 33%
uses headers 33% 0%
avg cost (USD) $0.0021 $0.0009
refusal rate 0% 0%
reading level high school middle school
Where to put this in your project
your-project/ <- your existing project
├── main.py <- don't touch this
├── prompts.py <- don't touch this
├── .env <- don't touch this (already has your API key)
└── test_prompts.py <- create this one new file
Import your prompts directly from your existing code:
from compare_prompts import compare
from prompts import PROMPT_V1, PROMPT_V2
compare(
prompts={"v1": PROMPT_V1, "v2": PROMPT_V2},
inputs=["your test questions here"],
model="gpt-4o-mini"
)
Setup your API key
Create a .env file in your project root (or use an existing one):
# Only one key is needed — whichever provider you use
OPENAI_API_KEY=sk-...
promptdiff automatically reads .env files. No extra configuration.
Get an API key
| Provider | Link | Env variable | Free tier? |
|---|---|---|---|
| OpenAI | platform.openai.com/api-keys | OPENAI_API_KEY |
No |
| Anthropic | console.anthropic.com | ANTHROPIC_API_KEY |
No |
| Google Gemini | aistudio.google.com/apikey | GEMINI_API_KEY |
Yes |
| Groq | console.groq.com/keys | GROQ_API_KEY |
Yes |
| Ollama | ollama.com | None needed | Yes (local) |
Supported models
Any model supported by LiteLLM works (2,600+ models):
compare(..., model="gpt-4o-mini") # OpenAI
compare(..., model="gpt-4o") # OpenAI
compare(..., model="claude-haiku-4-5") # Anthropic
compare(..., model="claude-sonnet-4-6") # Anthropic
compare(..., model="gemini/gemini-2.0-flash") # Google Gemini
compare(..., model="groq/llama-3.3-70b-versatile") # Groq (free)
compare(..., model="ollama/llama3") # Ollama (local, free)
compare(..., model="deepseek/deepseek-chat") # DeepSeek
Full list of all supported models: models.litellm.ai
Compare more than 2 prompts
compare(
prompts={
"baseline": "You are a helpful assistant.",
"concise": "You are a concise helpful assistant.",
"formal": "You are a professional formal assistant.",
"friendly": "You are a warm friendly assistant.",
},
inputs=["your test questions"]
)
Each prompt becomes a column. Same table, more columns.
See raw outputs
compare(
prompts={...},
inputs=[...],
show_outputs=True
)
Prints each raw LLM response below the table, grouped by input.
Faster execution with async
For many prompt+input combinations, run calls concurrently:
compare(
prompts={...},
inputs=[...],
use_async=True
)
What it measures
| Metric | Description |
|---|---|
| avg length (tokens) | Average response length in tokens |
| tone | Detected tone: neutral, formal, warm, or technical |
| uses lists | % of responses using bullet points or numbered lists |
| uses headers | % of responses using markdown headers |
| uses code blocks | % of responses using fenced code blocks |
| avg cost (USD) | Estimated cost per response based on token usage |
| refusal rate | % of responses that refused to answer |
| reading level | elementary / middle school / high school / college |
| avg sentence length | Average number of words per sentence |
Why not promptfoo?
promptfoo is excellent. Use it if you need CI/CD integration, red-teaming, or assertion-based testing with expected outputs.
promptdiff is for when you just want to run prompts right now and see how they behave differently — no YAML, no config, no web server, no predefined "correct" answers. Just a table in your terminal.
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 compare_prompts-0.1.2.tar.gz.
File metadata
- Download URL: compare_prompts-0.1.2.tar.gz
- Upload date:
- Size: 17.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2b42a80c5fa8a8c3b45afc2033d27148ad1a3ce6c02ba760afd421fa8a21a275
|
|
| MD5 |
f85864ffa7667d0893c7dc50855a744d
|
|
| BLAKE2b-256 |
8f7c56deda37401220c72e18e30fa74ff07714a8fc055c6f6c0fcfe12b2da7ca
|
File details
Details for the file compare_prompts-0.1.2-py3-none-any.whl.
File metadata
- Download URL: compare_prompts-0.1.2-py3-none-any.whl
- Upload date:
- Size: 14.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9e5c42ac98b110e218f52b6d0954d755b43dc1df518d8c41eb1fcd90ae6580e4
|
|
| MD5 |
545f9a9e3a0ad1483880e07e89b18088
|
|
| BLAKE2b-256 |
17c41db33682b30e349606019ec9e5e76550aa574ef8c666aeb9966436b08392
|