Pas 1 (BLOCKING) din Discord voice-to-voice test plan. Sweet spot empiric pe i7-6700T: faster-whisper small int8 @ cpu_threads=4 → p50 2.25s, p95 2.64s, mean RTF 0.46. Curba HT: 2t=3.25s → 4t=2.25s (sweet) → 6t=2.79s (regres +24% prin contention). tiny respinge — halucinează RO. - tools/voice_bench.py: harness benchmark cu 8 sample-uri RO sintetizate via Supertonic API, măsoară p50/p95/RTF pentru small+tiny pe N threads. - tools/voice_bench_results*.json: raw output 3 pass-uri (threads 2/4/6). - tasks/voice-bench-results*.md: summary markdown per pass. - tasks/lessons.md: HT contention rule — cpu_threads = physical cores, rulează sweep nu single-point pentru ML inference compute-bound. Budget updated în plan-uri: STT p50 1.5s → 2.5s, perceived 4s → 5s p50. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5.1 KiB
Voice Bench Results — Discord Voice-to-Voice Spike (BLOCKING Pas 1)
Generated: 2026-05-27 Hardware: i7-6700T (4 physical cores / 8 logical), Proxmox VM, no GPU Budget original: STT p50 < 1.50s (per CEO plan aspirational) Budget honest range: 1.5-3s (per Outside Voice #1, baked in CEO plan)
Final Recommendation: PASS cu small model + cpu_threads=4
small @ 4t → p50 2.25s, p95 2.64s, mean RTF 0.46. Cade în honest range "1.5-3s" deja acceptat. Transcript clean modulo normalizare numerică (deja în scope: src/voice/normalize.py).
Auto-decision script-ul (FALLBACK_TINY) este override-uit manual: tiny produce transcript ilizibil ("Stei putin", "muină să sun la nu a", "să mream in test de seare") — neutilizabil în RO. Latency-ul rapid nu compensează lipsa de înțelegere.
Surprise Finding: Threads Sweet Spot = 4, nu 6
Sweep complet:
| cpu_threads | small.p50 | small.p95 | mean RTF | Δ p50 vs threads=4 |
|---|---|---|---|---|
| 2 | 3.25s | 3.63s | 0.67 | +44% (slower) |
| 4 | 2.25s | 2.64s | 0.46 | baseline |
| 6 | 2.79s | 3.31s | 0.70 | +24% (slower!) |
tiny essentially flat (~0.5s) la orice thread count — CPU-light enough că nu beneficiază.
Explicație: i7-6700T = 4 physical cores + 4 hyperthreads. cpu_threads=4 fitează exact pe physical cores (no hyperthread contention). cpu_threads=6 spill-uiește pe hyperthreads care HURT compute-bound int8 inference (memory bandwidth contention, fără parallelism real). Lock în plan: cpu_threads=4 regardless of VM core count. Adăugarea de cores în VM nu mai accelerează small peste 4 threads.
Implicații pentru implementare
src/voice/pipeline.py→WhisperModel("small", device="cpu", compute_type="int8", cpu_threads=4)- Plan budget update: STT p50 = 2.25s (era 1.5s); perceived round-trip estimate = 3.5-5s (STT 2.25s + Claude TTFB 0.5-1s + streaming TTS first clause ~0.5s).
- Streaming Claude→TTS rămâne critic — fără el, total perceived = 6-8s, peste limita conversațională.
- Filler audio "Stai să-mi adun gândurile" (deja în plan) maschează cazurile p95 (>3s).
- Tiny model rămâne instalat dar doar pentru
/voice doctordegraded mode (Whisper OOM, low memory), NU pentru happy path.
Transcript Quality (4 threads run)
| Input | small output |
tiny output |
|---|---|---|
| "Salut, ce mai faci?" | "Salut ce mai faci!" | "Salut, ce mai fac?" |
| "Stai puțin să mă gândesc la asta." | "Stai putin să mă gândesc la asta." | "Stei putin să mă gândesc la asta." |
| "Am verificat în calendar și avem ședință cu echipa la trei după-amiază." | "Am verificat în calendari și avem sedință cu echipa la 3 după amiază." | "Am verificat în calendar și avem sedeință cu equipala 3 du pămiază." |
| "Costul total este o sută douăzeci și trei de lei și cincizeci de bani." | "Costul total este 120 și 3 delei și 50 de bani." | "Costul total este o suta 20 și 3 de lei și 50 de bani." |
| "Marius, vrei să-ți pun pe agenda de mâine să suni la NOAA?" | "Marius, vrei să-ți spun pe agenda de mâine să suni la noa a." | "Marius, vrei să-ți pun pe agenda de muină să sun la nu a." |
| "Vreau să-mi reamintești diseară..." | "Vreau să mi-răimintești di seară..." | "Vreau să mream in test de seare..." |
Pattern erori:
small: diacritice missing (putin/puțin,sedință/ședință), numere ca digiti ("3" în loc de "trei" — normalizator inverse din scope), acronime ("noa" pentru NOAA — expected, deferr), aglutinare minoră ("delei", "răimintești").tiny: cuvinte INVENTATE ("mream", "muină", "equipala", "sunilă"). Hallucination, nu doar misspell. Unusable.
Open Questions (pentru decizie finală)
- Acceptăm 2.25s p50? YES — în honest range CEO plan deja aprobat. User-facing communication: "Echo gândește 2-3 secunde înainte să răspundă" (vs. aspirational sub-secundă).
- Activate restul de 2 cores offline (5,6)? Marginal — nu va îmbunătăți peste threads=4 sweet spot. Worth doar pentru concurrent workloads (TTS + STT simultan, alte servicii).
- Network STT alternative (Groq/Deepgram)? Deferred —
small @ 4tconfirmat sufficient. Reconsiderăm DOAR dacă post-implementation p95 perceived >7s.
Hardware Context
- Intel(R) Core(TM) i7-6700T CPU @ 2.80GHz (Skylake mobile, 2015)
- Cores online (final): 6 logical (0-4, 7), 2 offline (5, 6)
- Physical cores: 4 (TUI 8 logical via HT)
- RAM: 6.0Gi total, ~2.0Gi available
- No GPU (CPU-only int8 inference)
- ctranslate2 4.7.2 + faster-whisper 1.2.1
Raw Data
tools/voice_bench_results.json— last run (threads=6)tools/voice_bench_results_threads4.json— WINNING config (threads=4)tools/voice_bench_results_threads2.json— baseline (threads=2)tasks/voice-bench-results-threads2.md— narrative threads=2tasks/voice-bench-results-threads4.md— narrative threads=4
Status
BLOCKING Pas 1 → CLEARED. Sweet spot identificat. Plan file ready pentru update.