Skip to main content

Wassitai

Ask an LLM a question, get back a validated Python object — not a string you have to parse.

Wassitai sends your prompt with a schema, picks the best structured-output method the provider supports, then extracts, repairs, validates and coerces the reply through a deterministic pipeline. If the result still doesn't fit the schema, it re-asks the model. Ships as the importable package wassitai, with a REST API and a browser playground on top.

pip install wassitai            # library
pip install "wassitai[api]"     # + REST API and playground

Code written against the pre-0.2 name still works: llm_parser remains importable as a deprecated alias for wassitai until 2.0. If you have an old editable install of the llm_parser distribution, run pip uninstall llm_parser first — pip won't replace it, and its source tree would keep shadowing the alias.

Features

  • 🤖 Any OpenAI-compatible provider — Groq, OpenAI, DeepSeek and OpenRouter as presets; Together, xAI, Ollama, vLLM or a local server with just base_url= and model=
  • 🧱 Five ways to write a schema — Pydantic model, {"field": "type"} dict, JSON Schema, or a JSON or XML schema string
  • 🔁 Object, JSON or XML out — the same validated result, rendered however you need it
  • 📊 Lists — ask for list[Invoice], get a list back
  • 🧪 Repairs before it fails — lifts JSON out of markdown fences and prose, fixes trailing commas, smart quotes and Python-repr output, then re-asks the model if it still doesn't fit
  • 🔒 Strict or flexible validation — exact types for production, coercion while prototyping
  • 💡 Diagnostics you can act on — every stage reports what it did, a confidence score falls as repairs accumulate, and errors are a typed tree with fixes in the message
  • 🎯 Pydantic all the way through — your model is the schema, the validator and the return type
  • 🌐 A playground, not just a library — browser console plus a beginner's guide
  • ✅ 329 tests — unit, integration and end-to-end, with no network calls

Python

from wassitai import Client
from pydantic import BaseModel

class Invoice(BaseModel):
    number: str
    total: float

client = Client.from_provider("groq", api_key="…", model="llama-3.3-70b-versatile")
invoice = client.generate("Extract the invoice from: …", schema=Invoice)   # -> Invoice

# A list, by asking for a list schema:
invoices = client.generate("Extract all invoices: …", schema=list[Invoice])

# Never raises — for batch pipelines:
res = client.try_generate("…", schema=Invoice)     # -> Result[Invoice]
if res.ok:
    print(res.value, res.confidence)

# Text you already have, no provider call:
from wassitai import parse, render
invoice = parse('{"number": "A1", "total": 9.5}', Invoice)
text = render(invoice, "json")

A schema can be a Pydantic model, a plain {"field": "type"} dict, or a JSON Schema. strict=True enforces exact types; the default coerces close-enough values ("3" → 3). max_retries caps how often the model is re-asked (default 1).

REST API & playground

uvicorn wassitai.api.app:app --reload

Playground at http://localhost:8000/, beginner's guide at /static/guide.html, OpenAPI reference at /docs.

Method Path Does
POST /v1/generate prompt + schema → validated object
POST /v1/parse text + schema → validated object (no provider call)
GET /v1/providers providers and their capabilities
GET /health liveness
curl -X POST http://localhost:8000/v1/generate \
  -H "X-Provider-Key: $GROQ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"provider":"groq","prompt":"Extract the invoice: …",
       "schema":{"number":"str","total":"float"}}'

Provider keys travel per-request in the X-Provider-Key header (or come from <PROVIDER>_API_KEY on the server) and are never stored, logged, or pre-filled into the browser. Errors map to status codes: 422 validation · 401 auth · 429 rate limit · 502 provider · 504 timeout.

How it works

generate() → schema adapter → strategy → provider → pipeline → validated object.

  • Strategy — resolved per provider in order native (JSON-schema mode) → tool_calling → prompt_repair, which is the universal floor and needs nothing from the provider.
  • Pipeline — six ordered stages: normalize → extract → syntax_repair → deserialize → validate → coerce. Each records a diagnostic, and the confidence score falls as repairs and re-asks accumulate.
  • Extending — Provider, Strategy, SchemaAdapter and Stage are the four interfaces; most providers need only a preset in wassitai/providers/__init__.py.

