Skip to main content

feather-structured-output

feather-structured-output is a lightweight Python library for turning LLM text responses into validated Python dictionaries.

It does not call an LLM, retry requests, or manage conversation history. It only handles schema definition, short JSON prompt generation, JSON extraction, field validation, normalization, and retry-friendly error messages.

Installation

This repository uses uv.

uv run pytest

Basic Usage

from feather_structured_output import IntField, Schema, StringField

schema = Schema(
    instruction="Extract the following JSON.",
    fields=[
        StringField(
            source_label="Company name",
            output_name="name",
            description="Use the formal company name.",
            example="Acme Corp",
        ),
        IntField(
            source_label="Quantity",
            output_name="quantity",
            gt=0,
        ),
    ],
)

prompt = schema.dump_prompt()

prompt becomes a compact JSON example with comments:

Extract the following JSON.

{
  "name": "Acme Corp", // Company name。String. Use the formal company name. Required.
  "quantity": 1 // Quantity。Integer. Greater than 0. Required.
}

Pass that prompt to any LLM client yourself, then validate the response:

result = schema.extract('{"name": "Acme Corp", "quantity": 3}')

if result.ok:
    data = result.data
else:
    retry_prompt = result.error_message

Fields

Available field types:

  • StringField
  • IntField
  • FloatField
  • BooleanField
  • ObjectField
  • UnionField

Common field options:

  • source_label: label from the source document or UI; optional
  • output_name: JSON key; if omitted, source_label is used
  • description: extra instruction for the LLM
  • example: sample value in the generated prompt
  • allowed_values: fixed allowed values for the field
  • presence: missing value policy
  • repeatable, min_items, max_items: array support

At least one of output_name or source_label is required when a field is used in a Schema.

Presence Policy

from feather_structured_output import PresencePolicy, StringField

StringField(
    output_name="note",
    presence=PresencePolicy.NULLABLE,
)

Policies:

  • REQUIRED: value is required
  • OMITTABLE: missing value is omitted from normalized data
  • NULLABLE: missing value is normalized to None
  • BLANKABLE: missing value is normalized to ""

"" is treated as a missing value during validation.

Arrays and Objects

from feather_structured_output import IntField, ObjectField, StringField

items = ObjectField(
    output_name="items",
    repeatable=True,
    min_items=1,
    fields=[
        StringField(output_name="name"),
        IntField(output_name="quantity", gt=0),
    ],
)

Fixed Values and Unions

Use allowed_values for fixed values. Use UnionField when a value may match more than one field shape.

from feather_structured_output import IntField, StringField, UnionField

dog_age = UnionField(
    output_name="dog_age",
    variants=[
        StringField(allowed_values=["N/A"]),
        StringField(allowed_values=["-"]),
        IntField(gt=0),
    ],
)

JSON Extraction

Schema.extract() accepts raw JSON or a single fenced json code block. Text outside one JSON code block is ignored.

result = schema.extract(
    """Here is the result:
```json
{"name": "Acme Corp", "quantity": 3}
```"""
)

Multiple JSON code blocks, non-JSON code blocks, invalid JSON, and non-object JSON values return ExtractResult with validation errors.

Custom Validators

Use validators for cross-field rules.

from feather_structured_output import IntField, Schema, StringField, ValidationError


def validate_octopus_legs(data: dict[str, object]) -> list[ValidationError]:
    if data.get("pet") == "octopus" and data.get("legs") != 8:
        return [
            ValidationError(
                path="legs",
                message={
                    "en": "legs must be 8 when pet is octopus.",
                    "ja": "pet が octopus の場合、legs は 8 である必要があります。",
                },
                actual=data.get("legs"),
            )
        ]
    return []


schema = Schema(
    fields=[
        StringField(output_name="pet"),
        IntField(output_name="legs", ge=0),
    ],
    validators=[validate_octopus_legs],
)

Validators run only after field validation succeeds. Exceptions raised inside a validator are not converted to LLM-facing validation errors.

Error Messages and Locale

English is the default. Japanese retry messages are available with locale="ja".

schema = Schema(
    locale="ja",
    fields=[IntField(output_name="quantity", gt=0)],
)

result = schema.extract('{"quantity": 0}')
print(result.error_message)

Internal message templates are split by locale under src/feather_structured_output/locales/.

Metadata

Release files for feather-structured-output 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for feather-structured-output 0.1.1
File Size Uploaded Provenance
feather_structured_output-0.1.1.tar.gz 13.5 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for feather-structured-output 0.1.1
File Interpreter ABI Platform
feather_structured_output-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 28.7 kB

Release files / feather_structured_output-0.1.1.tar.gz

Download URL feather_structured_output-0.1.1.tar.gz
Size 13.5 kB
Tags Source
SHA-256 checksum
How to use checksums
bfc69b8452e6bfb89d6c6da5848575d06d4a490e37b0fb9a2793bc3f8b1bffb7
BLAKE2b-256 checksum
How to use checksums
f6acd6e840514744d5b9dae1280d160cb049adb94e9d70c32c4267ad40d3fb72
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / feather_structured_output-0.1.1-py3-none-any.whl

Download URL feather_structured_output-0.1.1-py3-none-any.whl
Size 15.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0213f42adf650bc7c5283892a7afb9e24ca7148826571dba90df86c678ab1573
BLAKE2b-256 checksum
How to use checksums
233670816bfd4783196287cad85103ed011de2c58c06f865d523d42abc003efd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Security for feather-structured-output 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page