Metadata-Version: 2.4
Name: choiceone
Version: 1.0.1
Summary: Type-safe decision layer between your Python code and any AI model (ChoiceOne protocol).
Author: choiceone contributors
License: MIT
Keywords: ai,llm,structured-output,classification,decisions,system-one
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Provides-Extra: local
Requires-Dist: torch; extra == "local"
Requires-Dist: transformers; extra == "local"
Provides-Extra: server
Requires-Dist: fastapi; extra == "server"
Requires-Dist: uvicorn; extra == "server"
Provides-Extra: test
Requires-Dist: pytest; extra == "test"
Requires-Dist: fastapi; extra == "test"
Requires-Dist: uvicorn; extra == "test"
Requires-Dist: httpx; extra == "test"

# choiceone

A type-safe **decision layer** between your Python code and an AI model.

Instead of generating prose and parsing it back, `choiceone` sends an
unstructured `state` plus a closed set of typed questions and returns typed,
probabilistic decisions your code can branch on directly. Answers cannot have
a type error: they are always a distribution over the options you supplied.

Implements the "ChoiceOne" protocol: **state in, typed probabilistic
decisions out**.

## Install

```bash
pip install choiceone            # core, no model dependencies
pip install 'choiceone[local]'   # + local Hugging Face backend (torch, transformers)
pip install 'choiceone[server]'  # + HTTP server (fastapi, uvicorn)
```

## Quick start

```python
from choiceone import ChoiceOne, Choice

so = ChoiceOne()  # default local model
response = so(
    state="My running shoes arrived in the wrong size.",
    questions={
        "department": Choice(
            instructions="Which team should handle this?",
            criteria={
                "returns": "Exchanges, wrong or damaged items",
                "shipping": "Delivery status, delays, lost packages",
                "billing": "Charges, invoices, payment problems",
            },
        ),
    },
)

answer = response.answers["department"]
print(answer.choice, answer.probabilities, answer.confidence)
```

## Primitives

| Question | Returns |
|---|---|
| `Choice` | `choice`, `probabilities`, `confidence` |
| `Score`  | `score`, `legend`, `probabilities`, `confidence` |
| `Noul`   | `noul` (probability the statement is true, `0`-`1`) |

Every `Choice`/`Score` answer includes a `confidence` derived from how peaked
the distribution is, so your code can act automatically, ask, or escalate.

## Backends

The model side is a pluggable `Backend`. `choiceone` ships with two:

- `LocalBackend` — a local Hugging Face causal LM (default `Qwen/Qwen3-0.6B`).
  Text-generation-free: reads the next-token distribution.
- `OpenAIBackend` — any OpenAI-compatible `logprobs` endpoint (DeepSeek,
  OpenAI, vLLM, ...). Stdlib only.

Embed your own AI by subclassing `Backend` and implementing three methods:

```python
from choiceone import Backend

class MyBackend(Backend):
    def build_prompt(self, user_content): ...
    def count_tokens(self, texts): ...
    def probs_over_labels(self, prompts, labels_per_prompt): ...
```

## HTTP server

```bash
choiceone-serve --model Qwen/Qwen3-0.6B --port 8000
# POST /v1/choiceone  {"state": ..., "questions": {...}}
```

## License

MIT
