Skip to main content
A dataset holds examples whose answers you know. Evaluations and fine-tuning read from it. This request makes a tiny format example with two distinct contexts:
Save the returned dataset id. Then inspect rows, contexts, duplicates_removed, method and sha256. Two rows show the format, but they are not enough for a useful evaluation or fine-tune. Choose a different idempotency key for your next dataset.

Expected answers and outcome scores

Each row has a context and decisions, plus one of these fields:
  • A dataset uses one of them throughout.
  • Rows must not carry model or fallback. A fine-tune or an evaluation names its model.
  • Rows must not carry action policy fields, such as weights, costs or abstention. Those policies belong to inference.
  • A training dataset needs at least two distinct contexts, so that a held-out split is possible.
  • Identical examples are deduplicated.
  • Two rows that label one decision about one context differently are rejected with conflicting_labels. They are not averaged.

Decision IDs

Within a dataset, a decision ID names one decision. Every row that asks it must give the same kind, question and rubric. It must also give the same outcomes, in the same order, with the same descriptions. Repeating a decision unchanged is fine. A row that defines an ID another way is rejected with conflicting_decision. The message names both rows, by JSONL line for an upload. Give a different question its own ID.

Choose the evaluation set

Some contexts are held out to evaluate models, and never train them. You choose them in one of two ways:
  • Send the rows as examples. A hash of each context picks its side.
  • Send training and evaluation. Each row takes the side of its part.
One request uses one mode. The console offers the same choice.
  • training without evaluation is refused with insufficient_contexts.
  • A row never names its side. A row with side is refused. The code is invalid_request in a JSON body, and invalid_example in a file.
  • The fraction applies to groups of distinct contexts. Related examples stay together, so the actual share of examples can differ. The response’s split gives the actual train_rows and evaluation_rows.
The split is fixed across evaluations, training jobs and worker recovery. Changing a training seed doesn’t change it. Rows you add later keep each context on its side (add rows). The dataset’s evaluation_fraction says how its first version was split. Rows you add later have their own share. To choose another split, create another dataset. To score models on the evaluation rows, see Compare models.

Send files

For larger sets, save one example per line and send the file as a form:
To choose the evaluation rows yourself, send -F training=@training.jsonl -F evaluation=@evaluation.jsonl in place of examples and evaluation_fraction. The clients take them as training= and evaluation= in Python, and { training, evaluation } in TypeScript. Keep the files and their operation key for retries. The dataset’s input records the body’s format, json or multipart, with its byte count and its hash. The dataset’s hash identifies its validated content.

Upload errors

Inspect the saved rows

A version is the whole dataset at that point, so both files name it. The rows name no side, so the two files go back up as training and evaluation. Downloads are rate limited separately.

Add rows

A dataset grows in versions. Add rows, in either mode, to make its next version:
A JSON body takes the same fields: {"examples": [...]}, or {"training": [...], "evaluation": [...]}. Either part may be left out. The response is the dataset, with its new version, rows and split. You don’t need to know every decision ID when you start a dataset. Set allow_new_decision_ids to true, and an add may ask decisions the dataset doesn’t ask yet. Later adds then ask them as the dataset’s own. With examples, evaluation_fraction is the share of the new contexts held out for evaluation. It goes from 0.1 to 1, as a field or a form part. It is 0.2 when left out, whatever share the dataset was made with. So each add splits about 80/20 unless you choose otherwise.

How added rows are split

  • A row the dataset already holds is left out, and counted in duplicates_removed.
  • A row whose decisions come in another order is another row.
  • A context the dataset holds keeps its side of the split. So an evaluation row is never trained on.
  • A new context sent as training or evaluation takes that side.
  • For a new context sent in examples, a hash of the context picks its side, at the add’s evaluation_fraction.
  • Either way, its side is decided when it is added, and never moves.
Earlier versions never change. Fine-tunes and evaluations keep to the version they read. Each family that grows on the dataset can then continue on the new version, however many families share it. To compare models on the new version, start new evaluations (what is reused). GET /v1/datasets/{dataset_id}/versions lists the versions, newest first, with the rows each added. To read an earlier version, add version=N to /rows or /download.

Storage

Rows that take a dataset past pricing.dataset_free_rows examples (on GET /v1/onehot) hold its first day of storage. To cap that price, send max_price_usd in the JSON body or as a part of the form (cap a price).

Curate before training

Collect real cases that you have permission to use. Remove identifying data you don’t need. Agree on the labelling rule before you assign labels. Include difficult negatives, rare outcomes and unclear cases. Resolve disagreements, rather than treating a teacher’s answer as ground truth. The split keeps identical contexts together, but it can’t detect every semantic duplicate. Remove near-duplicates yourself, so they don’t leak across the split. Keep a separate evaluation set that represents future traffic. Compare against a simple baseline, such as the majority class.

Rename, delete and restore

A version’s rows never change, and each context keeps its side of the split. Add rows as a new version. Create another dataset when labels or wording change.

Delete a dataset

Deleting a dataset removes every version, your original uploads and the copies your fine-tunes kept of its rows. It can’t be undone.
  • Fine-tuned models and their metrics stay. A family that grows on the dataset keeps answering, but can’t continue (delete a family).
  • The answer is {"id": "…", "deleted": true}. Deleting again changes nothing.
  • The dataset is then in no list. Its reads, rows, download, rename and new work return 410 dataset_deleted. So do its fine-tunes’ held-out records.
  • While a fine-tune, evaluation or accepted prompt-tuning job that reads the dataset is queued, running or cancelling, deleting returns 409 in_use and changes nothing. A job that reads a copy of its rows counts too.
  • An upload retried with the same Idempotency-Key returns the dataset it made. Once you deleted that dataset, the retry returns 410 dataset_deleted. It never brings the dataset back.

Archived datasets

We archive a dataset ourselves when its next day of storage can’t be held. On a suspension, we archive every dataset that pays for storage (keep warm and storage). An archived dataset keeps its data, results and history. It starts no new work, which gets 409 dataset_archived. Next, label with teacher models, compare models, tune the wording or fine-tune a model.