Metadata-Version: 2.5
Name: promptdispatch
Version: 0.1.0
Summary: Route prompts to the best-fit LLM provider and model using TypeSafe AI's Jev.
Author: Hruthik Kommuru
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 3 - Alpha
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
Requires-Python: >=3.9
Provides-Extra: all
Requires-Dist: anthropic>=0.40; extra == 'all'
Requires-Dist: openai>=1.0; extra == 'all'
Provides-Extra: anthropic
Requires-Dist: anthropic>=0.40; extra == 'anthropic'
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == 'dev'
Provides-Extra: openai
Requires-Dist: openai>=1.0; extra == 'openai'
Description-Content-Type: text/markdown

# promptdispatch

`promptdispatch` is a small, framework-agnostic Python router for LLM requests. It uses TypeSafe AI's Jev decision model to classify a prompt, selects a model with deterministic Python rules, and dispatches through the provider's official SDK.

```text
user prompt
    │
    ├── Jev: task type ────┐
    ├── Jev: effort ───────┼──> deterministic registry filter ──> chosen model
    └── Jev: needs tools ──┘                                      │
                                                                  └──> provider API
```

Jev calls are closed-label decisions, not chat completions. `route()` makes three concurrent calls and never calls an OpenAI or Anthropic generation model. `predict()` calls `route()` once and reuses that decision.

## Install

Install both built-in provider adapters:

```bash
pip install "promptdispatch[all]"
```

Or install only one: `promptdispatch[openai]` or `promptdispatch[anthropic]`.

## Quick start

```python
from promptdispatch import DEFAULT_MODEL_REGISTRY, Router

router = Router(
    api_keys={
        "typesafe": "your-typesafe-key",
        "openai": "your-openai-key",
        "anthropic": "your-anthropic-key",
    },
    model_registry=DEFAULT_MODEL_REGISTRY,
    system_prompt="You are a concise engineering assistant.",
    guardrails=["Never invent test results."],
)

decision = router.route("Find and fix the race condition in this worker.")
# {"provider": "...", "model": "...", "effort": "high"}

result = router.predict("Explain why binary search is O(log n).")
# {"content": "...", "provider": "...", "model": "..."}
```

Each routing decision is appended to `decision_log.jsonl`, including the prompt, all three Jev choices and confidence scores, and the selected route. Prompts may contain sensitive data, so configure `decision_log_path` appropriately and do not commit the log.

## Deterministic v0.1 routing

1. Keep models whose `good_at` contains Jev's task type. If none match, use the full registry.
2. If tools are required, remove every model without tool support.
3. Map `low → fast`, `medium → balanced`, and `high → flagship`.
4. If several models remain, the first one in your registry wins.

Replace the registry at runtime with `router.update_model_registry(new_registry)`. This keeps `predict()` stable while leaving room for learned routing in a later release.

## Model metadata

The starter registry contains six current OpenAI and Anthropic examples. Costs are USD per million input/output text tokens at standard short-context rates and are metadata only in v0.1.0. Provider catalogs and prices change, so applications should own and update their registry.

## Development

```bash
python -m pip install -e ".[dev,all]"
pytest
```

The core has no LangChain dependency. OpenAI and Anthropic SDKs are optional extras.

## License

MIT
