https://gateway.errorbar.ai/v1 or the dashboard’s fine-tuning wizard.
You can also curate a managed dataset straight from your
logged traffic;
filtered by task, model, or auto-detected segment, with
a disjoint eval holdout. A dataset is a frozen snapshot: logs age out on
your retention window (7/30/90 days), but a dataset curated from them does
not: curate what matters before it expires.
Curation isn’t just a filter; it cleans as it builds. Only successful
responses are included; byte-identical duplicates (cache-replay collapse),
truncated answers (finish_reason=length), and empty replies are dropped, and
multi-turn conversations are reconstructed and folded so early turns aren’t
over-trained. Every build reports exactly what it kept and why
(“kept 4,812 of 6,003: 891 duplicates, 300 truncated…”).
Curating from logs
POST /v1/datasets/from_logs turns logged traffic
into a managed dataset. It needs an owner/admin key and a name (80 characters
or fewer); everything else narrows what feeds the build.
Choosing the traffic
The build reads the 50,000 most recent matching rows. Filter deliberately on
high-volume traffic rather than assuming a bare
name sweeps everything.
The quality ladder
quality.mode decides how high the bar sits. This is the part that makes a
dataset yours rather than merely clean:
cleaned — mechanical curation only (default)
cleaned — mechanical curation only (default)
Drops errored, truncated, empty, and duplicate exchanges. No judgement of
whether the answers were any good.
graded — only what a human passed
graded — only what a human passed
Keeps only exchanges a person graded pass. Free, and the highest-precision
option you have, bounded by how much you’ve graded.
The response reports
ungraded_excluded so you can see what the bar cost
you.judge — only what a calibrated judge passed
judge — only what a calibrated judge passed
Applies a calibrated judge at each conversation’s
terminal turn, which is how you get graded-quality selection at a volume no
person could grade by hand.
criterion_id is required, and the criterion
must be calibrated to the aligned tier, request-unit, and free of a drift
flag; a segment-bound judge only works on a build scoped to its segment.
Each refusal is written to the refusal ledger rather than silently
downgrading the build.In every mode, an exchange a human graded FAIL never enters a dataset — nor
does one sharing an agent run with a trace-scoped FAIL. The ladder raises the
bar; it never lowers it below your own grades.
Decontamination
decontaminate defaults to true: rows whose prompt shares a 13-word shingle
with a public benchmark’s test split are dropped, so a later benchmark score
measures capability rather than a memorised answer key. Pass false to keep
them. If the contamination index is unavailable the provenance records “not
checked” — never “clean”.
The eval split
holdout_pct (0–50) carves a second, disjoint {name}-eval dataset out of
the curated lines. No example appears in both, which is exactly what makes it
usable as an eval source: pass its id as sample_filters.dataset_id when
queueing an eval.
What the response tells you
A201 returns training_name / training_count, the eval pair when you asked
for a split, and two accounting objects worth reading rather than skipping:
summary—total,kept, anddroppedbroken out by reason (unparseable,errored,truncated,empty,duplicate,human_failed,contaminated), plus the multi-turn folding counts. A dataset is never silently thinner than you think.quality— what the gate actually did: the mode, the judge’skappaat build time,human_pass_kept,ungraded_excluded, and in judge modejudged,judge_passed,judge_failed,judge_unparsed, andjudge_spend_usd. A dataset never claims more than what happened.
400 and creates nothing.
Upload methods
Direct file
Upload a JSONL file directly as a training file.
Object storage (S3)
Use an S3-compatible bucket as a dataset source with your credentials.
Chunked upload
Large files upload in parts (chunked/multipart) so big datasets upload
reliably.
Uploading a training file
Upload a JSONL training file withPOST /v1/fine_tuning/files, and list your
files with GET /v1/fine_tuning/files.
trainingFileId (or
validationFileId) when creating a job.
Training formats
When you use a managed dataset, you map its columns into one of four training formats. Pick the format that matches your task:Text — raw text completion
Text — raw text completion
Plain text. Map a single column to the text field. Use for continued
pretraining or simple completion.
Prompts — prompt / completion pairs
Prompts — prompt / completion pairs
Prompt/completion pairs. Map one column to the prompt and one to the
completion. Use for instruction tuning.
Messages — chat format (role / content)
Messages — chat format (role / content)
OpenAI chat format: role/content conversations. Map the column that holds
the conversation. Use for chat/assistant fine-tuning.
Pretokenized — token-id arrays
Pretokenized — token-id arrays
Already-tokenized data as token-id arrays. Map
input_ids (and optionally
labels, attention_mask). Use when you control tokenization.Validation
JSONL is validated before a job starts. Line-level JSONL errors and format problems are surfaced with the exact reason, so you fix them before spending on a job rather than after. You can also preview dataset rows in the dashboard before training.Using a dataset in a job
Once your file or dataset is ready, reference it when creating a fine-tuning job. A managed dataset is converted to a training_file automatically, using the column-mapping format you chose; you then pass the resulting file id astrainingFileId.
Create a job
Start training with your prepared data.
Deploy the result
Serve a trained model on a dedicated endpoint.