Files
wehub-resource-sync 76d991c447
Auto Update PR / update-prs (push) Has been cancelled
CI / format-check (push) Has been cancelled
CI / test (3.10) (push) Has been cancelled
CI / test (3.11) (push) Has been cancelled
CI / test (3.12) (push) Has been cancelled
CI / live-api-tests (push) Has been cancelled
CI / plugin-integration-test (push) Has been cancelled
CI / ollama-integration-test (push) Has been cancelled
CI / test-fork-pr (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:37:14 +08:00

8.2 KiB

Custom Output Schema Example

LangExtract usually derives provider schema constraints from examples. For advanced cases, pass output_schema to constrain the raw model output more directly. This example restricts a status attribute to the enum values present and absent.

Examples are optional when output_schema is provided. When examples are included, they still guide the prompt; output_schema replaces only the provider schema constraint. The schema must describe LangExtract's JSON output envelope with a top-level extractions array.

Gemini and OpenAI support output_schema. Ollama does not currently support user-provided output schemas.

The helper emits additionalProperties: False so schemas work with OpenAI strict structured outputs. Gemini receives user-provided schemas through its native JSON Schema field, so JSON Schema keywords such as additionalProperties are preserved.

Full Pipeline Example

import langextract as lx

# Text with one affirmed and one negated condition.
input_text = "Patient has hypertension. Patient denies diabetes."

# Define extraction prompt.
prompt_description = """
Extract medical conditions and classify each condition status as present or
absent. Use exact text from the input for extraction_text.
"""

# Define example data. The status values mirror the enum in output_schema.
examples = [
    lx.data.ExampleData(
        text="Patient has asthma. Patient denies fever.",
        extractions=[
            lx.data.Extraction(
                extraction_class="condition",
                extraction_text="asthma",
                attributes={"status": "present"},
            ),
            lx.data.Extraction(
                extraction_class="condition",
                extraction_text="fever",
                attributes={"status": "absent"},
            ),
        ],
    )
]

# Build a LangExtract output envelope with an enum-constrained attribute.
output_schema = lx.schema.extractions_schema(
    lx.schema.extraction_item_schema(
        "condition",
        attributes={
            "status": {
                "type": "string",
                "enum": ["present", "absent"],
            }
        },
    )
)

result = lx.extract(
    text_or_documents=input_text,
    prompt_description=prompt_description,
    examples=examples,
    model_id="gemini-3.5-flash",
    output_schema=output_schema,
    temperature=0.0,
)

print(f"Input: {input_text}\n")
print("Extracted conditions:")
for extraction in result.extractions:
    status = extraction.attributes["status"]
    print(f"• {extraction.extraction_text}: {status}")

This will produce output similar to:

Input: Patient has hypertension. Patient denies diabetes.

Extracted conditions:
• hypertension: present
• diabetes: absent

Multiple Extraction Classes

For heterogeneous extraction classes, pass multiple item schemas. The helper wraps them in anyOf under extractions.items:

output_schema = lx.schema.extractions_schema(
    lx.schema.extraction_item_schema("condition"),
    lx.schema.extraction_item_schema("medication"),
)

Raw Schema Equivalent

For full control, pass a raw JSON schema dictionary. When targeting OpenAI strict mode, every object schema must declare required fields and additionalProperties: False.

Attribute objects use the <extraction_class>_attributes property name. LangExtract's resolver expects that suffix when parsing raw model output. Each extraction item should use extraction-class text keys such as condition; generic fields such as extraction_class, extraction_text, and attributes are not resolver output keys. Extraction class names ending in _attributes are reserved for attribute objects.

The full pipeline example above produces this equivalent envelope:

output_schema = {
    "type": "object",
    "properties": {
        "extractions": {
            "type": "array",
            "items": {
                "type": "object",
                "properties": {
                    "condition": {"type": "string"},
                    "condition_attributes": {
                        "type": "object",
                        "properties": {
                            "status": {
                                "type": "string",
                                "enum": ["present", "absent"],
                            }
                        },
                        "required": ["status"],
                        "additionalProperties": False,
                    },
                },
                "required": ["condition", "condition_attributes"],
                "additionalProperties": False,
            },
        }
    },
    "required": ["extractions"],
    "additionalProperties": False,
}

Use raw schemas when you need JSON Schema constructs that the helpers do not cover directly, such as custom anyOf variants. OpenAI strict structured outputs support anyOf; use strict=False only in lower-level provider code if you need to experiment with schema features outside OpenAI's strict subset.

Optional Attributes

The helper marks every supplied attribute as required by default so the schema is compatible with OpenAI strict structured outputs. To allow an attribute to be absent in practice, make the value nullable while keeping the key required:

output_schema = lx.schema.extractions_schema(
    lx.schema.extraction_item_schema(
        "condition",
        attributes={
            "status": {
                "anyOf": [
                    {"type": "string", "enum": ["present", "absent"]},
                    {"type": "null"},
                ]
            }
        },
    )
)

If you need a schema where an attribute key may be omitted entirely, use a raw schema for that provider-specific shape.

Errors and Pitfalls

  • Invalid envelopes raise InferenceConfigError before provider construction.
  • output_schema can be passed with either model_id/config or a preconfigured model when the provider supports user schemas.
  • Examples are optional with output_schema. When supplied, keep example classes and attribute names aligned with the schema to avoid confusing the model.
  • output_schema requires raw JSON provider output. Leave format_type unset or set it to lx.data.FormatType.JSON, and do not force fences.
  • Keep the resolver's default "_attributes" suffix. Custom attribute_suffix/extraction_attributes_suffix settings are incompatible with the raw schema envelope.
  • Do not combine output_schema with provider schema kwargs such as response_format, response_schema, or response_json_schema.
  • When targeting Gemini 2.0 models, add Gemini's propertyOrdering keyword to object schemas that need an explicit property order. The LangExtract helpers stay provider-neutral and do not add that Gemini-specific extension.
  • Raw schemas must describe extractions.items inline, including each extraction text key and <extraction_class>_attributes object. LangExtract does not resolve $ref for those resolver keys before provider construction.
  • Use anyOf, not oneOf, for item unions. Gemini treats oneOf like anyOf, and OpenAI strict structured outputs reject oneOf.
  • lx.schema.extraction_item_schema(..., additional_properties=False) applies that setting to both the outer extraction item object and its nested <extraction_class>_attributes object.
  • OpenAI uses strict structured outputs by default with LangExtract's default schema name. The lower-level OpenAISchema.from_schema_dict(..., schema_name=..., strict=False) constructor is an escape hatch for callers configuring provider models directly.
  • LangExtract validates only the output envelope locally; the provider API validates the JSON schema itself. OpenAI strict mode requires every object to list all properties in required and set additionalProperties: false — the lx.schema helpers emit compliant schemas, and the OpenAI API reports the exact path of any violation in hand-written schemas. Schema size/depth limits, enum limits, and keyword support also vary by provider, model, and endpoint.
  • Avoid stop/stop_sequences with output_schema: stop sequences can truncate schema-constrained JSON mid-document while the response still reports a normal finish reason.