Onboarding: Chapter "Evals" — Analysis Evals (References-Extraktion)
Lies dieses Dokument zuerst. Es ist deine Landkarte, bevor du irgendein Issue anfasst. Danach liest du das Glossar (weiter unten, vollständig eingebettet) — dort sind alle Domänen- und Eval-Begriffe erklärt. Erst dann öffnest du die einzelnen Tasks.
Big Picture
Tender-Zen ist eine multi-tenant SaaS-Plattform, die deutsche öffentliche Bauausschreibungen aggregiert und mit AI-Analyse die relevanten Informationen aus den Ausschreibungsunterlagen extrahiert. Eines der wichtigsten Extraktionsziele ist die Anforderung an Referenzen (geforderter Nachweis vergleichbarer Projekte) — sie entscheidet oft darüber, ob ein Nutzer eine Ausschreibung verfolgt oder verwirft (Pursue-or-Skip). Eine falsche Extraktion kann teuer werden: Die Vergabe ist ein high-stakes Echtgeld-Kontext.
Das Chapter "Evals" beantwortet eine einzige, aber zentrale Frage:
Wie gut ist diese AI-Extraktion wirklich — und merken wir sofort, wenn sie schlechter wird?
Heute haben wir darauf keine belastbare Antwort. Es gibt kein eval harness, keinen golden dataset, keine Scores. Wenn jemand den Extraktions-Prompt ändert oder das Modell wechselt, fliegt jede Verschlechterung blind durch. Das Chapter "Evals" baut die Antwort von Grund auf — beginnend mit einem bewusst schlanken v1.
Das Chapter hat zwei Epics:
- Analysis Evals — References-Extraktion (slug
analysis-evals) — der Fokus dieses Onboardings. Misst die Qualität der References-Extraktion aus Ausschreibungen. - Workspace Agent Eval — Tool-Use (slug
workspace-agent-eval) — eine separate, parallele Eval-Spur für den Workspace-Agenten (Tool-Use statt single-shot Extraktion). Wird hier nur eingeordnet, nicht detailliert.
Beide Epics liegen als GitHub Issues im Repo getzenai/tender-zen (nach der /req-Convention). Der Eval-Code lebt innerhalb von tender-zen unter evals/references/.
Background & Key Terms
Bevor du weiterliest: Die vollständige Begriffswelt — deutsches Vergabewesen (Domäne) und Eval-/AI-Engineering (Technik) — steht im Glossar ganz unten in diesem Dokument. Lies es einmal komplett durch. Die wichtigsten Begriffe in einem Satz:
- Ausschreibung = unser Input-Artefakt (das Dokument, woraus extrahiert wird).
- Anforderung an Referenzen = das Kern-Extraktionsziel (Anzahl, Mindestvolumen, Zeitraum, Leistungsart geforderter Referenzprojekte).
- ground truth = die als korrekt definierte Soll-Antwort eines Testfalls.
- human-anchored ground truth = ground truth, die ein Mensch festgelegt/verifiziert hat (nicht ein anderes Modell).
- LLM-as-judge / judge = ein Modell bewertet den Output eines anderen Modells (statt sprödem Exact-Match).
- format variance = inhaltlich gleich, formal verschieden — der Grund, warum wir einen judge statt String-Vergleich brauchen.
- single-shot = eine Inferenz, eine Antwort, keine Loops. So läuft die References-Extraktion in Produktion.
- prompt parity = Eval-Prompts sind identisch zu Produktions-Prompts.
Confirmed v1 vs. Phase 2
Was v1 ist (und bewusst NICHT ist)
v1 ist eine bewusst schlanke, manuelle / Claude-Code-getriebene Schleife auf nur 3 Ausschreibungen:
- Architektur
- BIM
- Softwareentwicklung
Es gibt in v1 kein automatisiertes Framework, kein DeepEval, keinen OpenRouter-Router, kein automatisches leaderboard und kein CI-regression-gate. Diese schwere Engineering-Arbeit ist Phase 2 und baut auf v1 auf — nicht parallel, nicht stattdessen. v1 beweist erst manuell, dass das Konzept trägt (vor allem: dass der judge zuverlässig ist), bevor wir industrialisieren.
Der Wert von v1: Wir lernen mit minimalem Aufwand, ob ein LLM-as-judge deutsche Vergabe-/References-Terminologie verlässlich gegen eine human-anchored ground truth scoren kann. Das ist die make-or-break-Frage (siehe unten).
Die v1-Schleife (4-Ordner-Loop)
1. original/ → Original-Ausschreibung (Input) liegt bereit
2. validation/ → ground truth wird per Convergence-Deep-Review erstellt (Soll)
3. llm-extraction/ → tender-zen extrahiert (single-shot, Gemini) → Output (Ist)
4. judge/ → LLM-as-judge vergleicht Ist gegen Soll → Score + BegründungDiese Schleife läuft pro Ausschreibung. Am Ende hast du für jede der 3 Ausschreibungen einen Score plus eine nachvollziehbare Begründung — und einen menschlichen Spot-Check, ob der judge überhaupt richtig urteilt.
Convergence-Deep-Review für die ground truth
Die ground truth in validation/ wird nicht mal eben von Hand getippt und auch nicht von einem einzelnen Modell gelabelt. Sie entsteht über eine Convergence-Deep-Review:
- >= 5 Subagents, mehrere Zyklen,
- kein early stop — der Prozess läuft, bis alle Subagents auf "keine Fehler" konvergieren,
- analog zu
/deep-review, aber für Dokument-Text-Korrektheit statt Code.
So wird verhindert, dass sich Modellfehler in unsere "korrekten" Antworten einschleichen. Das Ergebnis ist eine human-anchored ground truth mit hohem Vertrauen.
Phase 2 (Industrialisierung — NICHT v1)
Phase 2 baut auf der v1-Schleife auf und industrialisiert sie:
- Shared-Service-Refactor der Produktions-Extraktion (damit Eval und Produktion denselben Code-Pfad teilen → prompt parity),
- OpenRouter-Router, um schnell mehrere Modelle gegeneinander zu benchmarken,
- automatisches leaderboard über Runs/Modelle,
- CI-regression-gate, das PRs blockiert, wenn Scores unter eine Schwelle fallen,
- ggf. DeepEval / G-Eval als Framework-Unterbau.
Wichtig: Wenn du an v1 arbeitest, baust du nichts davon. Du hältst es schlank und manuell.
Workspace Agent Eval — Tool-Use (separates Epic)
Das zweite Epic (workspace-agent-eval) evaluiert den Workspace-Agenten, der nicht single-shot arbeitet, sondern Tool-Use macht (mehrstufige Agenten-Läufe). Es ist eine eigene Eval-Spur mit eigenen Herausforderungen (Tool-Calls bewerten statt Felder vergleichen). Es teilt sich die Begriffswelt aus dem Glossar, hat aber eine andere Mechanik. Hier nur zur Einordnung erwähnt — die Tasks dazu sind eigene Issues.
Folder Structure
Der gesamte Eval-Code und alle Artefakte für die References-Extraktion liegen unter evals/references/. (Dieser Ordner existiert im Repo noch nicht — ihn anzulegen ist Teil der ersten Tasks.)
evals/references/
original/ # die 3 Original-Ausschreibungen
# (Architektur, BIM, Softwareentwicklung)
# = Input-Artefakte (rohe Tender)
validation/ # ground truth: manuell/konvergenz-erstellte
# Soll-Extraktion (der Maßstab)
# entsteht per Convergence-Deep-Review
llm-extraction/<YYYY-MM-DD>_<model>/ # Outputs der tender-zen-Extraktion,
# pro Run / Datum / Modell getrennt
# z.B. 2026-06-25_gemini-2.5-flash/
judge/ # LLM-as-judge Comparison + Scores
# (extraction vs. validation)Merke dir die Richtungen:
original/ist der Input (die Ausschreibung).validation/ist die Soll-Seite (ground truth, was die AI extrahieren sollte).llm-extraction/<run>/ist die Ist-Seite (was die AI tatsächlich extrahiert hat). Jeder Run liegt in einem eigenen, mit Datum + Modell benannten Unterordner — so kannst du Runs vergleichen, ohne ältere zu überschreiben.judge/enthält den Vergleich Ist-gegen-Soll plus Score und Begründung.
The Make-or-Break Risk: German LLM-as-judge
Das gesamte Chapter steht und fällt mit einer Frage:
Kann ein LLM-as-judge die deutsche Vergabe-/References-Terminologie verlässlich gegen die human-anchored ground truth scoren?
Warum das das Hauptrisiko ist:
- Die References-Extraktion produziert natürliche Sprache mit starker format variance (mal "LP 5-9", mal "Leistungsphasen 5 bis 9", mal als Liste; "mind. 3 Referenzprojekte" vs. "drei Referenzen mind."). Ein Exact-Match-Vergleich ist hier nutzlos — deshalb brauchen wir einen judge.
- Aber: Der judge muss deutsches Fachvokabular (Eignungskriterien, Anforderung an Referenzen, Leistungsphasen, Vergabe) korrekt verstehen und inhaltliche Äquivalenz von echten Fehlern unterscheiden. Wenn der judge selbst die Domäne missversteht, sind alle Scores wertlos — und schlimmer: irreführend.
Wie wir das Risiko in v1 mitigieren: Der judge-Task (Phase 1) enthält einen menschlichen Spot-Check. Ein Mensch mit Domänenwissen prüft eine Stichprobe der judge-Urteile und vergleicht sie mit dem eigenen Urteil. Stimmen judge und Mensch überein, ist der judge kalibriert und wir vertrauen ihm. Weichen sie ab, tunen wir den judge-Prompt/-Kriterien, bevor wir weiterbauen. Ohne diesen bestandenen Spot-Check macht Phase 2 (Automatisierung, regression gate) keinen Sinn — wir würden eine kaputte Messung industrialisieren.
Faustregel: Frage bei jedem Fehlschlag zuerst: "Ist das ein echter Extraktionsfehler — oder nur format variance, die der judge falsch bestraft?"
Production Code Map (wie References-Extraktion HEUTE läuft)
Bevor du Evals baust, musst du verstehen, was du eigentlich evaluierst. Wichtig — und überraschend:
Es gibt keinen dedizierten References-Extraktions-Prompt und kein dediziertes Zod-Schema im Code. "References" (und "Reference Fit", "Personnel Match" etc.) sind user-/org-konfigurierte Analysis-Columns, gespeichert in der Tabelle
tender_analysis_column(prompt+output_typesind Daten, nicht Code). Die Extraktion ist ein generischer single-shot LLM-Call, getrieben voncolumn.prompt.
Die Seed-Daten liefern drei Beispiel-Columns (Zusammenfassung, Leistungsphasen, Eignung) unter src/routes/api/v1/test/seed/+server.ts:500-523. Eine "References"/"Referenzen"-Column würde genauso angelegt — ohne Spezialbehandlung im Code (Ausnahme: die dependsOnColumnId / artifactType-Branches des Reference-Fit-Consumers).
Kritisch: Es gibt ZWEI divergente Execution-Paths, mit unterschiedlichem Prompt-Aufbau, unterschiedlicher LLM-Call-Form und unterschiedlichen (beide hardcodiert falschen) modelUsed-Metadaten:
Path A — Synchronous Service (generateStructuredOutputWithMessages)
- Entry:
src/routes/api/v1/protected/analysis/run/+server.ts:66(POSTanalysis/run) →tenderAnalysisService.runAnalysis(...), inline; auch über Job-Executorsrc/lib/server/jobs/tender/tender-analysis-executor.ts:50. - Service:
src/lib/server/ai/tender-analysis-service.tsrunAnalysis()—:48- System-Prompt-Literal —
:114-115 sanitizePrompt(column.prompt)angewendet —:117- Schema-Auswahl nach
outputType—:140→getSchemaForOutputType():214-237(text →z.object({ value: z.string() })) - Strukturierter Multi-Message-Call —
:148-154; Fallback bei:158 - Hardcodiert FALSCHE Metadaten:
metadata.modelUsed: 'azure-openai'—:169(das Projekt nutzt Google Gemini, nicht Azure OpenAI) - Persistenz nach
tender_analysis_result—:174-184
Path B — Asynchronous Job (generateText, "single_prompt")
- Entry:
src/routes/api/v1/protected/tender-analysis/run/+server.ts:67(POSTtender-analysis/run) →triggerTenderAnalysis(...)enqueued einen Job (trigger-analysis.ts:418,JobType.TENDER_ANALYSIS). Dispatch:db-job-queue.ts:586,616-617→processTenderAnalysisJob. - Processor:
src/lib/server/jobs/tender/analysis-processor.tsprocessTenderAnalysisJob()—:39- Sprach-Instruktionen am Prompt —
applyLanguageInstructionsToColumn():271-289(dieser Path mutiert den Prompt; Path A nicht) - single_prompt-Path —
processSinglePrompt():294-351; Prompt-Assembly:305-321(keinsanitizePrompthier, anders als Path A) - Plain-Text-Call —
aiProvider.generateText(...)—:348(KEIN structured output, kein Zod) - Hardcodiert FALSCHE Metadaten:
metadata.modelUsed: 'gpt-4-turbo-preview'—:223(und:133); ebenfalls falsch — der Provider ist Gemini. - Reference-Fit-Context —
getTenderContentForAnalysis():470-717;dependsOnColumnId-Branch lädt das Upstream-References-Ergebnis:491-528.
Divergenz-Zusammenfassung: Path A = structured (generateObject, Zod-text-Schema), sanitized Prompt, keine Sprach-Mutation, modelUsed='azure-openai'. Path B = unstructured (generateText), unsanitized Prompt, sprach-mutierter Prompt, modelUsed='gpt-4-turbo-preview'. Beide Labels sind für das echte Gemini-Backend falsch.
Provider & Modell-Auflösung
- Factory:
src/lib/server/ai/providers/factory.ts—create(tracingContext?, modelOverride?):30. Keiner der beiden Analysis-Paths übergibt einenmodelOverride→ das Modell wird immer aus env/default aufgelöst. - Gemini-Provider:
src/lib/server/ai/providers/google-gemini-provider.ts— Modell-Auflösungthis.modelName = modelOverride || env.GEMINI_MODEL || 'gemini-2.5-flash'—:67. Das ist das Modell, das du evaluierst: Gemini 2.5-Flash (single-shot), perGEMINI_MODEL-Default. getAvailableModels()ist stale (gemini-1.5-*,gemini-2.0-flash-exp) —:363-365, inkonsistent zum Default:67.
Warum das für dich wichtig ist: Diese Divergenz und die falschen Metadaten sind genau der Grund, warum prompt parity so heikel ist. Wenn dein eval harness einen anderen Prompt-Pfad nutzt als Produktion, misst du etwas anderes als das, was Nutzer erleben. In Phase 2 ist das Aufräumen dieser Pfade (Shared-Service-Refactor) ein zentraler Schritt — in v1 musst du dir nur bewusst sein, welchen Pfad/Prompt deine Extraktion in llm-extraction/ tatsächlich getroffen hat.
Reference Docs (zuerst lesen)
- Meeting-Transcript:
docs/requirements-and-tasks/meeting-notes/— der Mitschnitt, aus dem dieses Chapter entstanden ist. Hier steht der Original-Kontext und das "Warum". - Reference-Creation-Feature:
ai-dev-docs/requirements/reference-creation-feature.md— beschreibt das Produkt-Feature rund um Referenzprojekte (Ist-Seite: die abgeschlossenen Projekte, die ein Unternehmen vorlegt). Hilft dir, die Domäne zu verstehen und die Richtung Soll-vs-Ist nicht zu verwechseln.
Ordered Task List (nach Epic / Phase)
Reihenfolge = Bearbeitungssequenz. In v1 arbeitest du strikt von oben nach unten — jeder Schritt baut auf dem vorherigen auf. Titel sind als deutsche User-Story-Phrasing mit englischen Tech-Nomen formuliert.
Epic: Analysis Evals — References-Extraktion (analysis-evals)
Phase 1 — v1 (lean, manueller 4-Ordner-Loop auf 3 Ausschreibungen)
- Als Eval-Entwickler lege ich die
evals/references/-Folder-Structure (original/validation/llm-extraction/judge) an, damit alle Eval-Artefakte einen festen Platz haben. - Als Eval-Entwickler kuratiere ich die 3 Original-Ausschreibungen (Architektur, BIM, Softwareentwicklung) in
original/, damit wir realistische Input-Artefakte haben. - Als Eval-Entwickler erstelle ich die human-anchored ground truth in
validation/per Convergence-Deep-Review (>= 5 Subagents, kein early stop), damit wir einen vertrauenswürdigen Maßstab haben. - Als Eval-Entwickler lasse ich die tender-zen References-Extraktion (single-shot, Gemini) auf den 3 Ausschreibungen laufen und lege die Outputs in
llm-extraction/<YYYY-MM-DD>_<model>/ab. - Als Eval-Entwickler baue ich den LLM-as-judge, der
llm-extraction/gegenvalidation/vergleicht und Scores + Begründungen injudge/schreibt — inklusive menschlichem Spot-Check zur Judge-Kalibrierung.
Phase 2 — Industrialisierung (baut auf v1 auf)
- Als Eval-Entwickler refaktoriere ich die Produktions-Extraktion in einen Shared Service, damit Eval und Produktion denselben Code-Pfad teilen (prompt parity).
- Als Eval-Entwickler integriere ich einen OpenRouter-Router, damit ich mehrere Modelle gegen denselben golden dataset benchmarken kann.
- Als Eval-Entwickler baue ich ein automatisches leaderboard über Runs/Modelle, damit Ergebnisse vergleichbar sichtbar werden.
- Als Eval-Entwickler baue ich ein regression gate in der CI, das PRs blockiert, wenn die Extraktions-Scores unter die Schwelle fallen.
Epic: Workspace Agent Eval — Tool-Use (workspace-agent-eval)
- Als Eval-Entwickler evaluiere ich den Workspace-Agenten auf korrekten Tool-Use (separate Eval-Spur, mehrstufig statt single-shot).
Definition of Ready (DoR)
Ein Task ist ready, bevor du anfängst, wenn:
- Du dieses Onboarding und das Glossar (unten) gelesen hast.
- Du weißt, welche der 4 Ordner (
original/,validation/,llm-extraction/,judge/) der Task berührt und in welche Richtung (Input / Soll / Ist / Vergleich). - Klar ist, ob der Task v1 (lean, manuell) oder Phase 2 (Industrialisierung) ist — und du nichts aus Phase 2 vorziehst.
- Bei Tasks, die ground truth erzeugen: klar ist, dass die Convergence-Deep-Review (>= 5 Subagents, kein early stop, "keine Fehler") der vorgeschriebene Weg ist — keine Abkürzung per Single-Model-Labeling.
- Etwaige
## Open Question-Blöcke im Issue sind beantwortet.
Definition of Done (DoD)
Ein Task ist done, wenn:
- Alle Acceptance Criteria des Issues erfüllt und überprüft sind.
- Die erzeugten Artefakte am korrekten Ort unter
evals/references/liegen (Runs in datum-/modell-benannten Unterordnern, nichts überschrieben). - Für judge-Tasks: der menschliche Spot-Check durchgeführt ist und judge-Urteile mit dem menschlichen Urteil hinreichend übereinstimmen (sonst judge tunen, dann erneut).
- prompt parity bewusst geprüft ist: der evaluierte Prompt/Pfad entspricht dem, was in Produktion läuft (oder Abweichungen sind dokumentiert).
- Temporäre Dateien (Prefix
tmp_) entfernt sind; kein Debug-console.log, kein auskommentierter Code. /deep-reviewals Verifikations-Schritt durchlaufen wurde (gemäß CLAUDE.md, falls Code geändert wurde).
Domain- und Technik-Glossar: Tender-Zen "Evals" Chapter
Willkommen im Evals-Chapter von Tender-Zen. Tender-Zen ist eine multi-tenant SaaS-Plattform, die deutsche öffentliche Bauausschreibungen aggregiert und mit AI-Analyse die relevanten Informationen aus Ausschreibungsunterlagen extrahiert. Dein Chapter beantwortet eine einzige, aber zentrale Frage: Wie gut ist diese AI-Extraktion wirklich – und merken wir sofort, wenn sie schlechter wird? Dieses Glossar erklärt dir die Begriffe aus zwei Welten: die fachliche Domäne (deutsches Vergaberecht, Ausschreibungen) und das technische Eval-Setup. Die Prosa ist auf Deutsch, etablierte IT- und Eval-Begriffe bleiben aus gutem Grund Englisch – genau so reden wir auch im Team.
Teil 1: Domänen-Begriffe (deutsches Vergabewesen)
Diese Begriffe beschreiben das, worüber die AI Aussagen trifft. Sie tauchen in den Ausschreibungsunterlagen auf, die unsere AI liest, und sind damit gleichzeitig das, was unsere Evals prüfen.
Ausschreibung
Eine Ausschreibung ist die öffentliche Bekanntmachung, mit der ein öffentlicher Auftraggeber (z.B. eine Kommune, die Deutsche Bahn oder die Bundeswehr) eine Bau- oder Planungsleistung am Markt nachfragt. Sie besteht aus mehreren Dokumenten (Bekanntmachung, Leistungsbeschreibung, Vertragsunterlagen, Eignungsanforderungen). Tender-Zen aggregiert diese Ausschreibungen von den fragmentierten deutschen Vergabeplattformen, und unsere AI liest die zugehörigen Dokumente. Für dich als Eval-Entwickler ist die Ausschreibung das Input-Artefakt: das, woraus die AI extrahiert.
Vergabe
Die Vergabe ist der formale Prozess, durch den ein öffentlicher Auftrag rechtssicher an ein Unternehmen vergeben wird – geregelt durch das deutsche Vergaberecht (z.B. VgV, VOB). "Ausschreibung" ist der Schritt am Anfang; "Vergabe" beschreibt den Gesamtprozess bis zur Zuschlagserteilung. Du wirst beide Begriffe oft synonym hören, aber technisch ist die Vergabe der übergeordnete Rahmen. Relevant für Evals: Fehler in der Extraktion können bei unseren Nutzern zu einer falschen Pursue-or-Skip-Entscheidung führen – die Vergabe ist ein high-stakes Echtgeld-Kontext, deshalb ist Extraktionsqualität nicht optional.
Eignungskriterien
Eignungskriterien sind die Anforderungen, die ein bietendes Unternehmen erfüllen muss, um überhaupt für den Auftrag in Frage zu kommen (Eignung = "ist dieses Unternehmen geeignet?"). Sie umfassen typischerweise wirtschaftliche, technische und personelle Leistungsfähigkeit. Wenn ein Unternehmen die Eignungskriterien nicht erfüllt, wird sein Angebot ausgeschlossen – egal wie gut der Preis ist. Die AI muss diese Kriterien zuverlässig aus den Dokumenten herausziehen, denn sie entscheiden, ob ein Tender für einen Nutzer überhaupt machbar ist.
Anforderung an Referenzen
Eine Anforderung an Referenzen ist ein spezifischer Unterpunkt der Eignungskriterien: Der Auftraggeber verlangt den Nachweis vergleichbarer, bereits abgeschlossener Projekte. Beispiel: "Mindestens drei Referenzprojekte im Hochbau mit einem Auftragsvolumen von je über 5 Mio. EUR aus den letzten fünf Jahren." Diese Anforderung an Referenzen ist eines der wichtigsten Extraktionsziele unserer AI – sie ist oft das, was über Pursue-or-Skip entscheidet, weil ein Unternehmen schlicht passende Referenzen haben muss. In unseren Evals ist die korrekte Extraktion der Anforderung an Referenzen (Anzahl, Mindestvolumen, Zeitraum, Leistungsart) ein Kern-Testfall.
Referenzprojekte
Referenzprojekte sind die abgeschlossenen Projekte, die ein Unternehmen vorweist, um eine Anforderung an Referenzen zu erfüllen. Auf der Produktseite gibt es dazu das Reference-Creation-Feature (siehe ai-dev-docs/requirements/reference-creation-feature.md): Nutzer pflegen ihre eigenen Referenzprojekte als Sammlung von Dokumenten, und die AI erstellt daraus formatierte Referenz-Dokumente für eine konkrete Ausschreibung. Merke dir die Richtung: Die Anforderung an Referenzen kommt aus der Ausschreibung (Soll-Seite); die Referenzprojekte gehören dem Unternehmen (Ist-Seite). Beide Seiten extrahiert bzw. verarbeitet die AI – und beide Seiten evaluierst du.
Leistungsphasen
Leistungsphasen (LP 1–9) sind die nach HOAI definierten Phasen einer Planungsleistung – von der Grundlagenermittlung (LP 1) über die Entwurfsplanung bis zur Objektbetreuung (LP 9). Ausschreibungen für Architektur- und Ingenieurleistungen geben genau an, welche Leistungsphasen beauftragt werden. Das ist hochrelevant für die Eignung (ein Büro muss die geforderten Phasen abdecken) und ein klassisches Extraktionsziel: Die AI muss erkennen, "hier sind LP 5–9 ausgeschrieben". In Evals testest du, ob die AI die richtigen Leistungsphasen-Nummern findet und keine erfindet (Stichwort ground truth, siehe unten).
Teil 2: Eval- und AI-Engineering-Begriffe
Diese Begriffe beschreiben das, womit du arbeitest: das Maschinen-für-die-Maschine, das die Qualität der AI-Extraktion misst und absichert.
Eval harness
Das eval harness ist die Test-Infrastruktur, die unsere AI-Extraktion automatisiert gegen einen Datensatz laufen lässt und die Ergebnisse bewertet. Stell es dir vor wie ein Test-Runner, aber für AI-Outputs statt für deterministischen Code. Das eval harness lädt Inputs (Ausschreibungsdokumente), ruft die AI auf, vergleicht den Output mit der erwarteten Antwort und produziert einen Score. Es ist das zentrale Werkzeug deines Chapters – fast jede Aufgabe berührt das eval harness.
Golden dataset
Der golden dataset ist die kuratierte Sammlung von Test-Inputs mit ihren bekannten korrekten Antworten – das Referenz-Set, gegen das jede Eval läuft. Für uns: eine Menge echter (oder realistisch nachgebauter) Ausschreibungen plus die jeweils korrekt extrahierten Felder (z.B. die korrekte Anforderung an Referenzen und die korrekten Leistungsphasen). Der golden dataset ist nur so gut wie seine Pflege: Er muss die Vielfalt echter Ausschreibungen abdecken (verschiedene Plattformen, Formate, Bundesländer), sonst evaluierst du an einer verzerrten Stichprobe.
Ground truth
Ground truth ist die als korrekt definierte Antwort für einen einzelnen Testfall – das, womit der AI-Output verglichen wird. Im golden dataset ist jeder Eintrag mit seiner ground truth annotiert. Wichtig: Ground truth ist nicht "die objektive Wahrheit aus dem Nichts" – jemand musste sie festlegen. Wer das ist und wie verlässlich es ist, führt direkt zum nächsten Begriff.
Human-anchored ground truth
Human-anchored ground truth bedeutet: Die korrekte Antwort wurde von einem Menschen mit Domänenwissen festgelegt oder verifiziert – nicht von einem anderen Modell. Gerade im Vergabe-Kontext ist das essenziell, weil die korrekte Lesart einer Anforderung an Referenzen oder von Eignungskriterien juristisch-fachliches Verständnis braucht. Human-anchored ground truth ist teurer zu erzeugen (ein Experte muss annotieren), aber sie verhindert, dass sich Modellfehler in deinen "korrekten" Antworten festsetzen. Faustregel im Chapter: Kernfälle sind human-anchored, nicht maschinell gelabelt.
LLM-as-judge
LLM-as-judge ist das Muster, bei dem ein LLM verwendet wird, um den Output eines anderen LLM (oder des gleichen) zu bewerten. Statt einen exakten String-Vergleich zu machen (was bei natürlicher Sprache zu spröde ist), fragst du ein Judge-Modell: "Stimmt diese extrahierte Anforderung inhaltlich mit der ground truth überein?" Das judge (das bewertende Modell) gibt ein Urteil, oft mit Begründung. Vorteil: robust gegen Formulierungsvarianten. Risiko: Der Judge kann selbst irren oder Biases haben – deshalb ankert man ihn an human-anchored ground truth und prüft den Judge selbst stichprobenartig.
Judge
Der judge ist konkret das Modell (oder die Modell-plus-Prompt-Kombination), das im LLM-as-judge-Setup die Bewertung vornimmt. "Den judge tunen" heißt: seinen Prompt und seine Kriterien so verbessern, dass seine Urteile mit denen menschlicher Experten übereinstimmen. Ein guter judge ist kalibriert – er ist weder zu nachsichtig noch zu streng.
G-Eval
G-Eval ist eine konkrete LLM-as-judge-Methode, bei der das Judge-Modell anhand einer per Prompt definierten Bewertungskette (Chain-of-Thought über explizite Kriterien) einen Score vergibt. Statt nur "richtig/falsch" produziert G-Eval abgestufte Scores entlang von Kriterien, die du in natürlicher Sprache beschreibst (z.B. "Vollständigkeit der extrahierten Eignungskriterien"). G-Eval ist in DeepEval (siehe unten) implementiert und einer der Standard-Bausteine unseres eval harness.
Format variance
Format variance beschreibt das Problem, dass die AI inhaltlich korrekt, aber formal unterschiedlich antworten kann – mal "LP 5-9", mal "Leistungsphasen 5 bis 9", mal als Liste. Ein naiver Exact-Match-Vergleich würde solche Antworten fälschlich als falsch werten. Format variance ist genau der Grund, warum wir LLM-as-judge / G-Eval statt String-Vergleich nutzen: Der Judge bewertet inhaltliche Äquivalenz trotz format variance. Beim Bauen von Evals musst du immer fragen: "Ist mein Fehlschlag echt – oder nur format variance?"
Convergence (subagent run-until-no-deviations)
Convergence bezeichnet bei uns das Muster, bei dem ein subagent denselben Eval- oder Verifikations-Durchlauf wiederholt ausführt, bis keine Abweichungen mehr auftreten ("run-until-no-deviations"). Statt eines einzigen Durchlaufs läuft der Prozess in Zyklen und stoppt erst, wenn das Ergebnis stabil ist – also konvergiert. Du wirst diesem Muster auch in unseren Review-Workflows begegnen (z.B. mehrere Review-subagents, die in Zyklen laufen, bis keine kritischen Findings mehr übrig sind). Im Eval-Kontext erhöht convergence das Vertrauen, dass ein Score nicht nur ein Zufallstreffer eines einzelnen Laufs war.
Regression gate
Ein regression gate ist ein automatischer Check (typischerweise in der CI), der einen Merge oder ein Deployment blockiert, wenn die Eval-Scores unter eine Schwelle fallen – also wenn eine Regression vorliegt. Beispiel: "Wenn die Extraktionsgenauigkeit für die Anforderung an Referenzen unter 90% fällt, blockiere den PR." Das regression gate ist der Punkt, an dem Evals von "nice metric" zu "schützt die Produktqualität" werden. Dein Chapter baut und pflegt diese Gates, damit ein Prompt-Change die Extraktion nicht heimlich verschlechtert.
CI
CI (Continuous Integration) ist unsere automatisierte Pipeline, die bei jedem Push/PR Tests, Type-Checks und Builds ausführt. Für dich relevant: Hier laufen die Evals und greift das regression gate. Ein roter CI-Lauf wegen einer Eval-Regression ist exakt das Signal, das dein Chapter erzeugen soll.
Prompt parity
Prompt parity bedeutet, dass die Prompts (und Modell-Einstellungen) in der Eval-Umgebung identisch zu denen in Produktion sind. Wenn dein eval harness einen anderen Prompt nutzt als der Produktions-Code, misst du etwas anderes als das, was Nutzer erleben – die Scores sind dann wertlos. Prompt parity sicherzustellen (z.B. indem Eval und Produktion denselben Prompt-Code importieren statt ihn zu duplizieren) ist eine wiederkehrende Sorgfaltspflicht. Verletzte prompt parity ist eine der heimtückischsten Fehlerquellen in Eval-Setups.
Single-shot
Single-shot beschreibt eine Inferenz, bei der das Modell die Aufgabe in einem Aufruf löst – ohne mehrere Runden, ohne Tool-Loops, ohne Self-Refinement. Viele unserer Extraktionen laufen single-shot (ein Dokument rein, strukturierter Output raus). Für Evals ist das relevant, weil single-shot-Ergebnisse leichter reproduzierbar und billiger zu evaluieren sind als mehrstufige Agenten-Läufe. Wenn jemand sagt "lass uns das erstmal single-shot evaluieren", meint er: ein Aufruf, eine Antwort, ein Score.
Teil 3: Tools und Libraries
Vercel AI SDK
Das Vercel AI SDK (im Code als ai / @ai-sdk/*-Pakete) ist unsere primäre TypeScript-Library für LLM-Aufrufe – einheitliches Interface über verschiedene Provider hinweg, plus strukturierter Output (Schema-validierte Extraktion via Zod), Streaming und Tool-Calls. Unsere Produktions-Extraktion (z.B. in src/lib/server/ai/) baut auf dem Vercel AI SDK auf. Wenn du Evals schreibst, die denselben Code-Pfad nutzen wollen (Stichwort prompt parity), gehst du über dieselben Vercel AI SDK-Aufrufe.
OpenRouter
OpenRouter ist ein Router-/Gateway-Dienst, der viele LLM-Provider hinter einer einzigen, OpenAI-kompatiblen API bündelt. Statt Accounts und SDKs für jeden Anbieter einzeln zu verdrahten, sprichst du über OpenRouter mit Modellen vieler Anbieter. Im Eval-Kontext ist das praktisch, um schnell verschiedene Modelle gegeneinander zu benchmarken (z.B. auf einem leaderboard), ohne den Code umzubauen.
DeepEval
DeepEval ist ein Open-Source-Eval-Framework (Python), das viele unserer Eval-Bausteine liefert – darunter eine fertige G-Eval-Implementierung, LLM-as-judge-Metriken und Helfer zum Aufbau eines golden dataset sowie zur CI-Integration. Wenn dein eval harness auf DeepEval aufsetzt, bekommst du Metriken, regression gate-Hooks und Reporting weitgehend out-of-the-box, statt sie selbst zu bauen.
Quick-Reference: Wie alles zusammenhängt
- Eine Ausschreibung (mit ihren Eignungskriterien, der Anforderung an Referenzen und den Leistungsphasen) geht als Input in die AI.
- Die AI extrahiert die Felder – in Produktion über das Vercel AI SDK, oft single-shot.
- Dein eval harness lässt diese Extraktion gegen den golden dataset laufen, dessen Einträge human-anchored ground truth tragen.
- Weil natürliche Sprache format variance hat, bewertet ein judge per LLM-as-judge / G-Eval (häufig via DeepEval) statt per Exact-Match.
- Convergence stellt sicher, dass Scores stabil sind; prompt parity stellt sicher, dass du das Richtige misst.
- In der CI blockiert ein regression gate Änderungen, die die Qualität senken.
Begriffe, die du bei uns oft hören wirst (Kurz-Cheatsheet)
| Begriff | In einem Satz |
|---|---|
| Ausschreibung | Die öffentliche Bekanntmachung eines Bauauftrags – unser Input-Artefakt. |
| Vergabe | Der gesamte rechtliche Beschaffungsprozess rund um die Ausschreibung. |
| Eignungskriterien | Was ein Bieter erfüllen muss, um zugelassen zu werden. |
| Anforderung an Referenzen | Geforderter Nachweis vergleichbarer Projekte – ein Kern-Extraktionsziel. |
| Referenzprojekte | Die abgeschlossenen Projekte, die ein Unternehmen als Nachweis vorlegt. |
| Leistungsphasen | HOAI-Phasen LP 1–9 einer Planungsleistung. |
| eval harness | Unsere Test-Infrastruktur für AI-Outputs. |
| golden dataset | Kuratiertes Test-Set mit bekannten korrekten Antworten. |
| ground truth | Die als korrekt definierte Antwort eines Testfalls. |
| human-anchored ground truth | Ground truth, die ein Mensch festgelegt/verifiziert hat. |
| LLM-as-judge / judge | Ein Modell bewertet den Output eines anderen Modells. |
| G-Eval | Kriterien-basierte LLM-as-judge-Methode mit abgestuften Scores. |
| format variance | Inhaltlich gleich, formal verschieden – Grund für judge statt Exact-Match. |
| convergence | Subagent läuft, bis keine Abweichungen mehr auftreten (run-until-no-deviations). |
| regression gate | CI-Check, der Qualitätsregressionen blockiert. |
| prompt parity | Eval-Prompts sind identisch zu Produktions-Prompts. |
| single-shot | Eine Inferenz, eine Antwort, keine Loops. |
| Vercel AI SDK | TypeScript-Library für LLM-Aufrufe und strukturierten Output. |
| OpenRouter | Router/Gateway über viele LLM-Provider hinweg. |
| DeepEval | Eval-Framework, das G-Eval und Judge-Metriken liefert. |