Files
selfphoneng/docs/spec/10-ai.md
T
2026-10-21 18:37:13 -05:00

2.4 KiB

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.