Training data is a list of examples
Fine-tuning teaches a model from examples you supply. Each example is a pair: what the model is given, and what you want back. Whatever your pairs do, the model copies.
So one careless spelling, repeated forty times, is forty lessons in the wrong thing.
By the end of this lesson
Note
I can write training examples a model can learn from.
Key words
| Word | What it means |
|---|---|
| Fine-tuning | training a model further on your examples |
| Prompt | the input half of a training pair |
| Completion | the answer half of a training pair |
| JSONL | a file with one JSON object on each line |
| Label | a fixed word that names a class |
The cells students fill in are left blank in this preview.
One pair on every line
A JSONL file holds one example a line. Each line is a small JSON object with a prompt and a completion.
A line is easy to check alone. If line 90 is broken, lines 1 to 89 still work. That is why this form is common for training files.
Worked example: three lines
| Line | What it holds | Verdict |
|---|---|---|
| 1 | prompt "I was charged twice", completion "billing" | Good |
| 2 | prompt "Wrong invoice" and no completion | Missing completion |
| 3 | prompt "Love your shop", completion "Other" | Unknown label: the case is wrong |
The cells students fill in are left blank in this preview.
Keep the form the same every time
A model learns the pattern in your pairs, including the faults. If "billing" is also spelt "Billing" and "bills", it learns three answers.
Choose a fixed list of labels, one spelling for each and one layout for every prompt. Then check the file with a program, not by eye.
A common mistake
Warning
Many people think more examples always help. A hundred clean pairs teach more than a thousand messy ones, because a model copies the faults too. Fix the file first, then add more.
Write the model helper, part 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const base = process.env.AI_URL || \"http://ai:4000\";' '// The token counts of a reply, or null when the reply carries none.' 'function count(data, name) {' ' return data.usage && typeof data.usage[name] === \"number\" ? data.usage[name] : null;' '}' > model.js"Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Write the model helper, part 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function ask(messages, sample, max) {' ' try {' ' const res = await fetch(base + \"/v1/chat/completions\", {' ' method: \"POST\",' ' headers: { \"content-type\": \"application/json\", authorization: \"Bearer lab\" },' ' body: JSON.stringify({ model: \"lab\", messages: messages, max_tokens: max || 100 }),' ' signal: AbortSignal.timeout(30000),' ' });' ' if (res.ok === false) throw new Error(\"status \" + res.status);' ' const data = await res.json();' ' const text = data.choices[0].message.content;' ' return { text, inTokens: count(data, \"prompt_tokens\"), outTokens: count(data, \"completion_tokens\"), recorded: false };' ' } catch (error) {' ' console.log(\"Recorded sample: no model answered (\" + error.message + \").\");' ' return { text: sample, inTokens: null, outTokens: null, recorded: true };' ' }' '}' 'module.exports = { ask };' >> model.js"Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Write the line checker, part 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { ask } = require(\"./model\");' 'const LABELS = [\"billing\", \"delivery\", \"other\"];' 'const lines = [' ' JSON.stringify({ prompt: \"I was charged twice\", completion: \"billing\" }),' ' JSON.stringify({ prompt: \"Where is my parcel\", completion: \"delivery\" }),' ' JSON.stringify({ prompt: \"Love your shop\", completion: \"Other\" }),' ' JSON.stringify({ prompt: \"Wrong invoice\" }),' ' JSON.stringify({ prompt: \"\", completion: \"other\" }),' ' \"not json at all\",' ' JSON.stringify({ prompt: \"Box arrived crushed\", completion: \"delivery\" }),' '];' > adapt2.js"Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Write the line checker, part 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function check(line) {' ' let row;' ' try { row = JSON.parse(line); } catch (e) { return \"not json\"; }' ' if (row === null || typeof row === \"string\" || typeof row === \"number\") return \"not an object\";' ' if (typeof row.prompt === \"undefined\" || typeof row.prompt === \"number\") return \"missing prompt\";' ' if (typeof row.completion === \"undefined\" || typeof row.completion === \"number\") return \"missing completion\";' ' if (row.prompt.trim() === \"\") return \"empty prompt\";' ' if (LABELS.includes(row.completion) === false) return \"unknown label\";' ' return \"\";' '}' >> adapt2.js"Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Write the line checker, part 3
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' ' let ok = 0;' ' lines.forEach(function (line, i) {' ' const why = check(line);' ' if (why === \"\") ok = ok + 1;' ' else console.log(\"line \" + (i + 1) + \": \" + why);' ' });' ' console.log(ok + \" of \" + lines.length + \" lines ok\");' ' const q = \"In one sentence, why must every training example use the same label spelling?\";' ' const sample = \"A model learns each spelling as a different answer, so mixed spellings split what it learns.\";' ' const reply = await ask([{ role: \"user\", content: q }], sample, 40);' ' console.log(\"model: \" + reply.text);' '}' 'main();' >> adapt2.js"Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Run the line checker
docker exec -w /home/node/project agent node adapt2.jsShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
What the checker found
The seven lines are invented. The checker reads each one alone and says the first fault it finds, so you fix one fault at a time.
The last line is one short model call. With no model it prints a Recorded sample.