Easier to read with cream paper, a tint, more contrast or larger text? Choose your colours and text, once, for every page.

Free lesson

Finding personal data in a prompt

After this lesson: I can find personal data in a prompt with rules and say what the rules miss.

60 min lesson8 commandsAI coding agent lab: use opencode to explain and fix code, and check its work

Finding personal data before it is sent

Personal data is any fact about a living person who could be identified from it. Finding it in a prompt matters, because a prompt can leave your computer and cannot be called back.

A name, an email address and a phone number all count. An app that sends messages to a model may send these without meaning to. You cannot protect what you cannot find, so finding it comes first.

By the end of this lesson

Note

I can find personal data in a prompt with rules and say what the rules miss.

Key words

WordWhat it meansExample
Personal dataa fact that points to one living person
Rulea test that a piece of text passes or failshas an @ sign
Shapehow a kind of value is written07700900123
False alarmtext the rule flags that is not personal
Misspersonal data the rules did not flag

The cells students fill in are left blank in this preview.

Rules find data that has a shape

Some personal data is always written the same way. An email address has an at sign and a dot. A UK mobile number is 11 digits starting 07.

A rule tests one shape. A finder splits a message into words and tests each word against every rule. It lists what it finds in the order the words appear.

Worked example: four rules

KindRuleInvented example
emailAn at sign, then a dot later[email protected]
phone11 digits, starting 0707700900123
niTwo capitals, six digits, one capitalQQ123456C
card16 digits4000000000000002

The cells students fill in are left blank in this preview.

Rules miss things and raise false alarms

A rule only knows shapes. A name has no shape, so no rule finds it. A phone number typed with spaces becomes three words, and none fits.

A false alarm is the opposite fault. A 16 digit order number has the card shape, so the rule flags it. Both faults are normal. Count them so you know how far to trust the rules.

Worked example: a miss and a false alarm

Message partA person saysThe rules sayResult
Ben SamplePersonalNothing foundMiss
07700 900 456PersonalNothing foundMiss
4000000000000002 (an order number)Not personalCardFalse alarm
[email protected]PersonalEmailCorrect

The cells students fill in are left blank in this preview.

A common mistake

Warning

Many people think a finder that prints nothing means the message is clean. It does not. It means no rule matched. A name or an address written in words has no shape. Say "no known shape found" and never "no personal data".

Write the model helper, part 1

Command
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

Command
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 finder, part 1

Command
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { ask } = require(\"./model\");' 'const messages = [' '  \"Please email [email protected] about the refund.\",' '  \"Call me on 07700900123 after five.\",' '  \"My number is 07700 900 456, ring any time.\",' '  \"NI number QQ123456C is on the form.\",' '  \"Order 4000000000000002 shipped to Ben Sample.\",' '];' 'const marked = [[\"[email protected]\"], [\"07700900123\"], [\"07700 900 456\"], [\"QQ123456C\"], [\"Ben Sample\"]];' > finder.js"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Write the finder, part 2

Command
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function clean(word) {' '  let w = word;' '  while (w.length > 0 && \".,;:?()\".includes(w[w.length - 1])) w = w.slice(0, -1);' '  return w;' '}' 'function digits(w, n) {' '  return w.length === n && w.split(\"\").every(function (c) { return c >= \"0\" && c <= \"9\"; });' '}' >> finder.js"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Write the finder, part 3

Command
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function kindOf(w) {' '  const at = w.indexOf(\"@\");' '  if (at > 0 && w.indexOf(\".\", at) > at + 1) return \"email\";' '  if (digits(w, 11) && w.startsWith(\"07\")) return \"phone\";' '  const ni = w.length === 9 && /[A-Z][A-Z]/.test(w.slice(0, 2)) && /[A-Z]/.test(w[8]);' '  if (ni && digits(w.slice(2, 8), 6)) return \"ni\";' '  if (digits(w, 16)) return \"card\";' '  return \"\";' '}' >> finder.js"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Write the finder, part 4

Command
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function find(text) {' '  const out = [];' '  text.split(\" \").forEach(function (word) {' '    const w = clean(word);' '    if (kindOf(w).length > 0) out.push({ kind: kindOf(w), value: w });' '  });' '  return out;' '}' 'function same(a, b) { return JSON.stringify(a) === JSON.stringify(b); }' >> finder.js"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Write the finder, part 5

Command
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' '  messages.forEach(function (text, i) {' '    const values = find(text).map(function (f) { return f.value; });' '    const missed = marked[i].filter(function (v) { return values.indexOf(v) < 0; });' '    const extra = values.filter(function (v) { return marked[i].indexOf(v) < 0; });' '    console.log((i + 1) + \" found \" + JSON.stringify(find(text)) + \" missed \" + JSON.stringify(missed) + \" false alarm \" + JSON.stringify(extra));' '  });' '  const q = \"In one short sentence, why can a rule not find a name?\";' '  const sample = \"A name has no fixed shape, so a rule has nothing to match.\";' '  const reply = await ask([{ role: \"user\", content: q }], sample, 60);' '  console.log(\"model said: \" + reply.text);' '}' 'main();' >> finder.js"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Run the finder

Command
docker exec -w /home/node/project agent node finder.js

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

What the Run prints

LineWhat it shows
1 found email ... missed [] false alarm []A correct find
3 found [] missed ["07700 900 456"]A number with spaces is missed
5 found card ... missed ["Ben Sample"]A name is missed
5 ... false alarm ["4000000000000002"]An order number looks like a card
model said: ...A sentence. The words differ each run

The cells students fill in are left blank in this preview.

About this lab and its source: AI coding agent lab: use opencode to explain and fix code, and check its work

Teaching a class? Set this module for your students with a teacher guide, marked assignments and a lab for every student.