Wie man ein Protokoll führt, das Manipulation zeigt
Eine Prüfspur ist ein Protokoll darüber, wer wann was geändert hat. Ein Protokoll, das jeder bearbeiten kann, ist kein Beweis, weil niemand merkt, ob es geändert wurde.
Eine Hash-Kette lässt eine Änderung auffallen. Eine Entscheidung wird festgehalten. Diese Lektion lässt die Aufzeichnung zeigen, ob sie geändert wurde.
Am Ende dieser Lektion
Notiz
Ich kann ein Protokoll führen, das zeigt, ob es geändert wurde.
Schlüsselwörter
| Begriff | Was er bedeutet | Beispiel |
|---|---|---|
| Nur anhängen | neue Einträge kommen dazu, alte werden nie geändert | |
| Hash | ein kurzer Fingerabdruck eines Textes | 1a47e90b |
| Kette | Einträge, die je den Hash des vorigen halten | |
| Manipulieren | einen Eintrag ohne Erlaubnis ändern | |
| Anker | der neueste Hash, an anderer Stelle aufbewahrt |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Ein Hash ist der Fingerabdruck eines Textes
Ein Hash macht aus jedem Text einen kurzen Code. Derselbe Text ergibt immer denselben Code. Ändern Sie einen Buchstaben, ändert sich der Code völlig.
Der Hash in dieser Lektion ist klein und zum Lernen gemacht. Er ist nicht sicher. Ein echtes Protokoll nutzt einen starken Hash aus einer Bibliothek, und die Idee ist dieselbe.
So rechnet der Lernhash
Starten Sie mit x gleich 2166136261. Nehmen Sie für jedes Zeichen des Textes seinen Zahlencode. Verknüpfen Sie x mit dem Code durch XOR. Multiplizieren Sie x mit 16777619 und behalten Sie nur die letzten 32 Bit.
Am Ende schreiben Sie x als acht Hexziffern. Die Protokolltexte hier nutzen nur Zeichen, die in JavaScript und Python dieselbe Zahl haben. Das Skript und Ihre Aufgabe rechnen gleich.
Durchgerechnetes Beispiel: drei Fingerabdrücke
| Text | Hash |
|---|---|
| (nichts) | 811c9dc5 |
| a | e40c292c |
| abc | 1a47e90b |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Eine Kette verknüpft jeden Eintrag mit dem letzten
Jeder Eintrag enthält seinen Text, den Hash des Eintrags davor und seinen eigenen Hash. Der eigene Hash entsteht aus dem vorigen Hash, einem senkrechten Strich und dem Text.
Bearbeiten Sie Eintrag 2, passt sein eigener Hash nicht mehr. Jeder Eintrag danach hält noch den alten Hash, die Verknüpfungen brechen also von dort an.
Durchgerechnetes Beispiel: fünf Einträge
| Eintrag | Text | Voriger Hash | Eigener Hash |
|---|---|---|---|
| 0 | Modell auf chat-v3 festgelegt | 00000000 | c699b650 |
| 1 | Canary auf 5 Prozent erhöht | c699b650 | 333b0203 |
| 2 | Canary auf 20 Prozent erhöht | 333b0203 | 60b6ba1c |
| 3 | für alle Nutzer freigegeben | 60b6ba1c | cdf3a573 |
| 4 | alte Version außer Betrieb genommen | cdf3a573 | 7e8ebe26 |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Ein häufiger Fehler
Warnung
Viele denken, eine Hash-Kette verhindere, dass jemand das Protokoll ändert. Das tut sie nicht. Sie zeigt nur eine Änderung. Wer die ganze Datei schreiben darf, kann jeden Hash neu bauen. Bewahren Sie den neuesten Hash, den Anker, dort auf, wo er nicht hinkommt, und vergleichen Sie ihn.
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\";' '// Die Token einer Antwort oder null, wenn sie keine nennt.' 'function zaehlen(daten, name) {' ' return daten.usage && typeof daten.usage[name] === \"number\" ? daten.usage[name] : null;' '}' > 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' '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 || 100 }),' ' signal: AbortSignal.timeout(30000),' ' });' ' if (res.ok === false) throw new Error(\"Status \" + res.status);' ' const d = await res.json();' ' return { text: d.choices[0].message.content, eingabe: zaehlen(d, \"prompt_tokens\"), ausgabe: zaehlen(d, \"completion_tokens\"), aufgezeichnet: false };' ' } catch (fehler) {' ' console.log(\"Aufgezeichnete Probe: Kein Modell hat geantwortet (\" + fehler.message + \").\");' ' return { text: probe, eingabe: null, ausgabe: null, aufgezeichnet: true };' ' }' '}' '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.
Das Prüfspur-Skript schreiben, Teil 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { fragen } = require(\"./model\");' 'const START = \"00000000\";' 'function hash(text) {' ' let x = 2166136261;' ' for (let i = 0; i < text.length; i++) {' ' x = x ^ text.charCodeAt(i);' ' x = Math.imul(x, 16777619) >>> 0;' ' }' ' return (\"00000000\" + x.toString(16)).slice(-8);' '}' > spur.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.
Das Prüfspur-Skript schreiben, Teil 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function anhaengen(kette, text) {' ' const vorher = kette.length > 0 ? kette[kette.length - 1].hash : START;' ' return kette.concat([{ text: text, vorher: vorher, hash: hash(vorher + \"|\" + text) }]);' '}' 'function ersterDefekt(kette) {' ' let vorher = START;' ' for (let i = 0; i < kette.length; i++) {' ' const e = kette[i];' ' if (e.vorher === vorher && e.hash === hash(e.vorher + \"|\" + e.text)) vorher = e.hash;' ' else return i;' ' }' ' return -1;' '}' >> spur.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.
Das Prüfspur-Skript schreiben, Teil 3
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const notizen = [\"Modell auf chat-v3 festgelegt\", \"Canary auf 5 Prozent erhöht\", \"Canary auf 20 Prozent erhöht\",' ' \"für alle Nutzer freigegeben\", \"alte Version außer Betrieb genommen\"];' 'let kette = [];' 'notizen.forEach(function (t) { kette = anhaengen(kette, t); });' 'const anker = kette[4].hash;' 'const gefaelscht = kette.map(function (e) { return { text: e.text, vorher: e.vorher, hash: e.hash }; });' 'gefaelscht[2].text = \"Canary auf 90 Prozent erhöht\";' 'let neu = [];' 'gefaelscht.forEach(function (e) { neu = anhaengen(neu, e.text); });' >> spur.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.
Das Prüfspur-Skript schreiben, Teil 4
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function jaNein(b) { return b ? \"ja\" : \"nein\"; }' 'async function main() {' ' console.log(\"Hash von abc: \" + hash(\"abc\"));' ' console.log(\"Erster defekter Eintrag im echten Protokoll: \" + ersterDefekt(kette));' ' console.log(\"Erster defekter Eintrag nach einer Änderung: \" + ersterDefekt(gefaelscht));' ' console.log(\"Neu gebautes Protokoll ist in sich stimmig: \" + jaNein(ersterDefekt(neu) === -1));' ' console.log(\"Neu gebautes Protokoll passt zum Anker: \" + jaNein(neu[4].hash === anker));' ' const f = \"Schreiben Sie in einem kurzen Satz, warum ein geänderter Eintrag in einer Hash-Kette leicht auffällt.\";' ' const probe = \"Jeder Eintrag hält den Fingerabdruck des vorigen, eine Änderung bricht also jede Verknüpfung danach.\";' ' const antwort = await fragen([{ role: \"user\", content: f }], probe, 60);' ' console.log(\"Das Modell sagte: \" + antwort.text);' '}' 'main();' >> spur.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üfspur ausführen
docker exec -w /home/node/project agent node spur.jsHier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Was der Run ausgibt
| Zeile | Was sie zeigt |
|---|---|
| Hash von abc: 1a47e90b | Jedes Mal derselbe Fingerabdruck |
| Erster defekter Eintrag im echten Protokoll: -1 | Keine gebrochene Verknüpfung |
| Erster defekter Eintrag nach einer Änderung: 2 | Die Änderung fällt bei Eintrag 2 auf |
| Neu gebautes Protokoll ist in sich stimmig: ja | Ein vollständiger Neubau besteht die Prüfung der Verknüpfungen |
| Neu gebautes Protokoll passt zum Anker: nein | Der Anker zeigt die Änderung trotzdem |
| Das Modell sagte: ... | Ein Satz aus dem Labor. Eine Aufgezeichnete Probe, wenn kein Modell antwortet |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.