Skip to content

StructX Roadmap

Last updated: 2026-07-11

This roadmap records future library work that should remain reproducible, portable, and safe across Python processes. It is ordered by dependency rather than calendar date.

Current Focus

The current priority is the stable extraction pipeline:

  • portable ExtractionRequest definitions
  • canonical type capabilities
  • synchronous and native asynchronous extraction
  • schema generation and refinement
  • deterministic custom-model handling
  • row-level outcomes and usage reporting
  • consistent document preparation and cleanup

Future: Declarative Business Validation

Status: Not scheduled

Business validation should extend the portable model definition without storing or executing arbitrary user code. Existing ModelField.validation constraints already cover deterministic field semantics such as:

  • gt, ge, lt, le, and multiple_of
  • min_length and max_length
  • string patterns
  • strict field handling
  • required, nullable, and default-value behavior

The next validation layer should support relationships between fields and domain rules that cannot be represented by one Pydantic Field.

Design Principles

  1. Store declarative rule data, never Python source, pickles, lambdas, or arbitrary expressions.
  2. Compile deterministic rules from trusted StructX implementations.
  3. Keep extraction success separate from business-validation status.
  4. Preserve every rule and outcome so an extraction can be reproduced.
  5. Make semantic LLM validation an explicit, metered phase rather than a hidden side effect of Pydantic parsing.
  6. Track validation usage through the same operation-local usage system as schema generation and extraction.
  7. Never modify extracted values silently.

Portable Rule Contract

ExtractionRequest should eventually contain a versioned list of typed rule definitions. Rules should use a discriminated union rather than a free-form expression language.

Illustrative deterministic rule:

{
  "id": "valid_contract_dates",
  "kind": "field_comparison",
  "left_field": "effective_date",
  "operator": "le",
  "right_field": "termination_date",
  "severity": "error",
  "message": "The effective date must not be after the termination date"
}

Initial deterministic rule types should be evaluated separately and added only when their semantics are unambiguous:

  • compare a field with another field
  • compare a field with a constant
  • require a field conditionally
  • require at least one field from a group
  • require exactly one field from a group
  • make fields mutually exclusive
  • restrict values to an allowed set
  • enforce date ordering
  • enforce numeric totals or ranges
  • enforce collection uniqueness where the type alone does not

Every rule should include:

  • stable identifier
  • rule kind and typed parameters
  • referenced fields
  • error or warning severity
  • user-facing failure message
  • schema version

The compiler must validate field references and rule compatibility when the model is created. It must not use eval, execute user expressions, or import user code.

Runtime Compilation

model_from_extraction_request() should compile supported deterministic rules into Pydantic model validators generated by StructX. These runtime callables are implementation details; the serialized rule definitions remain the source of truth.

model_to_extraction_request() should continue rejecting arbitrary validators from external Pydantic models. Models created by StructX can round-trip because they retain their original portable definition, including its rule data.

The compiler should return clear construction-time errors for:

  • missing field references
  • incompatible operand types
  • unsupported rule combinations
  • rules that require executable Python behavior
  • recursive or ambiguous dependencies between rules

Validation Outcomes

Validation should produce structured outcomes rather than only raising an exception:

{
  "rule_id": "valid_contract_dates",
  "status": "failed",
  "severity": "error",
  "fields": ["effective_date", "termination_date"],
  "reason": "The effective date is after the termination date",
  "suggested_value": null
}

Planned result semantics:

  • passed: rule was evaluated and satisfied
  • failed: an error-severity rule was violated
  • warning: a warning-severity rule was violated
  • skipped: required inputs were unavailable or null
  • error: the validation engine could not evaluate the rule

Row extraction status and validation status must remain separate. A row may be successfully extracted while failing one or more business rules.

Future: Semantic LLM Validation

Status: Not scheduled; dependent on deterministic validation outcomes

Semantic rules should be portable natural-language statements with explicit scope and behavior:

{
  "id": "deliverable_address",
  "kind": "semantic",
  "fields": ["address"],
  "statement": "The address must be complete enough for postal delivery",
  "severity": "warning",
  "action": "flag"
}

