Challenge 1.3: Text generieren
Was bekommst Du zurück, wenn Du ein LLM um Text bittest — nur den Text, oder mehr?
OVERVIEW
Abschnitt betitelt „OVERVIEW“generateText nimmt model + prompt als Input und gibt ein reichhaltiges Result-Objekt zurück. Neben dem Text bekommst Du Token-Verbrauch, den Grund für das Stoppen, einzelne Schritte und die rohe Response.
Ohne Verständnis des Result-Objekts: Du nutzt nur result.text und verpasst alles andere. Du hast keine Kontrolle über Kosten (Token-Tracking), kein Debugging (Finish Reason), kein Verständnis für Multi-Step-Verarbeitung (Steps). Wenn etwas schiefgeht, tappst Du im Dunkeln.
Mit Verständnis des Result-Objekts: Du trackst Token-Verbrauch für Kostenoptimierung, erkennst über finishReason, warum eine Antwort abgeschnitten wurde, und nutzt Callbacks für Logging und Monitoring. Volle Kontrolle statt Blackbox.
WALKTHROUGH
Abschnitt betitelt „WALKTHROUGH“Schicht 1: generateText Basics
Abschnitt betitelt „Schicht 1: generateText Basics“Die einfachste Form — model + prompt rein, result raus:
import { generateText } from 'ai';import { anthropic } from '@ai-sdk/anthropic';
const result = await generateText({ model: anthropic('claude-sonnet-4-5-20250514'), prompt: 'Erklaere Promises in JavaScript.',});generateText ist eine async Funktion. Sie wartet, bis das LLM die komplette Antwort generiert hat, und gibt dann das Result-Objekt zurück. Kein Streaming — alles auf einmal.
Schicht 2: Das Result-Objekt im Detail
Abschnitt betitelt „Schicht 2: Das Result-Objekt im Detail“Das Result-Objekt hat fuenf wichtige Properties:
// Der generierte Text als Stringresult.text// → "Promises in JavaScript sind Objekte, die einen..."
// Token-Verbrauch — wichtig für Kostenberechnungresult.usage// → { promptTokens: 12, completionTokens: 150, totalTokens: 162 }
// Warum hat das LLM aufgehoert zu generieren?result.finishReason// → 'stop' — LLM ist fertig (normal)// → 'length' — Token-Limit erreicht (Antwort abgeschnitten!)// → 'tool-calls' — LLM will ein Tool aufrufen
// Alle Schritte bei Multi-Step-Verarbeitungresult.steps// → [{ text, usage, finishReason, ... }]
// Rohe Response (Headers, Messages)result.response// → { headers, messages, body }Besonders wichtig: Wenn finishReason den Wert 'length' hat, wurde die Antwort abgeschnitten. Das bedeutet, das Token-Limit wurde erreicht, bevor das LLM fertig war. Du siehst dann eine unvollstaendige Antwort. In dem Fall kannst Du maxTokens erhöhen:
const result = await generateText({ model: anthropic('claude-sonnet-4-5-20250514'), maxTokens: 4096, // ← Standard ist oft niedriger prompt: '...',});Schicht 3: Die system + prompt Kombination
Abschnitt betitelt „Schicht 3: Die system + prompt Kombination“Mit dem system-Parameter gibst Du dem LLM eine Rolle. Der prompt ist dann die eigentliche Aufgabe. (Details zu System Prompts und wie Du sie optimal gestaltest, lernst Du in Challenge 1.6.)
const result = await generateText({ model: anthropic('claude-sonnet-4-5-20250514'), system: 'Du bist ein erfahrener TypeScript-Entwickler. Erklaere kurz und praezise.', // ← Rolle prompt: 'Erklaere Promises in JavaScript.', // ← Aufgabe});system beeinflusst, WIE das LLM antwortet (Stil, Ton, Perspektive). prompt bestimmt, WORUEBER es antwortet (Inhalt). Die Trennung ist wichtig — system bleibt oft gleich, waehrend prompt sich ändert.
Schicht 4: Callbacks — onFinish und onStepFinish
Abschnitt betitelt „Schicht 4: Callbacks — onFinish und onStepFinish“Callbacks werden aufgerufen, wenn die Generierung abgeschlossen ist. Nuetzlich für Logging, Kosten-Tracking oder Analytics:
const result = await generateText({ model: anthropic('claude-sonnet-4-5-20250514'), system: 'Du bist ein erfahrener TypeScript-Entwickler.', prompt: 'Erklaere Promises in JavaScript.', onFinish({ text, usage, finishReason }) { // ← Wird nach Abschluss aufgerufen console.log(`Tokens verbraucht: ${usage.totalTokens}`); // ← Kosten tracken console.log(`Finish Reason: ${finishReason}`); // ← Debugging }, onStepFinish({ stepNumber, finishReason, usage }) { // ← Pro Schritt (bei Multi-Step) console.log(`Schritt ${stepNumber} fertig.`); },});onFinish wird einmal am Ende aufgerufen. onStepFinish wird nach jedem einzelnen Schritt aufgerufen — relevant bei Tool Calls, wenn mehrere LLM-Aufrufe hintereinander passieren (das lernst Du in Level 3).
Aufgabe: Generiere Text mit system + prompt, logge das vollständige Result-Objekt und implementiere einen onFinish Callback.
import { generateText } from 'ai';import { anthropic } from '@ai-sdk/anthropic';
// TODO 1: Rufe generateText auf mit:// - model: anthropic('claude-sonnet-4-5-20250514')// - system: Eine Rolle Deiner Wahl// - prompt: Eine Frage Deiner Wahl// - onFinish: Callback der Tokens loggt
// TODO 2: Logge result.text// TODO 3: Logge result.usage.totalTokens// TODO 4: Logge result.finishReasonCheckliste:
-
systemundpromptbeide gesetzt -
result.textgeloggt -
result.usage.totalTokensgeloggt -
result.finishReasongeloggt -
onFinishCallback implementiert
Lösung anzeigen
import { generateText } from 'ai';import { anthropic } from '@ai-sdk/anthropic';
const result = await generateText({ model: anthropic('claude-sonnet-4-5-20250514'), system: 'Du bist ein erfahrener TypeScript-Entwickler. Erklaere Konzepte kurz und praezise mit Codebeispielen.', prompt: 'Was ist der Unterschied zwischen interface und type in TypeScript?', onFinish({ text, usage, finishReason }) { console.log(`\n--- onFinish Callback ---`); console.log(`Tokens verbraucht: ${usage.totalTokens}`); console.log(`Finish Reason: ${finishReason}`); },});
console.log('--- Generierter Text ---');console.log(result.text);
console.log('\n--- Details ---');console.log('Total Tokens:', result.usage.totalTokens);console.log('Prompt Tokens:', result.usage.promptTokens);console.log('Completion Tokens:', result.usage.completionTokens);console.log('Finish Reason:', result.finishReason);Erklärung: Der onFinish Callback wird aufgerufen, sobald die Generierung abgeschlossen ist — noch bevor Du result.text loggst. Das macht ihn ideal für Logging und Monitoring, weil er garantiert ausgefuehrt wird, egal was danach im Code passiert.
Ausfuehren:
npx tsx challenge-1-3.tsErwarteter Output (ungefaehr):
--- onFinish Callback ---Tokens verbraucht: 162Finish Reason: stop--- Generierter Text ---Interfaces und Types in TypeScript sind sich aehnlich...--- Details ---Total Tokens: 162Prompt Tokens: 18Completion Tokens: 144Finish Reason: stopCOMBINE
Abschnitt betitelt „COMBINE“Uebung: Kombiniere generateText mit der selectModel-Funktion aus Challenge 1.2. Generiere Text mit verschiedenen Modellen und vergleiche usage.totalTokens.
- Nutze
selectModel('zusammenfassen')für ein Flash-Modell - Nutze
selectModel('analysieren')für ein Pro-Modell - Stelle denselben
promptan beide Modelle - Vergleiche: Welches Modell verbraucht mehr Tokens? Welches antwortet besser?
Optional Stretch Goal: Baue eine trackCost-Funktion, die usage.totalTokens in geschaetzte Kosten umrechnet (z.B. 1 Token = $0.000003 für Claude Sonnet). Nutze den onFinish Callback, um die Kosten zu loggen.