feat: anti-loop guards + KV cache configurabile
Docker / build (cpu, cpu) (push) Canceled after 0s
Docker / build (nvidia/cuda:12.9.2-devel-ubuntu22.04, nvidia/cuda:12.9.2-runtime-ubuntu22.04, cuda, cuda12) (push) Canceled after 0s
Docker / build (nvidia/cuda:13.3.1-devel-ubuntu22.04, nvidia/cuda:13.3.1-runtime-ubuntu22.04, cuda, cuda13) (push) Canceled after 0s
Docker / build (vulkan, vulkan) (push) Canceled after 0s

Prevenzione allucinazioni/loop infiniti (Qwen3-TTS autoregressivo):
- block_repeated_ngrams: maschera i token che ricreerebbero un n-gram gia visto (n=4)
- has_repeating_cycle: ferma la generazione su cicli periodici (periodo 1-16, 4 ripetizioni)
- stuck detector: token dominante nella finestra recente (4 occorrenze in 8 token)
- fallback EOS quando tutti i logits sono mascherati (evita NaN)
- KV cache talker configurabile (--kv-cache, default 8192): 4096 overflowava con
  reference lunghe + testi lunghi ("decode would overflow cache")
- parametri esposti via API (no_repeat_ngram_size, loop_max_period, loop_repeats,
  loop_window) e CLI (--no-repeat-ngram, --loop-period, --loop-repeats, --loop-window)
- Docker: TTS_KV_CACHE env (default 8192)

Validato: testo 2788 char che prima degenerava in loop ora sintetizza pulito
(141s via API, nessuna ripetizione).
This commit is contained in:
enne2
2026-08-18 15:10:02 +02:00
parent 18742ea656
commit 7942e61b3a
11 changed files with 250 additions and 10 deletions
+6 -1
View File
@@ -223,6 +223,7 @@ void qt_init_default_params(struct qt_init_params * p) {
p->use_fa = true;
p->clamp_fp16 = false;
p->max_batch = 1;
p->talker_kv_size = 8192;
p->codec_chunk_sec = QT_CODEC_CHUNK_SEC_DEFAULT;
}
@@ -247,6 +248,10 @@ void qt_tts_default_params(struct qt_tts_params * p) {
p->subtalker_temperature = 0.9f;
p->subtalker_top_k = 50;
p->subtalker_top_p = 1.0f;
p->no_repeat_ngram_size = 4;
p->loop_max_period = 16;
p->loop_repeats = 4;
p->loop_window = 64;
p->dump_dir = nullptr;
p->cancel = nullptr;
p->cancel_user_data = nullptr;
@@ -362,7 +367,7 @@ struct qt_context * qt_init(const struct qt_init_params * params) {
}
if (!pipeline_tts_load(&q->pt, params->talker_path, params->codec_path, q->bp, params->use_fa,
params->clamp_fp16, max_batch, chunk_sec)) {
params->clamp_fp16, max_batch, chunk_sec, params->talker_kv_size)) {
qt_throw("qt_init: pipeline_tts_load failed for '%s' / '%s'", params->talker_path, params->codec_path);
}