From 0d4dfcc3f58ef2b7bfccead1b5e77ce717c92801 Mon Sep 17 00:00:00 2001 From: alkatrazz Date: Fri, 19 Jun 2026 21:29:38 +0200 Subject: [PATCH] =?UTF-8?q?feat(rag):=20embedder=20d=C3=A9di=C3=A9=20nomic?= =?UTF-8?q?-embed-text=20(768)=20au=20lieu=20de=20qwen3-8b?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit funk-docs utilisait le modèle de CHAT qwen3-8b (:1234, 4096 dim) comme embedder → similarités quasi indiscernables (tous les scores ~0.96, ranking médiocre). Bascule sur l'instance dédiée nomic-embed-text (:1238, 768 dim) — la même que la mémoire STT — déjà identifiée comme roadmap dans le README. rag-ingest ET rag-query alignés (même modèle/dim). Seuil rag-query abaissé 0.60→0.40 (nomic étale les scores plus bas). Collection recréée en 768. Mesure : scores désormais étalés 0.61-0.74, et les bons docs ressortent en tête (dnsmasq→dnsmasq.md, nftables→phase gateway, wedge→llama_server.md). Co-Authored-By: Claude Opus 4.8 --- ansible/roles/rag/README.md | 14 +++++++++----- ansible/roles/rag/files/rag-ingest | 9 ++++++--- ansible/roles/rag/files/rag-query | 9 ++++++--- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/ansible/roles/rag/README.md b/ansible/roles/rag/README.md index 7b4f04f..d335afa 100644 --- a/ansible/roles/rag/README.md +++ b/ansible/roles/rag/README.md @@ -15,10 +15,14 @@ Déploie la chaîne RAG sur storage-01 : scripts d'ingestion/requête + copie de |---|---| | `rag_docs_dir` | `/srv/data/rag/docs` | | `qdrant_url` | `http://127.0.0.1:6333` | -| `embed_url` | `http://192.168.10.20:1234/v1/embeddings` (llama-server GPU) | -| `embed_model` | `qwen3-8b` | +| `embed_url` | `http://192.168.10.20:1238/v1/embeddings` (instance **llama-embed** dédiée) | +| `embed_model` / dim | `nomic-embed-text` / 768 | | `rag_collection` | `funk-docs` | +> Ces valeurs sont les défauts codés dans `rag-ingest`/`rag-query` (surchargeables par env : +> `EMBED_URL`, `EMBED_MODEL`, `RAG_VECTOR_DIM`, `RAG_MIN_SCORE`, `RAG_EXCLUDE`). **`rag-ingest` +> et `rag-query` doivent utiliser le même modèle/dim**, sinon la recherche renvoie n'importe quoi. + ## Workflow après modification de `admin/` ```bash @@ -30,6 +34,6 @@ ssh storage-01 /usr/local/bin/rag-ingest # ré-in ## Caveats -- **Dépendances fortes** : Qdrant up (`:6333`) et llama-server GPU up (`:1234`) — sinon connection refused -- `rag-ingest` parcourt **tout** `/srv/data/rag/docs` y compris `hermes/builtin/` (rapports du bot) — pollution potentielle des résultats, exclusion à prévoir -- Les embeddings viennent du modèle de génération (Qwen3-8B) — un modèle d'embedding dédié (nomic-embed, bge-m3) est dans la roadmap +- **Dépendances fortes** : Qdrant up (`:6333`) et l'instance **llama-embed** up (`:1238`, `nomic-embed-text`) — sinon connection refused +- `rag-ingest` **exclut** `hermes/builtin/` (rapports auto-générés par hermes-auto-improve) via `RAG_EXCLUDE` — ils noyaient sinon la vraie doc (~84% des points) +- **Changement de modèle d'embedding** = changement de dimension → il faut **supprimer puis recréer** la collection (`curl -X DELETE …/collections/funk-docs` avant `rag-ingest`), sinon Qdrant refuse un vecteur de dim différente diff --git a/ansible/roles/rag/files/rag-ingest b/ansible/roles/rag/files/rag-ingest index 10a102a..f01e4c3 100644 --- a/ansible/roles/rag/files/rag-ingest +++ b/ansible/roles/rag/files/rag-ingest @@ -13,10 +13,13 @@ import urllib.request import urllib.error QDRANT_URL = os.environ.get("QDRANT_URL", "http://127.0.0.1:6333") -EMBED_URL = os.environ.get("EMBED_URL", "http://192.168.10.20:1234/v1/embeddings") -EMBED_MODEL = os.environ.get("EMBED_MODEL", "qwen3-8b") +# Embedder DÉDIÉ nomic-embed-text (gpu-01 :1238, dim 768) — pas le modèle de chat :1234. +# nomic est un vrai modèle d'embedding → similarités bien plus discriminantes que qwen3-8b. +# Doit rester aligné avec rag-query (même modèle/dim) et l'instance llama-embed (rôle llama_server). +EMBED_URL = os.environ.get("EMBED_URL", "http://192.168.10.20:1238/v1/embeddings") +EMBED_MODEL = os.environ.get("EMBED_MODEL", "nomic-embed-text") COLLECTION = os.environ.get("RAG_COLLECTION", "funk-docs") -VECTOR_DIM = 4096 +VECTOR_DIM = int(os.environ.get("RAG_VECTOR_DIM", "768")) CHUNK_MAX = 2000 # Dossiers (relatifs à docs_dir) exclus de l'index : rapports auto-générés par diff --git a/ansible/roles/rag/files/rag-query b/ansible/roles/rag/files/rag-query index 1ae5bc0..6426609 100644 --- a/ansible/roles/rag/files/rag-query +++ b/ansible/roles/rag/files/rag-query @@ -10,10 +10,13 @@ import os import urllib.request QDRANT_URL = os.environ.get("QDRANT_URL", "http://127.0.0.1:6333") -EMBED_URL = os.environ.get("EMBED_URL", "http://192.168.10.20:1234/v1/embeddings") -EMBED_MODEL = os.environ.get("EMBED_MODEL", "qwen3-8b") +# Doit matcher rag-ingest : embedder dédié nomic-embed-text (gpu-01 :1238, dim 768). +EMBED_URL = os.environ.get("EMBED_URL", "http://192.168.10.20:1238/v1/embeddings") +EMBED_MODEL = os.environ.get("EMBED_MODEL", "nomic-embed-text") COLLECTION = os.environ.get("RAG_COLLECTION", "funk-docs") -MIN_SCORE = 0.60 +# nomic étale les scores cosinus plus bas que qwen3-8b (qui saturait ~0.96) → seuil +# plus permissif pour ne pas écarter de bons passages. Surchargeable via RAG_MIN_SCORE. +MIN_SCORE = float(os.environ.get("RAG_MIN_SCORE", "0.40")) def _post(url, data):