1. Einleitung
Manchmal zeigen Kurse zum Prompt‑Engineering eine magische Beschwörungsformel:
«Erfinde keine Fakten und sage “ich weiß es nicht”, wenn keine Informationen vorliegen.»
Leider (oder zum Glück) ist das für eine ChatGPT App keine Silberkugel. Der Grund ist einfach: Das Modell sieht nicht nur euren system‑prompt, sondern auch:
- die Liste der Tools mit ihren Beschreibungen und Schemata;
- die Ergebnisse dieser Tools;
- die Dialoghistorie, einschließlich vorheriger Follow‑ups.
Wenn diese drei Schichten — system‑prompt, Tool‑Beschreibungen, Follow‑up‑Muster — einander widersprechen oder einfach „in der Luft hängen“, verhält sich das Modell wie ein klassischer Junior: fleißig, aber geneigt, Dinge zu erfinden.
Im Kurs verwenden wir die Idee einer „dreistufigen Abwehr gegen Halluzinationen“ (defense in depth):
- Stufe 1 — globale Regeln im system‑prompt;
- Stufe 2 — lokale Einschränkungen in der Definition jedes einzelnen Tools;
- Stufe 3 — Umgang mit Fehlern, leeren Ergebnissen und Follow‑ups.
In dieser Lektion verbinden wir alle drei Ebenen zu einem einheitlichen, abgestimmten Vertrag für unsere Lern‑App GiftGenius.
Insight
In der neuen Architektur der ChatGPT Apps ist das Feld für den system‑prompt verschwunden — formal gibt es ihn nicht mehr. Das bedeutet jedoch nicht, dass ihr auf globale Anweisungen für das Modell verzichten müsst. Es gibt einen Trick: Für ChatGPT sind Tool‑Beschreibungen genau wie klassischer System‑Text ebenfalls Prompt‑Text. Darüber könnt ihr die „Gehirn‑Firmware“ der App wieder etablieren.
Erstellt ein Service‑Tool, zum Beispiel about oder about_app. Es ist nicht für häufige Aufrufe gedacht, aber seine description wird vom Modell gleichberechtigt mit den anderen Tools gelesen. Deshalb könnt ihr in die Beschreibung den vollständigen system‑prompt einbetten. Am besten platziert ihr ihn nach einer kurzen technischen Beschreibung des Tools selbst. So erhält das Modell zu Beginn euren system‑prompt unverfälscht — und wendet ihn auf den gesamten weiteren Dialog und die Tool‑Aufrufe an.
Zur einfacheren Wartung empfehle ich, an den Anfang des system‑prompt eine explizite Versionsangabe zu setzen, zum Beispiel SYSTEM_PROMPT_VERSION: v3. Das hilft zu verstehen, warum sich das Modell anders verhält: Ihr seht sofort, mit welchem Instruktionssatz es arbeitet. Tritt in Production ein seltsames Verhalten auf, ist leicht zu erkennen, ob der Fehler zur alten oder zur neuen Prompt‑Version gehört.
Beispiel:
tool description
### Global assistant behavior for the entire GiftGenius App (ver 3.01)
*(system-level guidelines, not user-facing text)*
system prompt text
2. Welche Halluzinationen hat eine ChatGPT App (am Beispiel eines Geschenkekatalogs)
Um zu wissen, wie man etwas behandelt, ist es hilfreich, die Krankheit zu benennen. Im Kontext eines Katalogs (Geschenke, Produkte, Tarife) treten am häufigsten die folgenden Arten von Halluzinationen auf.
Erstens: frei erfundene Katalogeinträge. Ein Nutzer bittet um einen „digitalen Gutschein für ein Jahresabo eines konkreten Dienstes“ oder um ein sehr exotisches Geschenk, das es in eurem Feed nicht gibt, und das Modell erfindet, in dem Wunsch, hilfreich zu sein, fröhlich „Super Space Flight 3000 — einen Flug ins All“, den es in der GiftGenius‑Datenbank nie gab.
Zweitens: erfundene Attribute. Das Geschenk gibt es im Katalog, aber das Modell „schmückt“ die Realität: Es ändert den Preis, den Geschenktyp (digital vs. physisch), die Lieferbarkeit in das Land des Nutzers oder die Gültigkeitsdauer des Gutscheins, weil es „logischer“ erscheint oder „besser klingt“.
Drittens: halluzinierte Aktionen. Das Modell schreibt „Ich habe dieses Geschenk bereits gekauft und den Code an Ihre E‑Mail geschickt, $49 wurden von der Karte abgebucht“, obwohl euer GiftGenius‑Backend gar keinen Kaufversuch unternommen und keinen ACP/Stripe‑Flow gestartet hat.
Schließlich gibt es einen kombinierten Fall: Ein Tool liefert eine leere Liste (keine Geschenke für diese Filter und dieses Budget), und das Modell erfindet, um den Nutzer nicht zu enttäuschen, ein paar „Beispieloptionen“ und erklärt nicht, dass es diese im Katalog gar nicht gibt.
Unsere Aufgabe ist es, das Modell in diesen Situationen dazu zu bringen:
- ehrlich einzugestehen, dass es keine exakte Übereinstimmung im Katalog gibt;
- keine neuen Geschenke zu erfinden und keine Feldwerte zu verändern;
- dem Nutzer zu erklären, was genau passiert ist, und einen klaren nächsten Schritt vorzuschlagen.
Und zwar nicht über „Zaubersprüche“ an beliebigen Stellen, sondern über einen verknüpften Vertrag system‑prompt ↔ tools ↔ follow‑ups.
3. Schicht 1: den system‑prompt gegen Halluzinationen verstärken
Um die erfundenen Geschenke, Attribute und Aktionen aus dem vorherigen Abschnitt zu stoppen, verstärken wir zunächst die oberste Schicht — den system‑prompt: Wir geben dem Modell eine allgemeine „Philosophie“ für das Verhalten im Katalog vor.
In der ersten Lektion des Moduls habt ihr bereits einen grundlegenden system‑prompt verfasst à la: „Du bist GiftGenius, du hilfst beim Finden von Geschenken…“ und die Verantwortungsgrenzen des Assistenten sowie die Arbeit mit den Tools festgelegt.
Jetzt fügen wir explizite Anti‑Halluzinations‑Regeln hinzu.
Die Logik ist: Der system‑prompt gibt die allgemeine Philosophie des Verhaltens vor. Er kennt keine Details jedes Tools, kann aber:
- verbieten, Geschenke/Preise/Verfügbarkeit außerhalb des Katalogs zu erfinden;
- das Verhalten definieren, falls Tools leere Ergebnisse oder Fehler zurückgeben;
- klar zwischen Daten aus dem Geschenkekatalog und jeglichem „Allgemeinwissen des Modells“ unterscheiden lassen.
Beispiel für einen Ausschnitt eines system‑prompt (TypeScript‑Konstante in unserem Next.js‑Projekt, z. B. config/systemPrompt.ts):
// config/systemPrompt.ts
export const SYSTEM_PROMPT = `
# Rolle
Du bist GiftGenius, ein Assistent zur Auswahl von Geschenken
auf Basis des Geschenkekatalogs unserer Anwendung.
# Daten und Einschränkungen
- Erfinde keine Geschenke, die nicht im Katalog oder in Tool-Antworten vorkommen.
- Erfinde keine Preise, keine Verfügbarkeit, keinen Geschenktyp (digital/physisch),
keine Lieferregionen oder andere Attribute.
- Wenn ein Tool die nötigen Daten nicht geliefert hat oder ein Fehler auftrat,
sage das ehrlich und versuche nicht, Werte zu raten.
# Arbeit mit Tools
- Nutze die Tools des Geschenkekatalogs für alle faktischen Daten:
Geschenkeliste, Preise, Typen, Verfügbarkeit, SKU.
- Wenn ein Tool ein leeres Ergebnis liefert, sage, dass unter den aktuellen Bedingungen
keine passenden Geschenke vorhanden sind, und schlage vor, die Filter zu lockern
(Budget, Kategorie, Geschenktyp ändern).
`;
Hier sind einige Punkte wichtig.
Erstens trennen wir klar „Allgemeinwissen des Modells“ und „Anwendungsdaten“. Das Modell kann weiterhin erklären, worin sich ein digitales von einem physischen Geschenk unterscheidet oder welche Anlässe üblich sind, aber alle konkreten Geschenke, Preise und SKUs müssen ausschließlich aus den GiftGenius‑Tools stammen.
Zweitens beschreiben wir explizit, was bei Fehlern/leerem Ergebnis zu tun ist: nicht schweigen, nicht „kreativ werden“, sondern dem Nutzer ehrlich mitteilen, dass nichts gefunden wurde, und eine Parameteränderung vorschlagen.
Drittens fokussieren wir nicht auf ein abstraktes „halluziniere nicht“, sondern auf konkrete Verhaltensmuster, die an unsere Domäne gebunden sind (Geschenkekatalog und Kauf digitaler/physischer SKUs).
Diese Schicht hilft bereits stark, kann aber leicht durch eine ungenaue Tool‑Beschreibung „überstimmt“ werden. Gehen wir zu den Tool‑Beschreibungen über.
4. Schicht 2: Tool‑Beschreibungen (tool descriptions) und Schemata als formaler Vertrag
Das Modell entscheidet, wann und wie es euer Tool aufruft, in erster Linie anhand von:
- dem Tool‑Namen;
- der description des Tools;
- inputSchema / outputSchema (JSON Schema, das die Felder beschreibt).
Die Tool‑Beschreibung (tool description) ist also keine „Dokumentation für Menschen“, sondern ebenso Teil des Prompts, nur formalisierter. Viele Halluzinationen entstehen genau hier.
Stellen wir uns unser Tool recommend_gifts vor, das der Backend als Geschenkeauswahl aus dem GiftGenius‑Katalog implementiert.
Eine schlechte Beschreibung könnte so aussehen:
// SCHLECHT: zu vage
const recommendGiftsTool = {
name: "recommend_gifts",
description: "Wählt Geschenke für den Nutzer aus",
inputSchema: {
type: "object",
properties: {
profile: { type: "string" }
}
}
};
Formal ist alles korrekt, aber das Modell versteht daraus nicht:
- wo die Grenzen des Tools liegen;
- was zu tun ist, wenn keine Geschenke gefunden werden;
- dass es verboten ist, Geschenke und Preise außerhalb des Katalogs zu erfinden.
Eine gute Beschreibung erreicht mehrere Dinge gleichzeitig: Sie steckt die Domäne klar ab, erklärt, wann das Tool zu verwenden ist, und hält streng fest, dass keine Ergebnisse erfunden werden dürfen.
Beispiel (angepasst an den GiftGenius‑Vertrag mit segments, budget, locale, occasion):
// config/tools.ts
export const recommendGiftsTool = {
name: "recommend_gifts",
description: `
Geschenkeauswahl im GiftGenius-Katalog.
Verwende dieses Tool, wenn du eine Liste realer Geschenke
nach Empfängerprofil-Segmenten, Budget, Locale und Anlass benötigst.
Das Tool liefert nur solche Geschenke, die tatsächlich im
GiftGenius-Katalog vorhanden sind.
Erfinde KEINE Geschenke und deren Attribute außerhalb der Tool-Ergebnisse.
Wenn das Tool eine leere Liste zurückgibt, erfinde keine Alternativen,
sondern gehe in den Dialog über: Schlage vor, Budget, Geschenktyp,
Anlass oder andere Parameter zu ändern.
`.trim(),
inputSchema: {
type: "object",
properties: {
segments: {
type: "array",
description:
"Empfängerprofil-Segmente, z. B. ['tech', 'fitness'].",
items: { type: "string" }
},
budget: {
type: "object",
description: "Budgetrahmen für das Geschenk.",
properties: {
min: {
type: "number",
description: "Mindestbetrag, nicht negativ.",
minimum: 0
},
max: {
type: "number",
description: "Höchstbetrag, größer als 0.",
exclusiveMinimum: 0
},
currency: {
type: "string",
description: "Dreistelliger Währungscode, z. B. 'USD' oder 'RUB'.",
minLength: 3,
maxLength: 3
}
},
required: ["min", "max", "currency"]
},
locale: {
type: "string",
description:
"Locale des Nutzers (Sprache/Region), z. B. 'ru-RU' oder 'en-US'.",
minLength: 2
},
occasion: {
type: "string",
description:
"Anlass für das Geschenk: z. B. 'birthday', 'anniversary', 'new_year'."
}
},
required: ["segments", "budget", "locale", "occasion"]
}
};
Diese description leistet mehrere hilfreiche Dinge.
Sie sagt ausdrücklich, dass das Tool nur mit dem GiftGenius‑Geschenkekatalog arbeitet und dass alle konkreten Geschenke und Preise ausschließlich aus dessen Ergebnis stammen sollen.
Sie erklärt, wann das Tool zu verwenden ist: wenn eine Liste konkreter Geschenke unter bestimmten Parametern benötigt wird, nicht aber bei allgemeinen Theoriefragen über Geschenke.
Sie legt das Verhalten bei leerem Ergebnis fest: nicht erfinden, sondern in den Dialog übergehen (was wir später in den Follow‑ups fixieren).
Und das inputSchema hilft dem Modell, Entitäten aus der Nutzeranfrage zuverlässiger zu extrahieren: Segmente, Budget, Locale und Anlass. Die Angabe einer klaren Struktur und Feldbeschränkungen (min, max, currency mit fixer Länge) reduziert ebenfalls die Wahrscheinlichkeit merkwürdiger Kombinationen und Fehler beim Parsen.
Man kann auch die Kehrseite ergänzen — nicht nur „wann verwenden“, sondern auch wann nicht verwenden. Zum Beispiel, wenn die Anfrage offenkundig theoretisch ist:
description: `
...
Verwende dieses Tool nicht, wenn der Nutzer eine allgemeine Frage
zu Geschenken stellt, ohne eine Auswahl für eine konkrete Person zu erbitten
(z. B. "welche Geschenke sind zu Neujahr allgemein beliebt").
In solchen Fällen antworte direkt im Chat.
`.trim()
So synchronisiert ihr die Tool‑Beschreibung mit den Regeln aus dem system‑prompt zu „theoretischen“ vs. „praktischen“ Anfragen.
5. Schicht 3: Follow‑ups als UX‑ und Safety‑Schicht
Selbst wenn system‑prompt und Tool‑Beschreibungen perfekt sind, ist das Leben nicht perfekt:
- das Backend kann einen Fehler zurückgeben;
- der Katalog — eine leere Liste;
- die Ergebnisse — mehrdeutig oder zu zahlreich.
Wenn nicht festgelegt ist, was nach dem Tool‑Aufruf zu sagen ist, improvisiert das Modell: manchmal gut, manchmal mit erfundenen Fakten.
In Lektion 2 habt ihr bereits grundlegende UX‑Anweisungen gesehen: wie das Modell den App‑Start ankündigt, wie es das Szenario beendet und was es dem Nutzer „am Ende“ sagt. Jetzt ergänzen wir Follow‑up‑Muster, die Halluzinationen reduzieren.
Diese Muster werden gewöhnlich direkt im system‑prompt in einem eigenen Block beschrieben, etwa „Dialog nach der Arbeit mit Tools“.
Beispielausschnitt:
// Fortsetzung SYSTEM_PROMPT
export const SYSTEM_PROMPT = `
# ... vorherige Abschnitte ...
# Dialog nach der Arbeit mit Tools
- Wenn das Geschenke-Tool eine leere Liste zurückgibt:
1) sage ehrlich, dass unter den aktuellen Filtern keine passenden Geschenke gefunden wurden;
2) schlage vor, 1–2 Schlüsselparameter zu ändern
(Budget, Geschenktyp, Interessen des Empfängers, Anlass).
- Wenn das Tool zu viele Optionen liefert:
1) wähle 3–7 der relevantesten;
2) erkläre ausdrücklich, nach welchen Kriterien du sie ausgewählt hast
(Interessenmatch, Budgettreffer, Bewertung).
- Wenn ein Toolfehler auftritt:
1) erfinde keine Daten;
2) sage, dass ein technischer Fehler aufgetreten ist, und schlage vor,
es später erneut zu versuchen oder die Anfrage zu vereinfachen.
`.trim();
Damit „flashen“ wir dem Modell beispielhafte Follow‑up‑Formulierungen ein. Es wird diese mit eigenen Worten aussprechen, aber mit vorgegebener Struktur:
- Feststellung des Fakts (leer / zu viel / Fehler);
- ehrliche Benennung der Einschränkung;
- ein behutsamer Vorschlag für den nächsten Schritt.
Für einen Geschenkekatalog ist das entscheidend: Statt „Alles ok, hier sind drei Geschenke“ sagt das Modell bei leerem Ergebnis etwas wie:
«Unter Ihren aktuellen Bedingungen (digitales Geschenk zum Thema Weltraum bis $5 mit Lieferung nur in die USA) gibt es in unserem Katalog nichts. Soll ich das Budget erhöhen oder andere Kategorien vorschlagen?»
Beachtet: Das ist kein Tool‑Code, sondern Prompt‑Instruktion, die den erwarteten UX vorgibt.
6. Alles zusammenführen: die Evolution unseres GiftGenius
Schauen wir uns eine Mini‑Evolution unserer App an und reduzieren Schritt für Schritt den Halluzinationsgrad.
Ausgangsversion: wo alles bricht
Angenommen, wir hatten einen sehr minimalistischen system‑prompt:
export const SYSTEM_PROMPT = `
Du bist ein Assistent zur Geschenkeauswahl.
Hilf dem Nutzer, passende Ideen zu finden.
`;
Das Tool war so beschrieben:
export const recommendGiftsTool = {
name: "recommend_gifts",
description: "Wählt Geschenke für den Nutzer aus",
inputSchema: { type: "object" }
};
Follow‑up‑Instruktionen gibt es keine.
Was in der Praxis passiert:
- Wenn der Nutzer „ein digitales Geschenk für einen Gamer‑Freund bis $10“ verlangt und es in der Datenbank für diese Filter nichts gibt, kann das Modell:
- entweder das Tool gar nicht aufrufen und Geschenke aus dem Kopf erfinden;
- oder das Tool aufrufen, eine leere Liste erhalten, dies aber nicht erwähnen und Varianten erfinden;
- Wenn das Backend einen Fehler liefert, könnte das Modell annehmen, „irgendwas muss es geben“, und zu raten beginnen.
So entsteht die klassische Situation: im Chat eine schöne Antwort, in der Datenbank nichts dergleichen.
Neue Version des system‑prompt
Schreiben wir den system‑prompt mit den drei Schutzebenen neu. Teile davon habt ihr oben gesehen; hier vollständig:
// config/systemPrompt.ts
export const SYSTEM_PROMPT = `
# Rolle
Du bist GiftGenius, ein Assistent zur Auswahl von Geschenken
auf Basis des Geschenkekatalogs unserer Anwendung.
# Verantwortungsbereich
- Deine Aufgabe ist es, dem Nutzer zu helfen, passende Geschenke
aus dem Katalog auszuwählen und die Vor- und Nachteile zu erklären.
- Gib keine Versprechen über den tatsächlichen Kauf oder Versand eines Geschenks ab —
du hilfst nur bei der Auswahl und beim Vergleich.
Den Kauf und die Code-/Link-Ausgabe übernimmt das Backend nach ausdrücklicher Zustimmung des Nutzers.
# Daten und Einschränkungen
- Erfinde keine Geschenke, die nicht im Katalog oder in Tool-Antworten vorkommen.
- Erfinde keine Preise, Geschenktypen, Verfügbarkeit oder Lieferregionen.
- Wenn ein Tool keine Daten geliefert hat oder ein Fehler auftrat,
rate nicht, sondern teile das mit.
# Arbeit mit Tools
- Verwende die Tools des Geschenkekatalogs (z. B. profile_to_segments,
recommend_gifts, get_gift) für alle faktischen Daten
(Geschenkeliste, Preise, Typen, SKU, Beschreibungen).
- Antworte selbst (ohne Tools), wenn die Frage theoretisch ist
und keine Auswahl eines konkreten Geschenks erfordert.
# Dialog nach der Arbeit mit Tools
- Bei leerem Ergebnis: Erkläre ehrlich, dass nichts gefunden wurde
unter den aktuellen Bedingungen, und schlage vor, 1–2 Parameter zu ändern.
- Bei zu vielen Optionen: Wähle 3–7 der passendsten
und erkläre die Auswahlkriterien.
- Bei einem Toolfehler: Erfinde keine Daten, entschuldige dich für die Störung
und schlage vor, es erneut zu versuchen oder die Anfrage zu vereinfachen.
`.trim();
Jetzt weiß das Modell genau:
- wo es Berater für Geschenke ist und wo der „Back‑Office“‑Teil liegt (bei uns hinter den Tools);
- welche Daten es auf keinen Fall erfinden darf;
- wie es sich in typischen, nicht idealen Situationen verhalten soll.
Neue description und Schema für recommend_gifts
Wir haben den System‑Prompt verstärkt, nun bringen wir das Tool in Form und erstellen die finale Version seiner Beschreibung — auf Basis der Ideen aus Abschnitt 4.
// config/tools.ts
export const recommendGiftsTool = {
name: "recommend_gifts",
description: `
Geschenkeauswahl im GiftGenius-Katalog.
Verwende dieses Tool, wenn du Folgendes brauchst:
- eine Liste echter Geschenke mit aktuellen Preisen, Typ
(digital/physical) und Tags;
- eine Eingrenzung nach Interessensegmenten, Budget, Locale und Anlass.
NICHT VERWENDEN:
- wenn der Nutzer eine allgemeine theoretische Frage zu Geschenken stellt,
ohne eine Auswahl für eine konkrete Person zu wünschen;
- um Geschenke zu erfinden, die nicht im Katalog sind.
Wenn das Ergebnis leer ist, erfinde KEINE Geschenke selbstständig,
sondern gib die Kontrolle an den Dialog zurück (folge den Anweisungen des system‑prompt).
`.trim(),
inputSchema: {
type: "object",
properties: {
segments: {
type: "array",
description:
"Empfängerprofil-Segmente: z. B. 'tech', 'sport', 'books'.",
items: { type: "string" }
},
budget: {
type: "object",
description:
"Budgetrahmen für das Geschenk in der Währung des Nutzers (min/max).",
properties: {
min: { type: "number", minimum: 0 },
max: { type: "number", exclusiveMinimum: 0 },
currency: {
type: "string",
minLength: 3,
maxLength: 3,
description: "ISO‑4217‑Währungscode, z. B. 'USD' oder 'RUB'."
}
},
required: ["min", "max", "currency"]
},
locale: {
type: "string",
description: "Locale des Nutzers, z. B. 'ru-RU' oder 'en-US'."
},
occasion: {
type: "string",
description:
"Anlass für das Geschenk: 'birthday', 'anniversary', 'new_year' usw."
}
},
required: ["segments", "budget", "locale", "occasion"]
}
};
Hier gibt es einige Nuancen.
Wir verknüpfen das Toolverhalten explizit mit dem system‑prompt: Die Formulierung „folge den Anweisungen des system‑prompt“ erinnert das Modell daran, dass „leeres Ergebnis = ehrliches Gespräch statt Kreativität“ bedeutet.
Wir definieren negative Bedingungen („nicht verwenden…“, „nicht erfinden…“), was in der Praxis mindestens ebenso wichtig ist wie positive Beschreibungen.
Wir machen das inputSchema semantisch reichhaltig: Gute Beschreibungen und Einschränkungen helfen dem Modell, Anfragen korrekt Feldern zuzuordnen und bereits vor dem Tool‑Aufruf weniger „Fehler“ zu machen.
Follow‑up‑Muster im Widget‑Code und im Antwortformat
Neben textlichen Instruktionen haben wir einen weiteren Hebel — das Antwortformat des Tools selbst. Darüber können wir dem Modell ebenfalls signalisieren, was passiert ist, und den Spielraum für Fantasie verringern.
Formal werden Follow‑ups per Text im system‑prompt festgelegt, aber in eurem Next.js‑Widget könnt ihr zusätzlich die ToolOutput‑Struktur normalisieren, um dem Modell das Leben zu erleichtern und den Raum für Fantasie zu verkleinern.
Zum Beispiel vereinbaren wir, dass das Backend für recommend_gifts immer Folgendes zurückgibt:
// Antworttyp des Tools im Backend
export type RecommendGiftsResult = {
items: Array<{
id: string;
title: string;
price: number;
currency: "USD" | "EUR" | "RUB";
tags: ("digital" | "physical" | "education" | "fitness" | "tech")[];
}>;
// Feld, das das Backend setzt, um dem Modell explizit mitzuteilen, was passiert ist
status: "ok" | "empty" | "error";
errorMessage?: string;
};
Das Widget kann das hübsch darstellen, und das Modell kann sich beim Formulieren der Antwort am status orientieren. Im Apps SDK gebt ihr der Modellantwort das ToolOutput häufig als JSON‑Objekt zurück — es sieht dieses Feld also.
Im system‑prompt kann man einen kleinen Block ergänzen:
# Interpretation des Tool-Status
- Wenn status = "empty": siehe Abschnitt "Dialog nach der Arbeit mit Tools" und
erfinde keine Geschenke.
- Wenn status = "error": teile den technischen Fehler mit und versuche nicht,
den Kataloginhalt zu erraten.
Ja, das Modell könnte das auch so erschließen, aber eine explizite Anweisung reduziert die Chance auf „Raten“.
7. Praxis: die eigene App nachschärfen
Damit es nicht wie „schön auf Folien, aber…“ wirkt, beschreiben wir eine konkrete Übung, die ihr mit eurer aktuellen App (bei uns — GiftGenius) durchführen könnt. Wir machen ein kleines Refactoring entlang der drei Schutzschichten: system‑prompt, Tool‑Beschreibungen und Ergebnisverarbeitung.
Erstens, auf der Ebene des system‑prompt: Nehmt euren system‑prompt aus der ersten Lektion und findet die Stelle, an der Verantwortungsbereich und Tool‑Nutzung beschrieben sind. Ergänzt dort:
- ein Verbot, Entitäten außerhalb des Katalogs/der Datenbank zu erfinden (Geschenke, SKU, Preise);
- Regeln für den Fall eines leeren Ergebnisses und eines Toolfehlers;
- einen Abschnitt „Dialog nach der Arbeit mit Tools“ mit 2–3 Szenarien (leer, zu viel, Fehler).
Zweitens, auf der Ebene der Tool‑Beschreibungen: Öffnet die Beschreibung eures Schlüsseltools (bei euch kann das recommend_gifts, search_gifts, search_tariffs, calculate_quote etc. sein). Schreibt die description so um, dass sie:
- klar sagt, dass das Tool nur mit eurer Datenquelle arbeitet (Geschenke‑, Tarifkatalog usw.);
- erklärt, wann es gebraucht wird und wann nicht;
- explizite negative Einschränkungen enthält: „erfinde nicht…“, „nicht verwenden für…“.
Drittens, auf der Ebene der Tool‑Antwortstruktur: Falls die Tool‑Antwort noch kein Feld enthält, das den Status explizit beschreibt (status, resultType, hasMore) — fügt es im Backend‑Typ und im ToolOutput hinzu. Schreibt dann im system‑prompt, wie das Modell diesen Status im Dialog interpretieren soll.
Führt schließlich ein paar Anfragen im Dev Mode durch, darunter solche mit garantiert leeren oder grenzwertigen Ergebnissen. Achtet darauf, ob das Modell aufgehört hat zu erfinden und wie ehrlich es dem Nutzer die Einschränkungen erklärt.
In der nächsten Lektion werdet ihr solche Anfragen in ein sogenanntes golden prompt set formalisieren und daraus ein wiederholbares Testartefakt machen. Für den Moment ist wichtig, dass ihr den Unterschied praktisch spürt.
8. Typische Fehler beim Kampf gegen Halluzinationen via Prompts und Tools
Fehler Nr. 1: eine einzige Zauberformel „halluziniere nicht“ im system‑prompt.
Der Entwickler schreibt am Ende des Prompts: „Erfinde keine Informationen“ — und hält die Aufgabe für erledigt. In der Praxis halluziniert das Modell weiter, weil Tool‑Beschreibungen und Follow‑ups kein alternatives Verhalten vorgeben. Ohne konkrete Regeln „was statt des Erfindens zu tun ist“ (leeres Ergebnis eingestehen, Filter ändern vorschlagen, Fehler melden) hilft so eine Floskel kaum.
Fehler Nr. 2: Widerspruch zwischen system‑prompt und Tool‑description.
Im system‑prompt sagt ihr: „Erfinde keine Geschenke, die nicht im Katalog stehen“, und in der Tool‑Beschreibung steht: „Wählt passende Geschenke aus, und wenn nichts gefunden wird, kann es ähnliche Optionen nach eigenem Ermessen vorschlagen.“ Am Ende schwankt das Modell zwischen zwei Wahrheiten, und leider gewinnt die spezifischere (meist die Tool‑description). Beide Schichten müssen dasselbe sagen: Wenn ähnliche Optionen zulässig sind, muss das ebenfalls formalisiert werden (und dem Nutzer unbedingt erklärt werden, dass es keine exakte Übereinstimmung ist).
Fehler Nr. 3: zu vage Tool‑Beschreibungen.
Eine Beschreibung à la „Ein Tool, das dem Nutzer hilft, Aufgaben zu lösen“ gibt dem Modell kaum Information über die Tool‑Grenzen. In diesem Fall wird es das Tool entweder gar nicht verwenden oder bei jeder Gelegenheit aufrufen — und anschließend „Daten dazuerfinden“, wenn das Tool wenig oder nichts zurückgibt. Eine gute description muss diskriminativ sein: klar sagen, was das Tool tut und wann es nicht aufzurufen ist.
Fehler Nr. 4: keine Strategie für leere und fehlerhafte Ergebnisse.
Der Entwickler baut liebevoll ein Backend, das { items: [], status: "empty" } zurückgibt, erklärt dem Modell aber nirgends, was das bedeutet. Das Modell sieht ein leeres Array und schließt: „Dann sollte ich wohl etwas aus dem Allgemeinwissen vorschlagen.“ Im system‑prompt fehlt ein Abschnitt, der erklärt, wie solche Status zu interpretieren sind und was dem Nutzer zu sagen ist. Das Hinzufügen weniger klarer Regeln für leere/fehlerhafte Ergebnisse bringt enorme Qualitätsgewinne.
Fehler Nr. 5: der Versuch, Halluzinationen ausschließlich auf UI‑/Widget‑Ebene zu „heilen“.
Manchmal möchte man alles auf das Frontend abladen: „Wenn die Liste leer ist — zeige ich einen Platzhalter und lasse den Nutzer die Textantwort des Modells nicht sehen.“ Das kann den UX minimal abfedern, aber das Modell glaubt weiter an erfundene Entitäten und verhält sich in folgenden Turn‑Takes genauso. Der richtige Ansatz: zuerst die Instruktionen anpassen (system‑prompt, Tool‑Beschreibungen, Follow‑ups) und danach UI‑Schutzmechanismen ergänzen.
Fehler Nr. 6: den Einfluss von Metadaten und Schemata auf das Modellverhalten ignorieren.
Manche Entwickler sehen JSON Schema und Feldbeschreibungen als „nur für Form und Validierung“. Tatsächlich sind sie für ChatGPT ein wichtiger Prompt‑Bestandteil: Anhand der Beschreibungen versteht das Modell, welche Parameter es aus der Anfrage extrahieren muss und wie eine korrekte Antwort aussieht. Schwache oder inkonsistente Feldbeschreibungen (description, enum) erhöhen die Fehlerwahrscheinlichkeit und provozieren indirekt Halluzinationen.
Fehler Nr. 7: zu harte Verbote ohne Alternativen.
Mitunter wird der Prompt zu einer reinen Liste „Tu dies nicht, tu das nicht“, ohne zu sagen, was in schwierigen Fällen zu tun ist. Beispielsweise verbieten wir das Erfinden von Geschenken und beschränken uns auf den Katalog, sagen aber nichts zu theoretischen Fragen. In der Folge antwortet das Modell manchmal einfach „ich weiß es nicht“, obwohl es nützliche allgemeine Prinzipien zur Geschenkeauswahl erklären könnte. Versucht immer, nicht nur zu verbieten, sondern auch erlaubte Wege aufzuzeigen: „Wenn du kein Geschenk im Katalog findest — sage das ehrlich und schlage eine Anpassung der Anfrage vor“ oder „Wenn die Anfrage theoretisch ist — antworte selbst, ohne Tools“.
GO TO FULL VERSION