diff --git a/kazeia-android/app/src/main/java/com/kazeia/rag/Rag.kt b/kazeia-android/app/src/main/java/com/kazeia/rag/Rag.kt index 35e6a51..45147f9 100644 --- a/kazeia-android/app/src/main/java/com/kazeia/rag/Rag.kt +++ b/kazeia-android/app/src/main/java/com/kazeia/rag/Rag.kt @@ -112,6 +112,34 @@ class Rag( return total } + /** + * Synchronise le corpus FICHIERS → base : ingère tout fichier .txt/.md absent + * de la base ou dont le texte a changé (comparaison exacte sur le brut stocké). + * Idempotent et incrémental : n'embed que le delta → appelé à CHAQUE buildRag, + * c'est ce qui fait qu'une mise à jour OTA du composant rag_corpus est prise + * en compte au redémarrage suivant (sans intent manuel). Ne supprime jamais : + * les docs admin (hors fichiers) et les docs retirés du dossier restent — + * suppression via l'admin. NB : si l'admin a édité un doc PORTANT LE NOM d'un + * fichier seed, le fichier regagne au redémarrage (les ajouts admin doivent + * utiliser des noms propres, pas écraser le seed). + */ + @Synchronized + fun syncDir(dir: String): Int { + val d = java.io.File(dir) + if (!d.isDirectory) { log("syncDir: '$dir' absent"); return 0 } + val files = d.listFiles { f -> f.isFile && (f.name.endsWith(".txt") || f.name.endsWith(".md")) } + ?.sortedBy { it.name } ?: emptyList() + var changed = 0 + for (f in files) { + val txt = try { f.readText() } catch (e: Exception) { log("syncDir: lecture ${f.name} échec"); continue } + val src = f.nameWithoutExtension + if (db.docText(src) == txt) continue // déjà à jour → zéro embed + ingest(src, txt); changed++ + } + if (changed > 0) log("syncDir '$dir': $changed doc(s) (ré)ingéré(s) sur ${files.size}") + return changed + } + /** * Récupère le contexte pertinent pour [query] et le formate en bloc prêt à * injecter, ou null si rien au-dessus du seuil. Le seuil évite d'injecter du 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 209c4f9..74ac00a 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 @@ -2077,9 +2077,11 @@ Pas d'introduction, pas d'explication. Juste les 4 lignes en francais. /no_think val emb = com.kazeia.rag.EngineEmbedder(embModel, nThreads = 4, pooling = -1, queryPrefix = "query: ", passagePrefix = "passage: ", log = { m -> log(m) }) com.kazeia.rag.Rag(this@KazeiaService, emb, "e5-small") { m -> log(m) }.also { - // Auto-ingestion du corpus seed au 1er démarrage (base + docs vides). - if (it.isReady && it.count() == 0 && it.listDocs().isEmpty()) - it.ingestDir("${KazeiaApplication.MODELS_DIR}/../rag_corpus") + // Synchro corpus fichiers → base à CHAQUE build (idempotent, n'embed + // 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.reingestMissing() // embed les docs admin ajoutés hors-ligne rag = it com.kazeia.rag.RagHolder.instance = it