Gültiges JSON, falsche Daten
JSON mit einem Schema zu prüfen heißt, jedes Feld eines Datensatzes mit einer Liste von Regeln zu vergleichen. Die Regeln nennen den Typ, sagen, ob das Feld Pflicht ist, und listen die erlaubten Werte auf. Das ist wichtig, weil JSON, das sich parsen lässt, trotzdem „viele“ als Seitenzahl enthalten kann.
Die App einer Bibliothek bittet ein Modell um den Datensatz eines Buches. Die Antwort lässt sich fehlerfrei parsen. Dann kommt eine Seitenzahl als Text „180“ an, und die Summenseite zeigt Unsinn.
Am Ende dieser Lektion
Notiz
Ich kann eine Antwort mit einem Schema prüfen.
Schlüsselwörter
| Begriff | Was er bedeutet | Beispiel |
|---|---|---|
| Schema | eine Prüfliste der Felder eines Datensatzes | |
| Typ | die Art von Wert, die ein Feld enthält | ganzzahl |
| Pflichtfeld | ein Feld, das vorhanden sein muss | |
| Erlaubte Werte | die einzigen Werte, die ein Feld annehmen darf | roman, geschichte, wissenschaft |
| Fehler | eine Art, eine Regel zu verletzen | |
| Datensatz | ein Objekt mit einer Menge von Feldern |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Ein Schema ist eine Prüfliste
Parsen sagt, dass der Text JSON ist. Es sagt nicht, dass die Daten stimmen. Dafür brauchen Sie ein Schema: eine Regel für jedes Feld.
Eine Regel nennt den Typ des Feldes, sagt, ob es Pflicht ist, und manchmal seine erlaubten Werte. Ein Standard namens JSON Schema schreibt solche Regeln in einem festen Format. Hier schreiben Sie Ihre eigene Prüfliste, in Code.
Beispiel: ein Schema für ein Buch
| Feld | Typ | Pflicht | Erlaubte Werte |
|---|---|---|---|
| titel | text | ja | beliebiger Text |
| seiten | ganzzahl | ja | jede ganze Zahl |
| gattung | text | ja | roman, geschichte, wissenschaft |
| bewertung | zahl | nein | jede Zahl |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Alle Fehler sammeln, nicht nur den ersten
Eine Prüfung, die beim ersten Fehler aufhört, sagt wenig. Sammeln Sie alle Fehler in einer Liste, jeweils ein kurzer Text wie seiten: falscher Typ.
Die Liste dient zwei Zwecken. Sie entscheidet, ob der Datensatz angenommen wird, und die nächste Lektion schickt sie dem Modell als Rückmeldung zurück.
Die Modellhilfe schreiben, Teil 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const basis = process.env.AI_URL || \"http://ai:4000\";' 'async function fragen(nachrichten, probe, max) {' ' try {' ' const res = await fetch(basis + \"/v1/chat/completions\", {' ' method: \"POST\",' ' headers: { \"content-type\": \"application/json\", authorization: \"Bearer lab\" },' ' body: JSON.stringify({ model: \"lab\", messages: nachrichten, max_tokens: max || 200 }),' ' signal: AbortSignal.timeout(30000),' ' });' ' if (res.ok === false) throw new Error(\"Status \" + res.status);' ' return (await res.json()).choices[0].message.content;' > model.js"Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Die Modellhilfe schreiben, Teil 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' ' } catch (fehler) {' ' console.log(\"Aufgezeichnete Probe: Kein Modell hat geantwortet (\" + fehler.message + \").\");' ' const liste = [].concat(probe);' ' const runde = nachrichten.filter(function (m) { return m.role === \"assistant\"; }).length;' ' return liste[Math.min(runde, liste.length - 1)];' ' }' '}' 'module.exports = { fragen };' >> model.js"Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Die Schemaprüfung schreiben, Teil 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { fragen } = require(\"./model\");' '' '// Ein Schema ist eine Prüfliste: eine Regel für jedes Feld.' 'const schema = [' ' { name: \"titel\", typ: \"text\", pflicht: true },' ' { name: \"seiten\", typ: \"ganzzahl\", pflicht: true },' ' { name: \"gattung\", typ: \"text\", pflicht: true, erlaubt: [\"roman\", \"geschichte\", \"wissenschaft\"] },' ' { name: \"bewertung\", typ: \"zahl\", pflicht: false },' '];' > pruefung2.js"Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Die Schemaprüfung schreiben, Teil 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function istDatensatz(x) {' ' if (x === null) return false;' ' if (Array.isArray(x)) return false;' ' return typeof x === \"object\";' '}' '' 'function typStimmt(wert, typ) {' ' if (typ === \"text\") return typeof wert === \"string\";' ' if (typ === \"ganzzahl\") return Number.isInteger(wert);' ' if (typ === \"zahl\") return typeof wert === \"number\";' ' if (typ === \"boolesch\") return typeof wert === \"boolean\";' ' return false;' '}' >> pruefung2.js"Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Die Schemaprüfung schreiben, Teil 3
docker exec -w /home/node/project agent sh -c "printf '%s\n' '// Alle Fehler sammeln, nicht nur den ersten.' 'function fehlerFinden(datensatz, schema) {' ' if (istDatensatz(datensatz) === false) return [\"kein Objekt\"];' ' const gefunden = [];' ' for (const regel of schema) {' ' if (Object.prototype.hasOwnProperty.call(datensatz, regel.name) === false) {' ' if (regel.pflicht) gefunden.push(regel.name + \": fehlt\");' ' continue;' ' }' ' const wert = datensatz[regel.name];' ' if (typStimmt(wert, regel.typ) === false) gefunden.push(regel.name + \": falscher Typ\");' ' else if (regel.erlaubt && regel.erlaubt.includes(wert) === false) gefunden.push(regel.name + \": nicht erlaubt\");' ' }' ' return gefunden;' '}' >> pruefung2.js"Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Die Schemaprüfung schreiben, Teil 4
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function jsonHerausziehen(text) {' ' const anfang = text.indexOf(\"{\");' ' const ende = text.lastIndexOf(\"}\");' ' if (anfang === -1 || ende < anfang) return null;' ' try { return JSON.parse(text.slice(anfang, ende + 1)); } catch (fehler) { return null; }' '}' '' 'const datensaetze = [' ' { titel: \"Atlas der Flüsse\", seiten: 240, gattung: \"wissenschaft\" },' ' { titel: \"Gezeitentafeln\", seiten: \"180\", gattung: \"geschichte\" },' ' { titel: \"Mondbriefe\", seiten: 96, gattung: \"lyrik\", bewertung: 4.5 },' ' { seiten: 310, gattung: \"roman\", bewertung: \"gut\" },' '];' 'datensaetze.forEach(function (datensatz, nr) {' ' const gefunden = fehlerFinden(datensatz, schema);' ' console.log(\"Datensatz \" + (nr + 1) + \":\", gefunden.length === 0 ? \"ok\" : gefunden.join(\", \"));' '});' >> pruefung2.js"Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Die Schemaprüfung schreiben, Teil 5
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' ' const nachrichten = [{ role: \"user\", content: \"Erfinden Sie ein Buch für eine Hochschulbibliothek. Antworten Sie mit einem JSON-Objekt mit den Schlüsseln titel (Text), seiten (eine ganze Zahl) und gattung (roman, geschichte oder wissenschaft). Antworten Sie nur mit dem JSON.\" }];' ' // Aufgezeichnete Probe, nur benutzt, wenn kein Modell antwortet. Sie bricht absichtlich zwei Regeln.' ' const probe = JSON.stringify({ titel: \"Der stille Hafen\", seiten: \"210\", gattung: \"krimi\" });' ' const antwort = await fragen(nachrichten, probe, 100);' ' const datensatz = jsonHerausziehen(antwort);' ' const gefunden = fehlerFinden(datensatz, schema);' ' console.log(\"Datensatz des Modells:\", JSON.stringify(datensatz));' ' console.log(\"Fehler:\", gefunden.length === 0 ? \"keine\" : gefunden.join(\", \"));' '}' 'main();' >> pruefung2.js"Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Die Prüfung ausführen
docker exec -w /home/node/project agent node pruefung2.jsHier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Eine mögliche Ausgabe
| Zeile | Was sie zeigt |
|---|---|
| Datensatz 1 | ok |
| Datensatz 2 | seiten: falscher Typ |
| Datensatz 3 | gattung: nicht erlaubt |
| Datensatz 4 | titel: fehlt, bewertung: falscher Typ |
| Datensatz des Modells und Fehler | Ändern sich bei jedem Ausführen: ein Datensatz des Modells, dann seine Fehler oder keine |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Ein häufiger Fehler
Warnung
Viele glauben, „180“ und 180 seien dasselbe. Sie sehen gleich aus, aber ein Programm kann einen Text nicht wie eine Zahl addieren oder vergleichen. Prüfen Sie den Typ, nicht das Aussehen des Wertes.