tourney
Local-first benchmarking runner for AI models. Run your prompts against the field.
tourney runs your own prompts and datasets against multiple model APIs (your keys, your machine) and measures quality, latency, cost, and token usage — with the statistical rigor researchers expect: bootstrap confidence intervals, pinned model IDs, seeds, config hashes, and full run metadata in a local SQLite database. No hosted service, no telemetry.
Install
pip install "tourney[dashboard]" # or plain `pip install tourney` for CLI/library only
Five-minute quickstart
tourney init # scaffolds benchmark.yaml + cases.jsonl
tourney run benchmark.yaml
tourney show latest --failures
tourney serve # local dashboard at http://127.0.0.1:8355
benchmark.yaml:
name: math-word-problems
models:
- provider: openai
model: gpt-4o-2024-08-06 # pin dated IDs for reproducibility
- provider: anthropic
model: claude-sonnet-5
- provider: openai_compat # anything OpenAI-compatible: Ollama, vLLM, OpenRouter...
model: llama3.1:8b
base_url: http://localhost:11434/v1
defaults: {temperature: 0, max_tokens: 256, seed: 42}
prompt:
system: "Answer with only the final number."
user: "{{ question }}" # Jinja2 over each case's input
dataset: {path: cases.jsonl}
graders:
- {type: numeric, tolerance: 0.001}
run: {concurrency: 8, retries: 3, timeout_s: 60}
API keys come from environment variables (OPENAI_API_KEY, ANTHROPIC_API_KEY, or a custom api_key_env) — never from config files.
math-word-problems · run 01J9X4… · $0.213
┌──────────────────────┬───────┬──────────────┬─────────┬─────────┬─────────┬────────┐
│ model │ score │ 95% CI │ p50 lat │ p99 lat │ cost │ errors │
├──────────────────────┼───────┼──────────────┼─────────┼─────────┼─────────┼────────┤
│ claude-sonnet-5 │ 0.960 │ [0.89, 1.00] │ 944ms │ 2107ms │ $0.0920 │ 0 │
│ gpt-4o-2024-08-06 │ 0.940 │ [0.86, 0.98] │ 812ms │ 2431ms │ $0.1210 │ 0 │
└──────────────────────┴───────┴──────────────┴─────────┴─────────┴─────────┴────────┘
Why another eval tool?
- Local-first. Results live in
./.tourney/results.db(SQLite). Copy it, query it, commit exports. - Reproducible. Config hash, tourney/Python versions, git commit, and provider fingerprints stored per run. Deterministic graders by default; stats are seeded.
- Cheap to iterate. Responses are content-address cached — rerunning an unchanged benchmark costs $0.
- CI-native.
tourney run --json --fail-under 0.85exits non-zero when a model regresses. - Honest statistics. Bootstrap CIs over cases; errors score 0 instead of being dropped.
Graders
| type | what it checks |
|---|---|
exact_match |
normalized string equality (normalize: [strip, lowercase, collapse_whitespace]) |
contains |
substring presence |
regex |
pattern match (pattern:) |
numeric |
last number in the response vs expected, within tolerance |
json_schema |
output is valid JSON, optionally conforming to schema: |
Multiple graders per benchmark average into the case score. LLM-as-judge is planned as strictly opt-in.
Library
import tourney
result = tourney.run("benchmark.yaml")
result.summary() # per-model dicts: score, CI, latency percentiles, cost
result.to_records() # per-completion rows -> pd.DataFrame(result.to_records())
CLI reference
tourney init scaffold a new benchmark
tourney run <config> run it (--model, --limit, --no-cache, --json, --fail-under)
tourney list recent runs
tourney show <run|latest> summary table (--failures for the failing cases)
tourney export <run> --format jsonl | csv | md
tourney serve local dashboard (requires tourney[dashboard])
Extending
Third-party providers and graders register via entry points (tourney.providers, tourney.graders) — publish a package with a Provider or Grader subclass and it becomes available by name in configs. A mock provider ships in the box for dry runs and tests.
Development
pip install -e ".[dev]"
pytest # fully offline — network is disabled in the test suite
Apache-2.0.
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 tourney-0.1.0.tar.gz.
File metadata
- Download URL: tourney-0.1.0.tar.gz
- Upload date:
- Size: 35.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bf872afb963ec588874e727b892e15084907556aad4e248e0270057c2a452f45
|
|
| MD5 |
989d498adaf5dbdba4aede186c4c783a
|
|
| BLAKE2b-256 |
b24c51905d7edff82001f6195f4003d9116d44009e5fee8e742d1d9f8aa936d0
|
Provenance
The following attestation bundles were made for tourney-0.1.0.tar.gz:
Publisher:
release.yml on k-rthik/tourney
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tourney-0.1.0.tar.gz -
Subject digest:
bf872afb963ec588874e727b892e15084907556aad4e248e0270057c2a452f45 - Sigstore transparency entry: 2202527621
- Sigstore integration time:
-
Permalink:
k-rthik/tourney@af613c973b39334d229df4cd7019e38fa0279ebc -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/k-rthik
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@af613c973b39334d229df4cd7019e38fa0279ebc -
Trigger Event:
push
-
Statement type:
File details
Details for the file tourney-0.1.0-py3-none-any.whl.
File metadata
- Download URL: tourney-0.1.0-py3-none-any.whl
- Upload date:
- Size: 40.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
432da70d04b78b0cf477a95713759b3638378feecfb918026f5f999fb1f1ec02
|
|
| MD5 |
79502fdbc69aec257956a5c38f8b8c35
|
|
| BLAKE2b-256 |
c9894bba22ef43ea1bb0780ff9f411b0b836bfed7e670c5df2da537a11adc27c
|
Provenance
The following attestation bundles were made for tourney-0.1.0-py3-none-any.whl:
Publisher:
release.yml on k-rthik/tourney
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tourney-0.1.0-py3-none-any.whl -
Subject digest:
432da70d04b78b0cf477a95713759b3638378feecfb918026f5f999fb1f1ec02 - Sigstore transparency entry: 2202527650
- Sigstore integration time:
-
Permalink:
k-rthik/tourney@af613c973b39334d229df4cd7019e38fa0279ebc -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/k-rthik
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@af613c973b39334d229df4cd7019e38fa0279ebc -
Trigger Event:
push
-
Statement type: