Challenge 5.1: The Template
Wenn Du einen System Prompt schreibst — wie stellst Du sicher, dass er bei 20 verschiedenen API-Calls konsistent bleibt?
OVERVIEW
Abschnitt betitelt „OVERVIEW“Das Diagramm zeigt die Kernidee: Ein Prompt Template definiert eine feste Struktur mit XML Tags. Variablen werden dynamisch injiziert. Das Ergebnis ist ein konsistenter, wiederverwendbarer Prompt für beliebig viele API-Calls.
Ohne Template: Du kopierst Prompts per Copy-Paste in jede Datei. Jeder Prompt sieht leicht anders aus. Aenderungen am Ton oder Format müssen an 20 Stellen gleichzeitig gemacht werden. Das Ergebnis ist inkonsistent und nicht testbar.
Mit Template: Ein Prompt, eine Stelle, viele Aufgaben. Du aenderst die Variablen — der Rest bleibt gleich. DRY (Don’t Repeat Yourself), testbar, wartbar.
WALKTHROUGH
Abschnitt betitelt „WALKTHROUGH“Schicht 1: Die Grundstruktur (XML Tags für Sections)
Abschnitt betitelt „Schicht 1: Die Grundstruktur (XML Tags für Sections)“Anthropic empfiehlt, Prompts mit XML Tags zu strukturieren. Jeder Tag hat eine bestimmte Funktion und Position — die Reihenfolge folgt der Aufmerksamkeitsverteilung von LLMs:
<task-context>Rolle und Aufgabe — steht am ANFANG (hoher Einfluss)</task-context>
<background-data>Dokumente, Kontext — steht in der MITTE</background-data>
<examples>Few-Shot Beispiele — steht in der MITTE</examples>
<rules>Detaillierte Anweisungen — steht in der MITTE</rules>
<conversation-history>Chat-Verlauf — steht in der MITTE</conversation-history>
<the-ask>Die eigentliche Frage — steht am ENDE (hoher Einfluss)</the-ask>
<output-format>Ausgabeformat — steht am ENDE (hoher Einfluss)</output-format>LLMs gewichten Anfang und Ende staerker als die Mitte. Deshalb stehen <task-context> und <output-format> an den Raendern — dort, wo sie den groessten Einfluss haben.
Schicht 2: Variables und dynamische Inhalte
Abschnitt betitelt „Schicht 2: Variables und dynamische Inhalte“Die XML-Struktur allein ist statisch. Um sie wiederverwendbar zu machen, nutzt Du TypeScript Template Literals. Variablen werden an den richtigen Stellen injiziert:
// Template Literal: Variablen werden zur Laufzeit eingesetzt// Die ${...}-Ausdruecke werden durch die config-Werte ersetzt:// config.role → Rolle dynamisch// config.audience → Zielgruppe dynamisch// config.tone → Ton dynamisch// config.outputFormat → Format dynamischconst systemPrompt = `<task-context>Du bist ein ${config.role}.Deine Zielgruppe: ${config.audience}.</task-context>
<rules>- Schreibe ${config.tone}- Fachbegriffe beim ersten Auftreten erklären- Keine Annahmen ohne Kennzeichnung</rules>
<output-format>Formatiere Deine Antwort als: ${config.outputFormat}</output-format>`;Jede Variable macht den Prompt flexibel, ohne die Struktur zu veraendern. Derselbe Prompt funktioniert für einen “technischen Redakteur” genauso wie für einen “Marketing-Texter” — nur die Variablen ändern sich.
Schicht 3: Die buildSystemPrompt Funktion
Abschnitt betitelt „Schicht 3: Die buildSystemPrompt Funktion“Die letzte Schicht kapselt alles in einer wiederverwendbaren Funktion:
import { generateText } from 'ai';import { anthropic } from '@ai-sdk/anthropic';
interface PromptConfig { role: string; audience: string; tone: string; outputFormat: string;}
function buildSystemPrompt(config: PromptConfig): string { // ← Reusable Funktion return `<task-context>Du bist ein ${config.role}.Deine Zielgruppe: ${config.audience}.</task-context>
<rules>- Schreibe ${config.tone}- Fachbegriffe beim ersten Auftreten erklären- Keine Annahmen ohne Kennzeichnung- Codebeispiele müssen lauffaehig sein</rules>
<output-format>Formatiere Deine Antwort als: ${config.outputFormat}</output-format> `.trim();}
// Derselbe Prompt, verschiedene Konfigurationen:const result = await generateText({ model: anthropic('claude-sonnet-4-5-20250514'), system: buildSystemPrompt({ // ← Template wird hier genutzt role: 'technischer Redakteur', audience: 'Entwickler mit 2 Jahren Erfahrung', tone: 'professionell aber zugaenglich', outputFormat: 'Markdown mit Codebeispielen', }), prompt: 'Erklaere, was Context Engineering ist.',});
console.log(result.text);Die Funktion nimmt ein PromptConfig-Objekt und gibt einen vollstaendigen System Prompt als String zurück. Du kannst sie in Tests mocken, in verschiedenen Kontexten wiederverwenden und an einer Stelle ändern.
Aufgabe: Baue Deine eigene buildSystemPrompt-Funktion. Sie soll ein Template mit XML Tags zurueckgeben, das mindestens vier Sektionen hat.
Erstelle die Datei challenge-5-1.ts und fuehre sie aus mit: npx tsx challenge-5-1.ts
import { generateText } from 'ai';import { anthropic } from '@ai-sdk/anthropic';
interface PromptConfig { role: string; audience: string; tone: string; outputFormat: string;}
// TODO: Implementiere buildSystemPrompt// 1. Nutze Template Literals (Backticks)// 2. Setze XML Tags für die Struktur ein:// - <task-context> für Rolle und Zielgruppe// - <rules> für Tonalitaet und Einschraenkungen// - <output-format> für das gewuenschte Format// 3. Injiziere die config-Variablen an den richtigen Stellenfunction buildSystemPrompt(config: PromptConfig): string { // Dein Code hier return '';}
const result = await generateText({ model: anthropic('claude-sonnet-4-5-20250514'), system: buildSystemPrompt({ role: 'technischer Redakteur', audience: 'Entwickler mit 2 Jahren Erfahrung', tone: 'professionell aber zugaenglich', outputFormat: 'Markdown mit Codebeispielen', }), prompt: 'Erklaere, was Context Engineering ist.',});
console.log(result.text);Checkliste:
- Template nutzt XML Tags für Struktur
- Mindestens 4 Sektionen (role, audience, tone, format)
- Funktion gibt einen String zurück
- Code laeuft mit
generateText
Lösung anzeigen
import { generateText } from 'ai';import { anthropic } from '@ai-sdk/anthropic';
interface PromptConfig { role: string; audience: string; tone: string; outputFormat: string;}
function buildSystemPrompt(config: PromptConfig): string { return `<task-context>Du bist ein ${config.role}.Deine Zielgruppe: ${config.audience}.</task-context>
<rules>- Schreibe ${config.tone}- Fachbegriffe beim ersten Auftreten erklären- Keine Annahmen ohne Kennzeichnung- Codebeispiele müssen lauffaehig sein</rules>
<output-format>Formatiere Deine Antwort als: ${config.outputFormat}</output-format> `.trim();}
const result = await generateText({ model: anthropic('claude-sonnet-4-5-20250514'), system: buildSystemPrompt({ role: 'technischer Redakteur', audience: 'Entwickler mit 2 Jahren Erfahrung', tone: 'professionell aber zugaenglich', outputFormat: 'Markdown mit Codebeispielen', }), prompt: 'Erklaere, was Context Engineering ist.',});
console.log(result.text);Erklärung: Die Funktion nutzt <task-context> am Anfang für maximalen Einfluss auf die Rolle und <output-format> am Ende für maximale Kontrolle über das Format. Die <rules> stehen in der Mitte. Alle vier config-Variablen werden dynamisch injiziert.
Erwarteter Output (ungefaehr — LLM-Ausgaben variieren):
Context Engineering ist die systematische Gestaltung des Inputs...COMBINE
Abschnitt betitelt „COMBINE“Uebung: Nutze Dein Template jetzt mit streamText statt generateText. Streame die Antwort ins Terminal.
Du brauchst:
- Ersetze
generateTextdurchstreamText - Iteriere über
result.textStreammitfor await...of - Gib jeden Chunk mit
process.stdout.write(chunk)aus
Optional Stretch Goal: Fuege einen zweiten Aufruf hinzu, der dasselbe Template mit einer anderen Konfiguration nutzt (z.B. role: 'Marketing-Texter'). Vergleiche die Outputs.