Build with AI

How do you build a dataset that teaches the job, legally?

Written as of · Published · Updated · By Robert Scales, with AI tools · 5 min read

Short answer

Start from the decision the model must make, then collect examples of real use that you have the right to use, remove personal details and duplicates, and record where everything came from. In a measured test, the same model scored 100% on a careless split and 90% on an honest one, and it scored no better than chance on French messages it had never been shown.

A dataset teaches a job only if it looks like the job. That sounds obvious until you notice how often training data is whatever was easy to collect. A model learns the patterns in its examples, whether or not they are the ones you meant.

This project builds a small dataset for one decision: route each customer message of a fictional bike shop to refunds, shipping, repairs or accounts. All 2,120 raw messages are generated by a script, so no real person's data is involved. The companion script 03_build_dataset.py needs only scikit-learn and takes seconds. If you are preparing text for a language model rather than a routing decision, this guide to preparing a dataset covers the cleaning and storage steps at larger scale.

Step 1: write the job down first

Before collecting anything, fill in this sheet. It is a shorter cousin of the datasheets researchers proposed for documenting a dataset's motivation, composition, collection process and uses.

QuestionExample answer
What decision will the model make?Pick one of four queues
What does it see at that moment?The message text only, no customer history
Who writes those inputs?Customers, in English and French
What does a wrong answer cost?A delay of one transfer between queues
Who decides the right label, and how?Two staff members, written definitions
Where may this data come from?Our own messages, with notice and consent; openly licensed text

The second-to-last row is often skipped. If two careful people disagree on the label, the model cannot do better than they can.

Step 2: run it through four gates

Each record carries where it came from. The pipeline refuses, cleans, removes duplicates and then splits, keeping a count for every step.

OK_LICENCES = {"own-records-with-consent", "cc0", "cc-by-4.0"}

def pipeline(rows):
    kept = [r for r in rows if r["licence"] in OK_LICENCES]    # gate 1: rights
    for r in kept:
        r["text"], r["scrubbed"] = scrub(r["text"])            # gate 2: personal details
    seen, out = set(), []
    for r in kept:
        key = normalize(r["text"])                             # gate 3: duplicates
        if key not in seen:
            seen.add(key)
            out.append(r)
    return out                                                  # gate 4: split by wording family

Measured here on the synthetic data:

StepRows
Raw2,120
Refused: unknown or unapproved licence−236
Duplicates removed−236
Final1,648

The scrubber used patterns for email addresses, phone numbers and Canadian postal codes. It caught all 279 planted details, with no false alarms. Do not read too much into that perfect score: the script planted only the formats the patterns look for. Names in free text, such as "my neighbour Mara", pass straight through. On real data, have a person read a random sample, and treat scrubbing as a reduction of risk.

The final file ships with a manifest: row counts per label, per licence and a SHA-256 fingerprint, a short code that changes if one byte of the data changes. When a score moves next month, you can tell whether the data moved.

What the gates change, in numbers

Each figure below is an average of five runs. The model is deliberately simple: word counts fed to a logistic regression.

TestAccuracy
Duplicates kept, random split100%
Clean data, test on wordings never seen in training90.2%
Same honest test, 10% of training labels wrong72.2%
30% of training labels wrong60.5%
50% of training labels wrong41.3%
French messages, English-only training25.0%, exactly chance

The first two rows use the same recipe. The difference is the split. A careless split puts near-copies of a message on both sides, so the test measures memory. Splitting by wording family, all the variations of one way of asking, gives a much more useful number. scikit-learn has group-aware splitters for this. Real equivalents of a family include one customer, one document, one recording session.

The last row is the most important in a place like Québec. An English-only dataset gave a model that scored 25% on French, the same as a coin with four sides. Accuracy on your test set says nothing about the people who are missing from it.

This is general information and not legal advice. Rules differ by country and change; ask a lawyer before relying on any of this for a product.

