陪伴型 AI 語音與 Agent 平台
即時語音對話的陪伴型 AI。難的不是 STT → LLM → TTS,而是錄音、播放與斷線重連之間的狀態。
- AI / LLM
- Agents
- Web

Contents
概述
商業專案,工作室負責全端與 AI 應用層。這是一套陪伴型 AI 平台:語音對話之外,也處理記憶、知識檢索,以及家屬和照護人員的存取。前端有 LIFF、一般 Web 與管理介面,後端透過 Gateway 維持即時語音 Session。
問題
把 STT、LLM、TTS 串起來只是第一步。使用者可能還在錄音,上一段語音正在播放,又剛好斷線重連。部分轉錄、最終轉錄和 generation 也不一定照畫面收到的順序完成。只用一個 conversation state,這些狀態會互相蓋掉。
解法
把 utterance、generation 與播放狀態分開管理;turn 與 generation 綁定,晚到的舊轉錄不會啟動錯誤的回答。Session Continuity、identity、expiry 與 stale socket 檢查放在同一組規則。Agent 的 MCP、Tools、Skills、Knowledge Base 與外部搜尋放在後台設定與 Provider 邊界裡。
長者 / 家屬 / 照護人員 ──▶ LIFF / Web / Admin
│
▼
Fastify Gateway ──▶ WebSocket Voice Session
│
▼
Agent Runtime
┌─────────┼──────────┐
STT / LLM / TTS External Search PostgreSQL / Redis主要功能
- STT → LLM → TTS 的語音對話生命週期
- utterance、transcript、generation 與播放狀態管理
- WebSocket 斷線後的 Session Continuity、回放與取消
- 後台設定 MCP、Tools、Skills、Knowledge Base 與外部搜尋
- 長者、家屬與照護人員分開的資料權限、記憶保留與刪除流程
- Socket、Request、Log 與 Container Resource 限制
- 語音、閱讀模式與回放操作
架構
麥克風 ──▶ 部分轉錄 ──▶ 最終轉錄 ──▶ turn(綁定 generation id)
│
▼
LLM generation ──▶ TTS ──▶ 播放
│
舊 socket / 舊轉錄 ──▶ 比對 generation id ──▶ 不符則丟棄,不取消新的 generationConversation ──▶ Agent Runtime ──▶ Provider 邊界
│ ├─ MCP Servers(後台開關)
│ ├─ Tools / Skills(參數先受限制)
│ ├─ Knowledge Base
│ └─ External Search(不綁死單一服務)
└──▶ Memory(依角色決定保留與刪除)工程決策
狀態要拆開,不能共用一個 conversation state
錄音中、播放中、重連中是三件會同時發生的事。拆成 utterance、generation、playback 三組狀態,各自有明確的轉換,互相蓋掉的問題才消失。
轉錄順序不能直接當回答順序
turn 與 generation 綁在一起。晚到的舊轉錄比對不到現行 generation 就丟棄;舊 socket 也不能取消新的 generation。
斷線要分三種結果
可以恢復、應該停止、需要提示重新開始。Session Continuity、identity、expiry 與 stale socket 檢查放在同一組規則裡,才不會每個地方各判各的。
Agent 能力要能被控制
MCP、Tools、Skills、Knowledge Base 與外部搜尋不是每個情境都要開。放進後台設定與 Provider 邊界,對話流程不直接綁某一個搜尋服務,工具參數先經過限制。
畫面
未包含正式使用者資料或服務品牌。


技術
TypeScript、Fastify、React、LIFF、WebSocket、STT / LLM / TTS、Agent Tools、MCP、SearXNG、ElevenLabs、PostgreSQL、Redis、Docker。
結果與心得
- 即時語音的難處在協調,不在串接。狀態拆成 utterance、generation、playback 三組之後,互相蓋掉的問題才消失。
- 斷線先分類再處理:能恢復、該停止、要重來,三種結果各有一條路。
- 即時語音仍受瀏覽器權限、網路與外部語音服務影響,這一段應用層只能降低、無法消除。
公開範圍
只描述應用層的狀態協調、恢復、權限與資源控制,不含第三方 Provider 的 SLA。