Skip to main content

Validate, repair, retry LLM structured output (JSON/YAML/TOML/python-literal)

Project description

arcanada-output-guard

PyPI Python License: MIT

Validate, repair, and retry LLM structured output (JSON / YAML / TOML / Python literal) — battle-tested 15-strategy repair chain with two-pass orchestrator. Python sibling of @arcanada/output-guard with shared golden fixtures and byte-equal parity gate.

Install

pip install arcanada-output-guard
# or
uv add arcanada-output-guard
# or
poetry add arcanada-output-guard

Requires Python ≥ 3.11. Runtime deps: pyyaml, tomli-w, pydantic, jsonschema, json-repair.

Quick start

from output_guard import repair

# Functional API — format-only repair, no schema
result = repair('{"name": "Alice", "age": 30,}', "json")

print(result.data)                  # {'name': 'Alice', 'age': 30}
print(result.repaired)              # True
print(result.pass_)                 # 'A'
print(result.strategies_applied)    # ['fix-commas']

Stateful API with pydantic schema

from pydantic import BaseModel
from output_guard import OutputGuard

class User(BaseModel):
    name: str
    age: int

guard = OutputGuard(format="json", schema=User)
result = guard.repair('```json\n{"name": "Bob", "age": 25}\n```')

print(result.data)               # User(name='Bob', age=25)
print(result.pass_)              # 'A' or 'B'

Output format support

  • JSON — strict + relaxed parsing with common error recovery (trailing commas, unquoted keys, single→double quote, true/false casing, fenced blocks).
  • YAML — structural repair for indentation + missing keys.
  • TOML — fixing malformed tables and value assignments.
  • Python literaldict / list literals via safe ast.literal_eval.
  • Auto-detect — pass format="auto" to infer from content.

RepairResult semantics

@dataclass(frozen=True, slots=True)
class RepairResult:
    repaired: bool                       # False when raw was already valid
    raw: str                             # original input as supplied
    pass_: Literal["A", "B"]             # "A" = combined-apply; "B" = isolating fallback
    data: Any = None                     # parsed + (optionally) schema-validated payload
    strategies_applied: list[str] = []   # ordered list of repair strategies invoked

MAX_RETRIES exhaustion signals via ParseError raise, not via a pass_ value.

Async wrapper for LLM calls

import asyncio
from pydantic import BaseModel
from output_guard import guarded_generate, GuardedGenerateOptions

class Answer(BaseModel):
    result: int

async def my_llm(prompt: str, history=None) -> str:
    # call your LLM client here (OpenAI / Anthropic / OpenRouter / MC / etc.)
    return '{"result": 42}'

async def main():
    out = await guarded_generate(GuardedGenerateOptions(
        generate=my_llm,
        prompt='Return JSON {"result": <integer>}',
        schema=Answer,
        fmt="json",
        max_retries=3,
    ))
    print(out.data)                  # Answer(result=42)
    print(out.pass_)                 # 'A' | 'B'
    print(out.strategies_applied)

asyncio.run(main())

Error handling

from output_guard import (
    ParseError,
    SchemaValidationError,
    RepairError,
    GuardedGenerationError,
)

try:
    result = guard.repair(bad_input)
except SchemaValidationError:
    ...  # input parsed but doesn't satisfy schema
except ParseError:
    ...  # MAX_RETRIES exhausted — all strategies failed
except RepairError:
    ...  # a repair strategy itself raised
except GuardedGenerationError:
    ...  # guarded_generate gave up after max_retries LLM round-trips

Schema adapters

from output_guard import pydantic_adapter, jsonschema_adapter
from pydantic import BaseModel

class User(BaseModel):
    name: str
    age: int

# pydantic v2
adapter = pydantic_adapter(User)

# JSON Schema (dict)
adapter = jsonschema_adapter({
    "type": "object",
    "properties": {"name": {"type": "string"}, "age": {"type": "integer"}},
    "required": ["name", "age"],
})

Batch API

from output_guard import repair_batch

results = repair_batch(
    ['{"a": 1,}', '{"b": 2,}', '{"c": 3,}'],
    fmt="json",
)
# returns list[RepairResult]; per-item failure surfaces as RepairResult with repaired=False

Documentation

License

MIT — see LICENSE.


Жизнь одного человека имеет значение / One human life matters

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

arcanada_output_guard-0.1.3.tar.gz (49.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

arcanada_output_guard-0.1.3-py3-none-any.whl (26.0 kB view details)

Uploaded Python 3

File details

Details for the file arcanada_output_guard-0.1.3.tar.gz.

File metadata

  • Download URL: arcanada_output_guard-0.1.3.tar.gz
  • Upload date:
  • Size: 49.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for arcanada_output_guard-0.1.3.tar.gz
Algorithm Hash digest
SHA256 849bbe5cf3724b2058fb51daa62a966ac8d0dec46e7e498ca7c0e4c68d2f099c
MD5 dfea8411521c399a9b9c7b0fcfae0e1c
BLAKE2b-256 181f1271707c1e72911203bdf2aa99bdbda5851d1dfd6ac55a05d398336b1f6f

See more details on using hashes here.

Provenance

The following attestation bundles were made for arcanada_output_guard-0.1.3.tar.gz:

Publisher: publish-pypi.yml on Arcanada-one/output-guard

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file arcanada_output_guard-0.1.3-py3-none-any.whl.

File metadata

File hashes

Hashes for arcanada_output_guard-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 c073a2da5f6d5a9bb62426b9a26764a9b834d8316b5c33805a2561853f9926d1
MD5 4985b33363d8a8beaec4e4d3c221f9f8
BLAKE2b-256 f2f7d30aef18137b16ca02c29f2ad68e6decbacf5d34c6395ec0e9241d2aee0d

See more details on using hashes here.

Provenance

The following attestation bundles were made for arcanada_output_guard-0.1.3-py3-none-any.whl:

Publisher: publish-pypi.yml on Arcanada-one/output-guard

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page