Commit Graph

11 Commits

Author SHA1 Message Date
vh 9fe7479ddc fix(gateway-chat): honor UI endpoint/model/voice for TTS + standard-audio playback
The TTS path was hardwired to the parked zonos-gateway: it force-reverted the
endpoint field back to zonos :8890 on load, hardcoded model=ext-tts, and decoded
the response as Zonos-specific raw float32 PCM @ 44.1kHz. Result: quoted-text TTS
was dead once zonos was parked, and pointing the field elsewhere silently failed.

- Honor the interface: set endpoint/model/voice defaults only when a field is
  empty; never rewrite a user-typed value (removed the zonos auto-revert regex).
- Add a TTS model field (ttsModel); send the UI's model instead of hardcoding.
- Playback: request standard OpenAI /v1/audio/speech mp3 and decode via
  audioCtx.decodeAudioData (handles wav/mp3/ogg/flac from any endpoint).
- Defaults: endpoint = LiteLLM ext-tts alias (fleet TTS gateway), voice = nova.
2026-08-12 17:31:04 -07:00
vh 6a90a70ad8 feat(gateway-chat): repoint TTS to zonos-gateway (OpenAI /v1/audio/speech)
Point the in-page TTS at the zonos-gateway wrapper on irv-ml1:8890 (direct,
so streaming isn't buffered by LiteLLM): OpenAI-shape body (model: ext-tts,
input, voice), Cora default voice, float32@44.1kHz PCM decode. Quotes are
joined into a single stream call (prosody — no per-sentence chunking).
Migration regex rewrites stale saved endpoints (:8299/:8210, /tts[/stream],
:4000) to the new one.
2026-07-11 09:24:35 -07:00
vh f295cc1f46 fix(gateway-chat): chunk by quoted section, not sentence (prosody)
Per-sentence chunking generated each sentence cold, flattening intonation/prosody that
spans the whole quoted line. Chunk by QUOTED SECTION instead — each contiguous quote is
generated whole (max_tokens 2400) so its prosody stays intact; multiple quotes in a reply
still play serially on the shared clock. extractQuotes already returns exactly these spans;
dropped splitSentences.
2026-07-09 01:54:39 -07:00
vh a1f3023f70 feat(gateway-chat): pre-chunk quoted text by sentence, play serially
Split the quoted dialogue into sentences and stream each as its own short /tts/stream
request (max_tokens 900), queued back-to-back on one shared AudioContext clock (speechHead)
so playback is gapless and in order. First sentence starts fast; each chunk is short so it
generates cleanly (no ramble/cap risk); the next sentence generates while the current plays.
A newer reply supersedes via the ttsGen counter; 🔊 replays.
2026-07-09 01:49:45 -07:00
vh 033f3685f5 fix(gateway-chat): resume AudioContext on user gesture (no-sound / autoplay)
Browsers suspend the Web Audio AudioContext until a user gesture; speakQuotes fires on
reply-complete (no active gesture), so a suspended context played silently. Prime/resume
the context on any click or keydown (capture phase) so it's running before playback.
Server side was fine throughout (/tts + /tts/stream both 200 with valid audio).
2026-07-09 01:41:26 -07:00
vh 0655a37bf6 feat(morpheus): staged clone voices + max_tokens 3500 (context-clamped)
- max_tokens default 2400->3500 (~42s) in wrapper + gateway-chat client, with a _cap()
  clamp so prompt+gen never exceeds MAX_CTX (4096) — a cloning ref block is ~1100 tokens,
  so an unclamped 3500 would overflow context on the clone path.
- Staged clone voices: /voices dir of <name>.wav + <name>.txt, each encoded to its Orpheus
  reference block at startup; voice="<name>" zero-shot clones it. Beatrice (a chatterbox
  reference) staged as the first normal-voice clone. GET /voices lists baddy + clones.
- compose: mount voices dir + pass MORPHEUS_MAX_LEN to the wrapper (clamp must match engine).

vLLM concurrency (measured, --max-num-seqs 8, 250-tok reqs): near-linear batching — 8
concurrent finish in the same ~2.8s as 1 (707 tok/s, 8.1x single, flat per-req latency).
Chunked-sentence production can fan out for ~8x throughput; CPU SNAC decode is the scale
bottleneck, not generation.
2026-07-09 01:35:14 -07:00
vh f363fe6c84 fix(morpheus): raise TTS max_tokens 1200->2400 (long lines clipped at ~14.6s)
Cut-offs were the max_tokens=1200 ceiling (~14.6s of audio), not memory (~1250 tokens
<< 4096 context). Diagnosis: the repetition penalty is load-bearing for clean stops —
rep 1.0 => the model never emits end-of-speech and rambles to the cap; rep 1.1 (the
wrapper default) => clean natural stop. So normal lines already complete; only genuinely
long dialogue (>~14.6s, ~25+ words) hit the cap. Raised default + client max_tokens to
2400 (~29s), still within the 4096 context (no memory cost). Verified: a 49-word line
now finishes at 16.73s (was clipped at 14.6s).
2026-07-09 01:25:56 -07:00
vh da7682969b feat(morpheus,gateway-chat): streaming decode — TTFA ~4.5s -> ~0.8s
Wrapper gains POST /tts/stream: reads the vLLM token stream, decodes SNAC in WINDOWED
CHUNKS (every 6 frames, decode [2 ctx | 6 | 2 ctx] and emit only the middle 6 — context
both sides => seamless), and streams raw PCM16 (24kHz mono) as it generates. Windowed
(not per-frame) because per-frame CPU decode's per-call overhead x ~60 frames serialized
to ~7s (RTF 2.2); windowed keeps up (RTF ~0.97). Whole-clip /tts kept for non-browser use.

gateway-chat plays the stream via the Web Audio API (fetch reader -> int16->float32 ->
scheduled AudioBufferSourceNodes on a running clock; a new reply supersedes the prior
stream via a generation counter; 🔊 replays). Measured: TTFA 0.80s (was ~4.5s whole-clip),
RTF 0.97, full-duration match. CORS already covers the new route.

Deployed: tts rebuilt on irv-ml1, page pushed to ana-docker.
2026-07-09 01:14:25 -07:00
vh c948013a36 feat(gateway-chat): auto-voice quoted dialogue via mOrpheus TTS
Gateway-chat now auto-plays quoted text from each assistant reply through the mOrpheus
TTS endpoint. Sidebar gains a 🔊 toggle + endpoint/voice fields (persist in localStorage,
prefilled to irv-ml1:8299 / baddy). On reply-complete, straight and typographic double
quotes are extracted, joined, POSTed to /tts, and the returned WAV plays (click 🔊 to
replay; a new reply interrupts the prior clip).

Requires CORS on the wrapper (page served from ana-docker:8091 fetches irv-ml1:8299
cross-origin) — added CORSMiddleware(allow_origins=[*]) to the mOrpheus tts app (internal-
only endpoint). Verified end-to-end: preflight + POST return ACAO=*, valid 24kHz WAV.

Deployed: tts container rebuilt/recreated on irv-ml1; page pushed to ana-docker conf
(bind-mounted, live on next request).
2026-07-09 00:58:13 -07:00
vh 4c40b9fac6 feat(tools): gateway-chat.html — auto-discover gateway models + image upload for vision smoke
Model field now pulls /v1/models (the ↻ control; new gateway models just appear)
instead of a hardcoded stale list; 📎 attaches an image (base64 data: URL in
image_url content) so the multimodal models (Qwopus, image-judge) can be smoked.
Static-verified (JS syntax + element-id consistency); headless smoke was blocked
by a shared-browser version skew in /opt/ms-playwright, not a tool defect.
2026-06-19 11:56:20 -07:00
vh 984ca3d383 feat(tools): single-file gateway chat playground
Zero-dependency, zero-backend HTML chat UI for the LiteLLM gateway. The
browser talks straight to :4000 (gateway CORS is open), so it's just one
file you open — no container, no stack. System-prompt textarea, model
datalist, streaming SSE, renders reasoning_content for the -thinking/
-reasoning models, settings persist in localStorage.

Deliberately never sends a `tools` field, sidestepping the vLLM "tools
must not be an empty array" bug that breaks the LiteLLM admin UI
playground for vLLM-backed models (litellm #6228; the gateway's
strip_empty_tools hook can't reach the UI's in-process completion call).

Verified against the live gateway: streams + parses a real completion
with no tools sent.
2026-06-16 01:40:30 -07:00