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]>
GenerateOptions gains emotion_hint: Option<String>. After text
normalization, the hint (if Some) is prepended as `<tag> <text>` so the
Llama BPE tokenizer encodes it as ordinary tokens. Plumbed through
generate, generate_streaming, and generate_with_profile (via delegation),
plus a `--emotion-hint` flag on examples/generate and a Shared field
+ CLI flag on examples/converse_server (per-turn ConverseOptions).
GenerateOptions lost Copy because Option<String> isn't Copy; updated
the four callers that depended on it (bench, longform, converse synth
+ stream) to .clone() the opts at the call site. Cheap — the struct
is small and clones are per-turn, not per-frame.
On the un-adapted base this is a no-op cosmetic prefix. The point is to
unlock Phase 12.1-fine-tuned adapters: train with `[whisper] X` paired
with whispered audio, and the adapter learns the tag→prosody mapping at
inference time.
Verified end-to-end: --emotion-hint "[whisper]" --max-audio-ms 3000
produced a valid 24kHz mono WAV through tokenizer → backbone → Mimi
with no panics. Lib suite 96/96 (added 4 apply_emotion_hint unit tests).
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>