feat(rag): valider EngineEmbedder e5 in-app (E2E réel) + préfixe passage
Le dev kazeia-engine a livré le bridge CPU-only avec embedText (commit engine 655d65a) + un GGUF multilingual-e5-small fonctionnel (converter patché pour le tokenizer XLM-R/unigram). Bridge swappé dans jniLibs (ABI cohérente : libllama/ libggml déjà = build CPU-only du 2 juin). - Rag.ingest : les passages portent désormais le préfixe "passage: " (e5), en symétrie du "query: " de retrieve (EngineEmbedder.embedPassage). - Intent `rag_real_test` : valide le VRAI EngineEmbedder (e5) in-app. Validé device (CPU-only, untrusted_app) : embedder ready=true dim=384, AUCUN crash SELinux/fastrpc (la .so ne tire plus hexagon), retrieval FR correct — requête sommeil → doc insomnie en tête (top=0.88). embedText fonctionne in-app end-to-end. Le .so (gitignored) est un artefact build, hors git. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
3eab29beb2
commit
95a7a25335
|
|
@ -48,7 +48,10 @@ class Rag(
|
|||
val chunks = Chunker.chunk(rawText, source)
|
||||
var n = 0
|
||||
for ((i, ch) in chunks.withIndex()) {
|
||||
val v = embedder.embed(ch) ?: continue
|
||||
// e5 : les passages doivent porter le préfixe "passage: " (symétrique au
|
||||
// "query: " de retrieve). EngineEmbedder.embedPassage le gère ; le fallback
|
||||
// FakeEmbedder embed() sans préfixe (symétrique aussi).
|
||||
val v = (embedder as? EngineEmbedder)?.embedPassage(ch) ?: embedder.embed(ch) ?: continue
|
||||
db.insert(source, i, ch, modelTag, v); n++
|
||||
}
|
||||
log("ingest '$source': $n chunks")
|
||||
|
|
|
|||
|
|
@ -637,6 +637,29 @@ Pas d'introduction, pas d'explication. Juste les 4 lignes en francais. /no_think
|
|||
} catch (e: Exception) { log("RAG test error: ${e.message}"); e.printStackTrace() }
|
||||
}
|
||||
}
|
||||
intent?.getStringExtra("rag_real_test")?.let { query ->
|
||||
// Valide le VRAI EngineEmbedder in-app (e5-small via kazeia-engine CPU-only) :
|
||||
// prouve loadEmbedder/embedText sans crash SELinux + retrieval FR réel.
|
||||
log("RAG real test: '$query'")
|
||||
serviceScope.launch {
|
||||
try {
|
||||
val embModel = "${KazeiaApplication.MODELS_DIR}/embed-e5-small.gguf"
|
||||
val emb = com.kazeia.rag.EngineEmbedder(embModel, nThreads = 4, pooling = -1,
|
||||
queryPrefix = "query: ", passagePrefix = "passage: ", log = { m -> log(m) })
|
||||
log("RAG real: embedder ready=${emb.isReady} dim=${emb.dim}")
|
||||
if (!emb.isReady) { log("RAG real: embedder NON prêt — abort"); return@launch }
|
||||
val rag = com.kazeia.rag.Rag(this@KazeiaService, emb, "e5-small") { m -> log(m) }
|
||||
rag.clear()
|
||||
rag.ingest("insomnie", "L'insomnie est un trouble du sommeil fréquent. Pour mieux dormir, évitez les écrans le soir et gardez une heure de coucher régulière.")
|
||||
rag.ingest("solitude", "Le sentiment de solitude peut être douloureux. Renouer un petit lien social, même bref, aide beaucoup.")
|
||||
rag.ingest("respiration", "La respiration lente et profonde calme l'anxiété : inspirez quatre secondes, expirez six secondes, répétez.")
|
||||
rag.loadIndex()
|
||||
val ctx = rag.retrieve(query)
|
||||
log("RAG real RESULT (corpus=${rag.count()}):\n${ctx ?: "(rien au-dessus du seuil)"}")
|
||||
emb.close()
|
||||
} catch (e: Exception) { log("RAG real test error: ${e.message}"); e.printStackTrace() }
|
||||
}
|
||||
}
|
||||
if (intent?.hasExtra("cfg_set") == true) {
|
||||
// Maintenance/bench : persiste engine+model+prompt sans passer par le
|
||||
// ContentProvider CLI (qui casse sur les valeurs contenant ':'). Les
|
||||
|
|
|
|||
Loading…
Reference in New Issue