____ ______ __
/ __ \____ ___ ____ / ____/___ ____/ /____
/ / / / __ \/ _ \/ __ \/ __/ / __ \/ __ / ___/
/ /_/ / /_/ / __/ / / / /___/ / / / /_/ (__ )
\____/ .___/\___/_/ /_/_____/_/ /_/\__,_/____/
/_/
Model-agnostic LLM evaluation that feels like pytest.
Install
pip install openeval-ai
Optional extras:
pip install "openeval-ai[openai]" # OpenAI adapter
pip install "openeval-ai[anthropic]" # Anthropic adapter
pip install "openeval-ai[semantic]" # semantic_sim scorer
Quickstart (10 lines, zero config)
from openeval import EvalCase, run
from openeval.scorers import exact_match
cases = [EvalCase(input="2+2", expected_output="4")]
def my_model(prompt: str) -> str:
return "4"
summary = run(my_model, cases, {"exact": exact_match})
print(summary.pass_rate) # 1.0
Why OpenEval
- Scorers are just Python functions — composable, testable, versionable.
- Model-agnostic — OpenAI, Anthropic, Ollama, or any callable.
- CI-first — pytest plugin + GitHub Action for evals on every PR.
Architecture
flowchart LR
M[Your Model] --> A[Adapter]
A --> R[Runner / Async Runner]
R --> S[Scorers]
S --> E[EvalSummary]
E --> H[HTML Report]
E --> C[CLI]
E --> G[GitHub Action]
Comparison (benchmarks)
Benchmarks live in benchmarks/ and use a fully offline mock model for reproducibility.
Measured on 2026-03-20 with uv run benchmarks/run_all.py (see benchmarks/results.json).
Task A: 20-case Q&A (exact match), mock model with 10ms latency per call.
| Tool | Setup (LOC) | Setup time (s) | Run time (s) | Notes |
|---|---|---|---|---|
| OpenEval | 38 | 0.090 | 0.203 | ✅ |
| DeepEval | 44 | 2.250 | 0.261 | ✅ |
| Promptfoo | 50 | — | — | not run |
Notes:
- Promptfoo is optional in the harness; set
OPENEVAL_BENCH_PROMPTFOO=1to run it. - Promptfoo may require Node.js
>=20.20.0or>=22.22.0(newer thanv22.17.x).
Built-in scorers
| Scorer | What it does |
|---|---|
exact_match |
1.0 if output equals expected |
contains |
1.0 if expected appears in output |
regex(pattern) |
1.0 if output matches a regex |
semantic_sim |
cosine similarity via embeddings (optional extra) |
llm_judge(judge_fn) |
judge output quality 0.0–1.0 (bring your own judge) |
Built-in suites
| Suite | What it tests |
|---|---|
hallucination |
admits uncertainty vs fabricates |
factuality |
basic factual QA |
instruction_following |
formatting/constraint compliance |
Run a suite:
from openeval.suites import factuality
summary = factuality.run(lambda _: "Paris")
print(summary.pass_rate)
GitHub Action
# .github/workflows/eval.yml
name: LLM Eval
on: [pull_request]
jobs:
eval:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: OWNER/openeval-action@v1 # replace OWNER
with:
suite: hallucination
model: openai:gpt-4o-mini
threshold: "0.8"
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CLI
# Run a suite
openeval run --suite factuality --model ollama:llama3.2
# Parallel (async) + HTML report
openeval run --suite hallucination --model openai:gpt-4o-mini --async --concurrency 20 --output report.html
Async evaluation
import asyncio
from openeval import EvalCase, arun
from openeval.scorers import exact_match
cases = [EvalCase(input="2+2", expected_output="4")]
async def model(_prompt: str) -> str:
return "4"
summary = asyncio.run(arun(model, cases, {"exact": exact_match}, concurrency=20))
print(summary.pass_rate)
Examples
examples/01_basic_qa.pyexamples/02_openai_eval.pyexamples/03_compare_models.pyexamples/04_rag_eval.pyexamples/05_chatbot_eval.pyexamples/06_code_eval.pyexamples/07_custom_scorer.pyexamples/08_cicd_integration.py
Contributing
See CONTRIBUTING.md.
License
MIT — see LICENSE.
Metadata
Release files for openeval-ai 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| openeval_ai-0.1.0.tar.gz | 136.9 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| openeval_ai-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 167.0 kB
Release files / openeval_ai-0.1.0.tar.gz
| Download URL | openeval_ai-0.1.0.tar.gz |
|---|---|
| Size | 136.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
dd46eb0735cb57e56bad113ab639f7dd55fdc9ff4cb478913e7eead16ee6bd0e
|
|
BLAKE2b-256 checksum How to use checksums |
b4753babdb08da4766cd781320268fefc9b36933753220993d5ac593a3e0113c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.7.6
|
Release files / openeval_ai-0.1.0-py3-none-any.whl
| Download URL | openeval_ai-0.1.0-py3-none-any.whl |
|---|---|
| Size | 30.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
120ad8c7e589d983fd0ba535040bc736ce9851059fc3790cd9c2b579cfec43bc
|
|
BLAKE2b-256 checksum How to use checksums |
89b6f8197e70a1e635f61741a1637e8e24f71d6b82c6a7dd3f7b350355046957
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.7.6
|
Security for openeval-ai 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.