Regress is an open-source failure-to-eval compiler. Every LLM observability vendor captures traces and scores them — then leaves the hard part to you, by hand, forever: turning a cluster of bad outputs into a committed regression test that blocks the next bad deploy. Regress automates exactly that loop:
production trace → clustered failure → tracked issue → auto-generated eval → CI regression gate
Self-hostable, adoptable in under 5 minutes, SQLite by default, no account and no API key for Regress itself.
Does it actually work?
Yes — here's the whole loop run end to end against a real LlamaIndex RAG over SQuAD, with numbers straight out of the run:
| Stage | Result |
|---|---|
Ingest (one line: instrument()) |
100 questions → 200 traces, zero app changes |
| Score vs. gold answers | 21 real failures found (79% answer accuracy) |
| Cluster | 21 failures → 2 auto-titled issues |
| EvalGen | → 8 committed regression cases |
| Calibrate | judge-vs-human Cohen's κ = 0.435 |
| Gate | caught a degraded RAG (79% → 47%) at p < 0.00001, ignored a 4-pt noise drop |
Total API cost for the entire study: under $0.05. It even found (and fixed) a real bug in Regress itself. Full write-up → docs/case-study.md.
Quickstart
pip install git+https://github.com/arshadvani3/Regress.git
# once published to PyPI: pip install regress-ai
regress demo # load a sample scenario — see the whole loop, zero setup
regress up # then open http://localhost:8990
regress demo seeds a small sample (failing traces already scored and
clustered into Issues, including a regressed one) so the dashboard is
populated the moment you install — nothing to instrument first. regress demo --reset clears it. To point Regress at your app instead, change one line:
from regress import instrument
instrument() # patches OpenAI/Anthropic SDKs, emits OTel spans to localhost
Then use your app, open http://localhost:8990, watch traces stream in, and run the loop below. No Postgres, no account, no YAML until you want it.
How it works
┌────────────────────────────────────────────────┐
│ regress up (FastAPI) │
│ │
your app ──OTLP──▶ │ /v1/traces ──▶ Ingest ──▶ Store (SQLite/PG) │
(instrument() or │ + embeddings │
any OTel exporter) │ │
│ Scorer ── deterministic checks + judge ──▶ │
│ span/trace scores │
│ │
│ Clusterer ── embed failed traces ──▶ Issues │
│ (HDBSCAN, LLM-written titles, │
│ active → resolved → regressed) │
│ │
│ EvalGen ── issue ──▶ evals/<issue>.yaml │
│ │
│ Calibrator ── human labels ──▶ judge kappa │
│ │
│ Dashboard (React+TS+Tailwind, served static) │
└────────────────────────────────────────────────┘
CI: regress run evals/ --against <live app> ──▶ pass/fail + significance test
shipped as a reusable GitHub Action (.github/actions/gate)
Six stages, one command each:
| Stage | Command | What it does |
|---|---|---|
| Ingest | instrument() / any OTLP exporter |
Record LLM calls as traces |
| Score | regress score |
Deterministic checks + LLM-judge |
| Cluster | regress cluster |
Group failures into tracked Issues |
| EvalGen | regress evalgen |
Issue → YAML + pytest regression test |
| Gate | regress run --gate |
Fail CI on a significant regression |
| Calibrate | regress calibrate |
Measure how much to trust the judge |
→ Full walkthrough with the reasoning behind each stage (plus an interactive visual version).
Usage
A tour of the loop. Full flag-by-flag reference: docs/usage.md.
Ingest — one line in your app, or point any OTel exporter at regress up:
from regress import instrument
instrument() # every openai/anthropic call now exports a trace
Score — deterministic checks + an optional LLM-judge, configured in an
optional regress.yaml (regress init scaffolds one with a menu of
ready-to-use rubrics):
regress init # writes a starter regress.yaml
regress score --config regress.yaml
Cluster scored-bad traces into Issues (needs the cluster extra). A new
failure landing in a resolved issue flips it to regressed — a fix that
didn't hold:
pip install 'regress-ai[cluster]'
regress cluster
Generate evals — each issue becomes a sanitized, human-editable YAML eval
plus a pytest module (pytest evals/ works with no server):
regress evalgen
Or run score → cluster → evalgen in one shot:
regress analyze.
Gate CI — replay recorded traces, or hit your live app and block the deploy on a statistically significant drop (a two-proportion test, not a raw diff):
regress run evals/ --against http://localhost:8000/predict --gate
Calibrate the judge — hand-label a sample and get Cohen's κ, because the judge drives everything above:
regress calibrate --label 20 --labeler you@example.com
regress calibrate --report
Why not just Langfuse / Braintrust / <observability vendor>?
Those tools are excellent at the first half of the loop — capturing traces and scoring them. What they leave to you, manually, every time, is the second half: turning a cluster of bad traces into a committed regression test that blocks a bad deploy. Regress's only job is that second half, done automatically, and it speaks OpenTelemetry GenAI conventions so it plugs into whatever you're already exporting from. It's not replacing your observability stack — it's making one specific workflow (failure → eval → gate) something you never do by hand again.
Design principles
- Zero-config default path. SQLite + local embeddings (
bge-small-en-v1.5) out of the box. Postgres + pgvector is opt-in viaREGRESS_DB_URLfor scale. - Standards over SDK lock-in. Ingestion speaks OpenTelemetry GenAI
conventions over OTLP/HTTP.
instrument()is a convenience, not a requirement. - Everything is also a file. Generated evals are plain YAML + Python in your
repo, runnable with
regress runor plainpytest— no server in CI. - One process, one port for local dev; the judge works against any OpenAI-compatible endpoint, including a fully-local Ollama.
Non-goals (v0)
No hosted/multi-tenant SaaS, no auth beyond a single optional bearer token, no prompt-management/playground features, no fine-tuning loops, no non-GenAI OTel traffic, no Kubernetes manifests. The scope is intentional.
Status & what's next
Pre-alpha. The full loop — ingest → score → cluster → evalgen → gate → calibrate, plus the dashboard — works end to end, proven against a real LlamaIndex RAG (see the case study). It's a self-hosted single-node tool today; public APIs may still shift.
Streaming-completion capture already landed (instrument() traces
token-streamed responses without forcing non-streaming), and a shared
deployment can now require a bearer token (REGRESS_AUTH_TOKEN) and redact
PII before it's stored (REGRESS_SANITIZE_INGEST) — see
docs/usage.md. Where it goes next:
- Postgres + pgvector for teams past the single-node SQLite default —
the storage layer is already abstracted behind
REGRESS_DB_URL. - Async, cached judge calls so a large score run isn't a sequential wait and identical output+rubric pairs aren't re-judged.
- More judge backends beyond OpenAI-compatible — the judge is a thin provider-agnostic client, so Anthropic/Bedrock/local slot in cleanly.
Contributing
git clone https://github.com/arshadvani3/Regress.git && cd Regress
python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest && ruff check . && mypy src
The dashboard (dashboard/, Vite + React + TypeScript + Tailwind) is a separate
npm project that builds into src/regress/dashboard_dist/, which regress up
serves as static files:
cd dashboard && npm install
npm run dev # Vite dev server on :5173, proxies /api to :8990
npm run build # writes the bundle regress up serves
License
Apache-2.0. See LICENSE.
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 regress_ai-0.1.0.tar.gz.
File metadata
- Download URL: regress_ai-0.1.0.tar.gz
- Upload date:
- Size: 134.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d5b3ec985c14d91930fea45341e5e5c3cfaf9d51ceec90883e33169701eb5861
|
|
| MD5 |
faf9c640cc57a19f4071f2aeb4135519
|
|
| BLAKE2b-256 |
d5dbea2f90a42f9ecaaf760d4f5080307a0c2b972e63a4beb81607537774e66e
|
Provenance
The following attestation bundles were made for regress_ai-0.1.0.tar.gz:
Publisher:
release.yml on arshadvani3/Regress
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
regress_ai-0.1.0.tar.gz -
Subject digest:
d5b3ec985c14d91930fea45341e5e5c3cfaf9d51ceec90883e33169701eb5861 - Sigstore transparency entry: 2341629033
- Sigstore integration time:
-
Permalink:
arshadvani3/Regress@664a91f74ab2bdff439a4843e4f6698896494f10 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/arshadvani3
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@664a91f74ab2bdff439a4843e4f6698896494f10 -
Trigger Event:
push
-
Statement type:
File details
Details for the file regress_ai-0.1.0-py3-none-any.whl.
File metadata
- Download URL: regress_ai-0.1.0-py3-none-any.whl
- Upload date:
- Size: 77.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0faeb9ced0e9d233e702b6f524101e49be46249d34fffcf93a77457114bd9b36
|
|
| MD5 |
eb87d58e519698aca03f1b25dcdb603a
|
|
| BLAKE2b-256 |
a33478013b7b21761b4e2c83f15cd7bcc3c72d099a315b04a45372ba227771ab
|
Provenance
The following attestation bundles were made for regress_ai-0.1.0-py3-none-any.whl:
Publisher:
release.yml on arshadvani3/Regress
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
regress_ai-0.1.0-py3-none-any.whl -
Subject digest:
0faeb9ced0e9d233e702b6f524101e49be46249d34fffcf93a77457114bd9b36 - Sigstore transparency entry: 2341629054
- Sigstore integration time:
-
Permalink:
arshadvani3/Regress@664a91f74ab2bdff439a4843e4f6698896494f10 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/arshadvani3
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@664a91f74ab2bdff439a4843e4f6698896494f10 -
Trigger Event:
push
-
Statement type: