Commit Graph
4 Commits
Author SHA1 Message Date
osobhandClaude Opus 4.7 a5cedfb46a rtx-csm: emotional_speech_guide — CREMA-D vs RAVDESS firdhokk verdict
8-gen bench (4 emotions × 2 corpora) at seed=42 against firdhokk
Whisper-LV3:

  target    RAVDESS              CREMA-D
  happy     happy (0.999) ✓      happy (0.999) ✓
  angry     neutral (0.92)       sad (0.99)
  fearful   happy (0.998)        fearful (0.984) ✓
  sad       angry (0.99)         fearful (0.99)

CREMA-D 2/4 vs RAVDESS 1/4. Larger / more naturalistic corpus
produces more class-pure fearful direction. Neither corpus solves
angry or sad — recipe shifts into 'vague expressivity' rather than
class-specific corners.

Practical: prefer CREMA-D when available; A/B both per emotion if
class precision matters.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
2026-04-30 00:01:02 -07:00
osobhandClaude Opus 4.7 c413449930 rtx-csm: verify barge-in end-to-end + slow-mock LLM for testing
Phase 6c.3c verification: extended converse_client with
--barge-in-after-ms flag that injects a 200 ms audio frame N ms after
the assistant starts speaking, then watches for the
{"event":"barge_in"} server response.

Verified end-to-end on Metal:
  Input: 10.43s LibriSpeech FLAC
  STT transcript: matched correctly
  Mock LLM streamed 4-sentence response with 50ms/token delays
  Client injected barge-in 100 ms into TTS streaming
  Server log: "barge-in detected (4800 samples carried over)"
  Client log: "[server] barge_in event received -- TTS cancelled"
  WAV file: 1.60s of TTS captured before cutoff

Mock LLM upgraded to multi-sentence with tokio::time::sleep(50ms)
between chunks — exercises the streaming pipeline long enough for
barge-in tests to fire mid-response.

The full Rust Unmute conversational stack is now feature-verified:
voice-in, voice-out, interruptible, VAD-driven, authed, metrics-
instrumented. Strategic Phase 6 deliverable shipped end-to-end.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
2026-04-26 10:51:08 -07:00
osobhandClaude Opus 4.7 3212a72d90 rtx-csm: Phase 6c.3a + 6d.{auth,shutdown,metrics} — productionize converse
Production hardening pass on the Rust Unmute MVP:

6c.3a: streaming audio output. Replaced the "collect-then-send" loop
  with a tokio mpsc channel + tokio::join! between conv.run and the
  WS sender. Audio chunks are forwarded to the client AS each sentence
  completes TTS, instead of waiting for the full assistant response.
  Drop the channel sender at end of conv.run to signal the pump exit.

6d.auth: Bearer token auth. --auth-token flag (or RTX_AUTH_TOKEN env)
  on the server requires an Authorization: Bearer <token> header on the
  WebSocket upgrade. Rejected upgrades return 401. Server logs a warn
  if no token is configured (open dev mode). converse_client gains a
  matching --auth-token flag.

6d.shutdown: Graceful SIGINT/SIGTERM. tokio::signal handlers wired
  into axum::serve.with_graceful_shutdown(). Verified: SIGINT log line
  "received SIGINT, shutting down gracefully" + clean exit 0.

6d.metrics: /metrics Prometheus-style endpoint. Counters
  (turns_total, errors_total, connections_total) + gauges
  (connections_active, stt/tts/e2e_first_audio latency averages).
  Verified end-to-end: rtx_csm_turns_total 1 / errors_total 3 (from
  earlier 401 attempts) / e2e_first_audio_ms_avg 21295 / etc.

Verified all four together: 401 on bad/missing auth, 200 + WS upgrade
on correct auth, full round-trip metrics, clean SIGINT exit.

Phase 6 status:
  6a STT: working
  6b LLM client: working
  6c.1 text->LLM->TTS: working
  6c.2 WebSocket duplex MVP: working
  6c.3a streaming TTS chunks: working (this commit)
  6c.3b semantic VAD / barge-in: deferred
  6d.{auth,shutdown,metrics}: shipped (this commit)
  6d.rate-limit: deferred

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
2026-04-26 09:40:38 -07:00
osobhandClaude Opus 4.7 7e88a35f81 rtx-csm: Phase 6c.2 — Rust Unmute MVP, voice conversation round-trip
Full-stack pure-Rust voice conversation server + CLI client:

  Client -> Server  binary frames: 16-bit LE PCM @ 24 kHz mono
  Client -> Server  text "EOT": signal end-of-turn
  Server: STT (Kyutai 1B en/fr) -> transcript
          LLM (OpenAI-compatible OR mock echo) -> token stream
          Converse: sentence buffer -> CSM TTS -> 16-bit LE PCM
  Server -> Client  text {"event":"transcript","text":"..."}
  Server -> Client  binary frames: assistant audio
  Server -> Client  text {"event":"done","assistant":"..."}

Per-connection chat history; multiple turns supported per socket.
--mock-llm mode for testing without API keys (echoes user transcript).

examples/converse_server.rs: axum WebSocket server.
examples/converse_client.rs: CLI; streams WAV in as user turn, saves
  response audio out.

Verified end-to-end on Metal:
  Input: 10.43s LibriSpeech FLAC ("He hoped there would be stew...")
  STT transcript: matched (full sentence captured by 23/25 words)
  Mock LLM: "I heard you say: <transcript>."
  CSM TTS: response audio streamed back via WebSocket
  Round-trip wall-clock: 6.86s (TTFA on first audio chunk: 6.86s; the
  pipeline is sequential per turn — Phase 6c.3 would pipeline LLM
  tokens with TTS to get TTFA much lower).

This is the Rust Unmute MVP: PCM in, voice out, no Python in the
runtime path. Strategic Phase 6 deliverable.

Phase 6 status:
  6a STT: working
  6b LLM client: working
  6c.1 text->LLM->TTS: working
  6c.2 WebSocket duplex MVP: working (this commit)
  6c.3 streaming pipeline + auto-EOT + barge-in: deferred
  6d productionization: deferred

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
2026-04-26 09:30:00 -07:00