Skip to main content

The open-source prompt engineering toolkit. Test, compare, and evaluate prompts across any LLM.

Project description

PromptRacer

The open-source prompt engineering toolkit. Test, compare, and evaluate your prompts across any LLM — from your terminal or Python code.

Free & open-source alternative to LangSmith, PromptLayer, and Humanloop.

PyPI License: MIT Python 3.10+


Why PromptRacer?

  • One pip install — no web app, no database, no account needed
  • Multi-provider — OpenAI, Anthropic, Google Gemini, Ollama (local models)
  • Compare models side-by-side — latency, cost, and quality in one table
  • LLM-as-judge evaluation — automated scoring with customizable criteria
  • Version your prompts — save as YAML, track changes with git
  • Template variables — reusable prompts with {{placeholders}}
  • Batch test suites — define test cases in YAML, run them all at once
  • Streaming — real-time token streaming in the CLI
  • Export — save results to JSON or CSV
  • Retry & rate limiting — built-in resilience for production use
  • CLI + Python API — use it however you want

Install

pip install promptracer

# With specific providers:
pip install promptracer[openai]          # OpenAI
pip install promptracer[anthropic]       # Anthropic (Claude)
pip install promptracer[google]          # Google Gemini
pip install promptracer[all]             # All providers

Ollama works out of the box — no extra install needed (just have Ollama running locally).

Quick Start

Python API

from promptracer import Prompt, compare, evaluate

# Create a prompt with template variables
p = Prompt("Translate to {{lang}}: {{text}}")
p.set_vars(lang="English", text="Hola mundo")

# Run against a single model
result = p.run("openai/gpt-4o")
print(result.response)   # "Hello world"
print(result.latency)    # 0.82
print(result.cost)       # 0.0003

# Compare across models
results = compare(p, models=[
    "openai/gpt-4o",
    "anthropic/claude-sonnet-4-6",
    "gemini/gemini-2.5-flash",
    "ollama/llama3",
])
results.print_table()
# ┌──────────────────────────────┬──────────────┬─────────┬─────────────────┬─────────┐
# │ Model                        │ Response     │ Latency │ Tokens (in/out) │ Cost    │
# ├──────────────────────────────┼──────────────┼─────────┼─────────────────┼─────────┤
# │ openai/gpt-4o [fastest]      │ Hello world  │ 0.52s   │ 24/3            │ $0.0001 │
# │ anthropic/claude-sonnet-4-6  │ Hello world  │ 0.61s   │ 22/3            │ $0.0001 │
# │ gemini/gemini-2.5-flash      │ Hello world  │ 0.48s   │ 20/3            │ $0.0000 │
# │ ollama/llama3 [cheapest]     │ Hello world! │ 1.20s   │ 18/4            │ FREE    │
# └──────────────────────────────┴──────────────┴─────────┴─────────────────┴─────────┘

# Evaluate quality with LLM-as-judge
eval_result = evaluate(result, criteria="accuracy", judge="openai/gpt-4o-mini")
eval_result.print()
# ╭──────────── PromptRacer Eval ────────────╮
# │ Score: 9/10                            │
# │ Criteria: accuracy                     │
# │ Reasoning: Accurate translation...     │
# ╰────────────────────────────────────────╯

Save & Load Prompts as YAML

# Save — version control with git!
p.save("prompts/translate.yaml")

# Load
p2 = Prompt.load("prompts/translate.yaml")
# prompts/translate.yaml
template: "Translate to {{lang}}: {{text}}"
name: translate
system: You are a professional translator
vars:
  lang: English
  text: Hola mundo

Prompt Versioning

p = Prompt("Translate: {{text}}")
p.update("Translate accurately: {{text}}")
p.update("Translate accurately and naturally: {{text}}")

# View history
p.history()  # [{'version': 1, ...}, {'version': 2, ...}, {'version': 3, ...}]

# Compare versions
old, new = p.diff(1, 3)

CLI

# Set your API keys
export OPENAI_API_KEY=sk-...
export ANTHROPIC_API_KEY=sk-ant-...
export GEMINI_API_KEY=AI...

# Run a prompt
promptracer run "What is Python?" -m openai/gpt-4o

# Compare models
promptracer compare "Explain quantum computing" \
  -m "openai/gpt-4o,anthropic/claude-sonnet-4-6,ollama/llama3"

# With template variables
promptracer compare "Translate to {{lang}}: {{text}}" \
  -v lang=French -v text="Good morning" \
  -m "openai/gpt-4o,gemini/gemini-2.5-flash"

# Evaluate a response
promptracer eval "Write a haiku about coding" \
  -m openai/gpt-4o \
  -j openai/gpt-4o-mini \
  -c "creativity and adherence to haiku format"

# Create a prompt template
promptracer init my-prompt

Batch Test Suites

Define test cases in YAML and race models against each other:

# suites/translation.yaml
template: "Translate to {{lang}}: {{text}}"
system: "You are a professional translator"
models:
  - openai/gpt-4o
  - anthropic/claude-sonnet-4-6
  - ollama/llama3
