Der Spickzettel zur ersten Hälfte des Seminars KI-Features im eigenen Produkt: Wofür sich ein Sprachmodell eignet, wie ein Aufruf aufgebaut wird, was ins Schema gehört und woher belegbares Wissen kommt. Was das Feature auslösen darf und was es im Betrieb kostet, steht auf dem zweiten Blatt: KI-Features: handeln und betreiben.
Maßgeblich für API-Details ist die Herstellerdokumentation; dieses Blatt trifft eine Auswahl — die Entscheidungsraster, die einen Modellwechsel überleben.
Vier Fragen vor jedem KI-Feature
| Frage | Was daraus wird |
|---|---|
| Was ist eine gute Antwort? | der Goldstandard-Datensatz |
| Welcher Schaden entsteht bei einer falschen? | die Strenge der Belegpflicht |
| Woher stammt das Wissen? | Korpus und Retrieval |
| Was darf das Feature auslösen? | Werkzeuge und Rechtemodell |
Zu jeder Frage gehört ein Satz auf Papier, und zur ersten mindestens ein ausformuliertes Beispiel. Wer sie überspringt, baut ein Feature, dessen Umfang und Prüfbarkeit erst nach der Auslieferung feststehen.
Modul: Was ein Sprachmodell im Produkt wirklich leistet
Aufgabentypen und ihre Prüfbarkeit
| Aufgabe | Verlässlichkeit | Prüfbarkeit |
|---|---|---|
| Klassifizieren | hoch | gegen bekannte Beispiele |
| Extrahieren | hoch | Feld für Feld |
| Zusammenfassen | mittel | schwer, selten gefährlich |
| Frage und Antwort auf eigenem Bestand | mittel | nur mit Belegen |
| Umformulieren, Übersetzen | hoch | im Lesen |
| Rechnen, Zählen, exakt Nachschlagen | niedrig | gehört ins Werkzeug |
Die vorletzte Zeile ist der häufigste Wunsch und der Fall mit den meisten verdeckten Fehlern. Die Einordnung bestimmt, wie streng die Belegpflicht ausfällt, was ins Modell gehört und was in Code — und welche Zusagen das Feature überhaupt halten kann.
Ein KI-Feature unterscheidet sich in drei Punkten vom übrigen Code, und jeder hat eine Antwort:
| Eigenschaft | Antwort darauf |
|---|---|
| Nicht deterministisch | statistisch messen statt auf Gleichheit prüfen |
| Lautlose Verschlechterung | Goldstandard und Regressionslauf |
| Bewegliche Komponente | Modellwechsel als geplanter Vorgang |
Modul: Was ein Sprachmodell im Produkt wirklich leistet
Was in die Systemanweisung gehört
| Bestandteil | Ort |
|---|---|
| Rolle und Aufgabe | Systemanweisung |
| Belegpflicht und Verweigerungsregel | Systemanweisung |
| Ausgabeformat | Schema, nicht Prosa |
| Die Frage des Nutzers | Nutzernachricht |
| Gefundene Quellenstellen | Nutzernachricht, gekennzeichnet |
| Kennung und Rechte | gar nicht — die kommen aus der Sitzung |
antwort = client.messages.create(
model="claude-opus-5",
max_tokens=2000,
system=SYSTEM, # stabil, cachefähig
messages=[{"role": "user", "content": frage}],
)
Die Reihenfolge ist kein Detail: Der stabile Anfang lässt sich zwischenspeichern und wird dadurch billiger, Regeln in der Systemanweisung sind schwerer durch fremden Text zu überschreiben, und beim Debuggen ist sofort sichtbar, was Konfiguration war und was Eingabe. Die Systemanweisung liegt als eigene Datei im Repository, nicht als Zeichenkette im Code.
Modul: Der erste belastbare Aufruf
Abbruchgrund und Fehlerklasse
Wer nur auf den Text zugreift, merkt eine abgeschnittene Antwort nicht.
| Abbruchgrund | Reaktion im Code |
|---|---|
| fertig | Antwort verarbeiten |
| Längengrenze erreicht | erneut anfordern oder Aufgabe teilen |
| Werkzeug angefordert | Werkzeug ausführen, Ergebnis zurückgeben |
| Verweigerung | Fall protokollieren, Nutzer sauber informieren |
if antwort.stop_reason == "max_tokens":
raise UnvollstaendigeAntwort(antwort.id)
if antwort.stop_reason == "refusal":
return hinweis_an_nutzer(antwort.id)
text = antwort.content[0].text
Beim Wiederholen entscheidet die Fehlerklasse, nicht der Text der Meldung:
| Fehlerart | Reaktion |
|---|---|
| Ungültige Anfrage | nicht wiederholen, Programmierfehler |
| Nicht gefunden | nicht wiederholen, Konfiguration prüfen |
| Überlastung | wiederholen, wachsender Abstand, Obergrenze |
| Serverfehler | wiederholen, wachsender Abstand |
| Verbindungsabbruch | wiederholen |
Zeitgrenzen werden dabei mitgezählt — die Gesamtdauer ist Zeitgrenze mal Versuche.
Modul: Der erste belastbare Aufruf
Das Schema als Vertrag
Freitext zu parsen scheitert nicht laut, sondern leise: Eine Erklärung steht vor dem Ergebnis, eine Formatierungsmarkierung umschließt den Block, ein Feld fehlt, ein Anführungszeichen bricht die Struktur. Der Fehler wird nicht geworfen, sondern weitergereicht — und fällt in einem Modul auf, das mit dem Modell nichts zu tun hat.
antwort = client.messages.create(
model="claude-opus-5",
max_tokens=1500,
system=SYSTEM,
messages=[{"role": "user", "content": frage}],
output_config={"format": STOERUNG_SCHEMA},
)
Unwissen braucht einen ausdrücklichen Weg im Schema — ein Feature, das nie „ich weiß es nicht” sagen kann, erfindet stattdessen:
"antwort_moeglich": {"type": "boolean"},
"grund_falls_nein": {
"type": "string",
"enum": ["nicht im handbuch",
"widersprüchliche angaben",
"frage unklar"],
},
Ein Feld ohne Fortsetzung im Code gehört nicht ins Schema. Feste Wertelisten statt freier Zeichenketten, wo die Menge bekannt ist; Pflichtfelder nur dort, wo der Code ohne sie nicht auskommt. Die fachliche Prüfung bleibt außerhalb — eine erfundene Katalognummer sieht formal einwandfrei aus, nur der Abgleich mit dem Bestand findet sie.
Modul: Strukturierte Ausgaben statt Textparsen
Was in den Index gehört
| Quelle | Entscheidung |
|---|---|
| Gültige Handbücher und Fachdokumente | aufnehmen |
| Nachträge und Korrekturen | aufnehmen, mit Vorrang vor dem Original |
| Abgelöste Fassungen | nicht aufnehmen |
| Stammdaten (Katalog, Verzeichnis) | aufnehmen |
| Bestandszahlen, tagesaktuelle Werte | nicht aufnehmen, Werkzeug |
| Interne Diskussionen und Entwürfe | nicht aufnehmen |
Abgelöste Fassungen sind der schlimmste Fall — einmal richtig, heute falsch, weiterhin glaubwürdig. Und Retrieval löst weniger, als oft angenommen wird:
| Gelöst | Nicht gelöst |
|---|---|
| Wissen, das im Modell fehlt | dass ein Modell erfinden kann |
| Aktualität des Bestands | Widersprüche im Bestand |
| Belegbarkeit der Antwort | Berechtigungen |
| Nachvollziehbare Quellen | falsche Auswahl unter richtigen Treffern |
Modul: Retrieval: der Korpus
Metadaten entscheiden über die Brauchbarkeit
| Feld | Wozu |
|---|---|
| Dokument und Fassung | Beleg und Vorrangregel |
| Gültigkeitszeitraum | abgelöste Angaben erkennen |
| Produktlinie und Baujahre | Filter vor der Suche |
| Baugruppe, Themenbereich | Eingrenzung aus der Anfrage |
| Seitenzahl | Sprung in die Quelle |
| Sichtbarkeit | wer das Dokument sehen darf |
Filtern vor der Suche schlägt jede Verbesserung am Suchverfahren. Rechte gehören dabei in den Index-Filter und stammen aus der Sitzung, nie aus einer Modellausgabe:
filter = {"sichtbarkeit": {"$in": rollen(sitzung)}}
if baureihe:
filter["baureihe"] = baureihe
treffer = index.suche(frage, filter=filter, k=20)
Modul: Retrieval: der Korpus
Wo reine Ähnlichkeitssuche versagt
| Anfrage | Falscher Treffer |
|---|---|
| Teilenummer TW-4471-B | TW-4471-A, anderes Teil |
| Fehlercode E-12 | E-13, andere Ursache |
| Baujahr 2019 | 2018, andere Bauteilgeneration |
| Drehmoment 18 Nm | 18 Nm einer anderen Baugruppe |
Wer nur Vektorsuche einsetzt, glänzt bei allgemeinen Fragen und versagt bei den wichtigen — deshalb hybride Suche, sobald Bezeichner im Spiel sind. Gemessen wird das Retrieval getrennt von der Antwort, sonst dreht man abwechselnd an der falschen Schraube:
| Befund | Ansatzpunkt |
|---|---|
| Trefferquote niedrig | Schnitt, Metadaten, hybride Suche |
| Trefferquote hoch, Antwort schlecht | Anweisung, Schema, Modell |
| Beides schlecht | zuerst das Retrieval, dann den Rest |
Modul: Retrieval: Finden
Belege und die erwünschte Verweigerung
| Ohne Beleg | Mit Beleg |
|---|---|
| Antwort muss geglaubt werden | Antwort kann geprüft werden |
| Fehler fällt beim Kunden auf | Fehler fällt beim Nachsehen auf |
| Bestandslücke bleibt unsichtbar | Bestandslücke wird gemeldet |
Der Beleg ist kein Zusatz für Fortgeschrittene, sondern Teil der Ausgabe — und er wird technisch verankert (Dokument, Fassung, Seite), nicht im Freitext formuliert. Drei Kennzahlen bleiben dabei getrennt:
| Kennzahl | Bewertung |
|---|---|
| Richtige Antwort | Ziel |
| Verweigerung | akzeptabel, kostet eine Rückfrage |
| Falsche Antwort | teuer, kostet einen Einsatz |
Eine falsche Antwort ist teurer als zehn Verweigerungen — das gehört beziffert, bevor man Schwellen festlegt.
Was Belege nicht leisten: die falsche Auswahl (korrekt zitiert, falsche Produktlinie), den falschen Schluss (richtig zitiert, Folgerung steht so nicht da), die Auslassung (der Warnhinweis zwei Absätze weiter fehlt) und die Scheingenauigkeit (der Beleg wirkt so solide, dass niemand mehr prüft). Alle vier sehen in der Einzelantwort korrekt aus und lassen sich nur an einer Menge von Fällen erkennen.
Modul: Antworten mit Belegen
Typische Fallen
- Ein Modell einsetzen, weil es im Zielbild steht, nicht weil es die Aufgabe trifft.
- Exakte Nachschlagevorgänge dem Modell überlassen statt einem Werkzeug.
- Tests schreiben, die auf Zeichengleichheit der Antwort prüfen.
- Prompts in einer Datenbank pflegen, wo sie kein Review und keine Historie haben.
- Regeln in die Nutzernachricht schreiben, wo fremder Text sie überschreiben kann.
- Identitäten oder Rechte als Text in den Prompt geben.
- Fehler mit Zeichenkettenvergleich erkennen statt über Fehlerklassen — und dabei ungültige Anfragen wiederholen.
- Selbstberichtete Vertrauenswerte als Schwelle im Code verwenden.
- Klassifizierung, Antwort und Priorisierung in einem Aufruf verlangen — zwei einfache Aufrufe kosten kaum mehr und lassen sich getrennt messen.
- Alles indizieren, was greifbar ist, und Rechte hinterher filtern wollen.
- Retrieval einbauen, bevor jemand die tatsächlichen Fragen der Nutzer kennt.
- Den Einbettungs-Bezug wechseln, ohne den Index neu zu bauen.
- Suchen, obwohl der ganze Bestand in den Prompt passt.
- Zitate kürzen, bis sie nicht mehr im Original auffindbar sind.