dj-evals
Internal Django helper for running one eval function with multiple argument sets in parallel, so you can visually compare output, tool calls, usage, cost, and completion behavior as the runs happen.
Django setup
Add dj_evals to INSTALLED_APPS:
INSTALLED_APPS = [
"dj_evals",
]
Create one view that connects the package to your project. This is the only view required by dj-evals:
from django.contrib.admin.views.decorators import staff_member_required
from dj_evals import handle_eval_request
@staff_member_required
async def eval_run(request):
return await handle_eval_request(
request,
allowed_paths={"myapp.evals.echo_eval"},
# evaluation_model="meta/muse-spark-1.2-contributor", # Optional.
)
Mount that view in your URL configuration:
from django.urls import path
urlpatterns = [
path("evals/run/", eval_run, name="eval-run"),
]
Replace staff_member_required with your project's authorization check if staff-only access is not appropriate.
Link to eval suites
A project can have a small page that lists its eval suites. Use generate_eval_url() to build the URL behind each link:
from django.contrib.admin.views.decorators import staff_member_required
from django.shortcuts import render
from django.urls import reverse
from dj_evals import generate_eval_url
@staff_member_required
def eval_index(request):
question = (
"Give me 7 tips to improve my game in chess. "
"My ELO is 500. I make lots of blunders."
)
url = reverse("eval-run") + generate_eval_url(
"myapp.evals.echo_eval",
{
"model": "gpt-5.6-terra",
"question": question,
},
{
"model": "gpt-5.6-luna",
"question": question,
},
# Optional. Requires the configured evaluation model's API key.
expectations=[
"Don't leave things hanging",
"Castle early",
"The answer mentions using a checklist",
"The checklist is something simple yet effective",
],
)
return render(
request,
"eval_index.html",
{"eval_suites": [("Chess tips for beginners", url)]},
)
Render those URLs as normal links in eval_index.html:
{% for name, url in eval_suites %}
<a href="{{ url }}">{{ name }}</a>
{% endfor %}
Clicking the link opens the comparison page. Use Run all to start one POST request per argument set and render the streamed results side by side.
Expectations and Auto-rate use meta/muse-spark-1.2 through OpenRouter by default. OpenRouter model IDs (provider/model) use OPENROUTER_API_KEY; direct OpenAI model names use OPENAI_API_KEY.
Auto-rate scores completed runs and shows a detailed comparison. Re-judge checks the current expectations against those outputs without rerunning the evals.
Eval function contract
The eval function must be importable by dotted path and whitelisted in allowed_paths. It can be a sync or async function that returns one event, or an async generator that yields events.
def echo_eval(question="hello", model=""):
return question
async def async_eval(question="hello", model=""):
return question
async def streaming_eval(question="hello"):
yield {"type": "response.output_text.delta", "delta": question}
yield {"type": "response.output_text.done", "text": question}
yield {"type": "response.completed", "response": {"cost": 0}}
Eval argument dictionaries are passed to the eval function as keyword arguments. OpenAI Responses API events have first-class rendering for output text, reasoning, and tool calls.
Helper utilities
Split eval arguments
split_eval_arguments() separates arguments shared by every run from the arguments that differ:
from dj_evals import split_eval_arguments
common, different = split_eval_arguments(
{"company": "Avantel", "model": "fast"},
{"company": "Avantel", "model": "expert"},
)
Here, common is {"company": "Avantel"} and different contains the two model arguments.
Progress messages
You can yield EvalEvent for custom progress messages in the output panel:
from dj_evals import EvalEvent
async def streaming_eval():
event: EvalEvent = {
"type": "dj_evals.event",
"message": "Fetched documents",
}
yield event
Developers
Run a local demo server to try the library in a browser:
uv run --with daphne daphne -p 8003 examples.local_server:application
# or, if you have just installed:
just run
Then open http://127.0.0.1:8003/ and choose an example. The OpenAI example uses OPENAI_API_KEY; expectations use OPENROUTER_API_KEY.
Run checks from this repo:
uv run --with ruff ruff check .
uv run --with pytest --with pytest-asyncio pytest -q
# or, if you have just installed:
just test
Metadata
Release files for dj-evals 0.10.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| dj_evals-0.10.1.tar.gz | 105.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| dj_evals-0.10.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 205.5 kB
Release files / dj_evals-0.10.1.tar.gz
| Download URL | dj_evals-0.10.1.tar.gz |
|---|---|
| Size | 105.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d5c0dd672144694d4c8651c5b5ca363bff235fa10ae5ad5de93bcd46c444dacc
|
|
BLAKE2b-256 checksum How to use checksums |
ba15499981cf64a2301875360f69d598e839db069778982c222615f863df7e58
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / dj_evals-0.10.1-py3-none-any.whl
| Download URL | dj_evals-0.10.1-py3-none-any.whl |
|---|---|
| Size | 99.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e8409f622c72e29ebf5c057d705e9df5759e0e4c5e0a859aa4f1ee87ad4840ae
|
|
BLAKE2b-256 checksum How to use checksums |
71d92fcd68f3e6a2136fceab2cd3fd912ac3583b29a557462499e98d0935ba58
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|