# Voice Phase 2 Streaming — Cutover Plan ## Мета Безпечно ввімкнути Phase 2 sentence-chunking streaming (`/api/voice/chat/stream`) для **всіх голосових сесій** без регресій. ## Поточний стан (baseline) | Метрика | Значення | |---------|---------| | TTS p95 | ~1536ms ✅ | | gemma3 TTFA | ~2620ms ✅ | | qwen3.5 TTFA | ~8524ms ✅ (auto-promote qualified) | | qwen3:14b TTFA | ~11618ms ⚠ fallback only | | Streaming | enabled by default (checkbox ON) | --- ## Stages ### Stage 0 — Pre-conditions (blockers) Виконати **перед будь-яким Stage**: ```bash # 1. Voice canary preflight python3 ops/scripts/voice_canary.py --mode preflight # 2. Contract tests python3 -m pytest tests/test_voice_policy.py tests/test_voice_stream.py -v # 3. Degradation state check curl -s http://localhost:8002/api/voice/degradation_status | python3 -m json.tool # Очікування: state = "ok" ``` **Блокери:** - [ ] voice_canary preflight passed (Polina + Ostap OK) - [ ] 45/45 tests green - [ ] degradation_status state = "ok" - [ ] edge-tts версія = 7.2.7 (`docker exec dagi-memory-service-node2 pip show edge-tts | grep Version`) --- ### Stage 1 — 5% canary (feature flag в UI) Увімкнути `streamMode=true` за замовчуванням (вже є), але обмежити до 5% сесій через cookie. Реалізація (мінімальна): - BFF `/api/voice/chat/stream` вже є. - UI вже має `streamMode` checkbox (ON за замовчуванням). - Достатньо: **не блокувати**, але збирати метрики. **Що моніторити (10 хвилин):** ```bash # TTFA curl -s http://localhost:8002/api/voice/degradation_status # Логи docker logs sofiia-console --tail 50 | grep "voice_stream ok" # Underflows у browser console _voiceStats() ``` **SLO Gate Stage 1:** - `voice_ttfa_ms` p95 ≤ 6000ms (20% буфер) - `voice_tts_first_ms` p95 ≤ 2500ms - underflow_rate ≤ 5% (relaxed for canary) - No `emergency` state in degradation_status --- ### Stage 2 — 50% rollout Якщо Stage 1 пройшов 30 хвилин без SLO breach: - Переконатись що streamMode ON за замовчуванням. - Включити polling деградації (`_startDegradPolling` — вже активний). **Що додатково перевірити:** ```bash # Grafana dashboard (імпортувати ops/grafana_voice_dashboard.json) # Перевірити панелі 1-4 на наявність spike-ів # Voice latency audit bash ops/voice_latency_audit.sh 2>&1 | tail -30 ``` --- ### Stage 3 — 100% (production default) Умови: - Stage 2 стабільний ≥ 2 години - Усі алерти (ops/voice_alerts.yml) в стані "OK" (не firing) - `voice_queue_underflows_total` rate ≤ 0.017/s (1/хв) **Дії:** 1. Переконатись `streamMode` checkbox: `checked` by default — вже є. 2. Додати voice_canary у ops/cron/jobs.cron — вже є. 3. Задеплоїти ops/voice_alerts.yml у Prometheus. --- ## Rollback план Якщо будь-який SLO breach або degradation state ≠ ok: ```bash # 1. Негайний rollback: вимкнути stream mode у BFF # (без rebuild — через env var) docker exec sofiia-console env | grep VOICE_STREAM_DISABLED # Або через конфіг — додати VOICE_STREAM_DISABLED=true і перезапустити # 2. Перевірити стан curl -s http://localhost:8002/api/voice/degradation_status python3 ops/scripts/voice_canary.py --mode preflight # 3. Якщо TTS деградував — перезапустити memory-service docker restart dagi-memory-service-node2 sleep 10 && curl -s http://localhost:8000/voice/health ``` **Fallback chain (автоматичний):** 1. TTFA p95 > 5s → badge "⚠ AI SLOW", profile stays fast 2. TTFA p95 > 8s → badge "⚡ FAST MODE", voiceQuality checkbox auto-unchecked 3. TTS p95 > 2s → badge "⚠ TTS SLOW" 4. TTS p95 > 4s → badge "🔴 TTS DEGRADED", user informed --- ## Feature Flag (якщо потрібен explicit ON/OFF) Додати в `docker-compose.node2-sofiia.yml` → environment: ```yaml VOICE_STREAM_ENABLED: "true" # або "false" для rollback ``` Та в `main.py` `/api/voice/chat/stream`: ```python if not os.getenv("VOICE_STREAM_ENABLED", "true").lower() == "true": raise HTTPException(503, "Voice streaming disabled") ``` --- ## Метрики для Phase 2 auto-approve voice_policy_update.py читає ops/voice_canary_last.json + Prometheus і автоматично: 1. Оновлює `auto_promote` пороги в router-config.yml 2. Генерує ops/voice_latency_report.json ```bash python3 ops/voice_policy_update.py --apply ```