Catalog / LLM routing & guardrails
pydecide: one Python client and fallback chain for Jev, OpenRouter, Laya, cross-encoders
Choice, Score and Noul over any System One backend with a confidence policy: if a backend errors or is unsure, the next is tried. Ships a TypeSafe-compatible server.
# pydecide
[](https://github.com/gopaljigaur/decide/actions/workflows/ci.yml)
[](https://pypi.org/project/pydecide/)
`decide` is one Python client for typed decisions - Choice, Score and Noul -
over any "System One" decision model: TypeSafe's hosted Jev, OpenRouter's
Decisions endpoint, the open-weight laya family (PyTorch and MLX), any
sentence-transformers CrossEncoder, and a JSON-prompted LLM fallback. A
`Client` takes an ordered list of backends and a confidence policy: if a
backend errors or answers with low confidence, the next backend is tried.
The library also ships a small HTTP server that speaks TypeSafe's wire
protocol, so existing TypeSafe clients can point at a local model instead.
## Install
```bash
pip install pydecide
```
Local model backends and the server are optional extras:
```bash
pip install "pydecide[server]" # decide serve (FastAPI + uvicorn)
pip install "pydecide[laya]" # laya backend (PyTorch)
pip install "pydecide[mlx]" # laya_mlx backend (Apple Silicon; needs Python 3.11+)
pip install "pydecide[st]" # crossencoder backend (sentence-transformers)
pip install "pydecide[all]" # everything above
```
The `mlx` extra depends on `laya-mlx`, which requires Python 3.11 or newer;
on 3.10 the extra installs nothing and the `laya_mlx` backend is
unavailable.
## Quickstart: the fallback chain
`Client.from_env()` builds a backend chain from whatever is installed and
configured in the process environment. Pass an explicit `env=` mapping
instead (e.g. in tests) to configure from something other than
`os.environ`:
```python
from decide import Client, Choice, Score, Noul
client = Client.from_env()
r = client.decide(
state={"ticket": "I was charged twice, please refund."},
questions={
"team": Choice(