diff --git a/kazeia-android/app/src/main/java/com/kazeia/config/ConfigStore.kt b/kazeia-android/app/src/main/java/com/kazeia/config/ConfigStore.kt index 6228bf0..33ad3a7 100644 --- a/kazeia-android/app/src/main/java/com/kazeia/config/ConfigStore.kt +++ b/kazeia-android/app/src/main/java/com/kazeia/config/ConfigStore.kt @@ -71,16 +71,11 @@ class ConfigStore private constructor(private val file: File) { * modèle effectif est choisi par `speaker.modelId` (ModelRegistry). Champ * conservé pour compat config/télémétrie. */ val llmEngine: String = "lib", - /** Backend TTS : "lib" = libkazeia_tts unifié (SEUL compatible avec le - * libllama.so fork ql embarqué depuis 2026-06-02), "prod" = Qwen3TtsEngine - * legacy — CRASHE (SIGSEGV nativeInit, dérive ABI llama_context_params) tant - * que les .so legacy ne sont pas recompilés contre les headers fork ql. - * "cosyvoice" = CosyVoiceTtsEngine (clonage vocal 9 langues, CPU-only) — - * câblé mais NON activable tant que la collision libggml des libs livrées - * n'est pas levée côté engine (cf CosyVoiceTtsEngine.kt). - * Default "lib" depuis 2026-06-11 : l'ancien défaut "prod" mettait toute - * install fraîche en crash-loop au démarrage du service. */ - val ttsEngine: String = "lib", + /** Backend TTS : "cosyvoice" = CosyVoiceTtsEngine (clonage vocal 9 langues, + * CPU-only) = SEUL moteur depuis la bascule 2026-06-18 (legacy Qwen3-TTS/lib + * retirés). Champ conservé pour compat config ; KazeiaService ne charge que + * CosyVoice. */ + val ttsEngine: String = "cosyvoice", /** RAG (récupération de contexte injecté au prompt). Default OFF : tant que * kazeia-engine n'expose pas embedText + qu'aucun corpus n'est ingéré, * l'activer est inerte (l'embedder n'est pas prêt). Pilotable via admin. */ diff --git a/kazeia-android/app/src/main/java/com/kazeia/llm/EngineLlmEngine.kt b/kazeia-android/app/src/main/java/com/kazeia/llm/EngineLlmEngine.kt index d69545b..289f69c 100644 --- a/kazeia-android/app/src/main/java/com/kazeia/llm/EngineLlmEngine.kt +++ b/kazeia-android/app/src/main/java/com/kazeia/llm/EngineLlmEngine.kt @@ -22,15 +22,7 @@ class EngineJni { external fun sessionReset(h: Long) // repart du checkpoint système external fun getLastStats(h: Long): LongArray // [prefill_ms, decode_ms, n_tokens] - // -- TTS Talker (Qwen3-TTS) : I/O en embeddings, pas en tokens (vocab=3072 codes audio, pas de BPE). - // Le caller (cf. TalkerEngine.kt) construit les embeds de prefill (text+x-vector) et de step - // (sum 16 codecs + tts_pad + trailing_text_hidden), fait l'échantillonnage, et compose le - // pipeline Talker→CP→Decoder. Retours conventionnels : 0 = OK, négatif = erreur. - external fun nEmbd(h: Long): Int // taille d'un embed (1024 pour Talker-0.6B) - external fun nVocab(h: Long): Int // 3072 pour le Talker - external fun resetEmbeds(h: Long) // KV clear + pos=0, à appeler en début de génération TTS - external fun prefillEmbeds(h: Long, embdFlat: FloatArray, t: Int, outHidden: FloatArray): Int - external fun decodeEmbed(h: Long, embd: FloatArray, outLogits: FloatArray, outHidden: FloatArray): Int + // (Bindings TTS-Talker Qwen3-TTS retirés 2026-06-18 : TTS = CosyVoice, lib dédiée.) // -- Embeddings (RAG) : modèle dédié BERT-like (e5/bge), handle SÉPARÉ du LLM/TTS, CPU pur. // pooling: -1 = défaut du modèle (recommandé) ; 1 = MEAN (e5) ; 2 = CLS (bge). diff --git a/kazeia-android/app/src/main/java/com/kazeia/service/KazeiaService.kt b/kazeia-android/app/src/main/java/com/kazeia/service/KazeiaService.kt index dd498ec..b1c37aa 100644 --- a/kazeia-android/app/src/main/java/com/kazeia/service/KazeiaService.kt +++ b/kazeia-android/app/src/main/java/com/kazeia/service/KazeiaService.kt @@ -54,14 +54,9 @@ class KazeiaService : Service() { Pas d'introduction, pas d'explication. Juste les 4 lignes en francais. /no_think""" } - private lateinit var llm: LlmEngine - // Cascade Option E v2 : 2 ExecuTorchLlmEngine cohabitants in-process. - // - llm = Speaker Qwen3-4B (.pte ~3.3 GB ION, ~4.4 GB total) - // - thinkerEngine = Guard-0.6B (.pte ~700 MB ION) lazy-loaded au 1er PTT - // Total ION ~5.1 GB, marge OK pour TTS pic. QnnBackendUnifiedRegistry - // singleton partage le QnnBackendBundle (handle fastrpc DSP) entre les 2 - // contextes — pas de collision DSP, pas de subprocess. Cf - // project_kazeia_cascade_option_e dans la mémoire persistante. + private lateinit var llm: LlmEngine // Speaker (UnifiedLlmAdapter : GGUF défaut ou .pte) + // Cascade (off par défaut) : 2ᵉ moteur Thinker via UnifiedLlmAdapter, + // lazy au 1er tour (défaut Guard-4B .pte). nThreads réduit pour le Speaker. private var thinkerEngine: com.kazeia.llm.UnifiedLlmAdapter? = null private val thinkerLock = Object() @@ -208,10 +203,9 @@ Pas d'introduction, pas d'explication. Juste les 4 lignes en francais. /no_think val loadingState: StateFlow = _loadingState /** - * Cascade E v2 : crée la 2ᵉ ExecuTorchLlmEngine (Thinker = Guard-0.6B) dans - * le MÊME process app. Lazy au 1er PTT (~1-2 s de load 0.6B). Le - * QnnBackendUnifiedRegistry singleton réutilise le QnnBackendBundle du - * Speaker → un seul handle fastrpc DSP, 2 contextes/graphes coexistent. + * Cascade : crée le 2ᵉ moteur (Thinker, défaut Guard-4B .pte NPU) via + * UnifiedLlmAdapter dans le même process, lazy au 1er tour. Off par défaut + * (cascadeEnabled=false). nThreads réduit pour laisser des cœurs au Speaker. */ private fun ensureThinkerEngine() { synchronized(thinkerLock) { @@ -699,7 +693,6 @@ Pas d'introduction, pas d'explication. Juste les 4 lignes en francais. /no_think * ../voix/.wav. Hot-swap : effet au prochain segment synthétisé. */ fun setVoiceId(voiceId: String) { currentVoiceName = voiceId - val wavPath = "${KazeiaApplication.MODELS_DIR}/../voix/$voiceId.wav" when (val e = tts) { is com.kazeia.tts.CosyVoiceTtsEngine -> { e.setVoice(voiceId); log("Voix (cosyvoice): $voiceId") } else -> log("setVoiceId: moteur TTS inconnu — voix '$voiceId' ignorée") @@ -1526,11 +1519,7 @@ Pas d'introduction, pas d'explication. Juste les 4 lignes en francais. /no_think // as soon as the user finishes speaking, covering the LLM's TTFT. addMessage(bubble) val llmStreamStart = System.currentTimeMillis() - val sentenceCounter = java.util.concurrent.atomic.AtomicInteger(0) - // TTS coupé (llmOnly) → pas de session de synthèse ouverte ; la bulle - // se remplit token par token dans onToken (voir plus bas). - // Streaming LLM→TTS réservé à Qwen3 (NPU/Hexagon : pas de contention CPU avec - // le LLM). CosyVoice (CPU) passe par le chemin batch (voir note plus haut). + // TTS coupé (llmOnly) → pas de session ; la bulle se remplit token par token. // CosyVoice (CPU) : pas de streaming LLM→TTS (contention CPU). Le LLM décode // vite, puis synthèse batch via pipeline.speakText (qui streame déjà // phrase-par-phrase EN INTERNE). ttsStreamer reste donc null. diff --git a/kazeia-android/app/src/main/java/com/kazeia/ui/AudioVisualizerView.kt b/kazeia-android/app/src/main/java/com/kazeia/ui/AudioVisualizerView.kt index 9e831ee..482bfda 100644 --- a/kazeia-android/app/src/main/java/com/kazeia/ui/AudioVisualizerView.kt +++ b/kazeia-android/app/src/main/java/com/kazeia/ui/AudioVisualizerView.kt @@ -53,7 +53,7 @@ class AudioVisualizerView @JvmOverloads constructor( ) : View(context, attrs, defStyleAttr), Choreographer.FrameCallback { companion object { - /** Must match Qwen3TtsEngine.SPECTRUM_BANDS. Asserted at setSpeaking. */ + /** Nombre de bandes de spectre de l'orbe (visualiseur). */ private const val SPECTRUM_BANDS = 12 /** Listening-mode outline deformation modes (even = smooth blobs). */ private const val BLOB_MODES = 8