Metadata-Version: 2.4
Name: voicerouter
Version: 0.1.0
Summary: A local-first Python framework that turns voice messages into executable actions.
Author: Alessandro Valenti
License: MIT
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: local
Requires-Dist: faster-whisper>=1.0.0; extra == "local"
Requires-Dist: sentence-transformers>=2.2.2; extra == "local"
Requires-Dist: torch>=2.0.0; extra == "local"
Provides-Extra: audio
Requires-Dist: sounddevice>=0.4.6; extra == "audio"
Requires-Dist: numpy>=1.24; extra == "audio"
Requires-Dist: scipy>=1.10; extra == "audio"
Provides-Extra: nlp
Requires-Dist: spacy>=3.7.0; extra == "nlp"
Provides-Extra: ollama
Requires-Dist: ollama>=0.1.7; extra == "ollama"
Provides-Extra: server
Requires-Dist: fastapi>=0.110.0; extra == "server"
Requires-Dist: uvicorn>=0.27.0; extra == "server"
Provides-Extra: client
Requires-Dist: httpx>=0.27.0; extra == "client"
Requires-Dist: websockets>=12.0; extra == "client"
Provides-Extra: yaml
Requires-Dist: PyYAML>=6.0; extra == "yaml"
Provides-Extra: cli
Requires-Dist: typer>=0.12.0; extra == "cli"
Requires-Dist: rich>=13.0.0; extra == "cli"
Dynamic: license-file

# VoiceRouter

[![Python](https://img.shields.io/badge/python-3.10%2B-blue)](#)
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
[![Local-first](https://img.shields.io/badge/local--first-yes-brightgreen)](#)

Author: Alessandro Valenti

VoiceRouter is a local-first Python framework that turns voice/audio messages into executable Python actions.

Pipeline:

`audio → transcription → intent detection → parameter extraction → function routing`

No paid APIs. Local by default.

## Install

If your system Python is externally-managed (PEP 668), use a virtual environment:

```bash
python3 -m venv .venv
. .venv/bin/activate
python -m pip install -U pip
```

Base (interfaces only):

```bash
pip install -e .
```

Local STT + embeddings intent detection:

```bash
pip install -e ".[local,cli]"
```

Microphone live capture (optional):

```bash
pip install -e ".[audio]"
```

HTTP + WebSocket streaming server (optional):

```bash
pip install -e ".[server]"
```

If you want CPU-only PyTorch wheels (recommended for local-first CPU setups), install PyTorch from the CPU index first, then install VoiceRouter:

```bash
pip install --index-url https://download.pytorch.org/whl/cpu torch
pip install -e ".[local,cli]"
```

Optional NLP entities (spaCy):

```bash
pip install -e ".[nlp]"
python -m spacy download en_core_web_sm
```

Optional Ollama fallback:

```bash
pip install -e ".[ollama]"
```

Optional YAML intent config support:

```bash
pip install -e ".[yaml]"
```

## Quickstart

Create a router, register intents, and route an audio file:

```python
from voicerouter import VoiceRouter

router = VoiceRouter()


@router.intent(
    "create_ticket",
    examples=["open a ticket", "server is down", "I have a problem"],
)
def create_ticket(ctx):
    return {"status": "created", "params": ctx.params}


result = router.route("examples/server_down_en.wav")
print(result)
```

The first run may download open models from Hugging Face (e.g. the MiniLM embedding model). No paid APIs are used.

Return format:

```json
{
  "transcript": "...",
  "intent": "...",
  "confidence": 0.0,
  "params": {},
  "used_llm": false,
  "action_result": {}
}
```

## CLI

```bash
voicerouter intents
voicerouter route path/to/audio.wav
voicerouter listen
voicerouter serve --host 127.0.0.1 --port 8000
```

`listen` is best-effort and depends on optional local audio tooling (e.g. `sounddevice`, `numpy`, `scipy`).

## Streaming (HTTP / WebSocket)

Start the server:

```bash
voicerouter serve --host 127.0.0.1 --port 8000
```

Or run the example server (lets you customize intents in code):

```bash
.venv/bin/python examples/server_runner.py --host 127.0.0.1 --port 8000
```

Endpoints:

- `GET /health` → `{"status":"ok"}`
- `GET /intents` → `{"intents":[...]}`
- `POST /route` (multipart upload: `file=@audio.wav`) → routing result JSON
- `POST /route/bytes` (raw body bytes; default assumes wav) → routing result JSON
- `WS /ws/route` (send binary audio chunks, then send text `"end"`) → result JSON

### HTTP Upload (curl)

```bash
curl -sS -X POST "http://127.0.0.1:8000/route" \
  -F "file=@examples/server_down_en.wav"
```

### HTTP Upload (Python)

```bash
pip install httpx
.venv/bin/python examples/http_upload_client.py examples/server_down_en.wav
```

### WebSocket Audio Stream (Python)

```bash
pip install websockets
.venv/bin/python examples/ws_audio_stream_client.py examples/server_down_en.wav
```

## Example Script

Run the included example:

```bash
.venv/bin/python examples/basic_usage.py
```

Or pass your own audio file:

```bash
.venv/bin/python examples/basic_usage.py /path/to/audio.wav
```

## Microphone Live Example

```bash
pip install -e ".[local,audio]"
.venv/bin/python examples/microphone_live.py --seconds 5
```

## Design

- Transcription: `faster-whisper` backend (CPU-friendly `int8` by default)
- Intent detection: `sentence-transformers` embeddings similarity against examples
- Parameter extraction: regex rules by default, optional spaCy entity extraction
- Routing: decorator-based handlers with a typed context object
- Optional fallback: local Ollama JSON intent+params when confidence is low

## Extensibility

All major components are pluggable:

- Custom STT engines
- Custom intent detectors
- Custom parameter extractors
- Optional LLM fallback client

See `voicerouter/router.py` for the interfaces.

## License

MIT
