Testfälle erzeugen, ohne zu mogeln
Synthetische Bewertungsdaten sind Testfälle, die ein Programm macht. Tausend Fälle von Hand zu schreiben dauert lange, also erzeugen Teams sie aus Vorlagen.
Erfundene Fälle können sich wiederholen oder ihre eigene Antwort verraten. Diese Lektion macht Fälle aus einem Startwert und entfernt die schlechten.
Am Ende dieser Lektion
Notiz
Ich kann neue Fälle aus einem Startwert erzeugen und sagen, dass sie keine Kopien sind.
Schlüsselwörter
| Begriff | Was er bedeutet | Beispiel |
|---|---|---|
| Vorlage | ein Satz mit Lücken zum Füllen | Bitte tauschen Sie den {artikel} |
| Startwert | eine Zahl am Anfang, die einen Generator wiederholbar macht | |
| Beinahe-Dublette | ein Fall, der fast gleich einem anderen ist | |
| Leck | ein Fall, der seine Antwort oder seinen Trainingstext verrät | |
| Ähnlichkeit | wie viele Wörter zwei Texte teilen, in Prozent |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Eine Vorlage und ein Startwert machen Fälle
Eine Vorlage ist ein Satz mit Lücken, zum Beispiel Bitte tauschen Sie den {artikel}. Eine Liste von Artikeln füllt die Lücke. Jede Vorlage hat ein Label, die Antwort, die eine gute Funktion geben soll.
Ein Startwert ist eine Zahl, die einen Zähler startet. Derselbe Startwert wählt immer dieselben Vorlagen und Artikel, die Fälle wiederholen sich also.
Durchgerechnetes Beispiel: ein Generator mit Startwert
| Schritt | Was geschieht |
|---|---|
| Start | Der Startwert ist die erste Zahl |
| Ziehen | Mit 16807 malnehmen, den Rest nach der Teilung durch 2147483647 behalten |
| Wählen | Diese Zahl durch die Größe der Liste teilen, den Rest nehmen |
| Füllen | Den gewählten Artikel in die Lücke setzen |
| Wiederholen | Derselbe Startwert ergibt jedes Mal dieselben Fälle |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Beinahe-Dubletten lassen eine Menge größer aussehen
Zwei Fälle, die sich in einem Wort unterscheiden, bringen nichts Neues. Zählen Sie die Wörter, die beide teilen. Teilen Sie durch alle verschiedenen Wörter beider Texte.
Sagen wir, 80 Prozent oder mehr ist eine Beinahe-Dublette. Behalten Sie den ersten Fall und sortieren Sie den späteren aus.
Ein häufiger Fehler
Warnung
Viele denken, mehr erzeugte Fälle seien immer ein besserer Test. Sind die meisten Kopien, ist die Menge kleiner, als sie aussieht. Zählen Sie nur die Fälle, die keine Beinahe-Dubletten sind.
Zwei Arten von Leck verderben einen Test
Ein Leck der Antwort ist ein Fall, der sein eigenes Label enthält, zum Beispiel Ich fordere eine Erstattung mit dem Label erstattung. Eine Funktion kann bestehen, indem sie das Wort erkennt.
Ein Leck des Trainingstextes ist ein Fall, der einem Text gleicht, den die Funktion schon gesehen hat. Ein guter Wert darauf beweist Gedächtnis, kein Können.
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 Generator schreiben, Teil 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { fragen } = require(\"./model\");' 'const vorlagen = [' ' [\"Mein {artikel} kam {fehler} an, ich möchte mein Geld zurück\", \"erstattung\"],' ' [\"Ich fordere eine Erstattung für den {artikel}, er war {fehler}\", \"erstattung\"],' ' [\"Wo ist mein {artikel}? Er ist noch nicht angekommen\", \"verfolgung\"],' ' [\"Kann ich meinen {artikel} gegen eine andere Farbe tauschen\", \"umtausch\"],' ' [\"Der {artikel} ist {fehler} und ich hätte gern mein Geld erstattet\", \"erstattung\"],' ' [\"Wie ist der Stand der Lieferung für meinen {artikel}\", \"verfolgung\"],' '];' 'const artikel = [\"Wasserkocher\", \"Teppich\", \"Schal\", \"Becher\"];' 'const fehler = [\"kaputt\", \"beschädigt\", \"zerkratzt\"];' 'const training = [\"Wo ist mein Wasserkocher? Er ist noch nicht angekommen\", \"Kann ich meinen Teppich gegen eine andere Farbe tauschen\"];' > synth.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 Generator schreiben, Teil 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'let s = 23;' 'function naechste(groesse) { s = (s * 16807) % 2147483647; return s % groesse; }' 'function erzeugen(n) {' ' const aus = [];' ' for (let i = 1; i <= n; i++) {' ' const v = vorlagen[naechste(vorlagen.length)];' ' let text = v[0];' ' if (text.indexOf(\"{artikel}\") >= 0) text = text.replace(\"{artikel}\", artikel[naechste(artikel.length)]);' ' if (text.indexOf(\"{fehler}\") >= 0) text = text.replace(\"{fehler}\", fehler[naechste(fehler.length)]);' ' aus.push({ id: i, text: text, label: v[1] });' ' }' ' return aus;' '}' >> synth.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 Generator schreiben, Teil 3
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function wortliste(text) {' ' const w = text.toLowerCase().replace(/[,?.]/g, \" \").split(\" \").filter(function (x) { return x.length > 0; });' ' return w.filter(function (x, i) { return w.indexOf(x) === i; });' '}' 'function aehnlichkeit(a, b) {' ' const wa = wortliste(a);' ' const wb = wortliste(b);' ' const gemeinsam = wa.filter(function (w) { return wb.indexOf(w) >= 0; }).length;' ' return Math.floor(gemeinsam * 100 / (wa.length + wb.length - gemeinsam));' '}' 'function nah(text, liste) {' ' return liste.some(function (t) { return aehnlichkeit(text, t) >= 80; });' '}' >> synth.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 Generator schreiben, Teil 4
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' ' const behalten = [];' ' const gruende = {};' ' erzeugen(12).forEach(function (f) {' ' let grund = \"\";' ' if (wortliste(f.text).indexOf(f.label) >= 0) grund = \"Antwort verraten\";' ' else if (nah(f.text, training)) grund = \"Trainingstext verraten\";' ' else if (nah(f.text, behalten.map(function (k) { return k.text; }))) grund = \"Duplikat\";' ' if (grund === \"\") behalten.push(f);' ' else gruende[grund] = (gruende[grund] || 0) + 1;' ' });' >> synth.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 Generator schreiben, Teil 5
docker exec -w /home/node/project agent sh -c "printf '%s\n' ' console.log(\"behalten \" + behalten.length + \" von 12\");' ' console.log(\"aussortiert: \" + JSON.stringify(gruende));' ' console.log(\"erster behaltener: \" + behalten[0].text + \" -> \" + behalten[0].label);' ' const probe = \"Ändern Sie die Vorlage so, dass das Label-Wort nie im Text steht.\";' ' const q = \"Sagen Sie in einem kurzen Satz, wie ein erfundener Fall verhindert, dass er seine eigene Antwort verrät.\";' ' const antwort = await fragen([{ role: \"user\", content: q }], probe, 60);' ' console.log(\"Das Modell sagte: \" + antwort.text);' '}' 'main();' >> synth.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 Generator ausführen
docker exec -w /home/node/project agent node synth.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 |
|---|---|
| behalten 7 von 12 | Fälle, die nach den Prüfungen übrig sind |
| aussortiert: {...} | Wie viele Fälle herausflogen und warum |
| erster behaltener: ... -> ... | Ein sauberer Fall und sein Label |
| 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.