feat(rag): syncDir — synchro corpus fichiers→base à chaque démarrage
L'auto-ingestion ne jouait qu'à base vide (1er démarrage) : une MAJ OTA du composant rag_corpus déposait les nouveaux fichiers mais le RAG continuait de servir l'ancien corpus, sans aucun déclencheur (sauf intent manuel rag_ingest). Rag.syncDir(dir) : ingère tout fichier .txt/.md absent de la base ou dont le texte diffère du brut stocké (comparaison exacte). Idempotent, n'embed que le delta → appelé à CHAQUE buildRag, remplace le cas spécial « base vide ». Ne supprime jamais (docs admin et docs retirés du dossier restent — suppression via l'admin). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
3761e03d52
commit
747848a475
|
|
@ -112,6 +112,34 @@ class Rag(
|
||||||
return total
|
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 à
|
* 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
|
* injecter, ou null si rien au-dessus du seuil. Le seuil évite d'injecter du
|
||||||
|
|
|
||||||
|
|
@ -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,
|
val emb = com.kazeia.rag.EngineEmbedder(embModel, nThreads = 4, pooling = -1,
|
||||||
queryPrefix = "query: ", passagePrefix = "passage: ", log = { m -> log(m) })
|
queryPrefix = "query: ", passagePrefix = "passage: ", log = { m -> log(m) })
|
||||||
com.kazeia.rag.Rag(this@KazeiaService, emb, "e5-small") { m -> log(m) }.also {
|
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).
|
// Synchro corpus fichiers → base à CHAQUE build (idempotent, n'embed
|
||||||
if (it.isReady && it.count() == 0 && it.listDocs().isEmpty())
|
// que le delta) : couvre le 1er démarrage ET les MAJ OTA du composant
|
||||||
it.ingestDir("${KazeiaApplication.MODELS_DIR}/../rag_corpus")
|
// 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
|
it.reingestMissing() // embed les docs admin ajoutés hors-ligne
|
||||||
rag = it
|
rag = it
|
||||||
com.kazeia.rag.RagHolder.instance = it
|
com.kazeia.rag.RagHolder.instance = it
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue