Skip to main content

Samples

Everything you send to SDVM is a list of samples. Each sample declares a task_type so the service knows how to audit and fix it. Multiple-choice samples carry a context, a list of choices, the answer_index of the one correct choice, and an extra dict of passthrough metadata that comes back untouched. A question-answer sample is just the two fields, with the same extra passthrough. A conversation is its messages list, with the same extra. Each type has its own page under Sample types with the fields it holds and its shape on the wire.

The models

Each has an async twin (AsyncAuditor, AsyncFixer, AsyncRefinery) with the same run method.

The audit block

After an audit, every sample carries .audit: a dict of dimension name to verdict (true = healthy; false = defect; null = the check does not apply). Alongside the shape and content checks each type lists on its own page, sdvm-audit-1 returns these dimensions, per sample type: A verdict is a reading of the sample, not a lookup: on a borderline item it can differ between requests. Where it has to be stable, votes audits the sample several times and keeps the majority.
Auditor.aggregate(samples) adds a local, dataset-level view: per-field distributions, a per-dimension pass/fail rollup, and an answer-position bias check that tells you whether the correct answer sits in one slot too often.

The fix block

After a fix, every sample carries .fix:
changes lists what the fix did. flagged marks a sample the fix could not fully resolve, surfaced for review rather than shipped as a silent partial edit. attempts is how many tries the fixer got at it (see max_attempts). Filtering on flagged gives you a review queue:

The never-worse contract

sdvm-fix-1 fixes what the audit verdicts say is wrong. If a fix would introduce a new defect — a structural one, an empty field, mojibake or PII — it is withheld and the sample is flagged. A fix never leaves a sample worse than its input. Fixer does not judge whether a fix helped; that takes a reaudit, which is Refinery’s job.

The refine pipeline

Refinery runs, server-side, one pass of three stages:
Each stage has its own config — AuditorConfig(votes) for the two audits, FixerConfig(max_attempts) for the fix — and each returned sample carries one block per stage: .audit is the verdict before the fix (the one the fix was routed from, and the same block Auditor returns), .fix records what the fix changed, and .reaudit is the verdict after it, which is how you tell whether the fix helped. A sample the fix left alone is not re-audited; its .reaudit is None and its .audit still holds.

Limits

  • Up to 100 samples per request.
  • 100 requests per minute per key.
  • Token-based pricing with a minimum of $0.01 per request; see Pricing.
Last modified on September 18, 2026