Zum Inhalt springen
EN DE

Boss Fight: Eval-Pipeline für Chat Titles

Du baust eine komplette Eval-Pipeline für einen Chat-Titel-Generator. Das System nimmt eine User-Nachricht und generiert einen kurzen, beschreibenden Titel für den Chat. Deine Pipeline evaluiert die Qualität dieser Titel automatisch — mit deterministischen Scorern UND LLM-as-Judge.

So soll es funktionieren:

Input: "Ich brauche Hilfe mit TypeScript Generics und Constraints"
Title: "TypeScript Generics"
Input: "Wie konfiguriere ich Docker Compose für ein Multi-Container Setup?"
Title: "Docker Compose Setup"
Input: ""
Title: "Neuer Chat"

Dieses Projekt verbindet alle fuenf Bausteine:

Dataset (6.4), traceAISDKModel (6.1) und System Prompt fliessen in generateText (6.1), der Generated Title wird durch Deterministic Scorer (6.2) und LLM-as-Judge (6.3) bewertet, das Evalite Dashboard zeigt die Score-Analyse und Prompt Iteration verbessert den System Prompt
  1. Dataset (Challenge 6.4) — Erstelle ein Dataset mit mindestens 20 diversen Chat-Verlaeufen. Decke ab: technische Fragen, kurze Inputs, lange Inputs, leere Inputs, mehrdeutige Inputs, mehrsprachige Inputs.

  2. Task: generateText (Challenge 6.1) — Nutze generateText mit einem System Prompt, der den Titel-Generator steuert. Der System Prompt sollte Regeln definieren: maximale Laenge, keine Satzzeichen am Ende, beschreibend aber knapp.

  3. traceAISDKModel (Challenge 6.1) — Wrappe das Modell mit traceAISDKModel, um Token-Verbrauch und Latenz im Dashboard zu sehen.

  4. Deterministic Scorer: Titellaenge (Challenge 6.2) — Erstelle einen createScorer, der die Titellaenge bewertet:

    • 1-50 Zeichen → Score 1.0
    • 51-80 Zeichen → Score 0.5
    • 0 oder >80 Zeichen → Score 0.0
  5. Deterministic Scorer: Kein Punkt am Ende (Challenge 6.2) — Erstelle einen Scorer, der prüft, ob der Titel NICHT mit einem Punkt endet.

  6. LLM-as-Judge Scorer: Relevanz (Challenge 6.3) — Erstelle einen Scorer, der bewertet, ob der generierte Titel zur User-Nachricht passt. Nutze generateObject mit einem Zod Schema und einer Score-Skala.

  7. Mehrere Scorer kombiniert — Alle drei Scorer (Titellaenge, kein Punkt, Relevanz) müssen in einem scorers-Array laufen.

  8. Eval-Driven Iteration — Fuehre die Evals einmal aus, analysiere die Ergebnisse, passe den System Prompt an und fuehre die Evals erneut aus. Hat sich der Score verbessert?

Erstelle die Datei chat-titles.eval.ts und fuehre sie mit pnpm eval:dev aus.

Hinweis: Langfuse (Challenge 6.5) wuerdest Du in Production ergaenzen — hier fokussieren wir auf die Eval-Pipeline mit Evalite.

chat-titles.eval.ts
import { evalite } from 'evalite';
import { createScorer } from 'evalite';
import { traceAISDKModel } from 'evalite/ai-sdk';
import { generateText, generateObject } from 'ai';
import { openai } from '@ai-sdk/openai';
import { z } from 'zod';
// TODO 1: Erstelle den titleLength Scorer (createScorer)
// - 1-50 Zeichen → 1.0
// - 51-80 Zeichen → 0.5
// - 0 oder >80 → 0.0
// TODO 2: Erstelle den noTrailingPeriod Scorer (createScorer)
// - Endet NICHT mit Punkt → 1.0
// - Endet mit Punkt → 0.0
// TODO 3: Erstelle den titleRelevance Scorer (createScorer mit LLM-as-Judge)
// - Nutze generateObject mit einem Judge-Prompt
// - Score-Skala: A (perfekt relevant), B (teilweise relevant),
// C (vage relevant), D (nicht relevant)
// - Gib score + metadata (rationale) zurück
// TODO 4: Definiere den System Prompt für den Titel-Generator
// TODO 5: Erstelle das Dataset mit 20+ Test-Cases
// TODO 6: Erstelle die evalite() mit:
// - data: Dein Dataset
// - task: generateText mit traceAISDKModel
// - scorers: [titleLength, noTrailingPeriod, titleRelevance]

Deine Boss Fight ist bestanden, wenn:

  • Dataset mit mindestens 20 diversen Test-Cases (technisch, conversational, Edge Cases, mehrdeutig)
  • generateText mit traceAISDKModel als task — Titel werden vom LLM generiert
  • System Prompt definiert Regeln für Titel-Generierung (Laenge, Format, Stil)
  • titleLength Scorer bewertet die Laenge mit abgestuften Scores
  • noTrailingPeriod Scorer prüft auf fehlendes Punkt am Ende
  • titleRelevance Scorer nutzt LLM-as-Judge mit generateObject und Zod Schema
  • Alle drei Scorer laufen in einem scorers-Array
  • Mindestens eine Iteration: System Prompt anpassen, erneut evaluieren, Scores vergleichen
Hinweis 1: System Prompt Design

Ein guter System Prompt für Titel-Generierung könnte so aussehen:

Generate a short, descriptive title for the following chat message.
Rules:
- Maximum 50 characters
- No periods at the end
- Be specific, not generic
- If the input is empty, return "Neuer Chat"
- Use the language of the input

Starte damit und iteriere basierend auf den Eval-Ergebnissen.

Hinweis 2: Relevance Scorer Prompt

Der Judge-Prompt für Relevanz könnte die Frage stellen: “How well does this title describe the chat message?” und eine Skala anbieten:

  • A (1.0): Title captures the main topic precisely
  • B (0.7): Title is related but too vague or too specific
  • C (0.3): Title is only loosely related
  • D (0.0): Title is unrelated to the message
Hinweis 3: Edge Cases im Dataset

Vergiss nicht:

  • Leere Strings ('')
  • Nur Whitespace (' ')
  • Sehr kurze Inputs ('Hi', '?')
  • Sehr lange Inputs (200+ Zeichen)
  • Inputs mit Sonderzeichen, Emojis oder Code-Snippets
  • Inputs in verschiedenen Sprachen

Part of AI Learning — free courses from prompt to production. Jan on LinkedIn