Metadata-Version: 2.4
Name: duplexjev
Version: 0.2.0
Summary: Jev-style typed decisions about speech with zero decode steps: one forward pass answers many option groups about many clips.
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

Jev-style typed decisions about speech with **zero decode steps**. Give it audio and one or more option groups
(*has the user finished? which filler? which intent? speaker gender?*); every group comes back as a probability over
its options from a single forward pass. Many groups about many calls share one pass, with exact prefix sharing.

```bash
pip install "duplexjev[speech]"      # add [all] for the HTTP server
```

```python
from duplexjev import Decider, Question

d = Decider.from_pretrained("fixie-ai/ultravox-v0_6-qwen-3-32b")   # or a DuplexJev adapter
groups = [Question("turn", "Has the user finished the turn?", ["finished", "not finished"]),
          Question("gender", "Speaker gender", ["female", "male"])]

d.decide("call.wav", groups)
# {'turn': {'answer': 'finished', 'confidence': 0.97, 'probs': {...}}, 'gender': {...}}

# many clips: each option group names its clip(s) with audio=<id> | [ids] | "*"
d.decide_batch({"car1": "a.wav", "car2": "b.wav"},
               [Question("turn", "Has the user finished the turn?", ["finished", "not finished"], audio="*"),
                Question("gender", "Speaker gender", ["female", "male"], audio="car2")])
# {'car1': {'turn': ...}, 'car2': {'turn': ..., 'gender': ...}}
```

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

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