Semantic validation should run after ordinary extraction and deterministic Pydantic validation:

Extraction
    -> Pydantic field validation
    -> deterministic business rules
    -> batched semantic validation
    -> structured validation outcomes

The semantic validation engine should:

  • provide native sync and async APIs
  • validate the complete object when a rule crosses field boundaries
  • include relevant source evidence when available
  • batch compatible rules to avoid one model request per field
  • use a separately configurable validation model
  • isolate validation usage under a dedicated extraction step
  • preserve provider usage objects
  • return reasons and optional suggested corrections
  • default to flagging rather than mutating values
  • make any automatic correction explicit, opt-in, and auditable

Relationship To Instructor llm_validator

Instructor's llm_validator demonstrates the usefulness of semantic validation, but it should not be StructX's production execution model. The callable captures a synchronous client and model, performs a model request during Pydantic parsing, and does not report usage through StructX. Applying it to many fields or list items could also create hidden request multiplication.

StructX may provide an adapter for local synchronous use in the future, but the core implementation should be an operation-level async validation phase with explicit usage and outcomes.

Configuration And Usage

Semantic validation will likely require:

  • a validation section in ExtractionConfig
  • an optional validation model distinct from planning and extraction models
  • a new ExtractionStep.SEMANTIC_VALIDATION
  • validation usage merged into ExtractorUsage
  • per-row validation usage where evaluation occurs per row

No validation defaults should silently add model calls. Semantic validation must run only when the caller supplies semantic rules and enables evaluation.

Proposed Public API

Exact names remain open, but the API should make validation visible:

result = await extractor.extract_async(
    data=input_data,
    query=query,
    model=model,
    validate=True,
)

for row in result.rows:
    print(row.status)
    print(row.validation_status)
    print(row.validation_outcomes)

A standalone API may also be useful for validating existing objects without re-running extraction:

validation = await extractor.validate_async(
    data=existing_object,
    model=model,
    source=optional_source_evidence,
)

Implementation Phases

Phase 1: Rule Schema

  • Define versioned deterministic rule models.
  • Add rules to the portable extraction definition.
  • Validate field references and operand compatibility.
  • Document serialization and migration behavior.

Phase 2: Deterministic Compiler

  • Compile supported rules into trusted Pydantic validators.
  • Add structured validation outcomes.
  • Preserve extraction and validation status separately.
  • Add nested-model and collection coverage.
  • Add serialization and reconstruction tests for every rule type.

Phase 3: Semantic Validation Engine

  • Define the portable semantic rule schema.
  • Add sync and native async evaluation.
  • Add object and source-evidence context.
  • Batch compatible rules.
  • Add configurable validation models and parameters.
  • Track operation-level and row-level usage.
  • Add warnings, failures, reasons, and suggested corrections.

Phase 4: Corrections And Review

  • Add explicit correction proposals.
  • Preserve original and proposed values.
  • Require opt-in before automatic correction.
  • Record correction provenance and usage.
  • Add revalidation after accepted corrections.

Testing Requirements

  • deterministic rule serialization and reconstruction
  • invalid field references and incompatible operand types
  • nested models and collection rules
  • null and missing-value behavior
  • warning versus error semantics
  • stable outcomes across sync and async paths
  • semantic request batching and concurrency limits
  • semantic usage attribution
  • partial provider failures
  • suggested corrections that never overwrite originals implicitly
  • no model request when semantic validation is disabled

Open Decisions

  • whether validation rules belong directly on ExtractionRequest or in a versioned companion model
  • whether deterministic failures should raise during construction, extraction, or only appear as outcomes
  • how source evidence is selected and limited for semantic validation
  • whether one semantic request should validate one row or a bounded row batch
  • which correction actions are permitted in the core library
  • whether validation models should have independent retry and concurrency limits
  • how semantic validation interacts with Instructor retries during extraction

Maintenance

Keep future work in this file until it is scheduled. Once implementation begins, move accepted contracts into user guides and API documentation, and move completed work into the changelog.