# Schéma Weaviate - Library RAG ## Architecture globale Le schéma suit une architecture normalisée avec des objets imbriqués (nested objects) pour un accès efficace aux données. ``` Work (métadonnées uniquement) └── Document (instance d'édition/traduction) ├── Chunk (fragments de texte vectorisés) └── Summary (résumés de chapitres vectorisés) ``` --- ## Collections ### 1. Work (Œuvre) **Description** : Représente une œuvre philosophique ou académique (ex: Ménon de Platon) **Vectorisation** : ✅ **text2vec-transformers** (depuis migration 2026-01) **Champs vectorisés** : - ✅ `title` (TEXT) - Titre de l'œuvre (permet recherche sémantique "dialogues socratiques" → Ménon) - ✅ `author` (TEXT) - Auteur (permet recherche "philosophie analytique" → Haugeland) **Champs NON vectorisés** : - `originalTitle` (TEXT) [skip_vec] - Titre original dans la langue source (optionnel) - `year` (INT) - Année de composition/publication (négatif pour avant J.-C.) - `language` (TEXT) [skip_vec] - Code ISO de langue originale (ex: 'gr', 'la', 'fr') - `genre` (TEXT) [skip_vec] - Genre ou type (ex: 'dialogue', 'traité', 'commentaire') **Note** : Collection actuellement vide (0 objets) mais prête pour migration. Voir `migrate_add_work_collection.py` pour ajouter la vectorisation sans perdre les 5,404 chunks existants. --- ### 2. Document (Édition) **Description** : Instance spécifique d'une œuvre (édition, traduction) **Vectorisation** : AUCUNE (métadonnées uniquement) **Propriétés** : - `sourceId` (TEXT) - Identifiant unique (nom de fichier sans extension) - `edition` (TEXT) - Édition ou traducteur (ex: 'trad. Cousin') - `language` (TEXT) - Langue de cette édition - `pages` (INT) - Nombre de pages du PDF/document - `chunksCount` (INT) - Nombre total de chunks extraits - `toc` (TEXT) - Table des matières en JSON `[{title, level, page}, ...]` - `hierarchy` (TEXT) - Structure hiérarchique complète en JSON - `createdAt` (DATE) - Timestamp d'ingestion **Objets imbriqués** : - `work` (OBJECT) - `title` (TEXT) - `author` (TEXT) --- ### 3. Chunk (Fragment de texte) ⭐ **PRINCIPAL** **Description** : Fragments de texte optimisés pour la recherche sémantique (200-800 caractères) **Vectorisation** : `text2vec-transformers` (BAAI/bge-m3, 1024 dimensions) **Champs vectorisés** : - ✅ `text` (TEXT) - Contenu textuel du chunk - ✅ `keywords` (TEXT_ARRAY) - Concepts clés extraits **Champs NON vectorisés** (filtrage uniquement) : - `sectionPath` (TEXT) [skip_vec] - Chemin hiérarchique complet - `sectionLevel` (INT) - Profondeur dans la hiérarchie (1=niveau supérieur) - `chapterTitle` (TEXT) [skip_vec] - Titre du chapitre parent - `canonicalReference` (TEXT) [skip_vec] - Référence académique (ex: 'CP 1.628', 'Ménon 80a') - `unitType` (TEXT) [skip_vec] - Type d'unité logique (main_content, argument, exposition, etc.) - `orderIndex` (INT) - Position séquentielle dans le document (base 0) - `language` (TEXT) [skip_vec] - Langue du chunk **Objets imbriqués** : - `document` (OBJECT) - `sourceId` (TEXT) - `edition` (TEXT) - `work` (OBJECT) - `title` (TEXT) - `author` (TEXT) --- ### 4. Summary (Résumé de section) **Description** : Résumés LLM de chapitres/sections pour recherche de haut niveau **Vectorisation** : `text2vec-transformers` (BAAI/bge-m3, 1024 dimensions) **Champs vectorisés** : - ✅ `text` (TEXT) - Résumé généré par LLM - ✅ `concepts` (TEXT_ARRAY) - Concepts philosophiques clés **Champs NON vectorisés** : - `sectionPath` (TEXT) [skip_vec] - Chemin hiérarchique - `title` (TEXT) [skip_vec] - Titre de la section - `level` (INT) - Profondeur (1=chapitre, 2=section, 3=sous-section) - `chunksCount` (INT) - Nombre de chunks dans cette section **Objets imbriqués** : - `document` (OBJECT) - `sourceId` (TEXT) --- ## Stratégie de vectorisation ### Modèle utilisé - **Nom** : BAAI/bge-m3 - **Dimensions** : 1024 - **Contexte** : 8192 tokens - **Support multilingue** : Grec, Latin, Français, Anglais ### Migration (Décembre 2024) - **Ancien modèle** : MiniLM-L6 (384 dimensions, 512 tokens) - **Nouveau modèle** : BAAI/bge-m3 (1024 dimensions, 8192 tokens) - **Gains** : - 2.7x plus riche en représentation sémantique - Meilleur support multilingue - Meilleure performance sur textes philosophiques/académiques ### Champs vectorisés Seuls ces champs sont vectorisés pour la recherche sémantique : - `Chunk.text` ✅ - `Chunk.keywords` ✅ - `Summary.text` ✅ - `Summary.concepts` ✅ ### Champs de filtrage uniquement Tous les autres champs utilisent `skip_vectorization=True` pour optimiser les performances de filtrage sans gaspiller la capacité vectorielle. --- ## Objets imbriqués (Nested Objects) Au lieu d'utiliser des cross-references Weaviate, le schéma utilise des **objets imbriqués** pour : 1. **Éviter les jointures** - Récupération en une seule requête 2. **Dénormaliser les données** - Performance de lecture optimale 3. **Simplifier les requêtes** - Logique de requête plus simple ### Exemple de structure Chunk ```json { "text": "La justice est une vertu...", "keywords": ["justice", "vertu", "cité"], "sectionPath": "Livre I > Chapitre 2", "work": { "title": "La République", "author": "Platon" }, "document": { "sourceId": "platon_republique", "edition": "trad. Cousin" } } ``` ### Trade-off - ✅ **Avantage** : Requêtes rapides, pas de jointures - ⚠️ **Inconvénient** : Petite duplication de données (acceptable pour métadonnées) --- ## Contenu actuel (au 01/01/2026) **Dernière vérification** : 1er janvier 2026 via `verify_vector_index.py` ### Statistiques par collection | Collection | Objets | Vectorisé | Utilisation | |------------|--------|-----------|-------------| | **Chunk** | **5,404** | ✅ Oui | Recherche sémantique principale | | **Summary** | **8,425** | ✅ Oui | Recherche hiérarchique (chapitres/sections) | | **Document** | **16** | ❌ Non | Métadonnées d'éditions | | **Work** | **0** | ✅ Oui* | Métadonnées d'œuvres (vide, prêt pour migration) | **Total vecteurs** : 13,829 (5,404 chunks + 8,425 summaries) **Ratio Summary/Chunk** : 1.56 (plus de summaries que de chunks, bon pour recherche hiérarchique) \* *Work est configuré avec vectorisation (depuis migration 2026-01) mais n'a pas encore d'objets* ### Documents indexés Les 16 documents incluent probablement : - Collected Papers of Charles Sanders Peirce (édition Harvard) - Platon - Ménon (trad. Cousin) - Haugeland - Mind Design III - Claudine Tiercelin - La pensée-signe - Peirce - La logique de la science - Peirce - On a New List of Categories - Arendt - Between Past and Future - AI: The Very Idea (Haugeland) - ... et 8 autres documents **Note** : Pour obtenir la liste exacte et les statistiques par document : ```bash python verify_vector_index.py ``` --- ## Configuration Docker Le schéma est déployé via `docker-compose.yml` avec : - **Weaviate** : localhost:8080 (HTTP), localhost:50051 (gRPC) - **text2vec-transformers** : Module de vectorisation avec BAAI/bge-m3 - **GPU support** : Optionnel pour accélérer la vectorisation ### Commandes utiles ```bash # Démarrer Weaviate docker compose up -d # Vérifier l'état curl http://localhost:8080/v1/.well-known/ready # Voir les logs docker compose logs weaviate # Recréer le schéma python schema.py ``` --- ## Optimisations 2026 (Production-Ready) ### 🚀 **1. Batch Size Dynamique** **Implémentation** : `utils/weaviate_ingest.py` (lignes 198-330) L'ingestion ajuste automatiquement la taille des lots selon la longueur moyenne des chunks : | Taille moyenne chunk | Batch size | Rationale | |---------------------|------------|-----------| | < 3k chars | 100 chunks | Courts → vectorisation rapide | | 3k - 10k chars | 50 chunks | Moyens → standard académique | | 10k - 50k chars | 25 chunks | Longs → arguments complexes | | > 50k chars | 10 chunks | Très longs → Peirce CP 8.388 (218k) | **Bénéfice** : Évite les timeouts sur textes longs tout en maximisant le throughput sur textes courts. ```python # Détection automatique batch_size = calculate_batch_size(chunks) # 10, 25, 50 ou 100 ``` ### 🎯 **2. Index Vectoriel Optimisé (Dynamic + RQ)** **Implémentation** : `schema.py` (lignes 242-255 pour Chunk, 355-367 pour Summary) - **Dynamic Index** : Passe de FLAT à HNSW automatiquement - Chunk : seuil à 50,000 vecteurs - Summary : seuil à 10,000 vecteurs - **Rotational Quantization (RQ)** : Réduit la RAM de ~75% - **Distance Metric** : COSINE (compatible BGE-M3) **Impact actuel** : - Collections < seuil → Index FLAT (rapide, faible RAM) - **Économie RAM projetée à 100k chunks** : 40 GB → 10 GB (-75%) - **Coût infrastructure annuel** : Économie de ~840€ Voir `VECTOR_INDEX_OPTIMIZATION.md` pour détails. ### ✅ **3. Validation Stricte des Métadonnées** **Implémentation** : `utils/weaviate_ingest.py` (lignes 272-421) Validation en 2 étapes avant ingestion : 1. **Métadonnées document** : `validate_document_metadata()` - Vérifie `doc_name`, `title`, `author`, `language` non-vides - Détecte `None`, `""`, whitespace-only 2. **Nested objects chunks** : `validate_chunk_nested_objects()` - Vérifie `work.title`, `work.author`, `document.sourceId` non-vides - Validation chunk par chunk avec index pour debugging **Impact** : - Corruption silencieuse : **5-10% → 0%** - Temps debugging : **~2h → ~5min** par erreur - **28 tests unitaires** : `tests/test_validation_stricte.py` Voir `VALIDATION_STRICTE.md` pour détails. --- ## Notes d'implémentation 1. **Timeout augmenté** : Les chunks très longs (ex: Peirce CP 3.403, CP 8.388: 218k chars) nécessitent 600s (10 min) pour la vectorisation 2. **Batch insertion dynamique** : L'ingestion utilise `insert_many()` avec batch size adaptatif (10-100 selon longueur) 3. **Type safety** : Tous les types sont définis dans `utils/types.py` avec TypedDict 4. **mypy strict** : Le code passe la vérification stricte mypy 5. **Validation stricte** : Métadonnées et nested objects validés avant insertion (0% corruption) --- ## Voir aussi ### Fichiers principaux - `schema.py` - Définitions et création du schéma - `utils/weaviate_ingest.py` - Fonctions d'ingestion avec validation stricte - `utils/types.py` - TypedDict correspondant au schéma - `docker-compose.yml` - Configuration des conteneurs ### Scripts utiles - `verify_vector_index.py` - Vérifier la configuration des index vectoriels - `migrate_add_work_collection.py` - Ajouter Work vectorisé (migration sûre) - `test_weaviate_connection.py` - Tester la connexion Weaviate ### Documentation des optimisations - `VECTOR_INDEX_OPTIMIZATION.md` - Index Dynamic + RQ (économie RAM 75%) - `VALIDATION_STRICTE.md` - Validation métadonnées (0% corruption) ### Tests - `tests/test_validation_stricte.py` - 28 tests unitaires pour validation