Chunking et embeddings
Découper les documents en passages exploitables, les étiqueter (dont l'ACL), les vectoriser avec un modèle multilingue sous licence libre, et estimer la mémoire des index.
L'essentiel
- Le chunking découpe chaque document en passages de quelques centaines de tokens ; c'est l'unité que l'on retrouve, que l'on cite et que l'on protège.
- Point de départ retenu (hypothèse) : découpage par structure (articles, clauses, titres) via Docling, taille cible 400 à 800 tokens, chevauchement 10 à 15 %, en gardant page et section dans les métadonnées.
- Chaque chunk porte
dossier_idetacl_groups: c'est ce qui rend le filtre de permissions possible. - Modèle d'embeddings : multilingue, sous licence MIT ou Apache 2.0, exécutable en local. Candidats : bge-m3, multilingual-e5-large, Qwen3-Embedding, nomic-embed-text v2 ; jina-embeddings-v3 est écarté (CC BY-NC) 5. Le choix se fera par mesure sur un corpus français.
- Ordre de grandeur mémoire : 1 million de chunks à 1 024 dimensions en float32 = environ 4 Go de vecteurs bruts, plus l'index. Changer de modèle d'embeddings oblige à tout réindexer.
Stratégies de chunking
| Stratégie | Principe | Avantages | Inconvénients |
|---|---|---|---|
| Taille fixe + chevauchement | N tokens, overlap de M | simple, prévisible, « the safest default » pour le splitter récursif 2 | coupe au milieu d'un article ou d'un tableau |
| Par structure | un chunk par section, article, clause, avec fusion des petits et découpe des gros | respecte le sens juridique ; citation naturelle (« Article 4 ») | dépend de la qualité du parsing ; tailles hétérogènes |
| Sémantique | coupe quand la similarité entre phrases chute | belle en théorie | coûteuse ; une étude Vectara (NAACL 2025, citée par des synthèses) trouve que la taille fixe la surpasse souvent sur documents réels 2 |
| Hybride (Docling) | hiérarchie du document puis découpe tokenization-aware (HybridChunker : max_tokens, merge_peers, repeat_table_header) 1 | combine structure et bornes de taille ; répète l'en-tête des tableaux dans chaque morceau | lié à Docling |
| Parent-enfant | on indexe de petits chunks, on renvoie au LLM le parent (section entière) | précision de recherche + contexte de lecture | double stockage ; à implémenter |
Valeurs typiques trouvées dans les sources, toutes issues d'articles d'éditeurs et non d'études peer-reviewed 2 Communauté :
- 256 à 512 tokens pour les questions factuelles ; 512 à 1 024 pour l'analyse et le multi-hop ;
- « start at 512 with 10 to 20% overlap » ;
- Open WebUI : 1 000 caractères, overlap 100, par défaut 3 ; LibreChat RAG API : 1 500 caractères, overlap 100 4. Ces défauts sont en caractères, pas en tokens (environ 4 caractères par token en français : estimation grossière).
Cas particuliers
- Tableaux : un chunk par tableau ou par groupe de lignes avec en-tête répété ; conversion en Markdown pour l'embedding.
- Mails : un chunk par message (sans le fil cité) ; le sujet et la date sont préfixés au texte pour l'embedding.
- Très courts documents (courrier d'une page) : un seul chunk.
- Enrichissement contextuel : préfixer chaque chunk d'une ligne « Dossier X, pièce Y, section Z » avant vectorisation améliore souvent la recherche (pratique répandue, non mesurée ici) ; à tester.
Métadonnées par chunk
Le schéma complet est dans ingestion. Pour la recherche et la sécurité, les champs qui doivent être indexés dans la base vectorielle sont : dossier_id (filtre principal, index de partition), acl_groups (filtre secondaire), type, date_document, langue. Les champs d'affichage (chemin, page, section, bbox, texte) sont stockés dans le payload mais pas indexés.
Modèles d'embeddings candidats
Le français juridique est le critère ; la licence et l'exécution locale sont des prérequis. Les caractéristiques ci-dessous ne sont pas issues de nos recherches sauf pour jina-embeddings-v3 ; elles sont données de mémoire et marquées à vérifier Non vérifié. Les fiches détaillées sont dans la collection modèles.
| Modèle | Éditeur | Licence | Dimensions | Contexte | Remarques |
|---|---|---|---|---|---|
| bge-m3 | BAAI | MIT (à vérifier) | 1 024 (à vérifier) | 8 192 (à vérifier) | dense + sparse + multi-vecteur dans un seul modèle ; base du reranker bge-reranker-v2-m3 ; fiche bge-m3 |
| multilingual-e5-large | Microsoft | MIT (à vérifier) | 1 024 (à vérifier) | 512 (à vérifier) | référence multilingue éprouvée ; contexte court ; nécessite les préfixes query: / passage: ; fiche multilingual-e5-large |
| Qwen3-Embedding 0.6B / 4B / 8B | Alibaba | Apache 2.0 (à vérifier) | variables selon la taille (à vérifier) | 32k (à vérifier) | famille récente, instruction-aware ; le 8B est lourd pour de l'ingestion continue ; fiche qwen3-embedding-8b |
| nomic-embed-text v2 (MoE) | Nomic | Apache 2.0 (à vérifier) | 768 (à vérifier) | 512 (à vérifier) | multilingue, poids ouverts ; à comparer |
| jina-embeddings-v3 | Jina AI | CC BY-NC 4.0 | 1 024 | 8 192 | 570 M de paramètres, 89 langues ; usage commercial on-premise sur accord seulement : écarté 5 |
| all-MiniLM-L6-v2 | sentence-transformers | Apache 2.0 | 384 | 256 | défaut d'Open WebUI 3 ; anglais : à remplacer dès le POC |
Critères de choix
- Qualité en français sur nos documents : mesurée par recall@10 et MRR sur le jeu de questions du corpus fictif, pas par un classement MTEB générique.
- Longueur de contexte : 512 tokens suffisent si les chunks font 400 à 800 tokens ; un contexte plus long n'est utile que pour le parent-enfant.
- Coût d'inférence : l'ingestion initiale vectorise des centaines de milliers de chunks ; la requête vectorise une phrase. Un modèle de 0,5 à 1 milliard de paramètres tient sur CPU en secours et sur GPU sans gêner le LLM (estimation à mesurer sur la machine candidate, voir inférence).
- Sparse natif (bge-m3) : permet une recherche hybride sans moteur BM25 séparé, ce qui pèse dans Q-004.
- Licence : MIT ou Apache 2.0 uniquement pour une Box commercialisée.
Coût mémoire des index
Calcul (estimation, arithmétique simple) : un vecteur de d dimensions en float32 pèse 4 × d octets.
| Chunks | 768 dims | 1 024 dims | 4 096 dims |
|---|---|---|---|
| 100 000 | 0,3 Go | 0,4 Go | 1,6 Go |
| 1 000 000 | 3,1 Go | 4,1 Go | 16,4 Go |
| 5 000 000 | 15,4 Go | 20,5 Go | 82 Go |
À ajouter : l'index HNSW (liens du graphe, de l'ordre de quelques dizaines de pourcents du volume des vecteurs selon m : estimation), les métadonnées et le texte des chunks (souvent plus gros que les vecteurs), l'index BM25. pgvector rappelle que l'index doit tenir en mémoire pour être performant et que maintenance_work_mem conditionne sa construction 7. Qdrant propose la quantification scalaire, binaire ou produit et le stockage on-disk, avec un claim éditeur de réduction mémoire « up to 97% » 6 Constructeur.
Pour un cabinet, l'ordre de grandeur réaliste est de quelques centaines de milliers de chunks (hypothèse) : quelques gigaoctets, négligeable face aux 60 à 90 Go du LLM sur la machine candidate. Les modèles à 4 096 dimensions (Qwen3-Embedding-8B) multiplient tout par quatre sans gain garanti : à réserver aux tests.
Réindexation
Changer de modèle d'embeddings, de taille de chunk ou de parseur oblige à tout revectoriser : les vecteurs de deux modèles ne sont pas comparables. Prévoir dès le départ :
- une version de pipeline stockée dans chaque chunk (
pipeline_version) ; - une réindexation en double : nouvelle collection construite en arrière-plan, bascule atomique, ancienne conservée le temps de vérifier, puis supprimée ;
- une fenêtre de maintenance : sur CPU, revectoriser un million de chunks prend des heures (à mesurer) ; sur GPU, cela entre en concurrence avec le LLM ;
- le jeu d'évaluation rejoué avant bascule.
Questions ouvertes
Ce qu'il reste à tester
Sources
- 1Docling — README et documentation chunking (MIT, HybridChunker)GitHubFiabilité hauteDocling / IBM Research / LF AI & Data · publié v2.127.0, 14/09/2026 · consulté le 16 sept. 2026 · fiche source
- 2Stratégies de chunking pour le RAG (synthèses 2026)Article techniqueFiabilité moyenneFirecrawl / Prem AI · publié 2026 · consulté le 16 sept. 2026 · fiche source
- 3Open WebUI — variables d'environnement (docs + config.py)Documentation officielleFiabilité hauteOpen WebUI · publié lu le 16/09/2026 (main) · consulté le 16 sept. 2026 · fiche source
- 4LibreChat — RAG API (PostgreSQL + pgvector)Documentation officielleFiabilité hauteLibreChat · publié lu le 16/09/2026 · consulté le 16 sept. 2026 · fiche source
- 5Jina AI — jina-embeddings-v3 (annonce et licence CC BY-NC 4.0)Constructeur / éditeurFiabilité hauteJina AI · publié 2024-09 · consulté le 16 sept. 2026 · fiche source
- 6Qdrant — README et releases (Apache 2.0, v1.19.1)GitHubFiabilité hauteQdrant · publié v1.19.1, 04/09/2026 · consulté le 16 sept. 2026 · fiche source
- 7pgvector — README (filtrage, HNSW, iterative scan 0.8.0)GitHubFiabilité hautepgvector · publié v0.8.6 (README) ; 0.8.0 annoncé sur postgresql.org · consulté le 16 sept. 2026 · fiche source
- 8OWASP Top 10 for LLM Applications 2025 — LLM08 Vector and Embedding WeaknessesDocumentation officielleFiabilité hauteOWASP GenAI Security Project · publié mars 2025 · consulté le 16 sept. 2026 · fiche source