Wie Sie mit strukturierten XML-Prompts vorhersagbare, parsbare und produktionssichere KI-Ausgaben erzeugen

Bei myos bauen wir KI-Betriebssysteme für echte Unternehmen. Der Unterschied zwischen einem hübschen Demo und einem belastbaren Produktiv-Workflow entscheidet sich fast immer an einer Stelle: der Struktur des Prompts. XML-Prompting ist eine der zuverlässigsten Methoden, um Modell-Ausgaben vorhersagbar, maschinell auswertbar und sicher in nachgelagerten Code einbindbar zu machen.
Dieser Leitfaden ist unsere Arbeitsreferenz. Wir greifen darauf zurück, wenn wir Extraktions-Pipelines, Routing-Schichten und strukturierte Generierung entwerfen. Sie können die Vorlagen direkt übernehmen oder die Tag-Namen an Ihre Domäne anpassen.
XML eignet sich aus mehreren Gründen besonders gut für Prompts:
Setzen Sie XML ein, um Ausgaben zu erzwingen, Informationen zu extrahieren, Aufgaben zu routen, Formate durchzusetzen, Few-Shot-Beispiele zu kennzeichnen und Selbstprüfungen laufen zu lassen. Und das alles, ohne verstecktes schrittweises Nachdenken (Chain-of-Thought) zu verlangen.
Faustregel: XML oder JSON?
Wenn Ihre Prompts oder Ausgaben viel Freitext oder Code enthalten, spielt XML seine Stärken aus. Für rein numerische, flache Datenstrukturen kann JSON die kompaktere Wahl sein.
<code><![CDATA[
def add(a, b): return a + b
]]></code>Mit diesem Skelett starten Sie jeden neuen Prompt. Es enthält Metadaten, Aufgabe, Anweisungen, Eingabe, Ausgabeformat und einen Fehler-Handler.
<prompt>
<meta version="1.0" id="GEN-001"/>
<task>Fasse einen langen Artikel für eine vielbeschäftigte Führungskraft zusammen.</task>
<instructions>
- Schreibe in einfacher Sprache.
- Halte dich an 120 bis 150 Woerter.
- Ergaenze 3 stichpunktartige Highlights.
</instructions>
<input>
<article><![CDATA[
{{ARTIKEL HIER EINFUEGEN}}
]]></article>
</input>
<output_format>
<summary>120 bis 150 Woerter.</summary>
<highlights>
<bullet>Praegnante Aussage</bullet>
<bullet>Praegnante Aussage</bullet>
<bullet>Praegnante Aussage</bullet>
</highlights>
</output_format>
<error_handler>
Wenn die Eingabe fehlt oder nicht auswertbar ist, gib zurueck:
<error code="INPUT_INVALID" message="Grund hier"/>
</error_handler>
</prompt>Alle Vorlagen verzichten bewusst auf verstecktes Chain-of-Thought. Übernehmen Sie sie unverändert oder passen Sie die Tag-Namen an Ihre Domäne an.
<prompt>
<task>Extrahiere Firma, Produkt, Preis und Stimmung aus einer Rezension.</task>
<input>
<review><![CDATA[
Ich liebe den Acme Air 2000, nur 249 Dollar und leiser als mein alter Ventilator.
]]></review>
</input>
<output_format>
<extraction>
<company>string</company>
<product>string</product>
<price currency="USD">number</price>
<sentiment one_of="positive|neutral|negative">string</sentiment>
<key_points max="3">stichpunktartige Phrasen</key_points>
</extraction>
</output_format>
<instructions>
- Ist ein Feld unbekannt, setze ein leeres Tag (z. B. <price/>).
- Halte <key_points> auf hoechstens 3 kurze Stichpunkte.
</instructions>
</prompt><prompt>
<task>Klassifiziere die Absicht eines Support-Tickets.</task>
<labels>
<label id="bug">Fehlermeldung</label>
<label id="billing">Abrechnung</label>
<label id="feature">Feature-Wunsch</label>
<label id="other">Sonstiges</label>
</labels>
<input>
<ticket>Meine Karte wurde diesen Monat zweimal belastet.</ticket>
</input>
<output_format>
<classification>
<label_id one_of="bug|billing|feature|other">string</label_id>
<justification max_chars="180">Ein bis zwei Saetze.</justification>
</classification>
</output_format>
</prompt><prompt>
<persona>
<role>Customer Success Manager</role>
<tone>Professionell, hilfsbereit, knapp</tone>
<signature>Viele Gruesse, Alex (Customer Success)</signature>
</persona>
<task>Entwirf eine Antwort, die bestaetigt, beantwortet und naechste Schritte vorschlaegt.</task>
<input>
<email_from_customer><![CDATA[
Hallo, ich komme nach dem Zuruecksetzen meines Passworts nicht mehr ins Dashboard.
]]></email_from_customer>
</input>
<output_format>
<email>
<subject>string</subject>
<body>Klartext, kurze Absaetze</body>
<next_steps>
<step>Stichpunkt</step>
</next_steps>
</email>
</output_format>
</prompt><prompt>
<task>Erzeuge eine SQL-Abfrage aus einer natuerlichsprachlichen Frage und einem Schema.</task>
<schema><![CDATA[
tables:
orders(order_id, customer_id, total, created_at)
customers(customer_id, region)
]]></schema>
<input>
<question>Gesamtumsatz pro Region fuer das laufende Jahr 2024.</question>
</input>
<output_format>
<sql><![CDATA[
SELECT ...
]]></sql>
<assumptions max="3">
<item>kurzer Satz</item>
</assumptions>
<safety_checks>
<check>Sind die Datumsfilter korrekt?</check>
<check>Verbinden die Joins die richtigen Schluessel?</check>
</safety_checks>
</output_format>
</prompt><prompt>
<task>Wandle ein Meeting-Transkript in strukturierte Notizen um.</task>
<input>
<transcript><![CDATA[(Transkript einfuegen)]]></transcript>
</input>
<output_format>
<notes>
<topics>
<topic>...</topic>
</topics>
<decisions>
<decision>...</decision>
</decisions>
<action_items>
<item owner="Name" due="YYYY-MM-DD">...</item>
</action_items>
</notes>
</output_format>
</prompt><prompt>
<task>Leite die Nutzereingabe an den richtigen Handler weiter.</task>
<handlers>
<handler id="KB_SEARCH">Wissensdatenbank-Suche</handler>
<handler id="HUMAN_HANDOFF">Uebergabe an Mensch</handler>
<handler id="ORDER_STATUS">Bestellstatus</handler>
</handlers>
<input>
<utterance>Wo ist meine Bestellung Nr. 1234?</utterance>
</input>
<output_format>
<routing>
<handler_id one_of="KB_SEARCH|HUMAN_HANDOFF|ORDER_STATUS">ORDER_STATUS</handler_id>
<entities>
<order_id>1234</order_id>
</entities>
<confidence>0-1</confidence>
</routing>
</output_format>
</prompt><prompt>
<task>Kritisiere und verbessere den Entwurf, begrenze die Begruendung.</task>
<constraints>
<rationale_limit>120 Zeichen</rationale_limit>
</constraints>
<input>
<draft><![CDATA[(Entwurf einfuegen)]]></draft>
</input>
<output_format>
<improvement>
<revised><![CDATA[(ueberarbeiteter Text)]]></revised>
<rationale>max. 120 Zeichen</rationale>
<checks>
<check id="clarity">pass|fail</check>
<check id="tone">pass|fail</check>
<check id="length">pass|fail</check>
</checks>
</improvement>
</output_format>
</prompt>Mit der Python-Standardbibliothek lesen Sie die XML-Ausgabe in wenigen Zeilen aus:
import xml.etree.ElementTree as ET
def parse_extraction(xml_text: str):
root = ET.fromstring(xml_text)
ext = root.find('extraction')
return {
"company": (ext.findtext('company') or '').strip(),
"product": (ext.findtext('product') or '').strip(),
"price": (ext.findtext('price') or '').strip(),
"sentiment": (ext.findtext('sentiment') or '').strip(),
"key_points": [e.text.strip() for e in ext.findall('key_points/bullet') if e.text]
}Validierungs-Checkliste:
Mit ein paar bewährten Techniken werden Ihre Prompts deutlich stabiler:
| Anti-Pattern | Lösung |
|---|---|
| "Denke Schritt für Schritt und zeige deinen Gedankengang." | Fragen Sie nach kurzen Kernpunkten oder einer Checkliste: <key_points max="5">. |
| Unbenannte oder generische Tags wie <section1>. | Domänen-Substantive verwenden: <risks>, <mitigations>, <decision>. |
| Anweisungen mit Beispielen vermischt. | <instructions> und <examples> in getrennte Blöcke. |
| Freitext-Ausgaben, obwohl Struktur nötig ist. | Ein <output_format> mit Pflicht-Kindern vorgeben. |
| Code ohne CDATA eingebettet. | Code, JSON und Regex immer in CDATA kapseln. |
| Optionale Felder nicht spezifiziert. | Festlegen, wie Unbekanntes dargestellt wird (leeres Tag). |
Warum XML statt Markdown-Überschriften? XML ist maschinell parsbar und konsistent. Markdown ist gut für Menschen, aber mehrdeutig für Maschinen.
Kann ich XML mit Markdown mischen? Ja. Halten Sie die maschinenlesbaren Teile in XML, menschliche Hinweise können als Stichpunkte innerhalb von <instructions> stehen.
Was ist mit Sicherheit und Compliance? Nutzen Sie <checks>, um Regeln wie keine personenbezogenen Daten oder keine medizinische oder rechtliche Beratung zu erzwingen. Bei Verstoß geben Sie ein <error> aus.
Wie vermeide ich ausschweifende Begründungen? Begrenzen Sie sie über Attribute wie max_chars oder max und bevorzugen Sie Checklisten gegenüber Fließtext.