Skip to content

Antwort auf die Runde-3-Planung — deine fünf Fragen, alle beantwortet

Von Marco/Lenny-Team an Chris, Stand 2026-08-11. Bezug: ANTWORT_AN_MARCO_RUNDE3_PLAN.md.

Vorweg: Dein Einwand zum Pfad-Split war berechtigt und hat einen Fehler in meinem Dokument aufgedeckt. Dazu unten mehr — und eine Umsetzung, die dir die Arbeit abnimmt.


1. Fußzeilen-Kennung — gebaut, aber anders als vorgeschlagen

Umgesetzt. Nicht im Text, sondern als eigenes Feld in der JSON-Antwort:

{
  "choices": [{ "message": { "content": "…" } }],
  "lenny_path": "det"        // det | mix | llm | unknown
}

Warum nicht im Fußzeilentext: Ein Endnutzer soll kein pfad=llm lesen müssen. Als JSON-Feld ist es maschinenlesbar, unsichtbar für Menschen, und unbekannte Felder ignoriert jeder OpenAI-kompatible Client — es bricht nichts.

Bedeutung: | Wert | Formulierer | |---|---| | det | Lennys deterministischer Renderer (auch Tenant-Antworten) | | mix | Modell hat über die Erdung hinaus ergänzt | | llm | Sprachmodell — geerdet, frei oder Verweigerungspfad | | unknown | keine Wissens-Antwort (Bestätigung, Aktion) |

Wichtig für deine Auswertung: llm fasst drei Fälle zusammen, die deine Fußzeile weiterhin unterscheidet (geerdet / nicht gedeckt / unsicher). Nimm also beides: lenny_path für die Formulierer-Achse, die Fußzeile für die Wissensbasis-Achse. Genau die Trennung, auf die du bestanden hast.

Und du hattest recht. Dein Beleg — Übereinstimmung bei „teilweise" (39,6 % / 38,1 %) und „nicht gedeckt" (30,7 % / 32,8 %), aber keine bei „geprüft" gegen „deterministisch" (10,4 % / 0,8 %) — trifft genau: Eine geprüft-Antwort kann trotzdem vom Modell formuliert sein. Ich hatte in meinem Dokument die Fußzeilen-Kategorien als Pfade gelesen und damit zwei Achsen vermischt. Die Zahl 0,8 % stimmt für den Formulierer, nicht für die Wissensbasis. Danke fürs Nachrechnen statt Übernehmen.


2. KPI-Endpunkt — er läuft, es ist der Pfad

Kein Umzug, keine Abschaltung. Live geprüft:

/v1/kpi/relation_diversity        → 200   ← der richtige
/v1/kpi/relation_diversity?limit=5 → 200
/kpi/relation_diversity           → 404   ← ohne /v1
/v1/kpi                           → 404
/v1/kpi/relation_diversity/       → 307   (Schrägstrich am Ende)

Vermutlich das fehlende /v1. Zweite mögliche Ursache: Am 11.08. gab es acht Deploys, während derer der Container jeweils ein bis zwei Minuten weg war.

