Commit Graph
4 Commits
Author SHA1 Message Date
Omar Sobh 6a03aeba61 fix(cuda+csm): P0 rtx-backend-cuda compile fix + P2 rtx-csm clippy cleanup (#9)
Co-authored-by: Omar Sobh <[email protected]>
Co-committed-by: Omar Sobh <[email protected]>
2026-04-30 05:24:58 +00:00
osobhandClaude Opus 4.7 99a7e53aa8 rtx-csm: decoder activation capture — architectural hypothesis validated
Adds capture_decoder_activations on Model and ModelBackend, plus
--target-module decoder|backbone on examples/steering_extract.

Decoder mode runs a text-only prompt through the backbone (no
capture), Mimi-encodes the audio separately to grab the middle
frame's c0 token, teacher-forces that c0, and captures one mean-
pooled-over-seq vector per decoder layer. Result: 4 layers ×
1024 embed dim per call, much faster than backbone capture
(text-only prompts are short).

A/B with the canonical "Today I want to share..." prompt at seed
7 (the previously-identified low-WER seed):

  case          cos    WER    transcript
  baseline      0.76   0.36   "And today I want to share something some
                              funnel distraits"  (high baseline at this
                                                  seed)
  [email protected]  0.75   5.00   "Today, I want to share some needs of my
                              prey"  (backbone destroys content)
  [email protected]   0.86   0.93   "I'm not that tall. I'm not that tall."
                              (fluent but repetitive — biggest cos)
  [email protected]   0.61   2.57   over-steered
  [email protected]   0.61   2.14   broken

[email protected] is the largest speaker_cosine boost we've measured AND
produces clean English. Backbone steering at the same seed destroyed
content fidelity. This validates the architectural hypothesis: the
backbone carries semantic content (what the model says), the depth
decoder carries acoustic detail (how it sounds). Steering the
decoder shifts voice character without disturbing word content the
way backbone steering does.

Open issues: [email protected] produces repetitive output ("I'm not that
tall" three times). Likely lower scale (~0.5) plus the existing
repetition guard would fix it; left for follow-up.

Decoder vector magnitudes are ~10× smaller than backbone (norm 0.85
at deepest layer vs 14.9), so the appropriate scale is ~10× higher
than the backbone recipe (1.0 vs 0.1-0.3).

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
2026-04-29 12:59:28 -07:00
osobhandClaude Opus 4.7 3a67e4aa50 rtx-csm: Sprint 2 Phase B — steering vector extractor
Closes the loop on Phase A (apply hook). Adds:

- LlamaModel capture buffer + start/take_capture API. Pushes one
  mean-pooled-over-seq activation per layer into a per-call Vec when
  active. Steering apply runs first, so captures reflect post-steering
  state when both are on (extractor disables steering for the duration
  of the call to capture baseline activations).
- Model::capture_backbone_activations: teacher-forced forward over a
  built prompt, returns per-layer (embed_dim,) activation tensors.
- ModelBackend passthrough; FP-only (Quantized errors out).
- examples/steering_extract: reads emotion-labeled JSONL, accumulates
  per-emotion sums on CPU f32, writes per-layer
  (mean(target) - mean(baseline)) as `layer_<i>_steering` safetensors.

Smoke run on carlini2 manifest (excited vs surprised, 10 samples each):
- Vector norms grow monotonically with depth (layer 0: 2.25, layer 15:
  12.61) — consistent with deeper layers carrying richer
  emotion/style signal.
- Loaded into examples/generate at scales 0.5/1.0/2.0; quality_eval
  shows WER hits 1.0 immediately. This is the EmoSteer paper's warning
  ("large α may produce unintelligible speech") triggering at small
  α — diagnosis: the corpus is the problem, not the infrastructure.
  The emotion_tag labels in our existing manifests are noisy
  (emotion2vec output on lecture audio collapses to [surprised] /
  [excited] without a clean neutral pool), and 10 samples per pool
  is well short of the paper's 1000/emotion.

What this validates:
- End-to-end extraction → save → load → apply pathway works.
- quality_eval (Sprint 1) cleanly catches the regression — the metric
  foundation does its job.

What's next (a future session):
- Real emotion-labeled dataset (CREMA-D, ESD, RAVDESS) for proper
  pools with a true neutral baseline.
- Layer-subset experiments (paper steers layers 1,6,11,16,21 of 32;
  for our 16-layer backbone the analogue is roughly 1, 4, 8, 12).
- Listening test alongside the metric numbers.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
2026-04-29 08:57:41 -07:00
osobhandClaude Opus 4.7 15dd3575d4 Add rtx-csm: Rust-native port of Sesame CSM-1B with LoRA voice cloning
A new model crate at crates/models/rtx-csm implementing end-to-end
inference, quantization, and fine-tuning for Sesame's Conversational
Speech Model (CSM-1B). Built on candle 0.9 + Kyutai Mimi codec.

Key capabilities:
- Inference (FP F16 on Metal, F32 on CPU, BF16 on CUDA)
- Quantized inference (Q8_0 / Q4_K_M GGUF, ~3x speedup, ~50% memory)
- Streaming Mimi decode with proper StreamTensor state machine
- In-context voice cloning via SpeakerProfile
- Classifier-Free Guidance (Koel-TTS recipe)
- Long-form chunked generation with rolling context
- Audio post-processing (HPF + declick + EBU R128 LUFS)
- Text input normalization (brackets, times, unicode, length caps)
- Frame-level repetition guard (loop-escape)
- Top-k + top-p sampling
- LoRA fine-tuning end-to-end (training + inference, on FP and Q8 bases)
- In-process Whisper ASR via whisper-rs (under --features asr)
- Standalone TTS HTTP server (Axum)
- Bench harness with manifest export + per-prompt WER

Phases delivered: quantization, ASR/WER eval, LoRA voice cloning, HTTP
service. AudioSeal/WavLM/Unmute remain as documented future work.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
2026-04-25 18:33:57 -07:00