Ein Aufruf nimmt eine Nachrichtenliste
Ein Chat-Aufruf an ein Sprachmodell nimmt eine Liste von Nachrichten. Jede Nachricht hat eine Rolle und einen Text. Das Modell liest die ganze Liste und schreibt die nächste Nachricht.
Das ist wichtig, denn ein Modell behält nichts von einem Aufruf zum nächsten. Ein Chat, der ein Gedächtnis zu haben scheint, ist ein Programm, das die früheren Nachrichten jedes Mal erneut sendet.
Am Ende dieser Lektion
Notiz
Ich kann die Nachrichtenliste aufbauen, die ein Aufruf an ein Sprachmodell nimmt.
Schlüsselwörter
| Begriff | Was er bedeutet | Beispiel |
|---|---|---|
| Nachricht | ein Zug im Chat: eine Rolle und ein Text | |
| Rolle | von wem eine Nachricht stammt | user |
| System-Nachricht | die Anweisung, die das Verhalten des Modells festlegt | |
| Verlauf | die früheren Nachrichten, die bei jedem Aufruf erneut gesendet werden | |
| Anfragekörper | das JSON, das ein Programm mit einem Aufruf sendet |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Eine Nachricht ist eine Rolle und ein Text
Eine Nachricht ist ein Objekt mit zwei Schlüsseln. role sagt, wer spricht, und content enthält die Worte.
Es gibt drei Rollen. Die system-Nachricht legt fest, wie sich das Modell verhält. Eine user-Nachricht ist das, was die Person sagt. Eine assistant-Nachricht ist etwas, das das Modell früher gesagt hat.
Der Anfragekörper eines Aufrufs
{
"model": "lab",
"max_tokens": 60,
"messages": [
{ "role": "system", "content": "Sie antworten in einem kurzen Satz." },
{ "role": "user", "content": "Was ist eine Variable in der Programmierung?" }
]
}Einen Aufruf an das Modell des Labors senden
docker exec -w /home/node/project agent node -e '/* Der Anfragekörper: ein Modellname, eine Antwortgrenze und eine Liste von Nachrichten. */ const anfrage = { model: "lab", max_tokens: 60, messages: [ { role: "system", content: "Sie antworten in einem kurzen Satz." }, { role: "user", content: "Was ist eine Variable in der Programmierung?" } ] }; (async () => { try { const url = (process.env.AI_URL || "http://ai:4000") + "/v1/chat/completions"; const antwort = await fetch(url, { method: "POST", body: JSON.stringify(anfrage), headers: { "content-type": "application/json", authorization: "Bearer lab" } }); if (!antwort.ok) throw new Error("HTTP " + antwort.status); const daten = await antwort.json(); console.log("Antwort des Modells: " + daten.choices[0].message.content); } catch (fehler) { console.log("Kein Modell hat geantwortet (" + fehler.message + ")."); console.log("Aufgezeichnetes Beispiel: Eine Variable speichert einen Wert, den das Programm ändern kann."); } })();'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 Modell behält nichts zwischen Aufrufen
Jeder Aufruf steht für sich. Das Modell sieht nur die Nachrichten dieses einen Aufrufs.
Für ein Gespräch führt Ihr Programm eine Liste. Nach jeder Antwort fügt es Frage und Antwort hinzu. Beim nächsten Aufruf sendet es den Verlauf erneut, mit der neuen Frage am Ende.
Die Hilfsdatei labor.js schreiben
docker exec -w /home/node/project agent node -e 'require("fs").writeFileSync("labor.js", ["// labor.js, Teil 1: die einzige Stelle, die einen Aufruf an das Modell des Labors sendet.", "const basis = process.env.AI_URL || \"http://ai:4000\";", "", "async function senden(anfrage, zeitgrenze) {", " return fetch(basis + \"/v1/chat/completions\", {", " method: \"POST\",", " headers: { \"content-type\": \"application/json\", authorization: \"Bearer lab\" },", " body: JSON.stringify({ model: \"lab\", ...anfrage }),", " signal: AbortSignal.timeout(zeitgrenze || 30000),", " });", "}"].join("\n") + "\n")'Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Fragen mit aufgezeichnetem Beispiel ergänzen
docker exec -w /home/node/project agent node -e 'require("fs").appendFileSync("labor.js", ["", "// Teil 2: einmal fragen. Kann das Modell nicht antworten, kommt das aufgezeichnete Beispiel zurück.", "async function fragen(anfrage, beispiel) {", " try {", " const antwort = await senden(anfrage);", " if (!antwort.ok) throw new Error(\"HTTP \" + antwort.status);", " const daten = await antwort.json();", " return { etikett: \"Antwort des Modells\", text: daten.choices[0].message.content, daten: daten };", " } catch (fehler) {", " return { etikett: \"Aufgezeichnetes Beispiel\", text: beispiel, hinweis: fehler.message };", " }", "}", "", "module.exports = { senden, fragen };"].join("\n") + "\n")'Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Mit dem Verlauf fragen, dann ohne
docker exec -w /home/node/project agent node -e 'const labor = require("./labor.js"); const anweisung = { role: "system", content: "Antworten Sie in einem kurzen Satz." }; const verlauf = [ { role: "user", content: "Ich heiße Jonas." }, { role: "assistant", content: "Freut mich, Jonas." } ]; const frage = { role: "user", content: "Wie heiße ich?" }; (async () => { const mit = await labor.fragen({ max_tokens: 30, messages: [anweisung, ...verlauf, frage] }, "Sie heißen Jonas."); console.log("Mit dem Verlauf, " + mit.etikett + ": " + mit.text); const ohne = await labor.fragen({ max_tokens: 30, messages: [anweisung, frage] }, "Ihren Namen kenne ich nicht."); console.log("Ohne ihn, " + ohne.etikett + ": " + ohne.text); console.log("Nachrichten pro Aufruf: " + [anweisung, ...verlauf, frage].length + " und " + [anweisung, frage].length); })();'Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Ein häufiger Fehler
Warnung
Viele glauben, das Modell erinnere sich an den letzten Aufruf. Das stimmt nicht. Der zweite Aufruf ohne Verlauf konnte den Namen nicht kennen. Soll das Modell etwas nutzen, legen Sie es in die Nachrichten, die Sie senden.
Beispiel: was jeder Aufruf enthielt
| Aufruf | Gesendete Nachrichten | Was das Modell wissen kann |
|---|---|---|
| Mit dem Verlauf | system, user, assistant, user (4) | Den Namen Jonas |
| Ohne ihn | system, user (2) | Nichts über Jonas |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Die Reihenfolge der Nachrichten zählt
Setzen Sie die System-Nachricht an den Anfang. Danach wechseln die Züge ab: user, assistant, user und so weiter. Die letzte Nachricht kommt vom Benutzer, denn auf sie antwortet das Modell.
Die meisten Modell-APIs lehnen eine Liste ab, die diese Reihenfolge bricht, oder liefern seltsame Antworten. Prüfen Sie die Reihenfolge im eigenen Code, bevor Sie senden.
Zum Weiterdenken: die System-Nachricht ändern
Öffnen Sie den Verlaufs-Run und ändern Sie die Anweisung in »Antworten Sie auf Englisch«. Drücken Sie erneut auf Run.
Notieren Sie, was sich geändert hat und was nicht. Sagen Sie dann in einem Satz, warum die Anweisung in den gesendeten Nachrichten stehen musste.