evalmine
evalmine
Leaderboard-Zahlen haben noch nie vorhergesagt, wie sich eine Modelländerung auf die rund vierzig Aufgaben auswirkt, die du tatsächlich ausführst. Eines schneidet bei einem Benchmark am besten ab, du tauschst es ein, und es ist bei der Aufgabe, von der du abhängst, leise schlechter.
evalmine beantwortet eine Frage zu einer Modelländerung, auf deinen Aufgaben: Hat sie geholfen, geschadet oder mehr gekostet für dasselbe Ergebnis? Du schreibst eine YAML-Suite deiner Aufgaben. Sie führt sie über zwei oder mehr Modelle aus, prüft jede Antwort gegen das Schema, misst die Zeit und lässt einen LLM-Judge die Antworten paarweise in beiden Reihenfolgen vergleichen, sodass sich die Präferenz des Judges für das, was er zuerst sieht, aufhebt. Sie bewertet diesen Judge anhand deiner Präferenzlabels mit Cohens Kappa und weigert sich, eine Gewinnrate als Schlagzeile zu präsentieren, wenn sie nicht zeigen kann, dass der Judge dir zustimmt. Die Kosten stammen aus einer Preistabelle, die auf ein Datum festgelegt ist; ein unbekanntes Modell lässt den Lauf fehlschlagen, anstatt $0 zu kosten. Berichte werden nach Suite-Hash versioniert; ein MCP-Server mit drei Tools ermöglicht es einem Agenten, die Evals mitten in der Aufgabe auszuführen.
Ergebnis, bei der hier enthaltenen Beispielsuite gegen den Fake-Adapter: Kappa 0,25 über 12 Labels liegt unter der 0,40-Schwelle, also wird die 0,463-Gewinnrate markiert gedruckt, nicht als Schlagzeile. Diese Weigerung ist das Werkzeug, das funktioniert:
$ evalmine run examples/everyday-eight.yaml \
--models anthropic/claude-haiku-4-5,google/gemini-2.5-flash --fake
run 20260823T210009Z_c4545e4e_dbc76614 (everyday-eight)
report: reports/everyday-eight/20260823T210009Z_c4545e4e_dbc76614/report.md
calibration: below_floor - kappa 0.25 (fair) over 12 labels - headline eligible: false
google/gemini-2.5-flash vs anthropic/claude-haiku-4-5: win-rate 0.463 (UNCALIBRATED) [0.325-0.613] over schema-passing pairs only, n=20 - flips 3 - excluded 0
cost: $0.0658 this run (answers $0.0081, judge $0.0578); if uncached $0.0658Der Fake-Adapter ist deterministisch, daher lassen sich diese Zahlen bei einem sauberen Checkout exakt reproduzieren. Nichts oben hat einen Anbieter kontaktiert oder einen Cent ausgegeben.