Zwei Hinweise zum KPI selbst, weil ihr ihn auswertet: - Der Wert wurde korrigiert. Er zählte Kanten mit, deren Relation eine falsche Verbform ist („Ampel ordnen Verhalten") — 122 von 253. Der Endpunkt weist jetzt beides aus: pct_actional (roh, 2,44 %) und pct_actional_wellformed (1,34 %, die belastbare Zahl). Nichts wurde gelöscht, nur ehrlich getrennt. - Auslöser war euer Fund zu den *_offene_praedikate-Stapeln. Er stimmte, und er hat eine Lücke in unserer eigenen Messung aufgedeckt.


3. Zweiturn — geht schon, ohne neuen Parameter

Der Chat-Endpunkt ist OpenAI-förmig: messages ist eine Liste. Schickt einfach den ganzen Verlauf mit:

{"model": "lenny", "messages": [
  {"role": "user",      "content": "Was ist ein Vulkan?"},
  {"role": "assistant", "content": "…vorherige Antwort…"},
  {"role": "user",      "content": "Und wie entsteht der?"}
]}

_build_history() zieht daraus die user/assistant-Paare als Gesprächsverlauf. Es braucht also kein separates history-Feld. Eure 35 Zweiturn-Fragen können damit laufen.


4. Verweigerungspfad — scharf seit 2026-08-06

Commit 9a86dd2, Flag LENNY_ENABLE_CAUTIOUS_REFUSAL=1. Davor antwortete das Modell bei fehlendem Wissen frei (und erfand); seither formuliert es ausdrücklich unsicher und benennt Kategoriefehler.

Das passt zu eurem Bruch bei Frage 500/501 — und euer Fund ist der bessere Befund als unsere eigene Zahl. Wir hatten „22 von 60" als Grundlinie geführt, ohne den Bruch zu sehen. Eure Aufteilung (468–500 halluziniert, 501–527 durchgehend sauber) macht daraus 0 von 27 und deckt sich mit unserer Nachmessung 3 von 3. Wir übernehmen eure Lesart.

Wenn ihr die Zeitstempel eurer Fragen habt, ließe sich der Umschlagpunkt exakt gegen den Deploy legen.


5. Die ~126 Fragen/Tag — keine Grenze von unserer Seite

Euer Key (marco) hat 60 Anfragen pro Minute. Das sind rechnerisch 86.400 am Tag; ihr liegt bei 0,15 % davon. Es gibt kein Kontingent und keine Tagesgrenze.

Der begrenzende Faktor ist die Antwortzeit: Der Server rechnet CPU-only, eine Antwort mit Sprachmodell dauert typisch 20–40 Sekunden. Rein rechnerisch wären etwa 2.000–4.000 Fragen/Tag möglich, wenn ihr sequenziell durchlauft.

Ihr könnt also größere Runden planen. Zwei Bitten dazu: - Nicht parallelisieren — mehrere gleichzeitige Anfragen konkurrieren um dieselbe CPU und machen alles langsamer, nicht schneller. - Die Trainings-Crons laufen alle 1–4 Stunden und brauchen dieselbe CPU. Wenn eine Runde ungewöhnlich zäh ist, liegt es meist daran.


6. Was sich seit eurer letzten Messung geändert hat

Damit ihr wisst, wogegen ihr in Runde 3 messt — alles seit dem 10./11.08. live:

Antwortqualität - Output-Gate deckt jetzt auch den LLM-Pfad ab: Eine kaputte Antwort verliert ihr „geprüft"-Siegel (verstümmelter Begriff, fremde Sprache, Zeichenmüll). - Beide Finalizer wenden dieselben Wachen an — vorher liefen sechs Antwortpfade an Sanitisierung und Status-Footer vorbei. - Groß-/Kleinschreibung: im Renderer und per Prompt auch in der LLM-Ausgabe. - Genus/Artikel: „eine Wissenschaft" statt „Wissenschaft". - Offene Prädikate werden konjugiert statt weggelassen — „Ampel ordnet Verhalten" statt gar nichts. Das macht ~122 vorhandene Kanten erstmals sichtbar.

Wissenspipeline (betrifft eure Abdeckungs-Messung) - Der Enrich-Cron verlor 60 % seiner Läufe an Datenbank-Sperrfehlern. Behoben. - Vier Fehler im Judge behoben, darunter: ein LLM-Timeout zählte als inhaltliches „Nein", und eine Transliteration („Koerper" gegen „Körper") ließ Kandidaten ungeprüft durchfallen. - Die Open-Predicate-Ernte lieferte null Tripel, weil das Modell seine Antwort in einen Markdown-Codeblock verpackt und der Parser daran scheiterte. Behoben — jetzt 13–21 Vorschläge je Begriff.

Ein wiederkehrendes Muster, das euch beim Deuten hilft: An fünf Stellen sah ein technischer Ausfall aus wie ein fachliches Ergebnis — die DB-Sperre als „HTTP 500", der LLM-Timeout als „Kandidat abgelehnt", der Parserfehler als „im Artikel steht nichts". Wenn euch Zahlen begegnen, die nach Strenge aussehen, lohnt die Rückfrage, ob dahinter ein Ausfall steckt.


7. Zu eurer Runde-3-Planung

Der Zuschnitt überzeugt: 240 Fragen, durchgehend „Was ist X?", dreifach gegen Bestand gefiltert, Tiefe statt Breite. Besonders die Filterung gegen die 1106 Trainings-Stapel ist der richtige Griff — damit trifft jede Frage echtes Nichtwissen.

Eine Ergänzung aus unserer Sicht: Der Abdeckungs-Engpass ist nicht nur eine Frage der Menge. Von den ungeerdeten Fragen scheiterten 84 %, weil der Begriff gar nicht existierte — aber unsere einzige Quelle neuen Wissens war zur Hälfte von einem Datenbank-Bug blockiert. Der ist behoben; ob der Durchsatz jetzt wirklich steigt, messen wir gerade. Eure Runde 3 und dieser Fix wirken auf dieselbe Kennzahl, also sollten wir beim Auswerten sauber trennen, was wovon kam.

Und die 20 neuen Unsinnsfragen mit eurer Begründung („Robustheit heißt Übertragung, nicht Wiedererkennung") sind die richtige Entscheidung.