# AI Phone Bridge

An AI phone receptionist platform. Caller audio arrives over a WebSocket, is
transcribed by Qwen realtime ASR (Google Gemini as fallback), answered by a
Qwen LLM with tool calling, and spoken back through Qwen realtime TTS. An
alternative **Omni** mode runs ASR + LLM + TTS over a single DashScope realtime
WebSocket with barge-in. Around that core: multi-agent transfer, post-call
faithfulness QA, ACRS complaint dispatch, and a ChromaDB store for agent
profiles and conversation logs.

> **Scope of this README: the telephony bridge is excluded on purpose.**
> The `BT-AI-Bridge/` folder (Node.js Asterisk/ARI bridge with its own Docker
> image, dashboard and SQLite store) and the sibling `BT-KeyServer/` and
> `BT-Yeastar-Bridge/` folders are **not** covered here. They are deployed
> separately and have their own build files. This README gets the Python side
> running from a clean machine: the pipeline server, its test dashboard, and
> the DEVOPSAPI microservice. Without the bridge you test with a browser
> microphone, not a real phone call.

## Components and ports

| Component | Entry point | Default port | Env var |
|---|---|---|---|
| Caller WebSocket server | `qwen_pipeline_server.py` | 8767 | `PIPELINE_WS_PORT` |
| HTTP API + test dashboard | same process | 5555 | `PIPELINE_HTTP_PORT` |
| DEVOPSAPI (FastAPI, Azure DevOps tickets) | `DEVOPSAPI/main.py` | 8000 | (fixed in `main.py`) |

Both pipeline ports bind `0.0.0.0`. The HTTP API has **no authentication**;
keep it on a private network or behind a reverse proxy.

## Prerequisites

- **Python 3.9 or newer** (the code uses the standard-library `zoneinfo`
  module). Development and the test suite run on Python 3.13.
- A **DashScope API key** (Alibaba Model Studio, international region). The
  server exits immediately if `DASHSCOPE_API_KEY` is unset.
- Optional: a Google API key for the Gemini fallback transcriber.
- Optional: Azure DevOps organisation, project and PAT for DEVOPSAPI.
- `git`, and a browser with microphone access for the test dashboard.

## 1. Pipeline server: quick start

```bash
git clone <this repo>
cd AI-PHONE

python -m venv .venv
# Windows
.venv\Scripts\activate
# Linux / macOS
source .venv/bin/activate

pip install -r requirements.txt

# Create your env file from the template and fill in DASHSCOPE_API_KEY
copy .env.example .env      # Windows
cp .env.example .env        # Linux / macOS

python qwen_pipeline_server.py
```

On start the server prints:

```
  WebSocket : ws://localhost:8767
  Test page : http://localhost:5555/qwen_pipeline_test.html
```

The `.env` file is read from the repository root by the server's own loader
(key=value lines, `#` comments). Values already present in the process
environment take precedence.

First run creates two runtime folders next to the code, both git-ignored:
`chroma_db/` (profiles and conversation logs) and `recordings/`.

### Using the test dashboard

1. Open `http://localhost:5555/qwen_pipeline_test.html`.
2. In the **WebSocket** field (the connection panel near the bottom of the
   page, above the Start button), enter `ws://localhost:8767`. The default
   value in the page points at a production host, so change it on a new
   machine. The value is saved with the profile.
3. Build an agent profile (instructions, voice, tools, Audio Settings) and
   click **Save As** to store it in ChromaDB. To start from a working
   example, use **Import JSON** with `references/complaint_profile.json`.
   The other files in `references/` are transfer-agent and tool snippets
   you can paste into the matching sections.
4. Click **Start Conversation** and speak into the microphone. The page shows
   the transcript, tool calls, per-turn latency and cost.

`audio_timing.html` on the same port is a latency diagnostics page.

### Optional features

- **Gemini fallback ASR**: set `GOOGLE_API_KEY` and choose Gemini as the STT
  provider in the profile.
- **Noise suppression**: place a GTCRN ONNX model in `models/gtcrn/` (any
  `*.onnx` there is picked up) and install `onnxruntime`. The folder is
  git-ignored and is not shipped with the repo; without it the feature is a
  silent pass-through.
- **ACRS, Conversation Validator, WhatsApp and custom tool endpoints** are
  configured per profile in the dashboard, not through env vars.

## 2. DEVOPSAPI: quick start

A standalone FastAPI service that turns complaint tickets into Azure DevOps
work items. The pipeline reaches it only as an HTTP tool endpoint, so it is
optional unless a profile's complaint tool points at it.

```bash
cd DEVOPSAPI
pip install -r requirements.txt        # into the same venv is fine
# Put DEVOPS_ORG, DEVOPS_PROJECT, DEVOPS_PAT in DEVOPSAPI/.env (see .env.example)
python main.py
```

- Swagger UI: `http://localhost:8000/docs`, health check: `GET /health`.
- Tables are created automatically in `devops_tickets.db` (SQLite) on first
  start. Override the location with `DATABASE_URL`.
- `python init_db.py` seeds demo products, systems and support contacts. It
  **wipes** the tickets, support, system and product tables first, so never
  run it against real data.
- The service loads `.env` with python-dotenv, which searches from the
  `DEVOPSAPI/` folder upward, so the repo-root `.env` also works.

## 3. Running the tests

```bash
pip install -r tests/requirements.txt
# Most test files import the server module, which exits without a key.
# Any non-empty value works for the unit tests; nothing is called.
set DASHSCOPE_API_KEY=test        # Windows
export DASHSCOPE_API_KEY=test     # Linux / macOS
python -m pytest tests -q
```

Known state as of 2026-10-05: five tests in `tests/test_omni_routing.py` fail
because the shared `MockSession` in `tests/conftest.py` predates a server
attribute (`_record_tool_event`). They are not environment problems.

## Production launcher scripts

`start_flask.sh` and `stop_flask.sh` are the launch scripts from one specific
Linux host. They hard-code that host's project path and conda environment
name, so treat them as a reference for the intended process layout (pipeline
server plus DEVOPSAPI under `nohup`), not as portable scripts.

## Security notes

- Never commit `.env`, `DEVOPSAPI/.env`, or anything under `BT-AI-Bridge/secure/`.
  All three are git-ignored.
- Agent profiles can hold tool endpoint headers (API keys). `GET /api/profiles`
  returns them unredacted and unauthenticated, so do not expose port 5555
  publicly.

## Where the deeper documentation lives

Architecture, flows, API contracts, data models, risks and the bridge
subsystem are documented in the internal Obsidian vault maintained alongside
this repository (`AI-PHONE-BRAIN`). Start with
`Codebase Knowledge/00 AI Phone Bridge Project Index.md`.
