Skip to main content
Glama

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.0658

Der 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.

evalmine: Validiere die Suite, führe sie gegen den Fake-Adapter aus, lies die Kalibrierungs- und Gewinnraten-Abschnitte des Berichts, den es geschrieben hat

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 server

Python 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.yaml

Fü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 --fake

Fü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.50

Vor 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.

  • labels ist 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 n oder 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, dass n schrumpft, weshalb der Abschnitt "nur über schema-bestandene Paare, n=…" betitelt ist und n nie 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

run_suite(suite_path, models, max_cost, baseline, no_cache)

führt die Suite aus, gibt die Zusammenfassung und die Berichtspfade zurück

bis zum Limit

compare(report_a, report_b)

die Differenz zwischen zwei Berichten

nichts

last_report(suite_path)

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.md wird 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 tests

CI 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.

A
license - permissive license
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

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

  • A
    license
    Not graded
    quality
    C
    maintenance
    Provides 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.
    4
    Apache 2.0
  • A
    license
    A
    quality
    B
    maintenance
    Enables AI assistants to interact with Coval's evaluation platform for launching and monitoring evaluation runs, managing agents and test sets, and retrieving evaluation metrics.
    18
    33
    1
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables 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.
    1
    MIT

View all related MCP servers

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.

View all MCP Connectors

Latest Blog Posts

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