fix: défaut ttsEngine="lib" (crash-loop install fraîche) + ragCorpusDir externe-d'abord — v0.1.3
Deux bugs de prod trouvés en validant le cycle OTA corpus r2 : 1. ttsEngine default "prod" → toute install fraîche (release patient) chargeait Qwen3TtsEngine legacy → SIGSEGV déterministe dans llama_context ctor (libtts_talker_cpu compilé contre llama-upstream, libllama.so embarqué = fork ql depuis 2026-06-02, dérive ABI llama_context_params). La tablette release crash-loopait au démarrage du service depuis la migration ; la tablette dev ne le voyait pas (config tts_engine=lib persistée). → default "lib" (seul backend compatible avec les jniLibs livrés). 2. Le corpus RAG était résolu via MODELS_DIR/../rag_corpus : sur tablette dev, MODELS_DIR = legacy /data/local/tmp (modèles adb) → syncDir lisait l'ancien corpus alors que l'OTA dépose le composant rag_corpus dans le stockage externe. → KazeiaPaths.ragCorpusDir avec priorité INVERSE des modèles : l'externe (installeur/OTA) prime dès qu'il est non vide, fallback legacy. versionCode 4 / 0.1.3, publié catalog v6. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
747848a475
commit
16d56bfd4d
|
|
@ -44,8 +44,8 @@ android {
|
|||
applicationId = "com.kazeia"
|
||||
minSdk = 28
|
||||
targetSdk = 36
|
||||
versionCode = 2
|
||||
versionName = "0.1.1"
|
||||
versionCode = 4
|
||||
versionName = "0.1.3"
|
||||
|
||||
// WebDAV de distribution — injecté depuis local.properties.
|
||||
buildConfigField("String", "WEBDAV_BASE", "\"${localProp("webdav.base")}\"")
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ object KazeiaPaths {
|
|||
|
||||
private const val LEGACY_MODELS = "/data/local/tmp/kazeia/models"
|
||||
private const val LEGACY_LLM = "/data/local/tmp/kazeia-et"
|
||||
private const val LEGACY_RAG = "/data/local/tmp/kazeia/rag_corpus"
|
||||
|
||||
/** Racine modèles STT/TTS (Whisper, GGUF, qwen3-tts-npu ; voix via `/../`). */
|
||||
@Volatile var modelsDir: String = LEGACY_MODELS
|
||||
|
|
@ -35,6 +36,13 @@ object KazeiaPaths {
|
|||
@Volatile var llmDir: String = LEGACY_LLM
|
||||
private set
|
||||
|
||||
/** Corpus RAG. Priorité INVERSE des modèles : l'EXTERNE prime dès qu'il est
|
||||
* non vide, car c'est là que l'installeur/OTA dépose le composant
|
||||
* `rag_corpus` — sur une tablette dev, les modèles restent legacy mais le
|
||||
* corpus à jour arrive par le catalogue. Fallback legacy (adb push) sinon. */
|
||||
@Volatile var ragCorpusDir: String = LEGACY_RAG
|
||||
private set
|
||||
|
||||
@Volatile private var initialized = false
|
||||
|
||||
/**
|
||||
|
|
@ -50,8 +58,9 @@ object KazeiaPaths {
|
|||
val root = File(context.getExternalFilesDir(null), "kazeia")
|
||||
modelsDir = resolve(File(root, "models"), File(LEGACY_MODELS))
|
||||
llmDir = resolve(File(root, "llm"), File(LEGACY_LLM))
|
||||
ragCorpusDir = resolveExternalFirst(File(root, "rag_corpus"), File(LEGACY_RAG))
|
||||
initialized = true
|
||||
Log.i(TAG, "modelsDir=$modelsDir | llmDir=$llmDir")
|
||||
Log.i(TAG, "modelsDir=$modelsDir | llmDir=$llmDir | ragCorpusDir=$ragCorpusDir")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -61,4 +70,11 @@ object KazeiaPaths {
|
|||
legacy.absolutePath
|
||||
else
|
||||
external.absolutePath
|
||||
|
||||
/** Externe si non vide (déposé par l'installeur/OTA), sinon legacy (adb push). */
|
||||
private fun resolveExternalFirst(external: File, legacy: File): String =
|
||||
if (external.isDirectory && !external.list().isNullOrEmpty())
|
||||
external.absolutePath
|
||||
else
|
||||
legacy.absolutePath
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,10 +44,13 @@ class ConfigStore private constructor(private val file: File) {
|
|||
* EngineLlmAdapter (libkazeia_engine + GGUF Qwen3.5). Defaults safe = "prod".
|
||||
* Bascule "lib" nécessite libllama.so fork ql dans jniLibs. */
|
||||
val llmEngine: String = "prod",
|
||||
/** Backend TTS : "prod" = Qwen3TtsEngine legacy, "lib" = libkazeia_tts unifié.
|
||||
* Defaults safe = "prod". Bascule "lib" nécessite libllama.so fork ql + retrait
|
||||
* des classes legacy `tts_talker_cpu`/`tts_cp_cpu` (incompat ABI struct). */
|
||||
val ttsEngine: String = "prod",
|
||||
/** 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.
|
||||
* 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",
|
||||
/** 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. */
|
||||
|
|
@ -113,7 +116,7 @@ class ConfigStore private constructor(private val file: File) {
|
|||
ttsEnabled = true,
|
||||
sttEngine = "prod",
|
||||
llmEngine = "prod",
|
||||
ttsEngine = "prod"
|
||||
ttsEngine = "lib" // legacy "prod" = SIGSEGV avec le libllama fork ql embarqué
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -668,7 +668,7 @@ Pas d'introduction, pas d'explication. Juste les 4 lignes en francais. /no_think
|
|||
intent?.getStringExtra("rag_ingest")?.let { dirArg ->
|
||||
// (Ré)ingestion du corpus dans l'instance RAG live : clear + ingestDir.
|
||||
// dirArg vide -> dossier corpus par défaut. Brique de l'app admin future.
|
||||
val dir = dirArg.ifBlank { "${KazeiaApplication.MODELS_DIR}/../rag_corpus" }
|
||||
val dir = dirArg.ifBlank { com.kazeia.KazeiaPaths.ragCorpusDir }
|
||||
log("RAG ingest: $dir")
|
||||
serviceScope.launch {
|
||||
val r = rag
|
||||
|
|
@ -2081,7 +2081,7 @@ Pas d'introduction, pas d'explication. Juste les 4 lignes en francais. /no_think
|
|||
// que le delta) : couvre le 1er démarrage ET les MAJ OTA du composant
|
||||
// rag_corpus (nouveaux fichiers ingérés au redémarrage suivant).
|
||||
if (it.isReady)
|
||||
it.syncDir("${KazeiaApplication.MODELS_DIR}/../rag_corpus")
|
||||
it.syncDir(com.kazeia.KazeiaPaths.ragCorpusDir)
|
||||
it.reingestMissing() // embed les docs admin ajoutés hors-ligne
|
||||
rag = it
|
||||
com.kazeia.rag.RagHolder.instance = it
|
||||
|
|
|
|||
Loading…
Reference in New Issue