Pipeline RAG
Retrieval-Augmented Generation : chunking, embedding multi-provider et recherche hybride vectorielle + BM25.
REF-SPEC/AG002-RAG v1.0 — 2026-04-09
1. Principe
Le pipeline RAG de Sailor garantit que chaque réponse est fondée sur les documents du workspace. Les documents sont découpés en chunks, vectorisés et stockés. À chaque question, les chunks pertinents sont retrouvés par recherche vectorielle (ou BM25 en fallback) et injectés dans le contexte du LLM.
2. Architecture
Document source Chunking Embedding Stockage
(PDF, Word, ──▶ ~500 mots ──▶ Mistral / ──▶ chunks
Excel, HTML) overlap 100 Voyage / BLOB
+ TF-IDF index Ollama SQLite
│
│
Prompt LLM ◀── Formatage ◀── Résolution ◀── Recherche │
(enrichi) contexte sources vectorielle │
+ citations + sources (métadonnées ou BM25 │
document) │3. Chunking
| Paramètre | Valeur | Raison |
|---|---|---|
| Taille cible | ~500 mots | Équilibre contexte et précision |
| Overlap | 100 mots | Continuité d'information entre chunks |
| Token estimation | Oui | Suivi du budget token |
| Index TF-IDF | Simultané | Pré-calcul pour fallback BM25 |
4. Embedding multi-provider
Sailor implémente une chaîne de fallback à 3 niveaux pour les embeddings :
| Priorité | Provider | Modèle | Dimensions | Rate limits |
|---|---|---|---|---|
| 1 | Mistral | mistral-embed | 1024 | Généreux |
| 2 | Voyage AI | voyage-3-lite | 1024 | Free tier limité |
| 3 | Ollama | nomic-embed-text | 768 | Illimité (local) |
Batch processing
Les embeddings sont générés par batch avec retry et backoff exponentiel :
- Batch max : dépend du provider
- Retry : 3 tentatives avec délai croissant
- Stockage : Float32Array en BLOB dans la colonne
embedding
Re-embedding
La route /api/w/:slug/reembed permet de re-vectoriser tous les chunks d'un workspace (par exemple après changement de provider).
5. Recherche vectorielle
Algorithme
1. Embedding de la question (même provider que l'indexation)
2. Chargement en mémoire de tous les chunks du workspace
3. Calcul de la similarité cosinus avec chaque chunk
4. Tri par similarité décroissante
5. Retour des top K chunks (K = 8)Similarité cosinus
similarity(a, b) = (a · b) / (|a| × |b|)Le calcul est effectué en mémoire (pas de recherche vectorielle native SQLite dans cette version).
6. Recherche BM25 (fallback)
Activée automatiquement quand les chunks n'ont pas d'embeddings :
Composants
| Composant | Description |
|---|---|
| Tokenisation | Lowercase, suppression accents, filtrage stop-words français |
| TF | Fréquence du terme dans le chunk (pré-calculé dans chunk_terms) |
| IDF | Fréquence inverse du terme dans le workspace |
| Cache IDF | Par workspace, invalidé à chaque ajout de document |
Scoring BM25
score(q, chunk) = Σ IDF(qi) × (tf(qi, chunk) × (k1 + 1)) / (tf(qi, chunk) + k1)7. Injection dans le prompt
Les chunks retrouvés sont formatés et injectés dans le prompt système :
[Source 1: "Procédure RH v2"]
Le collaborateur doit soumettre sa demande de congés
au moins 15 jours avant la date de début...
[Source 2: "Convention collective"]
L'article 12 prévoit un délai de préavis de...Instructions au LLM
Le prompt système impose :
- Répondre uniquement à partir des sources fournies
- Citer chaque source utilisée avec
[[source:DOC_ID|TITRE]] - Répondre en français
- Utiliser le markdown pour la mise en forme
- Si l'information n'est pas dans les sources : le dire explicitement
8. Performance
| Mesure | Implémentation |
|---|---|
| Vérification connectivité | Toutes les 60 secondes |
| Batch embedding | Par lots avec retry |
| Cache IDF | Par workspace, invalidé à l'ajout |
| Température LLM | 0.3 (faible, pour réponses factuelles) |
| Max tokens | 4096 (Mistral), 2048 (Ollama) |