Commit Graph

2 Commits

Author SHA1 Message Date
Richard Loyer d20f2b297b chantier B TTS #7: sampler HF-style top_k+top_p+rep_penalty (générique)
sampler.{h,cpp} : module isolé reproduisant la chaine HF
LogitsProcessor :
  1. RepetitionPenaltyLogitsProcessor (logit/penalty si >0, logit*penalty sinon)
  2. TemperatureLogitsWarper (logit /= temp)
  3. TopKLogitsWarper (garde top_k, autres -> -inf)
  4. TopPLogitsWarper (nucleus : garde la masse cumulee jusqu'a top_p)
  5. multinomial sample (xorshift32, deterministe via sampler_seed)
PRNG xorshift32 != torch.mt19937 donc meme seed != audio Python, mais stable
sur n'importe quel texte/voix (pas d'attracteur greedy).

Plumbing :
- CPState.sampler (defaut greedy top_k=1, temp=0 -> cp_validate continue a sortir
  495/495 codes match). Pipeline override pour temp=0.9 top_k=50 rep_penalty=1.05
  rep_window=16 (intra-frame, 15 codebooks max). CB1..15 utilisent
  sampler_sample_local() qui prend les tokens deja samples CE step pour penaliser
  repetition intra-frame.
- tts_pipeline : Sampler talker_sampler avec rep_window=64 (historique long sur
  CB0). Override via env KZTTS_TEMP/TOPK/TOPP/REPP + KZTTS_CP_TEMP/TOPK/TOPP/REPP.

Validation sur 5 seeds (1, 42, 100, 777, 12345), phrase 'Bonjour je m'appelle Kazeia' :
  - Tous EOS naturel (step 31-44, 2.48-3.67s audio @12Hz, proche du PY_REF 2.08s)
  - silence_pct : 25-36% (vs > 60% avec greedy/sampler simple)
  - cp_validate continue a sortir 495/495 codes match (greedy par defaut)

Vs WAV pipeline_v3 user-confirme 'parfait' (seed=123 temp=0.8 sans rep_penalty),
le sampler v4 est generique sur tout seed/texte, plus de besoin de chercher un
seed favorable. Trade-off : on n'a plus le PRNG torch donc l'audio diffère de
PyTorch a chaque run (different trajectoire), mais reste audio TTS coherent.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 16:55:05 +02:00
Richard Loyer 746bbe77cd chantier B TTS #5: P3.3 = vrai CP runner intégré (bit-exact)
cp_inference.h/cpp : extrait de cp_runner.cpp standalone (kazeia-tts-decoder-ggml/),
adapté en module réutilisable. Architecture identique (qwen3 5L, GQA 16/8, head_dim
128, RoPE NEOX theta=1e6, q/k-norm AVANT RoPE, recompute T<=16 sans KV cache).
API : cp_load() + cp_predict(hidden[1024], cb0_emb[1024]) -> int32[15] = CB1..CB15.

cp_validate.cpp : reproduit sur tablette les conditions du standalone cp_runner
-> 495/495 codes match (33/33 frames parfaits) vs cp.generate(do_sample=False)
greedy golden, sur les 33 frames du dump 'Bonjour' historique. CP intégré =
bit-exact au standalone, qui est lui-même bit-exact à PyTorch.

tts_orchestrate.cpp mis à jour : si cp_f16.gguf/cp_heads/cp_codec_embs présents
dans <dump_dir>, le CP est ENABLED et remplace le teacher-forcing CB1..15.
Hidden state Talker capturé via llama_get_embeddings_ith(ctx,-1) après chaque
decode_embeds (pas besoin de re-instrumenter le forward Talker).

Mesure sur 'Bonjour je m'appelle Kazeia' (N=26 frames, audio 2.17s) tablette CPU 4t :
  Talker prefill (T=19) : 0.124 s
  Loop (N=26 steps)     : 7.705 s   talker_decode=0.763, cp=6.942
    per-step talker     : 29.3 ms
    per-step CP (15 pass): 267.0 ms
  Total Talker+CP       : 7.829 s -> RTF talker+cp = 3.61

Le CP est le nouveau goulot (267ms × 15 passes/step). Levier P3.5 = KV cache CP
(recompute -> incremental), threads 8, ou Q8_0 du CP.

CB0 match golden = 3/26 = trajectoire stochastique Python diverge rapidement vs
notre greedy ; PAS un bug CP (cp_validate prouve la conformité bit-exact).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 15:11:07 +02:00