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

Free lesson

Cost, access and privacy of images and voice

After this lesson: I can price a day of picture, page and sound inputs and flag the ones that need care.

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

A photo feature that costs too much

A team adds "ask about your photo" to an app. In a week the bill is high, a blind user cannot use it, and somebody asks why a face was stored for three months.

Pictures, pages and sound cost more than text, can leave people out, and can hold personal data. Plan for all three.

By the end of this lesson

Note

I can price a day of picture, page and sound inputs and flag the ones that need care.

Key words

WordWhat it means
Alternative textwords that stand in for a picture for a person who cannot see it
Transcriptthe words of a sound, written down
Personal datafacts that can identify a person, such as a face or a voice
Retentionhow long data is kept
Budgetthe most you plan to spend

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

Pictures, pages and sound are priced by size

Text is priced by its tokens (see the earlier module on cost and tracing). A picture is priced by its tiles, a page by its pages and a sound by its seconds.

In this lesson every request costs 1. A picture adds 20 and 10 a tile, a page adds 5 each, and sound adds 2 for every 10 seconds. These are invented units. Always read a real price list.

Pricing four inputs

InputSizeWorkingCost
Image6 tiles1 + 20 + 6081
Page4 pages1 + 2021
Audio25 seconds1 + 2 x 37
Audio10 seconds1 + 2 x 13

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

Access: who does the feature leave out?

A person who cannot see a picture needs alternative text. A person who cannot hear a sound needs a transcript. If a feature gives neither, it leaves those people out.

A model can often write both. But a person should check them, as the last lesson showed. Plan for the words to exist before a picture or a sound is stored.

A common mistake

Warning

Many people think a face or a voice is only personal data if the person is named. A face or a voice can identify a person even with no name beside it. Treat both as personal data, and keep them no longer than you need.

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 pricing script, part 1

Command
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { ask } = require(\"./model\");' 'const items = [' '  { id: 1, kind: \"image\", tiles: 6, alt: true, face: false, voice: false, days: 7 },' '  { id: 2, kind: \"image\", tiles: 16, alt: false, face: true, voice: false, days: 90 },' '  { id: 3, kind: \"page\", pages: 4, alt: true, face: false, voice: false, days: 30 },' '  { id: 4, kind: \"audio\", seconds: 25, alt: false, face: false, voice: true, days: 31 },' '];' > cost6.js"

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

Write the pricing script, part 2

Command
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function price(it) {' '  if (it.kind === \"image\") return 1 + 20 + 10 * it.tiles;' '  if (it.kind === \"page\") return 1 + 5 * it.pages;' '  if (it.kind === \"audio\") return 1 + 2 * Math.ceil(it.seconds / 10);' '  return 1;' '}' >> cost6.js"

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

Write the pricing script, part 3

Command
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function flags(it) {' '  const out = [];' '  if (it.face) out.push(\"face\");' '  if (it.voice) out.push(\"voice\");' '  if (it.alt === false && it.kind === \"image\") out.push(\"no alternative text\");' '  if (it.alt === false && it.kind === \"audio\") out.push(\"no transcript\");' '  if (it.days > 30) out.push(\"kept too long\");' '  return out;' '}' >> cost6.js"

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

Write the pricing script, part 4

Command
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' '  let total = 0;' '  for (const it of items) {' '    total += price(it);' '    console.log(it.id + \" \" + it.kind + \": cost \" + price(it) + \", flags \" + JSON.stringify(flags(it)));' '  }' '  console.log(\"total \" + total);' '  const q = \"Write one short notice telling users that their voice notes are deleted after 30 days.\";' '  const reply = await ask([{ role: \"user\", content: q }], \"Your voice notes are deleted after 30 days.\", 40);' '  console.log(\"reply: \" + reply.text);' '}' 'main();' >> cost6.js"

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

Price a day and flag inputs

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

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

The lines it prints

LineWhat it shows
1 image: cost 81, flags []A fine input: seen, short-lived
2 image: cost 181 ...A face, no alternative text and kept 90 days
4 audio: cost 7 ...A voice, no transcript and kept 31 days
total 290The four prices added up

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.