judge: openai/gpt-4o-mini
criteria: "accuracy and natural fluency"
cases:
  - name: "Spanish  English"
    vars: { lang: English, text: "Hola, ¿cómo estás?" }
    expected: "Hello, how are you?"
  - name: "Technical jargon"
    vars: { lang: English, text: "El algoritmo converge rápidamente" }
from promptracer import run_suite

results = run_suite("suites/translation.yaml")
for batch in results:
    batch.print_table()
# From CLI
promptracer batch suites/translation.yaml
promptracer batch suites/translation.yaml -o results.json

Streaming

promptracer run "Write a poem about AI" -m openai/gpt-4o --stream

Export Results

results = compare(p, models=["openai/gpt-4o", "ollama/llama3"])
results.to_json("results.json")
results.to_csv("results.csv")

Prompt Chains

Pipe the output of one prompt into the next — across different models:

from promptracer import Chain

result = (
    Chain()
    .step("Summarize this article: {{input}}", model="openai/gpt-4o")
    .step("Translate to Spanish: {{output}}", model="anthropic/claude-sonnet-4-6")
    .step("Make it sound poetic: {{output}}", model="ollama/llama3")
    .run(input="Long article text here...")
)

result.print()           # Shows each step with latency/cost
print(result.final_response)
print(result.total_cost)  # Total across all steps

Model Leaderboard

Race models and rank them by score:

promptracer leaderboard suites/translation.yaml
# ┌──────┬──────────────────────────────┬───────────┬───────────┬─────────────┬────────────┐
# │ Rank │ Model                        │ Avg Score │ Pass Rate │ Avg Latency │ Total Cost │
# ├──────┼──────────────────────────────┼───────────┼───────────┼─────────────┼────────────┤
# │ 1st  │ openai/gpt-4o               │ 9.2/10    │ 100%      │ 0.85s       │ $0.0032    │
# │ 2nd  │ anthropic/claude-sonnet-4-6  │ 8.8/10    │ 100%      │ 0.92s       │ $0.0028    │
# │ 3rd  │ ollama/llama3               │ 7.1/10    │ 75%       │ 2.10s       │ FREE       │
# └──────┴──────────────────────────────┴───────────┴───────────┴─────────────┴────────────┘

Cost Tracking

Every run is automatically logged. Check your spending anytime:

promptracer cost           # All time
promptracer cost today     # Last 24h
promptracer cost week      # Last 7 days
promptracer cost month     # Last 30 days
promptracer cost --clear   # Reset history

Project Config

Create a .promptracer.yaml in your project root:

default_model: openai/gpt-4o
default_judge: openai/gpt-4o-mini
models:
  - openai/gpt-4o
  - anthropic/claude-sonnet-4-6
  - ollama/llama3
criteria: "accuracy, relevance, and completeness"
track_costs: true

Async Support

import asyncio
from promptracer import Prompt
from promptracer.compare import acompare

async def main():
    p = Prompt("Explain {{topic}} simply")
    p.set_vars(topic="quantum computing")

    # All models run concurrently
    results = await acompare(p, models=[
        "openai/gpt-4o",
        "anthropic/claude-sonnet-4-6",
        "ollama/llama3",
    ])
    results.print_table()

asyncio.run(main())

Supported Models

Provider Prefix Example API Key
OpenAI openai/ openai/gpt-4o OPENAI_API_KEY
Anthropic anthropic/ anthropic/claude-sonnet-4-6 ANTHROPIC_API_KEY
Google Gemini gemini/ or google/ gemini/gemini-2.5-flash GEMINI_API_KEY
Ollama ollama/ ollama/llama3 None (local)

Contributing

Contributions are welcome! Please open an issue or submit a PR.

# Dev setup
git clone https://github.com/Unlucko/promptracer.git
cd promptracer
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"

# Run tests
pytest

# Lint
ruff check src/

License

MIT License — use it however you want.

Project details


Download files

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

Source Distribution

promptracer-0.3.0.tar.gz (23.4 kB view details)

Uploaded Source

Built Distribution

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

promptracer-0.3.0-py3-none-any.whl (27.8 kB view details)

Uploaded Python 3

File details

Details for the file promptracer-0.3.0.tar.gz.

File metadata

  • Download URL: promptracer-0.3.0.tar.gz
  • Upload date:
  • Size: 23.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for promptracer-0.3.0.tar.gz
Algorithm Hash digest
SHA256 d5545855eede88fb3ade68ce0405c9fb497955c83b1b6f1d7c19a09fe1c33a87
MD5 60c30ea56bda4612e432a5f1903bb12e
BLAKE2b-256 2975352466a431d88426a653a08fcbdd10a78b294412a07cf45ef402e1deff89

See more details on using hashes here.

File details

Details for the file promptracer-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: promptracer-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 27.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for promptracer-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 68578f86b54b8f2a3f4554c0a3e4d02348230031556b57ea07cfdf487f328891
MD5 d89ed7373d66243fbf3a70e152784df2
BLAKE2b-256 ee429bc202db4ae590afb6200af1411c7c7d6503be02f6fbb05ddec1dcdd9222

See more details on using hashes here.

Supported by

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