مهندسی سامانههای هوش مصنوعی · فصل ۱ — Gateway، Structured Output، Prompt Governance و Qualification · 134
Structured Outputs and Schema Validation
Design a structured-output contract that separates transport/syntax state, schema conformance, terminal model states and domain invariants; implement deterministic validation and failure handling so only outputs that satisfy the declared application contract are promoted downstream, while refusal, incomplete, schema-invalid and semantically-invalid states remain distinct and testable. میتواند «Structured Outputs و Schema Validation» را در یک workflow AI محدود طراحی کند و validation، authority، cost یا failure controls مرتبط را مشخص کند.
Lesson summary
Design a structured-output contract that separates transport/syntax state, schema conformance, terminal model states and domain invariants; implement deterministic validation and failure handling so only outputs that satisfy the declared application contract are promoted downstream, while refusal, incomplete, schema-invalid and semantically-invalid states remain distinct and testable.
میتواند «Structured Outputs و Schema Validation» را در یک workflow AI محدود طراحی کند و validation، authority، cost یا failure controls مرتبط را مشخص کند.
This lesson produces
میتواند «Structured Outputs و Schema Validation» را در یک workflow AI محدود طراحی کند و validation، authority، cost یا failure controls مرتبط را مشخص کند.
Who it is for
Foundation
Use a guided contract/evidence matrix and one worked provider/output/context/eval contrast.
Repair
Re-run only the failed contract or evidence dimension with a smaller deterministic synthetic fixture.
Experienced
Start from mixed provider evidence and require explicit capability/validation/governance/qualification trade-offs.
Prerequisites
1. The real problem: valid JSON is still not a valid result
When a model returns text that parses as JSON, only one boundary has been crossed. A dependable workflow separates at least four layers: model terminal state, parseability, schema conformance, and domain invariants. A failure at any layer must not be coerced into a plausible object with defaults. This lesson keeps refusal, incomplete, parse error, schema error, and semantic/domain error as distinct, testable states.
2. Define the application contract before the provider
Write the application contract independently of the provider: required fields, field types, enums, extra-property behavior, nullability, schema version, and business invariants. In the lab, the classifier must produce {category, priority, requires_human, evidence_ids}. That is the application contract. Whether a provider emits it through json_schema, a tool schema, or another mechanism is a separate capability. Provider changes therefore do not silently redefine business logic.
3. Check terminal state before parsing
Before calling a JSON parser, determine whether the response is data completion or another terminal state. Keep REFUSAL, INCOMPLETE, and COMPLETE separate. A refusal is not classifier data, and an incomplete response is not a partial object that the application may guess into completion. The harness classifies terminal state first and only attempts parsing for COMPLETE responses.
4. Parseability proves syntax only
If the text parses, you know the JSON syntax is readable. You do not yet know that required fields exist, enums are allowed, types are correct, or extra properties are forbidden. Parse status therefore gets its own explicit result such as PARSE_OK or PARSE_ERROR. The failure record also retains raw payload identity and the parse error class so downstream code does not need to interpret arbitrary exceptions.
5. Schema validation must be deterministic
After parsing, validate the object against a specific schema version. Required properties, types, enums, array-item types, and extra-property policy must be enforced deterministically. Lab schema v1 requires four core fields and rejects unknown properties. The goal is not to reimplement a provider feature; it is to create independent, repeatable evidence for the application's own contract.
6. A provider strict feature does not replace application validation
Structured-output or strict-tool features can reduce structural failures, but they do not remove application responsibility. A provider may support only a subset of JSON Schema, capabilities can vary across models, and non-data terminal states can still occur. Keep provider-facing and application-facing schemas explicitly mapped. If the required feature is unsupported, preserve UNSUPPORTED_CAPABILITY; do not silently fall back to JSON mode or free text unless policy explicitly allows it.
7. Domain invariants come after schema validation
A schema can assert that evidence_ids is an array of strings, but it cannot by itself prove that every ID belongs to the allowed evidence set. The application may also require requires_human=true whenever priority=high. Those are application invariants and run after schema validation. A schema-valid object that violates an invariant is DOMAIN_INVALID, not partial success.
8. Typed failures are better than scattered exceptions
Each failure needs a stable class, retryability, and promotion decision. Examples include PROVIDER_REFUSAL, RESPONSE_INCOMPLETE, PARSE_ERROR, SCHEMA_INVALID, and DOMAIN_INVALID. Downstream code should branch on these types instead of parsing exception text. Retry behavior must follow the failure class: some failures may justify a bounded regeneration, while others require schema, prompt, model, data, or human/application correction.
9. Treat additional properties and enum drift as first-class failures
Unexpected properties and enum drift are common integration failures. If downstream code branches over a closed enum, a new value can break behavior unless versioning catches it. Extra properties can also signal prompt or provider-shape drift. A strict contract using additionalProperties: false or an equivalent deterministic rule makes drift fail early and visibly instead of leaking into downstream logic.
10. Nullable is not the same as optional
An optional field may be absent. A nullable field may be present with null. In this lesson's transfer, schema v2 adds an optional nullable due_at field. The harness preserves the difference between absence, null, and a valid string. Automatically converting absence to null, or null to absence, is a semantic mutation unless the contract explicitly permits it.
11. Schema version is part of provenance
Every validation record must retain the schema version. Without it, the claim “this output validated” is incomplete. When v2 narrows the priority enum, a payload using priority=low may be valid under v1 and invalid under v2. That incompatibility must be recorded explicitly. Evidence for v1 does not automatically transfer to v2; the payload must be evaluated against the new version.
12. The promotion gate has four ordered stages
This lesson's promotion gate runs in order: 1) terminal state must be complete data; 2) payload must parse; 3) object must conform to the declared schema; 4) domain invariants must pass. Each stage emits its own failure and later stages do not run when an earlier gate fails. This prevents domain checks on malformed payloads and preserves an auditable evidence chain.
13. Separate retry, remediation, and human correction
Not every failure is retryable. INCOMPLETE may justify a bounded retry; a refusal should not trigger blind repetition. SCHEMA_INVALID can trigger prompt/model/schema-mapping remediation. DOMAIN_INVALID often points to source data or a human/application decision. Record retryability and remediation class with every failure so a workflow cannot enter an unbounded retry loop or hide cost behind repeated attempts.
14. Lab: eight deterministic fixtures
The lab contains eight fixtures: contract-valid baseline, malformed JSON, missing required field, a multi-violation structural case with type/enum/extra-property errors, provider refusal, incomplete response, schema-valid output with an unsupported evidence ID, and a schema-v2 transfer case with a narrowed enum. Each case produces eight fixed outputs: terminal state, parse result, schema conformance, domain result, promotion decision, failure class, retryability, and compatibility result. The reference run must pass exactly 64 assertions.
15. Exit checklist and transfer
Before exit, verify that the contract is versioned; terminal states are separate from data; parsing, schema validation, and domain validation are distinct; failures are typed; unsupported capability is not coerced into success; retries are bounded; schema version is retained in evidence; and promotion occurs only after all four gates pass. Then run the transfer: schema v2 adds nullable due_at and narrows priority. Re-run old and new fixtures and classify which failures justify retry, prompt/model/schema change, or human/application correction.
Assessment
There is no answer key in this lesson pack; answer it yourself and mark honestly. "Needs review" sends the lesson to your review queue.
Q1 retrieval
Why does valid JSON not prove a valid application result?
Q2 application
A COMPLETE response parses but is missing requires_human. What state should the harness emit?
Q3 diagnosis
A payload conforms to schema but contains evidence_id E-999 outside the allowed set. What failed?
Q4 evidence
What provenance must a validation record retain to make a prior PASS meaningful after schema change?
Q5 transfer
Schema v2 removes low from priority and adds optional nullable due_at. How should an old low-priority payload be treated?
Assessment rubric
A sufficient submission keeps terminal state, parsing, schema conformance, and domain invariants distinct; records schema version and exact fixture identity; preserves refusal/incomplete/invalid states without coercion; uses typed failures with bounded retry/remediation; and rebuilds the decision under schema v2 instead of inheriting v1 evidence. Any global claim that provider strict output proves truth, safety, authorization, or domain correctness is insufficient.
References & freshness
Case studies
Lesson visuals
Lab files
Implement evaluate(case) in starter.py. Return exactly eight fields: terminal_state, parse_result, schema_conformance, domain_invariant_result, promotion_decision, failure_class, retryability, and compatibility_result.
The application contract is a synthetic ticket classifier. Schema v1 requires category, priority, requires_human, and evidence_ids, rejects unknown properties, and permits priority low|medium|high. Schema v2 adds optional nullable due_at and narrows priority to medium|high. Categories are billing|technical|account. evidence_ids must be strings.
Domain rules: every evidence ID must occur in allowed_evidence_ids; and priority=high requires requires_human=true.
Processing order matters: classify terminal state first, then parse, then schema, then domain invariants. Do not manufacture missing fields, reinterpret refusal as data, or inherit v1 validation into v2.
Run python run_checks.py to verify the eight fixtures are well-formed. Your implementation should produce typed failures and bounded retryability rather than generic success/failure booleans.
Lesson media & slides
Teaching files (download)