Source of dataQuestion to answerUsual action
Your own records about customers or staffDid the person know it could be used this way? Is it personal information?Remove identifiers, check your privacy policy, get consent if the use is new
Openly licensed text, for example CC0 or CC BYWhich exact licence applies to which file? Must you credit?Keep the licence and the source with each file
Public domain booksPublic domain where you are? Added material may not beRecord the edition; remove any added notices
A website that you scrapeTerms of use? Copyright? Technical blocks?Assume no until shown otherwise
Other people's published model outputsDo the terms allow training?Read them first

In Canada, the Copyright Act lists fair dealing purposes such as research, private study and education, and text and data mining is not among the listed purposes. It also prohibits getting around technological protection measures, with listed exceptions. In the United States, courts are deciding these questions case by case, and how the material was obtained has mattered.

In Québec, Law 25 has strengthened the rules on personal information and the powers of the Commission d'accès à l'information. A dataset of customer messages very likely holds personal information. Using it to train a model may be a new purpose. Write down your answer, and ask the person responsible for privacy in your organization.

Try it: Take ten real examples of your own task and fill in the job sheet. Note every row where you wrote "not sure", and resolve those before you collect a single further example.

How do you know the data is enough before you train anything big?

Draw a learning curve: train on growing subsets and test on the same honest set. Measured here, averaged over five runs:

Training rowsAccuracy on unseen wordings
2040.9%
4050.8%
8071.8%
16083.8%
32088.9%
64090.4%
All (about 1,370)90.2%

Past about 640 rows, more of the same stopped helping. That is a signal to change what you collect, not how much. A second experiment shows it directly. With about 140 rows, using one wording family per label gave 40.5%; the same number of rows drawn across all the families gave 83.0%. Same size, double the skill.

If the curve is still climbing at your largest size, collect more of the same kind. If it is flat and you need better results, collect what is missing: new wordings, the hard cases, the second language. Then fix label errors, because the noise table shows how costly they are, and only after that consider a larger model. Before you believe any improvement, run the honest testing in project four.

Download the companion code for this series (zip), with every script and the recorded results.

Sources

  1. Datasheets for Datasets — arXiv, March 23, 2018
  2. Copyright Act (R.S.C., 1985, c. C-42) — Justice Laws Website, Government of Canada, November 7, 2024
  3. Entrée en vigueur des nouvelles dispositions de la Loi 25 — Gouvernement du Québec (Secrétariat à la réforme des institutions démocratiques, à l'accès à l'information et à la laïcité), September 22, 2023

From the Guide to Artificial Intelligence, by Robert Scales, published by Holistic Hybrid Inc. Share and adapt it under CC BY-NC-SA 4.0: credit the guide, link to https://guidetoartificialintelligence.com/en/learn/build-dataset-teaches-job-legally/, no commercial use without permission, and keep the same licence.

Get the free Guide to Artificial Intelligence

Sign up for the newsletter and receive the free guide: what changed in AI, one lesson, one prompt to try. Unsubscribe in one click.

How we handle your address

Back to top

Display

Your choices are saved in this browser only. No data is sent.

Text size
100%
Colours
Reading
More settings
Accessibility statement

Get the app

Add the guide to your home screen. It opens like an app, and the pages you have read stay available offline.

Read without a connection: download the articles

iPhone and iPad (Safari, Chrome, Edge)

  1. Tap the Share button (the square with an arrow). In Chrome and Edge, it is in the address bar or the menu.
  2. Choose “Add to Home Screen”.
  3. Tap “Add”.

Android (Chrome, Edge, Samsung Internet, Firefox)

  1. Open the browser menu (⋮ or ☰).
  2. Choose “Install app” or “Add to Home screen”.
  3. Confirm with “Install”.

Computer (Chrome, Edge)

  1. Click the install icon at the right end of the address bar, or open the browser menu (⋮ or …).
  2. In Chrome, choose “Cast, save and share”, then “Install page as app”. In Edge, choose “Apps”, then “Install this site as an app”.
  3. Click “Install”.

Mac (Safari)

  1. Open the File menu.
  2. Choose “Add to Dock”.
  3. Click “Add”.

Firefox on a computer can’t install a site as an app. Use Chrome, Edge or Safari instead.