Metadata-Version: 2.4
Name: duplexjev
Version: 0.1.0
Summary: Batched typed speech decisions without decoding: one forward pass answers many closed-set questions about many calls.
Author: Adventists.ai
License: Apache-2.0
Project-URL: Homepage, https://adventists-ai.github.io/duplexjev/
Project-URL: Repository, https://github.com/adventists-ai/duplexjev
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
Requires-Dist: torch>=2.1
Requires-Dist: transformers<4.58,>=4.51
Requires-Dist: numpy
Requires-Dist: soundfile
Requires-Dist: scipy
Provides-Extra: speech
Requires-Dist: accelerate; extra == "speech"
Requires-Dist: peft; extra == "speech"
Requires-Dist: transformers<4.56,>=4.51; extra == "speech"
Provides-Extra: server
Requires-Dist: fastapi; extra == "server"
Requires-Dist: uvicorn; extra == "server"
Requires-Dist: pydantic>=2; extra == "server"
Provides-Extra: all
Requires-Dist: accelerate; extra == "all"
Requires-Dist: peft; extra == "all"
Requires-Dist: transformers<4.56,>=4.51; extra == "all"
Requires-Dist: fastapi; extra == "all"
Requires-Dist: uvicorn; extra == "all"
Requires-Dist: pydantic>=2; extra == "all"
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: httpx; extra == "dev"
Dynamic: license-file

# duplexjev

Batched typed speech decisions without decoding. Every question — *has the user finished? which filler? which intent?*
— is answered as a probability over its options from a **single forward pass**, with no ASR or text decoding. Many
questions about many calls share one pass, with exact prefix sharing.

```bash
pip install duplexjev            # text models
pip install "duplexjev[all]"     # + speech checkpoints and the HTTP server
```

```python
from duplexjev import Decider, Question

d = Decider.from_pretrained("Qwen/Qwen3-8B")        # any causal LM; or a speech checkpoint (see below)
qs = [Question("turn", "Has the user finished the turn?", ["finished", "not finished"]),
      Question("intent", "What does the user want?", ["climate", "media", "navigation", "phone"])]
d.decide(["Turn on the air conditioning", "Navigate to the"], qs)
# [{'turn': {'answer': 'finished', 'confidence': 0.97, 'probs': {...}}, 'intent': {...}}, {...}]
```

Speech checkpoints (Ultravox format, including the DuplexJev adapters) take audio directly:
`Decider.from_pretrained("fixie-ai/ultravox-v0_6-qwen-3-32b").decide(["call1.wav", "call2.wav"], qs)`.

Serve with tick batching: `duplexjev serve --model <id> --tick-ms 160`.

Project: https://github.com/adventists-ai/duplexjev · License: Apache-2.0