Errors form one tree under LLMParserError: ConfigurationError (your bug), ProviderError (the network/provider's), and ParseError (the model's).

Providers

Built-in presets speak the OpenAI wire format: groq, openai, deepseek, openrouter. Any other OpenAI-compatible endpoint (Together, xAI, Ollama, vLLM, local) works by passing base_url= and model=. Native adapters for Anthropic, Gemini and Bedrock are planned behind the same Provider interface.

Why Wassitai

Wassitai Typical structured-output library
Providers 4 presets, plus any OpenAI-compatible endpoint via base_url= An adapter to write per provider
Output A validated object, or the same data as JSON or XML text JSON only
Validation Strict and flexible, chosen per call One fixed mode
On a bad answer Repairs it, then re-asks the model Raises and stops
When it fails Per-stage diagnostics and a confidence score A single validation error
Ships a UI Playground + beginner's guide Library only

Key differentiators

  1. Dual validation modes — coerce close-enough values while prototyping, enforce exact types in production, without changing your schema.
  2. It repairs before it gives up — malformed JSON is fixed, and a reply that still doesn't fit the schema is sent back to the model rather than thrown at you.
  3. It tells the truth about what happened — every stage records a diagnostic, and confidence drops as repairs and re-asks accumulate, so a "valid" object you shouldn't trust is visible.
  4. Any OpenAI-compatible endpoint — Together, xAI, Ollama, vLLM or a local server need a URL and a model name, not an adapter.
  5. JSON and XML — the same validated object renders to either.
  6. A playground, not just a library — a browser console that exercises the real REST API, with a guide written for people who have never called an LLM.

Use cases

  • Development — flexible validation for rapid prototyping
  • Production — strict validation for data integrity
  • Research — compare providers and strategies on the same prompt and schema
  • Education — plain-language guide and honest error messages
  • Experimentation — the playground, with no code to write

From a checkout

pip install -e ".[api,dev]"              # editable install with the API and test deps
pytest                                   # 329 tests, no network calls
pytest -m unit                           # or: integration, e2e, provider
pytest --cov=wassitai --cov-report=html

CI runs the same suite on Python 3.9–3.13, plus ruff over the current engine, the REST API and the llm_parser alias (the pre-0.2 core/ and llms/ modules are grandfathered).

Legacy API (removed in 2.0)

LLMParser.ask still works and still supports Gemini and HuggingFace, but is deprecated.

Old New
LLMParser("groq", api_key=k).ask(q, schema=S, fmt="json") Client.from_provider("groq", api_key=k).generate(q, schema=S)
...ask(q, schema=S, many=True) ...generate(q, schema=list[S])
strict_validation=True generate(..., strict=True)
need the JSON string back render(obj, "json")

The Streamlit UI at ui/app.py (streamlit run ui/app.py) targets this legacy path; the playground above is the current one.

License

MIT.

Contact

Issues and discussions on GitHub · kaa.kella.abdelaziz@gmail.com

Metadata

Release files for wassitai 0.2.0

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

Source distribution (sdist)

Source distribution for wassitai 0.2.0
File Size Uploaded
wassitai-0.2.0.tar.gz 256.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for wassitai 0.2.0
File Interpreter ABI Platform
wassitai-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 479.2 kB

Release files / wassitai-0.2.0.tar.gz

Download URL wassitai-0.2.0.tar.gz
Size 256.7 kB
Tags Source
SHA-256 checksum
How to use checksums
34db0e5dcb72e0ab17e85781f99d81e555a4aef4fb0402f7a86735750f1b770d
BLAKE2b-256 checksum
How to use checksums
30f2326e071f1d2d3a8616452cea585ea36617e329c5f095da2b14194577d28c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.10.12

Release files / wassitai-0.2.0-py3-none-any.whl

Download URL wassitai-0.2.0-py3-none-any.whl
Size 222.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3bbbbb3d28367e0df960fc3d636adcc4fd1b190dd2b0c4505bfd065270f29dac
BLAKE2b-256 checksum
How to use checksums
2136cfddfe995a3d6fadd77550bef85fb49d80147a811bad8601fed619b30d9c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.10.12

Release history Release notifications | RSS feed

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

This release

0.2.0 This release

2 release files

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