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:
StringFieldIntFieldFloatFieldBooleanFieldObjectFieldUnionField
Common field options:
source_label: label from the source document or UI; optionaloutput_name: JSON key; if omitted,source_labelis useddescription: extra instruction for the LLMexample: sample value in the generated promptallowed_values: fixed allowed values for the fieldpresence: missing value policyrepeatable,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 requiredOMITTABLE: missing value is omitted from normalized dataNULLABLE: missing value is normalized toNoneBLANKABLE: 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)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| feather_structured_output-0.1.1.tar.gz | 13.5 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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.