ai: Settings → AI (local endpoints only, with tests), the AI stack, voicemail transcripts
ci / check (push) Successful in 1m0s
ci / images (push) Successful in 26s

This commit is contained in:
iamdoubz committed 2026-10-21 18:37:13 -05:00
1 parent 274242ce32
commit a26a5ca740
25 files changed
+4889 -5

No files matched your search

+46
View File
@@ -0,0 +1,46 @@
# 10 — Local AI
Owner, 2026-10-21: AI features that run on the PBX server (or the local network) only. No call
audio, transcript or prompt leaves it.
## 1. Endpoints
Three OpenAI-style APIs, set in Settings → AI (`ai.llm`, `ai.stt`, `ai.tts`), with `AI_*` env
values as the starting defaults (`services/settings.ts`):
| Setting | API used | Reference server |
|---|---|---|
| `ai.llm` {url, model} | `POST chat/completions` | Ollama (`/v1`) |
| `ai.stt` {url, model} | `POST audio/transcriptions` (multipart, `response_format=json`) | Speaches (Whisper) |
| `ai.tts` {url, model, voice} | `POST audio/speech` (`response_format=wav`) | Speaches (Kokoro) |
`ai/client.ts` refuses any address that isn't `localhost` or an IP in 127/8, 10/8, 172.16/12,
192.168/16, ::1, fc00::/7 or fe80::/10, written as an IP: no DNS, so no lookup can send data
elsewhere. Checked on save and before every request. Redirects are refused. CGNAT (100.64/10,
Tailscale) is refused too: it may cross the internet.
`POST /api/ai/test {kind, endpoint}` (admin) sends one tiny request (a chat, a second of silence,
one sentence of speech) with the values in the form, saved or not.
`deploy/ai/compose.yml` is its own stack: Speaches on 127.0.0.1:8000 with the GPU, and an
optional Ollama.
## 2. Voicemail transcripts (`ai.voicemailTranscripts`)
When a new message is indexed (04 §5.6), before the webhook, live event and email, the WAV goes to
`ai.stt` (180 s timeout). The text is stored in `voicemail_messages.transcript`, added to the
email ("What they said (automatic, may have mistakes)") and shown on the voicemail page. A failure
is logged and the message goes out without it.
## 3. Next (in order)
1. Call recording transcripts and summaries: record each side (MixMonitor `r()`/`t()`), so who
said what needs no speaker detection; summary and action items from `ai.llm`; search.
2. Typed prompts (Sounds): `ai.tts`, replacing the Piper plan in M12.
3. Type-to-speak in the browser phone: the api speaks the text, the browser mixes it into the
call.
4. AI receptionist: a destination type; chan_websocket (Asterisk 23.0+/22.6+) streams the call to
the api; utterance-at-a-time STT → LLM with tools (transfer, take a message, hours, hang up) →
TTS. Says it's an AI first; 911 never goes through it; any doubt falls back to the menu or a
person.
GPU sharing: live calls first; background transcripts one at a time.