Jedes Bild davon ist ein echter Lauf. Nimm es mit vhs docs/demo.tape neu auf
(vhs, brew install vhs).
Status. v0.1.0, Vorabversion. Der Kern, die drei Provider-Adapter, Ausführungsprüfungen und die MCP-Oberfläche sind gebaut und getestet; die Preistabelle ist gegen die öffentliche Preisseite jedes Anbieters an ihrem festgelegten Datum verifiziert. Es gibt noch keinen Entscheidungslog-Eintrag — siehe Noch nicht.
Spezifikation: docs/spec.md. Sie ist der Vertrag, gegen den der Code geschrieben ist, und sie gewinnt gegenüber dieser README, wo immer die beiden abweichen. So funktioniert es im Detail: docs/learning/how-it-works.md (gestylte HTML-Darstellung).
Schnellstart
git clone https://github.com/hishamalward/evalmine.git && cd evalmine
python -m venv .venv && . .venv/bin/activate
pip install -e ".[dev]" # add ,mcp -> ".[dev,mcp]" for the MCP serverPython 3.10 oder neuer. Drei Laufzeitabhängigkeiten: PyYAML, jsonschema, httpx.
Überprüfe eine Suite, ohne etwas auszugeben. validate parst die Datei, wendet das JSON-Schema an, rendert jeden Prompt (ein nicht übereinstimmender {{placeholder}} ist ein harter Fehler) und löst jeden Modellstring gegen die Preistabelle auf. Null Netzwerkaufrufe.
evalmine validate examples/everyday-eight.yaml
# ok: examples/everyday-eight.yaml - 8 tasks, 20 cases, 12 labels; every prompt
# rendered; 3 model strings resolved against prices-2026-08-23.yamlFühre sie gegen den Fake-Adapter aus. --fake leitet jeden Modellstring an einen eingebauten deterministischen Adapter weiter: kein Schlüssel, kein Netzwerk, keine Ausgaben. Die beiden Modellstrings unten sind diejenigen, auf die sich die zwölf menschlichen Labels der Beispielsuite beziehen, sodass dieser Lauf den Kalibrierungspfad Ende-zu-Ende durchläuft.
evalmine run examples/everyday-eight.yaml \
--models anthropic/claude-haiku-4-5,google/gemini-2.5-flash --fakeFühre sie wirklich aus. Schlüssel kommen aus der Umgebung und von sonst nichts. Kopiere .env.example, fülle sie außerhalb des Repos aus und exportiere, was du brauchst.
export ANTHROPIC_API_KEY=...
export GOOGLE_API_KEY=...
evalmine run examples/everyday-eight.yaml \
--models anthropic/claude-haiku-4-5,google/gemini-2.5-flash \
--max-cost 0.50Vor dem ersten Live-Aufruf läuft eine Vorab-Schätzung. Wenn sie --max-cost überschreitet, wird der Lauf verweigert (Exit 4) und nichts ausgegeben. Ohne ein Limit irgendwo ist der CLI-Standard $2,00. Jeder Aufruf wird auf der Festplatte nach Inhalts-Hash zwischengespeichert, sodass ein erneuter Lauf kostenlos ist und ein Bericht reproduzierbar ist; --no-cache erzwingt frische Aufrufe und schreibt sie trotzdem.
Andere Befehle: evalmine prices [--for suite.yaml], evalmine last suite.yaml,
evalmine report <run-id>, evalmine compare <report_a> <report_b>.
Related MCP server: Coval MCP Server
Die Suite-Datei
Eine YAML-Datei enthält deine Aufgaben, die Judge-Konfiguration und deine Labels. Das mitgelieferte Beispiel ist examples/everyday-eight.yaml: acht erfundene Aufgaben (umschreiben, extrahieren, klassifizieren, erklären, kleine Codeänderung) über zwanzig Fälle, drei davon mit einem Ausgabeschema, mit zwölf Präferenzlabels. Das vollständige Schema ist Spezifikation §5; die Form ist:
suite: everyday-eight
version: 1
defaults: { temperature: 0, max_tokens: 700, timeout_s: 60 }
limits: { max_cost_usd: 1.50 }
judge:
model: anthropic/claude-sonnet-4-6
rubric: |
Prefer the answer that a competent colleague would ship without editing.
...
calibration: { min_kappa: 0.40, min_labels: 10, on_below_floor: flag }
tasks:
- id: ticket-triage
kind: classify # a free label, used only to group report rows
prompt: |
Classify this support ticket. Return JSON only.
Ticket:
{{ticket}}
schema: { type: object, required: [category, severity], ... }
rubric: | # appended to the suite rubric for this task
In addition to the suite rubric: ...
cases:
- id: charged-twice
vars: { ticket: "I was charged twice this month..." }
labels:
- { task: ticket-triage, case: charged-twice,
baseline: anthropic/claude-haiku-4-5,
candidate: google/gemini-2.5-flash,
prefer: candidate, note: "team-wide lockout is high, not medium" }Drei Dinge an dieser Datei sind beabsichtigt:
Templating ist nicht Jinja. Genau
{{name}}, einmal ersetzt, keine Ausdrücke und keine Filter. Ein Platzhalter ohne passende Variable ist ein harter Fehler beim Laden, denn eine stillschweigend leere Variable ist der einfachste Weg, ein Eval leise bedeutungslos zu machen.Unbekannte Schlüssel sind Fehler, auf jeder Ebene. Ein vertipptes
rubrik:, das ignoriert wird, erzeugt einen Bericht, der gut aussieht und nichts bedeutet.labelsist die Quelle der Glaubwürdigkeit des Tools. Sie sind deine Urteile, aufgezeichnet, bevor du die Gewinnrate siehst, und der Judge wird gegen sie bewertet. Eine Suite ohne Labels läuft trotzdem; sie kann nur keine Schlagzeilenzahl erzeugen.
Ersetze das Beispiel durch deine eigenen Aufgaben. Das ist der ganze Sinn des Tools.
Ausführungsprüfungen für Code-Aufgaben
Prosa ist ein schlechter Stellvertreter für Code, der läuft. Ein Fall kann einen check deklarieren: ein Bash-Schnipsel, der den Code der Antwort erhält ($ANSWER ist eine Datei, $ANSWER_TEXT der
Text) und mit 0 endet, wenn er funktioniert. Er läuft in einem frischen Temp-Verzeichnis, unter einem Timeout,
mit aus der Umgebung entfernten Geheimnissen, und wird nie zwischengespeichert. Jeder umzäunte
Block in der Antwort läuft, in Reihenfolge, jeder auf seiner eigenen Fixture; der letzte Block ist
das Urteil und die früheren werden daneben aufgezeichnet, sodass eine Antwort, die
einen falschen Block zurückzieht und einen zweiten schreibt, auf dem zweiten bewertet wird und
den Rückzug zeigt.
- id: jq-remote
vars: { task: "Write a jq filter ... the JSON is in postings.json" }
check:
setup: 'printf "[{\"t\":\"a\",\"remote\":true}]" > postings.json'
run: 'jq -r "$(cat "$ANSWER")" postings.json | grep -q a'Das Ergebnis — bestanden/nicht bestanden, Exit-Code, Ausgabe — steht neben der Antwort in
answers.jsonl, der Scorecard und der HTML-Paaransicht, und dem Judge wird es
mit einer festen Regel gezeigt: Eine Antwort, deren Prüfung fehlgeschlagen ist, kann eine bestandene nicht schlagen. Spezifikation §6.6.
So liest man einen Bericht
reports/<suite>/<run-id>/report.md zusammen mit report.json, report.html,
answers.jsonl und pairs.jsonl. Lies ihn in dieser Reihenfolge.
1. Kalibrierung, zuerst. Sie wird absichtlich über den Gewinnraten gedruckt. Du willst Cohens Kappa zwischen den Urteilen des Judges und deinen Labels, mit seinem Landis-Koch-Bandnamen dazu, und die 3x3-Konfusionsmatrix darunter. Kappa statt einfacher Übereinstimmung, weil Übereinstimmung aufgebläht wird, sobald eine Kategorie dominiert, und das wird sie: Judges lernen, dass Gleichstände sicher sind. Die Matrix sagt dir, wie der Judge falsch liegt, was wichtig ist — ein Judge, der nie "Gleichstand" sagt, wenn du es tust, ist ein anderes Problem als einer, der systematisch bevorzugt, was neu ist. Darunter zeigt dir eine Aufschlüsselung nach Aufgabe, wo: Ein Kappa kann einen Judge verbergen, der bei deiner Umschreibaufgabe ausgezeichnet und bei deiner Triage-Aufgabe nutzlos ist, und der Durchschnitt ist die Erkenntnis, die du verlieren würdest.
2. Eine Gewinnrate, der du nicht vertrauen solltest. Drei Bedingungen, jede einzelne reicht:
headline_eligible: false— Kappa liegt unter der Schwelle, es gibt zu wenige Labels, oder Kappa ist undefiniert, weil beide Bewerter durchgehend eine Kategorie verwendet haben. Der Bericht verbietet, dass die Zahl eine Schlagzeile wird, markiert jede Zahl mit einem Dolch, und die JSON- und jede MCP-Antwort tragen dieselbe Markierung, sodass ein Agent, der die Zusammenfassung liest, die Zahl nicht ohne den Vorbehalt zitieren kann.Flip-Rate über 0,30. Ein Flip ist ein Paar, bei dem der Judge seine Antwort geändert hat, als die beiden Antworten die Plätze tauschten. Über etwa einem Drittel misst die Gewinnrate Präsentationsreihenfolge, nicht Qualität. Der Bericht sagt das in derselben Tabelle.
Ein kleines
noder ein schrumpfendes. Die Gewinnrate wird über nur schema-bestandene Paare berechnet: Ein Paar, bei dem eine Seite nicht geparst oder ihr Schema nicht bestanden hat, wird ausgeschlossen, nicht als Niederlage gewertet, sodass ein Modell, das schlecht darin ist, JSON auszugeben, keinen Qualitätsvergleich für einen Formatierungsfehler verliert. Der Preis ist, dassnschrumpft, weshalb der Abschnitt "nur über schema-bestandene Paare, n=…" betitelt ist undnnie ohne die Schema-Bestehensrate auf demselben Bildschirm gedruckt wird.
Bevor du eine Zahl veröffentlichst, erhöhe min_kappa auf 0,60. Der mitgelieferte Standard ist
0,40 — die übliche Untergrenze für faire bis moderate Übereinstimmung, niedrig genug, dass eine erste
Suite mit einem Dutzend Labels sie plausibel überschreiten kann. Das ist die Schwelle für eine Zahl selbst zu verwenden, mit deiner eigenen Erinnerung daran, wie die Kennzeichnung lief. 0,60 —
"substanziell" — ist die Schwelle für jemand anderem eine Zahl zu sagen, wo diese Erinnerung
nicht mitreist. Das Tool wird großzügig ausgeliefert, damit eine erste Suite es wert ist, zweimal ausgeführt zu werden; diese Empfehlung existiert, damit eine erste Suite nicht in einem Blogbeitrag landet.
3. Dann die Scorecard, und lies Kosten mit Qualität, nie danach. Schema-Bestehensrate (als native oder prompted gekennzeichnet, weil ein Anbieter, der ein Schema für dich durchsetzt, und einer, der nur höflich gebeten wurde, nicht dieselbe Messung sind), die Exec-Bestehensrate mit ihrem n, wo eine Aufgabe Ausführungsprüfungen deklariert, p50- und p95-Latenz mit
ihrem n, Kosten für diesen Lauf und Kosten, wenn nicht zwischengespeichert. Ein Kandidat, der
0,55 für das Dreifache des Geldes gewinnt, ist eine andere Entscheidung als einer, der 0,55 für die Hälfte gewinnt.
4. Die Tabelle nach Aufgabe, schlechteste zuerst. Eine Schlagzeilen-Gewinnrate, die sich nicht bewegt hat, während sich drei Aufgaben um 0,4 in entgegengesetzte Richtungen bewegten, ist die Erkenntnis, die du sonst verpassen würdest. evalmine compare A B druckt genau diese Bewegungen zwischen zwei Läufen.
5. report.html und der Kennzeichnungsablauf. Jeder Lauf schreibt auch eine
in sich geschlossene Seite — kein Server, keine Abhängigkeiten, öffnet sich über einen file://-Pfad. Gleiche
Abschnitte, plus jedes bewertete Paar nebeneinander mit den Modellnamen verborgen und dem Urteil des Judges weggeklappt, sodass du die Antworten genau so liest, wie der Judge sie gelesen hat. A bevorzugen · Gleichstand · B bevorzugen unter jedem, dann Labels-YAML kopieren gibt dir die
labels:-Einträge zum Einfügen in deine Suite: zehn Minuten Klicken statt
einer halben Stunde manuelles Bearbeiten, was den Unterschied zwischen einer Kalibrierungsmenge ausmacht, die wächst, und einer, die es nicht tut.
Der Bericht enthält keine Adjektive und gibt keine Empfehlung. Urteile kommen in DECISIONS.md, formuliert aus deinem Urteil — der Bericht füllt die Vorlage für dich am Ende jedes Laufs vor.
MCP
evalmine-mcp ist ein stdio-MCP-Server, der genau drei Tools bereitstellt, die dieselben core.py-Funktionen aufrufen, die auch die CLI aufruft:
tool | tut | gibt aus |
| führt die Suite aus, gibt die Zusammenfassung und die Berichtspfade zurück | bis zum Limit |
| die Differenz zwischen zwei Berichten | nichts |
| den neuesten Bericht für eine Suite | nichts |
Registriere ihn, indem du .mcp.json.example nach .mcp.json kopierst. Installiere zuerst das Extra: pip install -e ".[mcp]".
Der Punkt ist, dass ein Agent deine Evals mitten in der Aufgabe ausführen kann — "bevor du das Modell in dieser Datei austauschst, führe die Suite aus und sag mir die Gewinnrate" — statt dass eine Person danach einen Bericht liest.
Drei Tools statt der gesamten CLI, weil eine agentenorientierte Oberfläche die kleinste Menge an Verben sein sollte, die die Entscheidung unterstützt, und jedes zusätzliche Tool ist eine weitere Möglichkeit, Geld auszugeben, das niemand autorisiert hat.
Die Limits und warum der Standard des Agenten niedriger ist als deiner. Das Limit ist ein Parameter
von core.run_suite(), kein CLI-Flag, das MCP neu implementiert: Es gibt genau eine
Stelle, an der Geld ausgegeben werden kann, und dort ist es begrenzt. Wenn der Agent
max_cost liefert, wird es verwendet, aber eine Anfrage über EVALMINE_MCP_MAX_COST_CEILING ($5,00 standardmäßig)
wird rundweg abgelehnt, nicht geklemmt und ausgeführt. Wenn der Agent es weglässt, ist das Limit min(suite.limits.max_cost_usd, EVALMINE_MCP_MAX_COST), standardmäßig $1,00 —
die Hälfte der $2,00 der CLI, weil der Mensch an der CLI die Zahl getippt hat und der Agent nicht. Ein Lauf über dem Limit gibt eine strukturierte Ablehnung zurück, gibt nichts aus und wird nie stillschweigend gekürzt, um zu passen; ein gekürzter Lauf erzeugt eine kleinere Zahl, die wie eine vollständige aussieht.
run_suite gibt die Zusammenfassung und die Pfade zurück, niemals rohe Provider-Antworten. Diese bleiben in answers.jsonl auf der Festplatte. Ein Tool, das jede Antwort zurück in den Kontext eines Agenten streamt, kostet den Aufrufer mehr als die Auswertung selbst und verwandelt eine Eval-Harness in einen Exfiltrationspfad für alles, was in deinen Prompts steht. suite_path muss ebenfalls innerhalb von EVALMINE_MCP_SUITE_ROOT aufgelöst werden (Standard: das Arbeitsverzeichnis des Servers).
Verwandte Arbeiten
promptfoo und Braintrust sind die offensichtlichen Werkzeuge hier, und beide sind leistungsfähiger als dieses.
promptfoo hat weitaus mehr Assertion-Typen, einen Web-Viewer, Red-Teaming und eine Provider-Abdeckung, die nicht nur drei ist. Braintrust ist eine gehostete Plattform: Tracing, Datensätze aus Produktionslogs, eine echte UI, Zusammenarbeit und die operative Reife, die damit einhergeht, das Produkt von jemandem zu sein. Wenn du Breite willst oder ein Team, das auf dieselben Zahlen schaut, nimm eines von denen.
evalmine existiert aus drei engeren Gründen.
Der Richter ist gegen dich kalibriert, oder seine Zahl wird nicht gedruckt. Beide oben genannten können mit einem LLM-Richter bewerten. Keiner macht die Kalibrierung auf deine Labels zur Bedingung dafür, ob eine Gewinnrate zitierbar ist. Diese Umkehrung – die Verweigerung als Standard – ist die ganze These, und es ist kein Feature, das man an ein Tool anflanschen kann, das die Zahl trotzdem liefert.
Das Entscheidungsprotokoll ist ein Artefakt erster Klasse. Die Ausgabe einer Auswertung ist keine Zahl, sondern eine Entscheidung, die du in sechs Monaten verteidigen musst.
DECISIONS.mdwird vom Bericht vorausgefüllt und von einem Menschen geschrieben, und es liegt in deinem Repository neben dem Code, um den es bei der Entscheidung ging.Die Oberfläche ist klein genug, um sie in einer Sitzung zu lesen. Ungefähr 6.000 Zeilen einschließlich vier Adaptern, der Berichte und der Ausführungsprüfungen. Kein LLM-Framework, keine Provider-SDKs – drei handgeschriebene POSTs an dokumentierte JSON-Endpunkte. Diese Kosten sind real und es lohnt sich, sie zu benennen: Wenn ein Provider seine API ändert, erfahren wir es durch einen Bruch, nicht durch ein Upgrade.
Wenn dir diese drei nicht wichtig sind, ist die ehrliche Empfehlung promptfoo.
Noch nicht
Nicht im Umfang von v0.1.0, und die README sagt das, anstatt dich es selbst entdecken zu lassen: RAG- oder Retrieval-Eval; Agent- oder Multi-Turn-Trajektorien; Feintuning von irgendetwas; eine Web-UI; alles Gehostete; mehr als drei Provider; automatische Rubrik-Generierung; MCP-Tools über die drei oben genannten hinaus.
Jede Zahl in dieser README stammt vom Fake-Adapter auf der erfundenen Beispiel-Suite. Noch kein beschrifteter Lauf auf einer echten Suite hat eine kalibrierte Zahl oder einen DECISIONS.md-Eintrag erzeugt; das kommt vor jedem v0.1.0-Tag.
Entwicklung
pip install -e ".[dev,mcp]"
python -m pytest -q # 310 tests, none of which make a network call
python -m ruff check src testsCI läuft auf {ubuntu, macos, windows} x {3.10, 3.13}, jeder Zweig führt jeden Test aus, plus einen Secret-Scan über den Arbeitsbaum und die vollständige Git-Historie. Kein API-Schlüssel gehört in dieses Repository, und evalmine run weigert sich zu starten, wenn eine Suite-Datei eine Zeichenkette enthält, die mit einem bekannten Schlüsselpräfix übereinstimmt.
Siehe CONTRIBUTING.md. Änderungen beginnen in docs/spec.md.
Lizenz
MIT. Siehe LICENSE.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
AlicenseNot gradedqualityCmaintenanceProvides advanced evaluation tools for assessing AI safety, alignment, and performance of LLM outputs. Enables programmatic evaluation of quality, safety metrics like toxicity and PII detection, and operational metrics including carbon footprint and cost estimation.4Apache 2.0
Coval MCP Serverofficial
AlicenseAqualityBmaintenanceEnables AI assistants to interact with Coval's evaluation platform for launching and monitoring evaluation runs, managing agents and test sets, and retrieving evaluation metrics.18331MIT- AlicenseNot gradedqualityAmaintenanceEnables LLM evaluation and observability by uploading documents, building test sets, running RAG pipelines, and automatically scoring answers for groundedness, hallucination risk, retrieval quality, latency, and cost, with tools exposed to MCP-compatible clients.1MIT
- AlicenseNot gradedqualityBmaintenanceExposes a run_suite tool to evaluate whether an AI agent is safe to operate internal web apps, scoring task completion and forbidden-action violations to gate CI/CD pipelines.361Apache 2.0
Related MCP Connectors
Build, validate, and deploy multi-agent AI solutions from any AI environment.
See, price, and control every tool call your AI agents make: policy checks, cost, and audit tools.
Runtime permission, approval, and audit layer for AI agent tool execution.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/hishamalward/evalmine'
If you have feedback or need assistance with the MCP directory API, please join our Discord server