Zwei Agenten, eine Akte, ein verlorenes Update
Gemeinsamer Zustand ist ein Datensatz, den mehrere Agenten lesen und schreiben. Das ist wichtig, denn zwei Agenten, die beide lesen und dann beide schreiben, können die Arbeit des anderen unbemerkt löschen.
Nichts stürzt ab. Der Datensatz behält einfach den letzten Schreibvorgang, und ein guter Fund ist weg.
Am Ende dieser Lektion
Notiz
Ich kann Agenten einen Datensatz teilen lassen, ohne dass sie sich überschreiben, und die Konflikte melden.
Schlüsselwörter
| Begriff | Was er bedeutet |
|---|---|
| Gemeinsamer Datensatz | eine einzige Kopie der Fakten, die alle Agenten lesen und schreiben |
| Nachricht | Text, den ein Agent an einen anderen schickt |
| Version | eine Zahl, die mit jedem angenommenen Schreibvorgang steigt |
| Basisversion | die Version, die ein Schreibender vor dem Schreiben gelesen hat |
| Konflikt | ein Schreibvorgang auf Basis eines Feldes, das sich seitdem geändert hat |
| Verlorenes Update | ein Schreibvorgang, der einen anderen unbemerkt löscht |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Nachrichten oder ein gemeinsamer Datensatz
Agenten können Nachrichten austauschen. Jeder behält seine Kopie dessen, was er gehört hat, nichts gerät in Konflikt, aber die Kopien laufen auseinander.
Oder sie teilen einen Datensatz. Es gibt eine Wahrheit, aber zwei Schreibende können kollidieren. Die meisten Teams brauchen beides: Nachrichten für das, was zu tun ist, einen Datensatz für das, was bekannt ist.
Ausgearbeitetes Beispiel: Nachrichten und Datensatz
| Nachrichten | Gemeinsamer Datensatz | |
|---|---|---|
| Wer die Fakten hält | Jeder Agent für sich | Ein einziger Ort |
| Können zwei Agenten abweichen | Ja, und niemand weiß es | Nein, es gibt einen Wert |
| Kann ein Schreibvorgang verloren gehen | Nein | Ja, wenn Schreibvorgänge nicht geprüft werden |
| Am besten für | Einem Arbeiter sagen, was zu tun ist | Was das Team bisher gefunden hat |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Ein Schreibvorgang nennt die gelesene Version
Geben Sie jedem Feld eine Version. Liest ein Agent, merkt er sich die Version. Schreibt er, schickt er diese Basisversion zurück.
Der Datensatz nimmt den Schreibvorgang nur an, wenn sich das Feld seitdem nicht geändert hat. Sonst antwortet er mit einem Konflikt, und der Agent liest neu und entscheidet. Ein Feld, das noch niemand geschrieben hat, kann nicht in Konflikt geraten.
Ein häufiger Fehler
Warnung
Viele lösen einen Konflikt, indem der spätere Schreibvorgang gewinnt. Das ist das verlorene Update, nur mit einer Logzeile mehr. Ein Konflikt ist eine Frage an den Schreibenden: den neuen Wert lesen, dann entscheiden.
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.
Den gemeinsamen Datensatz schreiben, Teil 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { fragen } = require(\"./model\");' 'const akte = { version: 0, felder: {} };' 'function lesen() {' ' return { version: akte.version, felder: JSON.parse(JSON.stringify(akte.felder)) };' '}' > zustand.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.
Den gemeinsamen Datensatz schreiben, Teil 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' '// Ein Schreibvorgang nennt die gelesene Version. Er gilt nur, wenn niemand das Feld seitdem geändert hat.' 'function schreiben(agent, feld, wert, basis) {' ' const f = akte.felder[feld];' ' const wort = \" schreibt \" + feld + \" ab Version \" + basis + \": \";' ' if (f && f.version > basis) {' ' console.log(agent + wort + \"KONFLIKT, gehalten auf Version \" + f.version + \" von \" + f.von);' ' return false;' ' }' ' akte.version += 1;' ' akte.felder[feld] = { wert: wert, version: akte.version, von: agent };' ' console.log(agent + wort + \"übernommen, Datensatz auf Version \" + akte.version);' ' return true;' '}' >> zustand.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.
Den gemeinsamen Datensatz schreiben, Teil 3
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' ' const a = lesen();' ' const b = lesen();' ' schreiben(\"Kalkulator\", \"kosten\", \"108 Euro\", a.version);' ' if (schreiben(\"Leser\", \"kosten\", \"120 Euro\", b.version) === false) {' ' const neu = lesen();' ' console.log(\"Leser liest neu: kosten ist \" + neu.felder.kosten.wert + \" auf Version \" + neu.version);' ' schreiben(\"Leser\", \"kosten_notiz\", \"die zweite Zahl war 120\", neu.version);' ' }' ' schreiben(\"Leser\", \"wollen\", \"212 von 400\", b.version);' ' await zuletzt();' '}' >> zustand.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.
Den gemeinsamen Datensatz schreiben, Teil 4
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function zuletzt() {' ' const q = [{ role: \"user\", content: \"Schreiben Sie eine Notiz mit weniger als 12 Wörtern: Zwei Zahlen für dieselben Kosten stimmen nicht überein.\" }];' ' const notiz = (await fragen(q, \"Zwei Zahlen für dieselben Kosten weichen ab, prüfen Sie die Quelle.\", 30)).text.trim();' ' schreiben(\"Prüfer\", \"notiz\", notiz, akte.version);' ' const namen = Object.keys(akte.felder);' ' console.log(\"Felder: \" + namen.map(function (k) { return k + \"@\" + akte.felder[k].version; }).join(\", \"));' '}' 'main();' >> zustand.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.
Den gemeinsamen Datensatz starten
docker exec -w /home/node/project agent node zustand.jsHier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Das ist ein Ersatz
Das Labor hat keine Datenbank, der Datensatz ist ein Objekt im Skript. Ein echtes Team nutzt eine Datenbank, die diese Prüfung in einem einzigen Schritt macht. Prüfen und dann schreiben als zwei Schritte lässt einer anderen Schreibenden eine Lücke.
Der eine Live-Aufruf formuliert eine Notiz. Ihre Worte sind bei jedem Lauf anders.
Eine mögliche Ausgabe
| Zeile | Was sie zeigt |
|---|---|
| Kalkulator schreibt kosten ab Version 0: übernommen, Datensatz auf Version 1 | Der erste Schreibende gewinnt |
| Leser schreibt kosten ab Version 0: KONFLIKT, gehalten auf Version 1 von Kalkulator | Der zweite hatte eine alte Version gelesen |
| Leser liest neu: kosten ist 108 Euro auf Version 1 | Der Leser holt sich den aktuellen Stand |
| Leser schreibt kosten_notiz ab Version 1: übernommen, Datensatz auf Version 2 | Nach erneutem Lesen schreibt er eine Notiz |
| Leser schreibt wollen ab Version 0: übernommen, Datensatz auf Version 3 | Ein neues Feld kann nicht in Konflikt geraten |
| Prüfer schreibt notiz ab Version 3: übernommen, Datensatz auf Version 4 | Die Notiz stammt vom Modell und ist bei jedem Lauf anders |
| Felder: kosten@1, kosten_notiz@2, wollen@3, notiz@4 | Die Version, bei der jedes Feld zuletzt geschrieben wurde |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.