docs: Remove obsolete documentation files from library_rag
Cleaned up 15 obsolete MD files that were temporary session reports and outdated documentation, now replaced by the organized docs/ structure and comprehensive README.md. Removed files: - ANALYSE_ARCHITECTURE_WEAVIATE.md (superseded by docs/migration-gpu/) - ANALYSE_RAG_FINAL.md (session report) - ANALYSE_RESULTATS_RESUME.md (session report) - COMPLETE_SESSION_RECAP.md (session report) - EXPLICATION_SUMMARY_CHUNK.md (old technical docs) - FIX_HIERARCHICAL.md (session report) - INTEGRATION_SUMMARY.md (session report) - PLAN_LLM_SUMMARIZER.md (old planning docs) - QUICKSTART_SUMMARY_SEARCH.md (superseded by README.md) - README_SEARCH.md (superseded by README.md) - REFACTOR_SUMMARY.md (session report) - SESSION_SUMMARY.md (session report) - TTS_INSTALLATION_GUIDE.md (not used) - WEAVIATE_GUIDE_COMPLET.md (superseded by README.md) - WEAVIATE_SCHEMA.md (superseded by schema.py comments) Retained documentation: ✓ README.md (main documentation) ✓ docs/ (organized migration and project docs) ✓ docs_techniques/ (technical specifications) ✓ .claude/CLAUDE.md (Claude Code instructions) ✓ examples/ (usage examples) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,613 +0,0 @@
|
|||||||
# Analyse Architecture Weaviate - Library RAG
|
|
||||||
|
|
||||||
**Date**: 2026-01-03
|
|
||||||
**Dernier commit**: `b76e56e` - refactor: Suppression tous fonds beiges header section
|
|
||||||
**Status**: Production (13,829 vecteurs indexés)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📋 Table des Matières
|
|
||||||
|
|
||||||
1. [Vue d'Ensemble de la Base Weaviate](#1-vue-densemble-de-la-base-weaviate)
|
|
||||||
2. [Collections et leurs Relations](#2-collections-et-leurs-relations)
|
|
||||||
3. [Focus: Œuvre, Document, Chunk - La Hiérarchie Centrale](#3-focus-œuvre-document-chunk---la-hiérarchie-centrale)
|
|
||||||
4. [Stratégie de Recherche: Résumés → Chunks](#4-stratégie-de-recherche-résumés--chunks)
|
|
||||||
5. [Outils Weaviate: Utilisés vs Non-Utilisés](#5-outils-weaviate-utilisés-vs-non-utilisés)
|
|
||||||
6. [Recommandations pour Exploiter Weaviate à 100%](#6-recommandations-pour-exploiter-weaviate-à-100)
|
|
||||||
7. [Annexes Techniques](#7-annexes-techniques)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 1. Vue d'Ensemble de la Base Weaviate
|
|
||||||
|
|
||||||
### 1.1 Architecture Générale
|
|
||||||
|
|
||||||
Library RAG utilise **Weaviate 1.34.4** comme base vectorielle pour indexer et rechercher des textes philosophiques. L'architecture suit un modèle **normalisé avec dénormalisation stratégique** via nested objects.
|
|
||||||
|
|
||||||
```
|
|
||||||
┌─────────────────────────────────────────────────────────────┐
|
|
||||||
│ WEAVIATE DATABASE │
|
|
||||||
├─────────────────────────────────────────────────────────────┤
|
|
||||||
│ │
|
|
||||||
│ Work (0 objets) Document (16 objets) │
|
|
||||||
│ └─ Métadonnées œuvre └─ Métadonnées édition │
|
|
||||||
│ (vectorisé) (non vectorisé) │
|
|
||||||
│ │
|
|
||||||
│ Chunk (5,404 objets) ⭐ Summary (8,425 objets) │
|
|
||||||
│ └─ Fragments vectorisés └─ Résumés vectorisés │
|
|
||||||
│ COLLECTION PRINCIPALE (recherche hiérarchique) │
|
|
||||||
│ │
|
|
||||||
└─────────────────────────────────────────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
### 1.2 Statistiques Clés
|
|
||||||
|
|
||||||
| Collection | Objets | Vectorisé | Taille estimée | Utilisation |
|
|
||||||
|------------|--------|-----------|----------------|-------------|
|
|
||||||
| **Chunk** | **5,404** | ✅ Oui (text + keywords) | ~3 MB | **Recherche sémantique principale** |
|
|
||||||
| **Summary** | **8,425** | ✅ Oui (text + concepts) | ~5 MB | Recherche hiérarchique par chapitres |
|
|
||||||
| **Document** | **16** | ❌ Non | ~10 KB | Métadonnées éditions |
|
|
||||||
| **Work** | **0** | ✅ Oui (title + author)* | 0 B | Prêt pour migration |
|
|
||||||
|
|
||||||
**Total vecteurs**: 13,829 (5,404 chunks + 8,425 summaries)
|
|
||||||
**Ratio Summary/Chunk**: 1.56 (1.6 résumés par chunk, excellent pour recherche hiérarchique)
|
|
||||||
|
|
||||||
\* *Work est configuré avec vectorisation depuis migration 2026-01 mais actuellement vide*
|
|
||||||
|
|
||||||
### 1.3 Modèle de Vectorisation
|
|
||||||
|
|
||||||
**Modèle**: BAAI/bge-m3
|
|
||||||
**Dimensions**: 1024
|
|
||||||
**Contexte**: 8192 tokens
|
|
||||||
**Langues supportées**: Grec ancien, Latin, Français, Anglais
|
|
||||||
|
|
||||||
**Migration Dec 2024**: MiniLM-L6 (384-dim) → BGE-M3 (1024-dim)
|
|
||||||
- **Gain**: 2.7x plus riche en représentation sémantique
|
|
||||||
- **Performance**: Meilleure sur textes philosophiques/académiques
|
|
||||||
- **Multilingue**: Support natif grec/latin
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 2. Collections et leurs Relations
|
|
||||||
|
|
||||||
### 2.1 Architecture des Collections
|
|
||||||
|
|
||||||
```
|
|
||||||
Work (Œuvre philosophique)
|
|
||||||
│
|
|
||||||
│ Nested in Document.work: {title, author}
|
|
||||||
│ Nested in Chunk.work: {title, author}
|
|
||||||
▼
|
|
||||||
Document (Édition/traduction spécifique)
|
|
||||||
│
|
|
||||||
│ Nested in Chunk.document: {sourceId, edition}
|
|
||||||
│ Nested in Summary.document: {sourceId}
|
|
||||||
▼
|
|
||||||
├─► Chunk (Fragments de texte, 200-800 chars)
|
|
||||||
│ └─ Vectorisé: text, keywords
|
|
||||||
│ └─ Filtres: sectionPath, unitType, orderIndex
|
|
||||||
│
|
|
||||||
└─► Summary (Résumés de chapitres/sections)
|
|
||||||
└─ Vectorisé: text, concepts
|
|
||||||
└─ Hiérarchie: level (1=chapitre, 2=section, 3=subsection)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2.2 Collection Work (Œuvre)
|
|
||||||
|
|
||||||
**Rôle**: Représente une œuvre philosophique canonique (ex: Ménon de Platon)
|
|
||||||
|
|
||||||
**Propriétés**:
|
|
||||||
```python
|
|
||||||
title: TEXT (VECTORISÉ) # "Ménon", "République"
|
|
||||||
author: TEXT (VECTORISÉ) # "Platon", "Peirce"
|
|
||||||
originalTitle: TEXT [skip_vec] # "Μένων" (grec)
|
|
||||||
year: INT # -380 (avant J.-C.)
|
|
||||||
language: TEXT [skip_vec] # "gr", "la", "fr"
|
|
||||||
genre: TEXT [skip_vec] # "dialogue", "traité"
|
|
||||||
```
|
|
||||||
|
|
||||||
**Vectorisation**: Activée depuis 2026-01
|
|
||||||
- ✅ `title` vectorisé → recherche "dialogues socratiques" trouve Ménon
|
|
||||||
- ✅ `author` vectorisé → recherche "philosophie analytique" trouve Haugeland
|
|
||||||
|
|
||||||
**Status actuel**: Vide (0 objets), prêt pour migration
|
|
||||||
|
|
||||||
### 2.3 Collection Document (Édition)
|
|
||||||
|
|
||||||
**Rôle**: Représente une édition ou traduction spécifique d'une œuvre
|
|
||||||
|
|
||||||
**Propriétés**:
|
|
||||||
```python
|
|
||||||
sourceId: TEXT # "platon_menon_cousin"
|
|
||||||
edition: TEXT # "trad. Cousin, 1844"
|
|
||||||
language: TEXT # "fr" (langue de cette édition)
|
|
||||||
pages: INT # 120
|
|
||||||
chunksCount: INT # 338 (nombre de chunks extraits)
|
|
||||||
toc: TEXT (JSON) # Table des matières structurée
|
|
||||||
hierarchy: TEXT (JSON) # Hiérarchie complète des sections
|
|
||||||
createdAt: DATE # 2025-12-09T09:20:30
|
|
||||||
|
|
||||||
# Nested object
|
|
||||||
work: {
|
|
||||||
title: TEXT # "Ménon"
|
|
||||||
author: TEXT # "Platon"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Vectorisation**: ❌ Non (métadonnées uniquement)
|
|
||||||
|
|
||||||
### 2.4 Collection Chunk ⭐ (PRINCIPALE)
|
|
||||||
|
|
||||||
**Rôle**: Fragments de texte optimisés pour recherche sémantique (200-800 caractères)
|
|
||||||
|
|
||||||
**Propriétés vectorisées**:
|
|
||||||
```python
|
|
||||||
text: TEXT (VECTORISÉ) # Contenu du fragment
|
|
||||||
keywords: TEXT_ARRAY (VECTORISÉ) # ["justice", "vertu", "connaissance"]
|
|
||||||
```
|
|
||||||
|
|
||||||
**Propriétés de filtrage** (non vectorisées):
|
|
||||||
```python
|
|
||||||
sectionPath: TEXT [skip_vec] # "Présentation > Qu'est-ce que la vertu?"
|
|
||||||
sectionLevel: INT # 2 (profondeur hiérarchique)
|
|
||||||
chapterTitle: TEXT [skip_vec] # "Présentation"
|
|
||||||
canonicalReference: TEXT [skip_vec] # "Ménon 80a" ou "CP 5.628"
|
|
||||||
unitType: TEXT [skip_vec] # "argument", "définition", "exposition"
|
|
||||||
orderIndex: INT # 42 (position séquentielle 0-based)
|
|
||||||
language: TEXT [skip_vec] # "fr", "en", "gr"
|
|
||||||
```
|
|
||||||
|
|
||||||
**Nested objects** (dénormalisation):
|
|
||||||
```python
|
|
||||||
work: {
|
|
||||||
title: TEXT # "Ménon"
|
|
||||||
author: TEXT # "Platon"
|
|
||||||
}
|
|
||||||
document: {
|
|
||||||
sourceId: TEXT # "platon_menon_cousin"
|
|
||||||
edition: TEXT # "trad. Cousin"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Exemple d'objet**:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"text": "SOCRATE. - Peux-tu me dire, Ménon, si la vertu peut s'enseigner?",
|
|
||||||
"keywords": ["vertu", "enseignement", "question socratique"],
|
|
||||||
"sectionPath": "Présentation > Qu'est-ce que la vertu?",
|
|
||||||
"sectionLevel": 2,
|
|
||||||
"chapterTitle": "Présentation",
|
|
||||||
"canonicalReference": "Ménon 70a",
|
|
||||||
"unitType": "argument",
|
|
||||||
"orderIndex": 0,
|
|
||||||
"language": "fr",
|
|
||||||
"work": {
|
|
||||||
"title": "Ménon ou de la vertu",
|
|
||||||
"author": "Platon"
|
|
||||||
},
|
|
||||||
"document": {
|
|
||||||
"sourceId": "platon_menon_cousin",
|
|
||||||
"edition": "trad. Cousin"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2.5 Collection Summary (Résumés)
|
|
||||||
|
|
||||||
**Rôle**: Résumés LLM de chapitres/sections pour recherche hiérarchique
|
|
||||||
|
|
||||||
**Propriétés vectorisées**:
|
|
||||||
```python
|
|
||||||
text: TEXT (VECTORISÉ) # Résumé généré par LLM
|
|
||||||
concepts: TEXT_ARRAY (VECTORISÉ) # ["réminiscence", "anamnèse", "connaissance innée"]
|
|
||||||
```
|
|
||||||
|
|
||||||
**Propriétés de filtrage**:
|
|
||||||
```python
|
|
||||||
sectionPath: TEXT [skip_vec] # "Livre I > Chapitre 2"
|
|
||||||
title: TEXT [skip_vec] # "La réminiscence et la connaissance"
|
|
||||||
level: INT # 1=chapitre, 2=section, 3=subsection
|
|
||||||
chunksCount: INT # 15 (nombre de chunks dans cette section)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 3. Focus: Œuvre, Document, Chunk - La Hiérarchie Centrale
|
|
||||||
|
|
||||||
### 3.1 Modèle de Données
|
|
||||||
|
|
||||||
L'architecture suit un modèle **normalisé avec dénormalisation stratégique** :
|
|
||||||
|
|
||||||
```
|
|
||||||
┌──────────────────────────────────────────────────────────────┐
|
|
||||||
│ MODÈLE NORMALISÉ │
|
|
||||||
├──────────────────────────────────────────────────────────────┤
|
|
||||||
│ │
|
|
||||||
│ Work (Source de vérité unique) │
|
|
||||||
│ title: "Ménon ou de la vertu" │
|
|
||||||
│ author: "Platon" │
|
|
||||||
│ year: -380 │
|
|
||||||
│ language: "gr" │
|
|
||||||
│ genre: "dialogue" │
|
|
||||||
│ │
|
|
||||||
│ ├─► Document 1 (trad. Cousin) │
|
|
||||||
│ │ sourceId: "platon_menon_cousin" │
|
|
||||||
│ │ edition: "trad. Cousin, 1844" │
|
|
||||||
│ │ language: "fr" │
|
|
||||||
│ │ pages: 120 │
|
|
||||||
│ │ chunksCount: 338 │
|
|
||||||
│ │ work: {title, author} ← DÉNORMALISÉ │
|
|
||||||
│ │ │
|
|
||||||
│ │ ├─► Chunk 1 │
|
|
||||||
│ │ │ text: "Peux-tu me dire, Ménon..." │
|
|
||||||
│ │ │ work: {title, author} ← DÉNORMALISÉ │
|
|
||||||
│ │ │ document: {sourceId, edition} ← DÉNORMALISÉ │
|
|
||||||
│ │ │ │
|
|
||||||
│ │ ├─► Chunk 2... │
|
|
||||||
│ │ └─► Chunk 338 │
|
|
||||||
│ │ │
|
|
||||||
│ │ ├─► Summary 1 (chapitre 1) │
|
|
||||||
│ │ │ text: "Cette section explore..." │
|
|
||||||
│ │ │ level: 1 │
|
|
||||||
│ │ │ document: {sourceId} ← DÉNORMALISÉ │
|
|
||||||
│ │ │ │
|
|
||||||
│ │ └─► Summary N... │
|
|
||||||
│ │ │
|
|
||||||
│ └─► Document 2 (Loeb Classical Library) │
|
|
||||||
│ sourceId: "plato_meno_loeb" │
|
|
||||||
│ edition: "Loeb Classical Library" │
|
|
||||||
│ language: "en" │
|
|
||||||
│ ... (même structure) │
|
|
||||||
│ │
|
|
||||||
└──────────────────────────────────────────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3.2 Pourquoi Nested Objects au lieu de Cross-References ?
|
|
||||||
|
|
||||||
**Avantages**:
|
|
||||||
1. ✅ **Requête unique** - Récupération en une seule requête sans joins
|
|
||||||
2. ✅ **Performance** - Pas de jointures complexes côté application
|
|
||||||
3. ✅ **Simplicité** - Logique de requête plus simple
|
|
||||||
4. ✅ **Cache-friendly** - Toutes les métadonnées dans un seul objet
|
|
||||||
|
|
||||||
**Trade-off**:
|
|
||||||
- Pour 5,404 chunks: ~200 KB de duplication
|
|
||||||
- Économie de temps: ~50-100ms par requête (évite 2 roundtrips Weaviate)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 4. Stratégie de Recherche: Résumés → Chunks
|
|
||||||
|
|
||||||
### 4.1 Pourquoi Deux Collections Vectorisées ?
|
|
||||||
|
|
||||||
**Problème**: Chercher directement dans 5,404 chunks peut manquer le contexte global
|
|
||||||
|
|
||||||
**Solution**: Architecture à deux niveaux
|
|
||||||
|
|
||||||
```
|
|
||||||
┌─────────────────────────────────────────────────────────────┐
|
|
||||||
│ RECHERCHE À DEUX NIVEAUX │
|
|
||||||
├─────────────────────────────────────────────────────────────┤
|
|
||||||
│ │
|
|
||||||
│ Niveau 1: MACRO (Summary - 8,425 objets) │
|
|
||||||
│ "Quels chapitres parlent de la réminiscence?" │
|
|
||||||
│ └─► Identifie: Chapitre 2, Section 3 │
|
|
||||||
│ │
|
|
||||||
│ Niveau 2: MICRO (Chunk - 5,404 objets) │
|
|
||||||
│ "Quelle est la définition exacte de l'anamnèse?" │
|
|
||||||
│ └─► Trouve: Chunk #42 dans la section identifiée │
|
|
||||||
│ │
|
|
||||||
└─────────────────────────────────────────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
**Avantages**:
|
|
||||||
1. ✅ Meilleure précision (contexte chapitres + détails chunks)
|
|
||||||
2. ✅ Performance optimale (filtrer chunks par section identifiée)
|
|
||||||
3. ✅ Hiérarchie exploitée (level 1=chapitre, 2=section, 3=subsection)
|
|
||||||
|
|
||||||
### 4.2 Stratégies de Recherche Implémentables
|
|
||||||
|
|
||||||
#### Stratégie 1: Sequential Search (Résumés puis Chunks)
|
|
||||||
|
|
||||||
**Cas d'usage**: Recherche approfondie avec contexte
|
|
||||||
|
|
||||||
```python
|
|
||||||
# 1. Chercher dans Summary (macro)
|
|
||||||
summaries = client.collections.get("Summary")
|
|
||||||
summary_results = summaries.query.near_text(
|
|
||||||
query="théorie de la réminiscence",
|
|
||||||
limit=5,
|
|
||||||
filters=Filter.by_property("level").equal(1) # Chapitres uniquement
|
|
||||||
)
|
|
||||||
|
|
||||||
# 2. Extraire sections pertinentes
|
|
||||||
relevant_sections = [
|
|
||||||
s.properties['sectionPath']
|
|
||||||
for s in summary_results.objects
|
|
||||||
]
|
|
||||||
|
|
||||||
# 3. Chercher chunks dans ces sections (micro)
|
|
||||||
chunks = client.collections.get("Chunk")
|
|
||||||
chunk_results = chunks.query.near_text(
|
|
||||||
query="qu'est-ce que l'anamnèse?",
|
|
||||||
limit=10,
|
|
||||||
filters=Filter.by_property("sectionPath").like(f"{relevant_sections[0]}*")
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Performance**: 2 requêtes (~50ms chacune) = 100ms total
|
|
||||||
|
|
||||||
#### Stratégie 2: Hybrid Two-Stage avec Score Boosting
|
|
||||||
|
|
||||||
**Algorithme recommandé pour production**:
|
|
||||||
|
|
||||||
```python
|
|
||||||
def hybrid_search(query: str, limit: int = 10) -> List[ChunkResult]:
|
|
||||||
"""Recherche hybride résumés → chunks avec boosting."""
|
|
||||||
|
|
||||||
# Stage 1: Summary search (macro)
|
|
||||||
summaries = client.collections.get("Summary")
|
|
||||||
summary_results = summaries.query.near_text(
|
|
||||||
query=query,
|
|
||||||
limit=3, # Top 3 chapitres
|
|
||||||
filters=Filter.by_property("level").less_or_equal(2),
|
|
||||||
return_metadata=wvq.MetadataQuery(distance=True)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Stage 2: Chunk search avec boost par section
|
|
||||||
chunks = client.collections.get("Chunk")
|
|
||||||
all_chunks = []
|
|
||||||
|
|
||||||
for summary in summary_results.objects:
|
|
||||||
section_path = summary.properties['sectionPath']
|
|
||||||
summary_score = 1 - summary.metadata.distance
|
|
||||||
|
|
||||||
# Chercher chunks dans cette section
|
|
||||||
chunk_results = chunks.query.near_text(
|
|
||||||
query=query,
|
|
||||||
limit=5,
|
|
||||||
filters=Filter.by_property("sectionPath").like(f"{section_path}*"),
|
|
||||||
return_metadata=wvq.MetadataQuery(distance=True)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Booster le score des chunks
|
|
||||||
for chunk in chunk_results.objects:
|
|
||||||
chunk_score = 1 - chunk.metadata.distance
|
|
||||||
boosted_score = (chunk_score * 0.7) + (summary_score * 0.3)
|
|
||||||
|
|
||||||
all_chunks.append({
|
|
||||||
'chunk': chunk,
|
|
||||||
'score': boosted_score,
|
|
||||||
'context_chapter': section_path
|
|
||||||
})
|
|
||||||
|
|
||||||
# Trier par score boosted
|
|
||||||
all_chunks.sort(key=lambda x: x['score'], reverse=True)
|
|
||||||
return all_chunks[:limit]
|
|
||||||
```
|
|
||||||
|
|
||||||
**Impact**: +15-20% précision, ~120ms latence
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 5. Outils Weaviate: Utilisés vs Non-Utilisés
|
|
||||||
|
|
||||||
### 5.1 Outils Actuellement Utilisés ✅
|
|
||||||
|
|
||||||
1. **Semantic Search (near_text)** - Recherche sémantique principale
|
|
||||||
2. **Filters (Nested Objects)** - Filtrage par author, work, language
|
|
||||||
3. **Fetch Objects** - Récupération par ID
|
|
||||||
4. **Batch Insertion** - Insertion groupée adaptative (10-100 objets)
|
|
||||||
5. **Delete Many** - Suppression en masse
|
|
||||||
|
|
||||||
### 5.2 Outils Weaviate NON Utilisés ❌
|
|
||||||
|
|
||||||
#### 1. Hybrid Search (Sémantique + BM25) ⚠️ **HAUTE PRIORITÉ**
|
|
||||||
|
|
||||||
**Qu'est-ce que c'est?**
|
|
||||||
Combine recherche vectorielle (sémantique) + BM25 (mots-clés exacts)
|
|
||||||
|
|
||||||
**Exemple d'implémentation**:
|
|
||||||
```python
|
|
||||||
result = chunks.query.hybrid(
|
|
||||||
query="qu'est-ce que la vertu?",
|
|
||||||
alpha=0.75, # 75% vectoriel, 25% BM25
|
|
||||||
limit=10,
|
|
||||||
filters=filters,
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Impact attendu**: +10-15% précision sur requêtes factuelles
|
|
||||||
|
|
||||||
#### 2. Generative Search (RAG natif) 🚨 **HAUTE PRIORITÉ**
|
|
||||||
|
|
||||||
**Qu'est-ce que c'est?**
|
|
||||||
Weaviate génère directement une réponse synthétique à partir des chunks
|
|
||||||
|
|
||||||
**Exemple**:
|
|
||||||
```python
|
|
||||||
result = chunks.generate.near_text(
|
|
||||||
query="qu'est-ce que la réminiscence chez Platon?",
|
|
||||||
limit=5,
|
|
||||||
grouped_task="Réponds à la question en utilisant ces 5 passages",
|
|
||||||
)
|
|
||||||
|
|
||||||
# Résultat contient:
|
|
||||||
# - result.objects: chunks trouvés
|
|
||||||
# - result.generated: réponse LLM générée
|
|
||||||
```
|
|
||||||
|
|
||||||
**Impact**: Réduction 50% latence end-to-end (RAG complet en une requête)
|
|
||||||
|
|
||||||
#### 3. Reranking (Cohere, Voyage AI) ⚠️ **MOYENNE PRIORITÉ**
|
|
||||||
|
|
||||||
Re-score les résultats avec un modèle spécialisé
|
|
||||||
|
|
||||||
**Impact**: +15-20% précision top-3, +50-100ms latence
|
|
||||||
|
|
||||||
#### 4. RAG Fusion (Multi-Query Search) ⚠️ **MOYENNE PRIORITÉ**
|
|
||||||
|
|
||||||
Génère N variantes de la requête et fusionne les résultats
|
|
||||||
|
|
||||||
**Impact**: +20-25% recall
|
|
||||||
|
|
||||||
### 5.3 Matrice Priorités
|
|
||||||
|
|
||||||
| Outil | Priorité | Difficulté | Impact Précision | Impact Latence | Coût |
|
|
||||||
|-------|----------|------------|------------------|----------------|------|
|
|
||||||
| **Hybrid Search** | 🔴 Haute | Faible (1h) | +10-15% | +5ms | Gratuit |
|
|
||||||
| **Generative Search** | 🔴 Haute | Moyenne (3h) | +30% (RAG E2E) | -50% E2E | LLM API |
|
|
||||||
| **Reranking** | 🟡 Moyenne | Faible (2h) | +15-20% top-3 | +50-100ms | $0.001/req |
|
|
||||||
| **RAG Fusion** | 🟡 Moyenne | Moyenne (4h) | +20-25% recall | x3 requêtes | Gratuit |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 6. Recommandations pour Exploiter Weaviate à 100%
|
|
||||||
|
|
||||||
### 6.1 Quick Wins (1-2 jours d'implémentation)
|
|
||||||
|
|
||||||
#### Quick Win #1: Activer Hybrid Search
|
|
||||||
|
|
||||||
**Fichier à modifier**: `schema.py`
|
|
||||||
|
|
||||||
```python
|
|
||||||
# Ajouter index BM25
|
|
||||||
wvc.Property(
|
|
||||||
name="text",
|
|
||||||
data_type=wvc.DataType.TEXT,
|
|
||||||
index_searchable=True, # ← Active BM25
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Fichier à modifier**: `mcp_tools/retrieval_tools.py`
|
|
||||||
|
|
||||||
```python
|
|
||||||
# Remplacer near_text par hybrid
|
|
||||||
result = chunks.query.hybrid(
|
|
||||||
query=input_data.query,
|
|
||||||
alpha=0.75, # 75% vectoriel, 25% BM25
|
|
||||||
limit=input_data.limit,
|
|
||||||
filters=filters,
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Impact**: +10% précision, <5ms surcoût
|
|
||||||
|
|
||||||
#### Quick Win #2: Implémenter Two-Stage Search
|
|
||||||
|
|
||||||
Créer `utils/two_stage_search.py` avec l'algorithme hybrid boosting (voir section 4.2)
|
|
||||||
|
|
||||||
**Impact**: +15-20% précision, ~120ms latence
|
|
||||||
|
|
||||||
### 6.2 High-Impact Features (1 semaine d'implémentation)
|
|
||||||
|
|
||||||
#### Feature #1: Generative Search (RAG Natif)
|
|
||||||
|
|
||||||
**Étape 1**: Activer module dans docker-compose.yml
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
services:
|
|
||||||
weaviate:
|
|
||||||
environment:
|
|
||||||
GENERATIVE_ANTHROPIC_APIKEY: ${ANTHROPIC_API_KEY}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Étape 2**: Endpoint Flask
|
|
||||||
|
|
||||||
```python
|
|
||||||
@app.route("/search/generative", methods=["GET"])
|
|
||||||
def search_generative():
|
|
||||||
query = request.args.get("q", "")
|
|
||||||
|
|
||||||
chunks = client.collections.get("Chunk")
|
|
||||||
result = chunks.generate.near_text(
|
|
||||||
query=query,
|
|
||||||
limit=5,
|
|
||||||
grouped_task=f"Réponds à: {query}. Utilise les passages fournis.",
|
|
||||||
)
|
|
||||||
|
|
||||||
return jsonify({
|
|
||||||
"answer": result.generated,
|
|
||||||
"sources": [...]
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
**Impact**: RAG complet en une requête, -50% latence E2E
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 7. Annexes Techniques
|
|
||||||
|
|
||||||
### 7.1 Exemple de Requête Complète
|
|
||||||
|
|
||||||
```python
|
|
||||||
import weaviate
|
|
||||||
from weaviate.classes.query import Filter
|
|
||||||
|
|
||||||
client = weaviate.connect_to_local()
|
|
||||||
chunks = client.collections.get("Chunk")
|
|
||||||
|
|
||||||
# Recherche: "vertu" chez Platon en français
|
|
||||||
result = chunks.query.near_text(
|
|
||||||
query="qu'est-ce que la vertu?",
|
|
||||||
limit=10,
|
|
||||||
filters=(
|
|
||||||
Filter.by_property("work").by_property("author").equal("Platon") &
|
|
||||||
Filter.by_property("language").equal("fr")
|
|
||||||
),
|
|
||||||
return_metadata=wvq.MetadataQuery(distance=True)
|
|
||||||
)
|
|
||||||
|
|
||||||
for obj in result.objects:
|
|
||||||
props = obj.properties
|
|
||||||
similarity = 1 - obj.metadata.distance
|
|
||||||
|
|
||||||
print(f"Similarité: {similarity:.3f}")
|
|
||||||
print(f"Texte: {props['text'][:100]}...")
|
|
||||||
print(f"Œuvre: {props['work']['title']}")
|
|
||||||
print(f"Référence: {props['canonicalReference']}")
|
|
||||||
print("---")
|
|
||||||
|
|
||||||
client.close()
|
|
||||||
```
|
|
||||||
|
|
||||||
### 7.2 Glossaire Weaviate
|
|
||||||
|
|
||||||
| Terme | Définition |
|
|
||||||
|-------|------------|
|
|
||||||
| **Collection** | Équivalent d'une "table" en SQL |
|
|
||||||
| **Object** | Une entrée dans une collection |
|
|
||||||
| **Vector** | Représentation numérique (1024-dim pour BGE-M3) |
|
|
||||||
| **near_text** | Recherche sémantique par similarité |
|
|
||||||
| **hybrid** | Recherche combinée (vectorielle + BM25) |
|
|
||||||
| **Nested Object** | Objet imbriqué (ex: `work: {title, author}`) |
|
|
||||||
| **HNSW** | Index vectoriel performant |
|
|
||||||
| **RQ** | Rotational Quantization (-75% RAM) |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Conclusion
|
|
||||||
|
|
||||||
### Points Clés
|
|
||||||
|
|
||||||
1. **Architecture solide** - 4 collections avec nested objects
|
|
||||||
2. **13,829 vecteurs** - Base de production opérationnelle
|
|
||||||
3. **Ratio 1.56 Summary/Chunk** - Excellent pour recherche hiérarchique
|
|
||||||
4. **Utilisation 30%** - Beaucoup de potentiel non exploité
|
|
||||||
|
|
||||||
### Roadmap Recommandée
|
|
||||||
|
|
||||||
**Q1 2026** (Quick Wins):
|
|
||||||
1. Hybrid Search (1 jour)
|
|
||||||
2. Two-Stage Search (3 jours)
|
|
||||||
3. Métriques/monitoring (2 jours)
|
|
||||||
|
|
||||||
**Q2 2026** (High Impact):
|
|
||||||
1. Generative Search (1 semaine)
|
|
||||||
2. Reranking (3 jours)
|
|
||||||
3. Semantic caching (3 jours)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Dernière mise à jour**: 2026-01-03
|
|
||||||
**Version**: 1.0
|
|
||||||
@@ -1,206 +0,0 @@
|
|||||||
# Analyse Finale du Système RAG Library - État au 2026-01-03
|
|
||||||
|
|
||||||
## Résumé Exécutif
|
|
||||||
|
|
||||||
Le système RAG a été considérablement amélioré grâce à la génération de résumés LLM de haute qualité. La recherche dans la collection **Summary** fonctionne excellemment (90% de visibilité des documents riches). Cependant, la recherche dans la collection **Chunk** souffre d'une domination écrasante des chunks Peirce (97% de la base), rendant les autres documents pratiquement introuvables.
|
|
||||||
|
|
||||||
## État de la Base de Données
|
|
||||||
|
|
||||||
### Collection Summary
|
|
||||||
- **Total**: 114 résumés
|
|
||||||
- **Riches** (>100 chars): 106 résumés
|
|
||||||
- **Vides** (titres): 8 résumés
|
|
||||||
|
|
||||||
**Répartition par document:**
|
|
||||||
- Tiercelin: 51 résumés (43 riches)
|
|
||||||
- Haugeland: 50 résumés
|
|
||||||
- Platon: 12 résumés
|
|
||||||
- La logique de la science: 1 résumé
|
|
||||||
|
|
||||||
**Performance de recherche**: 90% de visibilité (54/60 résultats sur 15 requêtes réelles)
|
|
||||||
|
|
||||||
### Collection Chunk
|
|
||||||
- **Total**: 5,230 chunks
|
|
||||||
- **Peirce**: 5,068 chunks (97%)
|
|
||||||
- **Haugeland**: 50 chunks (1%)
|
|
||||||
- **Platon**: 50 chunks (1%)
|
|
||||||
- **Tiercelin**: 36 chunks (0.7%)
|
|
||||||
- **Autres**: 26 chunks (0.5%)
|
|
||||||
|
|
||||||
**Ratio problématique**: 97:3 (Peirce:Autres)
|
|
||||||
|
|
||||||
## Travaux Réalisés
|
|
||||||
|
|
||||||
### Phase 1: Génération des Résumés
|
|
||||||
| Document | Résumés | Coût | Statut |
|
|
||||||
|----------|---------|------|--------|
|
|
||||||
| Tiercelin | 43 | $0.63 | ✅ Complet |
|
|
||||||
| Platon | 12 | $0.14 | ✅ Complet |
|
|
||||||
| La logique de la science | 1 | $0.02 | ✅ Complet |
|
|
||||||
| Haugeland | 50 | $0.44 | ✅ Complet |
|
|
||||||
| **TOTAL** | **106** | **$1.23** | **✅ Complet** |
|
|
||||||
|
|
||||||
### Phase 2: Nettoyage de la Base
|
|
||||||
1. **Suppression de 7 doublons vides** (Tiercelin)
|
|
||||||
2. **Suppression de 8,313 résumés vides Peirce**
|
|
||||||
- Avant: 10% de visibilité
|
|
||||||
- Après: 63% → 90% (avec Haugeland)
|
|
||||||
|
|
||||||
## Performance par Type de Recherche
|
|
||||||
|
|
||||||
### ✅ Recherche dans Summary (EXCELLENT)
|
|
||||||
**15 requêtes réelles testées** couvrant 5 domaines:
|
|
||||||
- Pragmatisme/Peirce (3 requêtes)
|
|
||||||
- Platon/Vertu (3 requêtes)
|
|
||||||
- IA/Philosophie de l'esprit (3 requêtes)
|
|
||||||
- Sémiotique (3 requêtes)
|
|
||||||
- Épistémologie (3 requêtes)
|
|
||||||
|
|
||||||
**Résultat**: 90% de visibilité des résumés riches (54/60 résultats)
|
|
||||||
|
|
||||||
**Exemple de qualité**:
|
|
||||||
- Query: "Can virtue be taught according to Plato?"
|
|
||||||
- Top 3: Tous Platon, similarité 71-72%
|
|
||||||
- Résumés pertinents et informatifs
|
|
||||||
|
|
||||||
### ❌ Recherche dans Chunks (PROBLÉMATIQUE)
|
|
||||||
|
|
||||||
#### Test 1: Questions génériques sur l'IA (domaine de Haugeland)
|
|
||||||
**10 requêtes AI-spécifiques**:
|
|
||||||
- "What is the Turing test?"
|
|
||||||
- "Can machines think?"
|
|
||||||
- "What is a physical symbol system?"
|
|
||||||
- "How do connectionist networks work?"
|
|
||||||
- etc.
|
|
||||||
|
|
||||||
**Résultats (50 total)**:
|
|
||||||
- 🔴 Peirce: 44/50 (88%)
|
|
||||||
- 🟣 Haugeland: 5/50 (10%)
|
|
||||||
- 🟢 Platon: 1/50 (2%)
|
|
||||||
|
|
||||||
**Conclusion**: Même sur son domaine propre, Haugeland est écrasé.
|
|
||||||
|
|
||||||
#### Test 2: Recherche hiérarchique (Summary → Chunks)
|
|
||||||
**Stratégie**:
|
|
||||||
1. Identifier documents pertinents via Summary (fonctionne bien)
|
|
||||||
2. Filtrer chunks de ces documents (échoue - Peirce domine toujours)
|
|
||||||
|
|
||||||
**Exemple**:
|
|
||||||
- Query: "How do connectionist networks work?"
|
|
||||||
- Summary identifie correctement: Haugeland "Connectionist networks"
|
|
||||||
- Mais Chunk search retourne: 5/5 chunks Peirce (0/5 Haugeland)
|
|
||||||
|
|
||||||
**Limitation technique**: Weaviate v4 ne permet pas de filtrer par nested objects dans les requêtes → filtrage en Python après récupération.
|
|
||||||
|
|
||||||
## Problème Central
|
|
||||||
|
|
||||||
### Domination des Chunks Peirce
|
|
||||||
**Cause**: 5,068 chunks Peirce sur 5,230 total (97%)
|
|
||||||
|
|
||||||
**Impact**:
|
|
||||||
- Les chunks Peirce ont des similarités sémantiques élevées (73-77%) sur presque toutes les requêtes
|
|
||||||
- Ratio trop déséquilibré pour laisser apparaître d'autres documents
|
|
||||||
- Même la recherche hiérarchique ne résout pas le problème
|
|
||||||
|
|
||||||
**Contrainte utilisateur**:
|
|
||||||
> "NE SUPPRIME PAS LES CHUNKLS D EPEIRCE BORDEL"
|
|
||||||
|
|
||||||
Pas de suppression des chunks Peirce permise.
|
|
||||||
|
|
||||||
## Solutions Proposées
|
|
||||||
|
|
||||||
### Option A: Summary comme Interface Principale (RECOMMANDÉ)
|
|
||||||
**Statut**: Prouvé et fonctionnel (90% de visibilité)
|
|
||||||
|
|
||||||
**Avantages**:
|
|
||||||
- ✅ Fonctionne immédiatement (déjà testé)
|
|
||||||
- ✅ Coût: $0 (déjà implémenté)
|
|
||||||
- ✅ Performance excellente démontrée
|
|
||||||
- ✅ Interface utilisateur claire
|
|
||||||
|
|
||||||
**Mise en œuvre**:
|
|
||||||
```python
|
|
||||||
# Recherche primaire dans Summary
|
|
||||||
summary_results = summaries.query.near_text(
|
|
||||||
query=user_query,
|
|
||||||
limit=10,
|
|
||||||
return_metadata=wvq.MetadataQuery(distance=True)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Afficher résumés avec contexte
|
|
||||||
for result in summary_results:
|
|
||||||
print(f"Document: {result.properties['document']['sourceId']}")
|
|
||||||
print(f"Section: {result.properties['title']}")
|
|
||||||
print(f"Résumé: {result.properties['text']}")
|
|
||||||
print(f"Concepts: {', '.join(result.properties['concepts'])}")
|
|
||||||
```
|
|
||||||
|
|
||||||
**Flux utilisateur**:
|
|
||||||
1. User pose une question
|
|
||||||
2. Système retourne résumés pertinents (comme Google Scholar)
|
|
||||||
3. User peut cliquer pour voir les chunks détaillés d'une section
|
|
||||||
|
|
||||||
### Option B: Système Hybride
|
|
||||||
**Statut**: Nécessite développement
|
|
||||||
|
|
||||||
**Fonctionnalités**:
|
|
||||||
- Toggle "Recherche par résumés" / "Recherche détaillée"
|
|
||||||
- Mode résumés par défaut (pour découverte)
|
|
||||||
- Mode chunks pour requêtes très précises
|
|
||||||
|
|
||||||
**Coût**: ~2-3 jours de développement UI
|
|
||||||
|
|
||||||
### Option C: Régénération Résumés Peirce
|
|
||||||
**Statut**: Non implémenté
|
|
||||||
|
|
||||||
**Estimation**:
|
|
||||||
- 5,068 chunks → ~500-600 sections
|
|
||||||
- Regroupement intelligent nécessaire
|
|
||||||
- Coût: $45-50
|
|
||||||
- Temps: 15-20 heures (génération + ingestion)
|
|
||||||
|
|
||||||
**Risque**: Peut ne pas résoudre le problème si les résumés Peirce restent sémantiquement proches de toutes les requêtes.
|
|
||||||
|
|
||||||
## Tests Disponibles
|
|
||||||
|
|
||||||
Tous les scripts de test sont dans `generations/library_rag/`:
|
|
||||||
|
|
||||||
1. **test_summaries_validation.py** - Validation complète des résumés
|
|
||||||
2. **test_real_queries.py** - 15 requêtes réelles sur Summary
|
|
||||||
3. **test_hierarchical_search.py** - Test Summary → Chunks
|
|
||||||
4. **test_haugeland_ai.py** - Test spécifique IA (domaine Haugeland)
|
|
||||||
|
|
||||||
## Recommandation Finale
|
|
||||||
|
|
||||||
**Implémenter Option A immédiatement**:
|
|
||||||
1. Interface de recherche principale sur Summary
|
|
||||||
2. 90% de visibilité déjà prouvée
|
|
||||||
3. Coût $0, temps < 1 jour
|
|
||||||
4. Respecte la contrainte (pas de suppression chunks Peirce)
|
|
||||||
|
|
||||||
**Future améliorations** (optionnel):
|
|
||||||
- Option B: Ajouter mode hybride si demandé
|
|
||||||
- Option C: Considérer seulement si vraiment nécessaire
|
|
||||||
|
|
||||||
## Statistiques Finales
|
|
||||||
|
|
||||||
### Coûts Totaux
|
|
||||||
- Génération résumés: $1.23
|
|
||||||
- Suppression données vides: $0
|
|
||||||
- **Total projet**: $1.23
|
|
||||||
|
|
||||||
### Résultats
|
|
||||||
- 106 résumés riches de haute qualité
|
|
||||||
- 90% de visibilité en recherche Summary
|
|
||||||
- Base de données propre et optimisée
|
|
||||||
- Interface de recherche fonctionnelle
|
|
||||||
|
|
||||||
### Performance
|
|
||||||
- Summary search: 90% pertinence ✅
|
|
||||||
- Chunk search: 10% pertinence ❌ (mais solution identifiée)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Date**: 2026-01-03
|
|
||||||
**Système**: Weaviate 1.34.4 + BGE-M3 (1024-dim)
|
|
||||||
**LLM**: Claude Sonnet 4.5 (résumés) + text2vec-transformers (vectorisation)
|
|
||||||
@@ -1,436 +0,0 @@
|
|||||||
# Analyse des Résultats de Recherche - Collection Summary
|
|
||||||
|
|
||||||
**Date**: 2026-01-03
|
|
||||||
**Requête**: "Peirce et la sémiose"
|
|
||||||
**Collection**: Summary (8,425 objets)
|
|
||||||
**Résultats retournés**: 20
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 Statistiques Globales
|
|
||||||
|
|
||||||
| Métrique | Valeur | Évaluation |
|
|
||||||
|----------|--------|------------|
|
|
||||||
| **Total résultats** | 20 | ✅ Bon |
|
|
||||||
| **Similarité moyenne** | 0.716 | ⚠️ Moyenne (< 0.75) |
|
|
||||||
| **Meilleur score** | 0.723 | ⚠️ Faible pour top-1 |
|
|
||||||
| **Plus mauvais score** | 0.713 | ⚠️ Très faible |
|
|
||||||
| **Niveau hiérarchique** | 100% Level 1 | ❌ Pas de diversité |
|
|
||||||
| **Documents sources** | 1 seul | ❌ Pas de diversité |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚨 Problèmes Critiques Identifiés
|
|
||||||
|
|
||||||
### 1. Résumés Vides (CRITIQUE)
|
|
||||||
|
|
||||||
**Observation**: Tous les 20 résumés ont un champ `text` vide ou minimal.
|
|
||||||
|
|
||||||
**Exemple**:
|
|
||||||
```
|
|
||||||
Résumé: Peirce: CP 3.592
|
|
||||||
```
|
|
||||||
|
|
||||||
**Attendu**:
|
|
||||||
```
|
|
||||||
Résumé: Ce passage explore la théorie peircéenne de la sémiose comme processus
|
|
||||||
triadique impliquant le signe (representamen), l'objet et l'interprétant.
|
|
||||||
Peirce développe l'idée que la signification n'est jamais binaire mais
|
|
||||||
nécessite toujours cette relation ternaire irréductible...
|
|
||||||
```
|
|
||||||
|
|
||||||
**Impact**:
|
|
||||||
- ❌ La recherche ne peut pas matcher le contenu sémantique réel
|
|
||||||
- ❌ Les résumés ne servent à rien (pas de contexte)
|
|
||||||
- ❌ Impossible d'identifier les sections pertinentes
|
|
||||||
|
|
||||||
**Cause probable**:
|
|
||||||
- Les Summary n'ont jamais été remplis avec de vrais résumés LLM
|
|
||||||
- Le pipeline d'ingestion a sauté l'étape de génération de résumés
|
|
||||||
- OU les résumés ont été générés mais pas insérés dans Weaviate
|
|
||||||
|
|
||||||
### 2. Concepts Vides (CRITIQUE)
|
|
||||||
|
|
||||||
**Observation**: Le champ `concepts` est vide pour tous les résumés.
|
|
||||||
|
|
||||||
**Exemple**:
|
|
||||||
```
|
|
||||||
Concepts:
|
|
||||||
```
|
|
||||||
|
|
||||||
**Attendu**:
|
|
||||||
```
|
|
||||||
Concepts: sémiose, triade, signe, interprétant, représentamen, objet, signification
|
|
||||||
```
|
|
||||||
|
|
||||||
**Impact**:
|
|
||||||
- ❌ Impossible de filtrer par concepts philosophiques
|
|
||||||
- ❌ Perte d'une dimension sémantique clé
|
|
||||||
- ❌ Les résumés ne peuvent pas booster la recherche
|
|
||||||
|
|
||||||
### 3. Pas de Chunks Associés (CRITIQUE)
|
|
||||||
|
|
||||||
**Observation**: Tous les résumés ont `chunksCount: 0`.
|
|
||||||
|
|
||||||
**Exemple**:
|
|
||||||
```
|
|
||||||
Chunks dans cette section: 0
|
|
||||||
```
|
|
||||||
|
|
||||||
**Attendu**:
|
|
||||||
```
|
|
||||||
Chunks dans cette section: 15-50
|
|
||||||
```
|
|
||||||
|
|
||||||
**Impact**:
|
|
||||||
- ❌ Les résumés ne sont pas liés aux chunks
|
|
||||||
- ❌ Impossible de faire une recherche hiérarchique (Summary → Chunk)
|
|
||||||
- ❌ La stratégie two-stage est cassée
|
|
||||||
|
|
||||||
**Cause probable**:
|
|
||||||
- Les Summary ont été créés mais sans lien avec les Chunks
|
|
||||||
- Le champ `document.sourceId` dans Summary ne match pas avec `document.sourceId` dans Chunk
|
|
||||||
- OU les Summary ont été créés pour des sections qui n'ont pas de chunks
|
|
||||||
|
|
||||||
### 4. Similarité Faible (ALERTE)
|
|
||||||
|
|
||||||
**Observation**: Scores entre 0.713 et 0.723.
|
|
||||||
|
|
||||||
**Analyse**:
|
|
||||||
| Score | Interprétation |
|
|
||||||
|-------|----------------|
|
|
||||||
| > 0.90 | Excellent match |
|
|
||||||
| 0.80-0.90 | Bon match |
|
|
||||||
| 0.70-0.80 | Match moyen |
|
|
||||||
| **0.71-0.72** | **Match faible** ⚠️ |
|
|
||||||
| < 0.70 | Pas pertinent |
|
|
||||||
|
|
||||||
**Pourquoi c'est faible ?**
|
|
||||||
- Le modèle BGE-M3 match uniquement sur "Peirce: CP X.XXX" (titre)
|
|
||||||
- Pas de contenu sémantique à matcher
|
|
||||||
- La requête "Peirce et la sémiose" ne trouve que "Peirce" dans le titre
|
|
||||||
|
|
||||||
**Comparaison attendue**:
|
|
||||||
- Avec vrais résumés: scores 0.85-0.95
|
|
||||||
- Avec concepts remplis: boost de +0.05-0.10
|
|
||||||
|
|
||||||
### 5. Pas de Diversité Hiérarchique (ALERTE)
|
|
||||||
|
|
||||||
**Observation**: 100% des résultats sont Level 1 (chapitres).
|
|
||||||
|
|
||||||
**Distribution**:
|
|
||||||
```
|
|
||||||
Chapitre (Level 1): 20 résultats (100%)
|
|
||||||
Section (Level 2): 0 résultats (0%)
|
|
||||||
Subsection (Level 3): 0 résultats (0%)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Impact**:
|
|
||||||
- ❌ Pas de navigation hiérarchique
|
|
||||||
- ❌ Tous les résultats au même niveau de granularité
|
|
||||||
- ❌ Impossible de drill-down dans les sous-sections
|
|
||||||
|
|
||||||
**Cause probable**:
|
|
||||||
- Les Summary ont été créés uniquement pour les Level 1
|
|
||||||
- Le pipeline n'a pas généré de résumés pour Level 2/3
|
|
||||||
|
|
||||||
### 6. Un Seul Document Source (ALERTE)
|
|
||||||
|
|
||||||
**Observation**: 100% des résultats viennent de `peirce_collected_papers_fixed`.
|
|
||||||
|
|
||||||
**Impact**:
|
|
||||||
- ⚠️ Pas de diversité (autres auteurs sur la sémiose ignorés)
|
|
||||||
- ⚠️ Biais vers Peirce (normal pour la requête, mais limite les perspectives)
|
|
||||||
|
|
||||||
**Note**: Ceci peut être acceptable car la requête contient "Peirce", mais d'autres documents comme "Tiercelin - La pensée-signe" devraient aussi matcher.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔍 Analyse Détaillée des Résultats
|
|
||||||
|
|
||||||
### Top 5 Résultats
|
|
||||||
|
|
||||||
#### [1] CP 3.592 - Similarité: 0.723
|
|
||||||
|
|
||||||
**Référence Peirce**: CP 3.592 (Collected Papers, Volume 3, §592)
|
|
||||||
|
|
||||||
**Contenu actuel**: VIDE (juste "Peirce: CP 3.592")
|
|
||||||
|
|
||||||
**Ce que CP 3.592 devrait contenir** (selon index Peirce):
|
|
||||||
- Volume 3 = Exact Logic
|
|
||||||
- Section probable: Théorie des signes ou logique des relations
|
|
||||||
- Contenu attendu: Discussion sur la triplicité du signe
|
|
||||||
|
|
||||||
**Action requise**: Vérifier le JSON source `peirce_collected_papers_fixed_chunks.json` pour voir si le résumé existe.
|
|
||||||
|
|
||||||
#### [2] CP 2.439 - Similarité: 0.719
|
|
||||||
|
|
||||||
**Référence**: CP 2.439 (Volume 2 = Elements of Logic)
|
|
||||||
|
|
||||||
**Contenu attendu**: Probablement sur la classification des signes ou la sémiotique.
|
|
||||||
|
|
||||||
#### [3] CP 2.657 - Similarité: 0.718
|
|
||||||
|
|
||||||
**Référence**: CP 2.657 (Volume 2)
|
|
||||||
|
|
||||||
**Contenu attendu**: Classification des arguments ou inférence.
|
|
||||||
|
|
||||||
#### [4] CP 5.594 - Similarité: 0.717
|
|
||||||
|
|
||||||
**Référence**: CP 5.594 (Volume 5 = Pragmatism and Pragmaticism)
|
|
||||||
|
|
||||||
**Contenu attendu**: Relation entre pragmatisme et théorie des signes.
|
|
||||||
|
|
||||||
#### [5] CP 4.656 - Similarité: 0.717
|
|
||||||
|
|
||||||
**Référence**: CP 4.656 (Volume 4 = The Simplest Mathematics)
|
|
||||||
|
|
||||||
**Contenu attendu**: Logique mathématique ou théorie des relations.
|
|
||||||
|
|
||||||
### Distribution par Volume Peirce
|
|
||||||
|
|
||||||
| Volume | Résultats | Thématique principale |
|
|
||||||
|--------|-----------|----------------------|
|
|
||||||
| **CP 2** | 7 | Elements of Logic (forte pertinence) |
|
|
||||||
| **CP 3** | 3 | Exact Logic (pertinence moyenne) |
|
|
||||||
| **CP 4** | 2 | Mathematics (faible pertinence) |
|
|
||||||
| **CP 5** | 4 | Pragmatism (pertinence moyenne) |
|
|
||||||
| **CP 7** | 4 | Science and Philosophy (faible pertinence) |
|
|
||||||
|
|
||||||
**Analyse**: Les résultats du Volume 2 (Elements of Logic) sont les plus pertinents pour "sémiose", ce qui est cohérent.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🛠️ Diagnostic Technique
|
|
||||||
|
|
||||||
### Vérification 1: Les Summary existent-ils dans Weaviate ?
|
|
||||||
|
|
||||||
```python
|
|
||||||
import weaviate
|
|
||||||
|
|
||||||
client = weaviate.connect_to_local()
|
|
||||||
summaries = client.collections.get("Summary")
|
|
||||||
|
|
||||||
# Compter objets
|
|
||||||
count = summaries.aggregate.over_all(total_count=True)
|
|
||||||
print(f"Total Summary: {count.total_count}") # Attendu: 8,425
|
|
||||||
|
|
||||||
# Vérifier un objet au hasard
|
|
||||||
result = summaries.query.fetch_objects(limit=1)
|
|
||||||
obj = result.objects[0].properties
|
|
||||||
print(f"Exemple Summary:")
|
|
||||||
print(f" text: '{obj.get('text', 'VIDE')}'")
|
|
||||||
print(f" concepts: {obj.get('concepts', [])}")
|
|
||||||
print(f" chunksCount: {obj.get('chunksCount', 0)}")
|
|
||||||
```
|
|
||||||
|
|
||||||
**Résultat attendu**: 8,425 objets existent, mais avec champs vides.
|
|
||||||
|
|
||||||
### Vérification 2: Comparer avec les Chunks
|
|
||||||
|
|
||||||
```python
|
|
||||||
chunks = client.collections.get("Chunk")
|
|
||||||
|
|
||||||
# Chercher chunks sur "sémiose"
|
|
||||||
result = chunks.query.near_text(
|
|
||||||
query="Peirce et la sémiose",
|
|
||||||
limit=10
|
|
||||||
)
|
|
||||||
|
|
||||||
for obj in result.objects:
|
|
||||||
props = obj.properties
|
|
||||||
similarity = 1 - obj.metadata.distance
|
|
||||||
print(f"Similarité: {similarity:.3f}")
|
|
||||||
print(f"Texte: {props['text'][:100]}...")
|
|
||||||
print(f"Section: {props['sectionPath']}")
|
|
||||||
print("---")
|
|
||||||
```
|
|
||||||
|
|
||||||
**Hypothèse**: Les Chunks devraient avoir de meilleurs scores (0.85-0.95) car ils contiennent le vrai contenu.
|
|
||||||
|
|
||||||
### Vérification 3: Inspecter le JSON source
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Vérifier si les résumés existent dans le JSON
|
|
||||||
jq '.summaries | length' output/peirce_collected_papers_fixed/peirce_collected_papers_fixed_chunks.json
|
|
||||||
|
|
||||||
# Afficher un résumé
|
|
||||||
jq '.summaries[0]' output/peirce_collected_papers_fixed/peirce_collected_papers_fixed_chunks.json
|
|
||||||
```
|
|
||||||
|
|
||||||
**Hypothèses possibles**:
|
|
||||||
1. ✅ Les résumés existent dans le JSON mais n'ont pas été insérés dans Weaviate
|
|
||||||
2. ✅ Les résumés ont été insérés mais avec des champs vides
|
|
||||||
3. ❌ Les résumés n'ont jamais été générés (pipeline incomplet)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📋 Plan d'Action Recommandé
|
|
||||||
|
|
||||||
### Phase 1: Diagnostic Approfondi (30 min)
|
|
||||||
|
|
||||||
1. **Vérifier le JSON source**:
|
|
||||||
```bash
|
|
||||||
cd output/peirce_collected_papers_fixed
|
|
||||||
cat peirce_collected_papers_fixed_chunks.json | jq '.summaries[0:3]'
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Vérifier un Summary dans Weaviate**:
|
|
||||||
```python
|
|
||||||
# Dans test_resume.py, ajouter après la recherche:
|
|
||||||
print("\n=== INSPECTION DÉTAILLÉE ===")
|
|
||||||
summaries = client.collections.get("Summary")
|
|
||||||
result = summaries.query.fetch_objects(
|
|
||||||
filters=Filter.by_property("document").by_property("sourceId").equal("peirce_collected_papers_fixed"),
|
|
||||||
limit=5
|
|
||||||
)
|
|
||||||
for obj in result.objects:
|
|
||||||
print(f"UUID: {obj.uuid}")
|
|
||||||
print(f"Text length: {len(obj.properties.get('text', ''))}")
|
|
||||||
print(f"Concepts count: {len(obj.properties.get('concepts', []))}")
|
|
||||||
print(f"ChunksCount: {obj.properties.get('chunksCount', 0)}")
|
|
||||||
print("---")
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Comparer avec Chunk**:
|
|
||||||
- Chercher "sémiose" dans Chunk
|
|
||||||
- Comparer les scores de similarité
|
|
||||||
|
|
||||||
### Phase 2: Correction selon Diagnostic (1-4h)
|
|
||||||
|
|
||||||
**Scénario A**: Les résumés existent dans le JSON mais pas dans Weaviate
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Ré-injecter uniquement les Summary
|
|
||||||
python utils/weaviate_ingest.py --reingest-summaries --doc peirce_collected_papers_fixed
|
|
||||||
```
|
|
||||||
|
|
||||||
**Scénario B**: Les résumés dans Weaviate sont corrompus
|
|
||||||
|
|
||||||
```python
|
|
||||||
# Supprimer et recréer les Summary pour ce document
|
|
||||||
from utils.weaviate_ingest import delete_summaries, ingest_summaries
|
|
||||||
|
|
||||||
delete_summaries("peirce_collected_papers_fixed")
|
|
||||||
ingest_summaries("peirce_collected_papers_fixed")
|
|
||||||
```
|
|
||||||
|
|
||||||
**Scénario C**: Les résumés n'ont jamais été générés
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Régénérer les résumés avec LLM
|
|
||||||
python utils/llm_summarizer.py --doc peirce_collected_papers_fixed --force
|
|
||||||
python utils/weaviate_ingest.py --doc peirce_collected_papers_fixed --summaries-only
|
|
||||||
```
|
|
||||||
|
|
||||||
### Phase 3: Validation (30 min)
|
|
||||||
|
|
||||||
1. **Ré-exécuter test_resume.py**:
|
|
||||||
```bash
|
|
||||||
python test_resume.py
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Vérifier les améliorations**:
|
|
||||||
- Scores de similarité: 0.85-0.95 attendu
|
|
||||||
- Texte résumé: 100-500 caractères attendu
|
|
||||||
- Concepts: 5-15 mots-clés attendus
|
|
||||||
- ChunksCount: > 0 attendu
|
|
||||||
|
|
||||||
3. **Tester la recherche two-stage**:
|
|
||||||
```python
|
|
||||||
# Créer test_two_stage.py
|
|
||||||
from utils.two_stage_search import hybrid_search
|
|
||||||
|
|
||||||
results = hybrid_search("Peirce et la sémiose", limit=10)
|
|
||||||
# Vérifier que ça fonctionne maintenant
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 Résultats Attendus Après Correction
|
|
||||||
|
|
||||||
### Exemple de Résultat Idéal
|
|
||||||
|
|
||||||
```
|
|
||||||
[1] Similarité: 0.942 | Level: 2
|
|
||||||
Titre: La sémiose et les catégories phanéroscopiques
|
|
||||||
Section: Peirce: CP 5.314 > La sémiose et les catégories
|
|
||||||
Document: peirce_collected_papers_fixed
|
|
||||||
Concepts: sémiose, triade, signe, interprétant, représentamen, objet, priméité, secondéité, tiercéité
|
|
||||||
|
|
||||||
Résumé:
|
|
||||||
Ce passage fondamental expose la théorie peircéenne de la sémiose comme
|
|
||||||
processus triadique irréductible. Peirce articule la relation entre signe
|
|
||||||
(representamen), objet et interprétant avec ses trois catégories universelles:
|
|
||||||
la Priméité (qualité pure), la Secondéité (réaction) et la Tiercéité (médiation).
|
|
||||||
La sémiose est définie comme un processus potentiellement infini où chaque
|
|
||||||
interprétant devient à son tour un nouveau signe, créant une chaîne sémiotique
|
|
||||||
sans fin. Cette conception s'oppose radicalement aux théories binaires du signe
|
|
||||||
(signifiant/signifié) et fonde l'épistémologie pragmatiste de Peirce.
|
|
||||||
|
|
||||||
Chunks dans cette section: 23
|
|
||||||
```
|
|
||||||
|
|
||||||
**Améliorations**:
|
|
||||||
- ✅ Similarité: 0.723 → 0.942 (+30%)
|
|
||||||
- ✅ Texte: 13 chars → 600 chars
|
|
||||||
- ✅ Concepts: 0 → 9
|
|
||||||
- ✅ ChunksCount: 0 → 23
|
|
||||||
- ✅ Niveau: Toujours 1 mais avec vrais sous-niveaux possibles
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 Comparaison Avant/Après (Projeté)
|
|
||||||
|
|
||||||
| Métrique | Avant | Après | Gain |
|
|
||||||
|----------|-------|-------|------|
|
|
||||||
| **Similarité moyenne** | 0.716 | 0.88 | +23% |
|
|
||||||
| **Texte moyen** | 13 chars | 350 chars | +2600% |
|
|
||||||
| **Concepts moyens** | 0 | 7 | +∞ |
|
|
||||||
| **ChunksCount moyen** | 0 | 18 | +∞ |
|
|
||||||
| **Utilité recherche** | 10% | 95% | +850% |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔗 Documents Liés
|
|
||||||
|
|
||||||
- `ANALYSE_ARCHITECTURE_WEAVIATE.md` - Architecture complète de la base
|
|
||||||
- `WEAVIATE_GUIDE_COMPLET.md` - Guide d'utilisation Weaviate
|
|
||||||
- `test_resume.py` - Script de test (ce fichier a généré l'analyse)
|
|
||||||
- `resultats_resume.txt` - Résultats bruts de la recherche
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎓 Conclusion
|
|
||||||
|
|
||||||
### État Actuel: ❌ COLLECTION SUMMARY NON FONCTIONNELLE
|
|
||||||
|
|
||||||
La collection Summary existe (8,425 objets) mais est **inutilisable** pour la recherche car:
|
|
||||||
1. Les résumés sont vides (juste des titres)
|
|
||||||
2. Les concepts sont absents
|
|
||||||
3. Pas de lien avec les Chunks (chunksCount=0)
|
|
||||||
4. Scores de similarité très faibles (0.71-0.72)
|
|
||||||
|
|
||||||
### Impact sur l'Architecture RAG
|
|
||||||
|
|
||||||
**Stratégie Two-Stage cassée**:
|
|
||||||
- ❌ Impossible de faire Summary → Chunk
|
|
||||||
- ❌ Pas de recherche hiérarchique
|
|
||||||
- ✅ Chunk search seul fonctionne (mais perd le contexte)
|
|
||||||
|
|
||||||
**Solution de contournement actuelle**:
|
|
||||||
- Utiliser uniquement la recherche directe dans Chunk
|
|
||||||
- Ignorer complètement Summary
|
|
||||||
- Perdre 8,425 vecteurs (~60% de la base)
|
|
||||||
|
|
||||||
### Priorité: 🔴 HAUTE
|
|
||||||
|
|
||||||
Cette correction est **critique** pour exploiter l'architecture à deux niveaux de Library RAG.
|
|
||||||
|
|
||||||
**ROI attendu**: +30% précision, recherche hiérarchique fonctionnelle, 60% de la base vectorielle activée.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Dernière mise à jour**: 2026-01-03
|
|
||||||
**Auteur**: Analyse automatisée
|
|
||||||
**Version**: 1.0
|
|
||||||
@@ -1,445 +0,0 @@
|
|||||||
# Session Complète - RAG Library Optimization
|
|
||||||
|
|
||||||
**Date**: 2026-01-03
|
|
||||||
**Durée**: Session complète
|
|
||||||
**Objectif**: Résoudre le problème de dominance des chunks Peirce et intégrer une solution dans Flask
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📋 Table des Matières
|
|
||||||
|
|
||||||
1. [Problème Initial](#problème-initial)
|
|
||||||
2. [Travaux Préliminaires](#travaux-préliminaires)
|
|
||||||
3. [Solution Développée](#solution-développée)
|
|
||||||
4. [Intégration Flask](#intégration-flask)
|
|
||||||
5. [Livrables](#livrables)
|
|
||||||
6. [Résultats](#résultats)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Problème Initial
|
|
||||||
|
|
||||||
### État de la Base de Données
|
|
||||||
- **Chunk Collection**: 5,230 chunks total
|
|
||||||
- Peirce: 5,068 chunks (97%)
|
|
||||||
- Autres: 162 chunks (3%)
|
|
||||||
|
|
||||||
### Impact
|
|
||||||
- Recherche directe dans Chunks: **10% de visibilité** pour documents riches
|
|
||||||
- Même sur requêtes ultra-spécifiques (ex: "What is the Turing test?"), Peirce domine 88% des résultats
|
|
||||||
- Haugeland n'apparaît que dans 10% des résultats sur son propre domaine (IA)
|
|
||||||
|
|
||||||
### Contrainte Utilisateur
|
|
||||||
> **"NE SUPPRIME PAS LES CHUNKLS D EPEIRCE BORDEL"**
|
|
||||||
|
|
||||||
❌ Pas de suppression des chunks Peirce permise
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Travaux Préliminaires
|
|
||||||
|
|
||||||
### Phase 1: Génération des Résumés (Déjà Effectué)
|
|
||||||
|
|
||||||
| Document | Résumés | Coût | Statut |
|
|
||||||
|----------|---------|------|--------|
|
|
||||||
| Tiercelin | 43 | $0.63 | ✅ |
|
|
||||||
| Platon | 12 | $0.14 | ✅ |
|
|
||||||
| La logique de la science | 1 | $0.02 | ✅ |
|
|
||||||
| Haugeland | 50 | $0.44 | ✅ |
|
|
||||||
| **TOTAL** | **106** | **$1.23** | ✅ |
|
|
||||||
|
|
||||||
### Phase 2: Nettoyage de la Base
|
|
||||||
|
|
||||||
1. ✅ Suppression de 7 doublons vides (Tiercelin)
|
|
||||||
2. ✅ Suppression de 8,313 résumés vides Peirce
|
|
||||||
- Avant: 10% de visibilité
|
|
||||||
- Après: 63% → 90% (avec Haugeland)
|
|
||||||
|
|
||||||
### Phase 3: Tests de Validation
|
|
||||||
|
|
||||||
**Scripts créés**:
|
|
||||||
- `test_summaries_validation.py` - Validation complète
|
|
||||||
- `test_real_queries.py` - 15 requêtes réelles
|
|
||||||
- `test_hierarchical_search.py` - Test Summary → Chunks
|
|
||||||
- `test_haugeland_ai.py` - Test domaine IA spécifique
|
|
||||||
|
|
||||||
**Résultats**:
|
|
||||||
- Summary search: **90% de visibilité** ✅
|
|
||||||
- Chunk search: **10% de visibilité** ❌
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Solution Développée
|
|
||||||
|
|
||||||
### Option A: Summary-First Interface (Sélectionnée)
|
|
||||||
|
|
||||||
**Principe**: Utiliser la collection Summary (équilibrée, haute qualité) comme point d'entrée principal.
|
|
||||||
|
|
||||||
**Avantages**:
|
|
||||||
- ✅ 90% de visibilité démontrée
|
|
||||||
- ✅ Coût: $0 (réutilise résumés existants)
|
|
||||||
- ✅ Respecte la contrainte (pas de suppression)
|
|
||||||
- ✅ Performance immédiate
|
|
||||||
|
|
||||||
**Alternatives Considérées**:
|
|
||||||
- Option B: Système hybride (nécessite développement UI)
|
|
||||||
- Option C: Régénération résumés Peirce (~$45-50, 15-20h)
|
|
||||||
|
|
||||||
### Architecture Summary Collection
|
|
||||||
|
|
||||||
```
|
|
||||||
Summary Collection (114 résumés)
|
|
||||||
├─ Tiercelin: 51 résumés (LLM-generated)
|
|
||||||
├─ Haugeland: 50 résumés (LLM-generated)
|
|
||||||
├─ Platon: 12 résumés (LLM-generated)
|
|
||||||
└─ Logique: 1 résumé (LLM-generated)
|
|
||||||
|
|
||||||
Vectorisation: BAAI/bge-m3
|
|
||||||
- Dimensions: 1024
|
|
||||||
- Context window: 8192 tokens
|
|
||||||
- Multilingual: EN, FR, Latin, Greek
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Intégration Flask
|
|
||||||
|
|
||||||
### Fichiers Créés/Modifiés
|
|
||||||
|
|
||||||
#### 1. Backend (`flask_app.py`)
|
|
||||||
**Ajouts**:
|
|
||||||
- `search_summaries_backend()` - Fonction de recherche
|
|
||||||
- `@app.route("/search/summary")` - Route Flask
|
|
||||||
- Logique d'icônes par document (🟣🟢🟡🔵⚪)
|
|
||||||
|
|
||||||
**Lignes**: 2907-3046 (~140 lignes)
|
|
||||||
|
|
||||||
#### 2. Template (`templates/search_summary.html`)
|
|
||||||
**Caractéristiques**:
|
|
||||||
- Interface cohérente avec design existant
|
|
||||||
- Bannière d'info sur performance (90% vs 10%)
|
|
||||||
- Cartes de résumés avec animations
|
|
||||||
- Badges de concepts
|
|
||||||
- Suggestions pré-remplies
|
|
||||||
- Bouton bascule vers recherche classique
|
|
||||||
|
|
||||||
**Taille**: ~320 lignes HTML/CSS/Jinja2
|
|
||||||
|
|
||||||
#### 3. Navigation (`templates/base.html`)
|
|
||||||
**Modification**:
|
|
||||||
- Ajout lien "📚 Recherche Résumés" dans sidebar
|
|
||||||
- Badge "90%" de performance
|
|
||||||
- Active state highlighting
|
|
||||||
|
|
||||||
**Lignes modifiées**: 709-713
|
|
||||||
|
|
||||||
### Tests d'Intégration
|
|
||||||
|
|
||||||
**Script**: `test_flask_integration.py`
|
|
||||||
|
|
||||||
**Résultats**: ✅ 100% de réussite (12/12 checks)
|
|
||||||
|
|
||||||
```
|
|
||||||
Test 1: What is the Turing test?
|
|
||||||
✅ Found Haugeland icon 🟣
|
|
||||||
✅ Results displayed
|
|
||||||
✅ Similarity scores displayed
|
|
||||||
✅ Concepts displayed
|
|
||||||
|
|
||||||
Test 2: Can virtue be taught?
|
|
||||||
✅ Found Platon icon 🟢
|
|
||||||
✅ Results displayed
|
|
||||||
✅ Similarity scores displayed
|
|
||||||
✅ Concepts displayed
|
|
||||||
|
|
||||||
Test 3: What is pragmatism?
|
|
||||||
✅ Found Tiercelin icon 🟡
|
|
||||||
✅ Results displayed
|
|
||||||
✅ Similarity scores displayed
|
|
||||||
✅ Concepts displayed
|
|
||||||
|
|
||||||
Test 4: Navigation link
|
|
||||||
✅ Link present
|
|
||||||
✅ Label found
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Livrables
|
|
||||||
|
|
||||||
### Documentation (7 fichiers)
|
|
||||||
|
|
||||||
1. **ANALYSE_RAG_FINAL.md** (15 KB)
|
|
||||||
- Analyse complète du système
|
|
||||||
- État de la base de données
|
|
||||||
- Performance par type de recherche
|
|
||||||
- Solutions proposées
|
|
||||||
|
|
||||||
2. **search_summary_interface.py** (8 KB)
|
|
||||||
- Script standalone pour ligne de commande
|
|
||||||
- Mode interactif + single query
|
|
||||||
- Fonction `search_summaries()`
|
|
||||||
|
|
||||||
3. **README_SEARCH.md** (7 KB)
|
|
||||||
- Guide d'utilisation complet
|
|
||||||
- Exemples d'utilisation
|
|
||||||
- Architecture technique
|
|
||||||
- Prochaines étapes
|
|
||||||
|
|
||||||
4. **SESSION_SUMMARY.md** (5 KB)
|
|
||||||
- Résumé exécutif de la session
|
|
||||||
- Métriques de performance
|
|
||||||
- Recommandation finale
|
|
||||||
|
|
||||||
5. **INTEGRATION_SUMMARY.md** (10 KB)
|
|
||||||
- Détails de l'intégration Flask
|
|
||||||
- Tests de validation
|
|
||||||
- Architecture technique
|
|
||||||
- Support et débogage
|
|
||||||
|
|
||||||
6. **QUICKSTART_SUMMARY_SEARCH.md** (6 KB)
|
|
||||||
- Guide de démarrage rapide
|
|
||||||
- Exemples de recherche
|
|
||||||
- Troubleshooting
|
|
||||||
- Conseils d'utilisation
|
|
||||||
|
|
||||||
7. **COMPLETE_SESSION_RECAP.md** (ce fichier)
|
|
||||||
- Vue d'ensemble complète
|
|
||||||
- Chronologie des travaux
|
|
||||||
- Tous les résultats
|
|
||||||
|
|
||||||
### Code (3 fichiers)
|
|
||||||
|
|
||||||
1. **flask_app.py** (modifié)
|
|
||||||
- +140 lignes de code
|
|
||||||
- Fonction backend + route
|
|
||||||
|
|
||||||
2. **templates/search_summary.html** (nouveau)
|
|
||||||
- ~320 lignes HTML/CSS/Jinja2
|
|
||||||
- Interface complète
|
|
||||||
|
|
||||||
3. **templates/base.html** (modifié)
|
|
||||||
- Navigation mise à jour
|
|
||||||
- Badge performance
|
|
||||||
|
|
||||||
### Tests (2 fichiers)
|
|
||||||
|
|
||||||
1. **test_flask_integration.py** (nouveau)
|
|
||||||
- 4 tests automatisés
|
|
||||||
- Validation complète
|
|
||||||
|
|
||||||
2. **search_summary_interface.py** (réutilisable)
|
|
||||||
- CLI pour tests manuels
|
|
||||||
- Peut être importé
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Résultats
|
|
||||||
|
|
||||||
### Métriques de Performance
|
|
||||||
|
|
||||||
| Métrique | Avant (Chunk) | Après (Summary) | Amélioration |
|
|
||||||
|----------|---------------|-----------------|--------------|
|
|
||||||
| Visibilité documents riches | 10% | 90% | **+800%** |
|
|
||||||
| Haugeland sur requêtes IA | 10% | 100% | **+900%** |
|
|
||||||
| Platon sur requêtes Vertu | 20% | 100% | **+400%** |
|
|
||||||
| Tiercelin sur Pragmatisme | 0% | 100% | **∞** |
|
|
||||||
| Temps de réponse | ~300ms | ~300ms | = |
|
|
||||||
|
|
||||||
### Tests de Précision
|
|
||||||
|
|
||||||
**15 requêtes réelles testées** (5 domaines):
|
|
||||||
|
|
||||||
1. **Pragmatisme/Peirce**: 3/3 ✅
|
|
||||||
2. **Platon/Vertu**: 3/3 ✅
|
|
||||||
3. **IA/Esprit**: 3/3 ✅
|
|
||||||
4. **Sémiotique**: 3/3 ✅
|
|
||||||
5. **Épistémologie**: 3/3 ✅
|
|
||||||
|
|
||||||
**Résultat Global**: 100% de précision sur tous les tests
|
|
||||||
|
|
||||||
### Coûts
|
|
||||||
|
|
||||||
| Poste | Montant | Détail |
|
|
||||||
|-------|---------|--------|
|
|
||||||
| Génération résumés (déjà fait) | $1.23 | 106 résumés LLM |
|
|
||||||
| Développement interface | $0 | Temps de développement |
|
|
||||||
| Infrastructure | $0 | Weaviate existant |
|
|
||||||
| **Total projet** | **$1.23** | Coût total |
|
|
||||||
|
|
||||||
### Accessibilité
|
|
||||||
|
|
||||||
**URL**: `http://localhost:5000/search/summary`
|
|
||||||
|
|
||||||
**Navigation**: Menu ☰ → "📚 Recherche Résumés"
|
|
||||||
|
|
||||||
**Paramètres**:
|
|
||||||
- Nombre de résultats: 5, 10, 15, 20
|
|
||||||
- Seuil de similarité: 60%, 65%, 70%, 75%
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Impact Utilisateur
|
|
||||||
|
|
||||||
### Avant (Recherche Chunk)
|
|
||||||
|
|
||||||
**Expérience**:
|
|
||||||
```
|
|
||||||
Query: "What is the Turing test?"
|
|
||||||
|
|
||||||
Résultats:
|
|
||||||
1. ⚪ Peirce CP 4.162 - 73.5%
|
|
||||||
"This idea of discrete quantity..."
|
|
||||||
2. ⚪ Peirce CP 5.520 - 73.5%
|
|
||||||
"Doctor X. Yours seemed marked..."
|
|
||||||
3. ⚪ Peirce CP 2.143 - 73.5%
|
|
||||||
"All these tests, however..."
|
|
||||||
4. ⚪ Peirce CP 5.187 - 73.3%
|
|
||||||
"We thus come to the test..."
|
|
||||||
5. ⚪ Peirce CP 7.206 - 73.2%
|
|
||||||
"Having, then, by means of..."
|
|
||||||
|
|
||||||
❌ 0/5 résultats pertinents
|
|
||||||
```
|
|
||||||
|
|
||||||
### Après (Recherche Summary)
|
|
||||||
|
|
||||||
**Expérience**:
|
|
||||||
```
|
|
||||||
Query: "What is the Turing test?"
|
|
||||||
|
|
||||||
Résultats:
|
|
||||||
1. 🟣 Haugeland - 69.5%
|
|
||||||
Computers and intelligence
|
|
||||||
"This section examines Turing's 1950 prediction..."
|
|
||||||
Concepts: Turing test, AI, computation...
|
|
||||||
📄 1 passage détaillé
|
|
||||||
|
|
||||||
2. 🟣 Haugeland - 68.8%
|
|
||||||
Computer Science as Empirical Inquiry
|
|
||||||
"Newell and Simon present computer science..."
|
|
||||||
Concepts: empirical inquiry, symbolic system...
|
|
||||||
📄 1 passage détaillé
|
|
||||||
|
|
||||||
3. 🟣 Haugeland - 66.6%
|
|
||||||
The Turing test
|
|
||||||
"This section explores two foundational..."
|
|
||||||
Concepts: Turing test, intentionality...
|
|
||||||
📄 1 passage détaillé
|
|
||||||
|
|
||||||
✅ 3/3 résultats pertinents (100%)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Recommandations
|
|
||||||
|
|
||||||
### Court Terme ✅
|
|
||||||
|
|
||||||
1. **Promouvoir la Recherche Summary** comme interface principale
|
|
||||||
- Mettre en avant dans la navigation (déjà fait)
|
|
||||||
- Badge "90%" de performance (déjà fait)
|
|
||||||
|
|
||||||
2. **Former les utilisateurs**
|
|
||||||
- Guide QUICKSTART disponible
|
|
||||||
- Suggestions de recherche intégrées
|
|
||||||
|
|
||||||
3. **Monitorer l'usage**
|
|
||||||
- Logs Flask pour analytics
|
|
||||||
- Feedback utilisateurs
|
|
||||||
|
|
||||||
### Moyen Terme (Optionnel)
|
|
||||||
|
|
||||||
1. **Améliorer l'interface**
|
|
||||||
- Bouton "Voir chunks détaillés" sur chaque résumé
|
|
||||||
- Route `/summary/<uuid>/chunks` pour expansion
|
|
||||||
|
|
||||||
2. **Ajouter des fonctionnalités**
|
|
||||||
- Filtres par auteur/document
|
|
||||||
- Historique de recherche
|
|
||||||
- Export résultats
|
|
||||||
|
|
||||||
3. **Mode hybride**
|
|
||||||
- Toggle Summary/Chunk
|
|
||||||
- Comparaison côte-à-côte
|
|
||||||
|
|
||||||
### Long Terme (Si Besoin)
|
|
||||||
|
|
||||||
1. **Régénération Peirce** (~$45-50)
|
|
||||||
- Seulement si nécessaire
|
|
||||||
- Améliorerait aussi la recherche Chunk
|
|
||||||
|
|
||||||
2. **Analytics avancés**
|
|
||||||
- Graphe de concepts
|
|
||||||
- Suggestions intelligentes
|
|
||||||
- Recherches liées
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Conclusion
|
|
||||||
|
|
||||||
### Objectifs Atteints ✅
|
|
||||||
|
|
||||||
1. ✅ Problème de visibilité résolu (10% → 90%)
|
|
||||||
2. ✅ Contrainte respectée (pas de suppression Peirce)
|
|
||||||
3. ✅ Solution production-ready implémentée
|
|
||||||
4. ✅ Documentation complète fournie
|
|
||||||
5. ✅ Tests validés (100% de précision)
|
|
||||||
6. ✅ Intégration Flask fonctionnelle
|
|
||||||
|
|
||||||
### État Final
|
|
||||||
|
|
||||||
**Base de Données**:
|
|
||||||
- Summary: 114 résumés (106 riches)
|
|
||||||
- Chunk: 5,230 chunks (intacts)
|
|
||||||
- Performance Summary: 90% ✅
|
|
||||||
- Performance Chunk: 10% ❌ (mais toujours disponible)
|
|
||||||
|
|
||||||
**Application Flask**:
|
|
||||||
- Route `/search/summary` opérationnelle
|
|
||||||
- Navigation intégrée avec badge "90%"
|
|
||||||
- Interface moderne et responsive
|
|
||||||
- Tests automatisés passants
|
|
||||||
|
|
||||||
**Documentation**:
|
|
||||||
- 7 fichiers de documentation
|
|
||||||
- Guides utilisateur complets
|
|
||||||
- Documentation technique détaillée
|
|
||||||
|
|
||||||
### Recommandation Finale
|
|
||||||
|
|
||||||
**Utiliser `/search/summary` comme interface de recherche principale.**
|
|
||||||
|
|
||||||
La recherche Summary offre:
|
|
||||||
- 📊 **90% de visibilité** vs 10% en recherche directe
|
|
||||||
- 🎯 **100% de précision** sur tests
|
|
||||||
- ⚡ **Performance identique** (~300ms)
|
|
||||||
- 📚 **Métadonnées riches** (concepts, auteur, résumés)
|
|
||||||
- 🚀 **Meilleure UX** pour découverte de documents
|
|
||||||
|
|
||||||
La recherche Chunk reste disponible via `/search` pour les cas d'usage spécifiques nécessitant des citations exactes.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Fichiers de Référence Rapide
|
|
||||||
|
|
||||||
| Besoin | Fichier |
|
|
||||||
|--------|---------|
|
|
||||||
| Démarrage rapide | `QUICKSTART_SUMMARY_SEARCH.md` |
|
|
||||||
| Intégration technique | `INTEGRATION_SUMMARY.md` |
|
|
||||||
| Analyse complète | `ANALYSE_RAG_FINAL.md` |
|
|
||||||
| Guide utilisateur | `README_SEARCH.md` |
|
|
||||||
| Vue d'ensemble | Ce fichier |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Auteur**: Claude Sonnet 4.5
|
|
||||||
**Date**: 2026-01-03
|
|
||||||
**Durée**: Session complète
|
|
||||||
**Statut**: ✅ Projet Complet et Fonctionnel
|
|
||||||
|
|
||||||
**ROI**: +800% de visibilité pour $1.23 d'investissement initial
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
*Fin du rapport de session*
|
|
||||||
@@ -1,739 +0,0 @@
|
|||||||
# Lien entre Summary et Chunk - Explication Complète
|
|
||||||
|
|
||||||
**Date**: 2026-01-03
|
|
||||||
**Fichiers analysés**: `utils/weaviate_ingest.py`, `schema.py`, `pdf_pipeline.py`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📋 Table des Matières
|
|
||||||
|
|
||||||
1. [Vue d'Ensemble](#1-vue-densemble)
|
|
||||||
2. [Lien Théorique entre Summary et Chunk](#2-lien-théorique-entre-summary-et-chunk)
|
|
||||||
3. [Comment les Summary sont Créés](#3-comment-les-summary-sont-créés)
|
|
||||||
4. [Pourquoi les Summary sont Vides](#4-pourquoi-les-summary-sont-vides)
|
|
||||||
5. [Comment Corriger le Problème](#5-comment-corriger-le-problème)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 1. Vue d'Ensemble
|
|
||||||
|
|
||||||
### Architecture Hiérarchique
|
|
||||||
|
|
||||||
```
|
|
||||||
Document (ex: Peirce Collected Papers)
|
|
||||||
│
|
|
||||||
├─► TOC (Table des Matières)
|
|
||||||
│ └─ Structure hiérarchique des sections
|
|
||||||
│
|
|
||||||
├─► Summary (8,425 objets) - MACRO
|
|
||||||
│ └─ Un résumé pour chaque section de la TOC
|
|
||||||
│ └─ Vectorisé pour recherche sémantique chapitres
|
|
||||||
│
|
|
||||||
└─► Chunk (5,404 objets) - MICRO
|
|
||||||
└─ Fragments de texte (200-800 chars)
|
|
||||||
└─ Vectorisé pour recherche sémantique fine
|
|
||||||
```
|
|
||||||
|
|
||||||
### Lien entre Summary et Chunk
|
|
||||||
|
|
||||||
Le lien devrait être **par sectionPath** :
|
|
||||||
|
|
||||||
```python
|
|
||||||
Summary:
|
|
||||||
sectionPath: "Peirce: CP 5.314 > La sémiose et les catégories"
|
|
||||||
chunksCount: 23 # ← Nombre de chunks dans cette section
|
|
||||||
text: "Ce passage explore la théorie de la sémiose..."
|
|
||||||
|
|
||||||
Chunk 1:
|
|
||||||
sectionPath: "Peirce: CP 5.314 > La sémiose et les catégories"
|
|
||||||
text: "Un signe, ou representamen, est quelque chose..."
|
|
||||||
|
|
||||||
Chunk 2:
|
|
||||||
sectionPath: "Peirce: CP 5.314 > La sémiose et les catégories"
|
|
||||||
text: "La sémiose est l'action du signe..."
|
|
||||||
|
|
||||||
... (21 autres chunks)
|
|
||||||
|
|
||||||
Chunk 23:
|
|
||||||
sectionPath: "Peirce: CP 5.314 > La sémiose et les catégories"
|
|
||||||
text: "Ainsi la relation triadique est irréductible..."
|
|
||||||
```
|
|
||||||
|
|
||||||
**Principe**: Tous les Chunks avec le même `sectionPath` appartiennent au Summary correspondant.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 2. Lien Théorique entre Summary et Chunk
|
|
||||||
|
|
||||||
### 2.1 Modèle de Données
|
|
||||||
|
|
||||||
#### Summary (Résumé de Section)
|
|
||||||
|
|
||||||
**Fichier**: `utils/weaviate_ingest.py:86-100`
|
|
||||||
|
|
||||||
```python
|
|
||||||
class SummaryObject(TypedDict):
|
|
||||||
"""Structure d'un Summary dans Weaviate."""
|
|
||||||
|
|
||||||
sectionPath: str # "Peirce: CP 5.314 > La sémiose"
|
|
||||||
title: str # "La sémiose et les catégories"
|
|
||||||
level: int # 2 (profondeur hiérarchique)
|
|
||||||
text: str # "Ce passage explore..." (RÉSUMÉ LLM)
|
|
||||||
concepts: List[str] # ["sémiose", "triade", "signe"]
|
|
||||||
chunksCount: int # 23 (nombre de chunks dans cette section)
|
|
||||||
document: {
|
|
||||||
sourceId: str # "peirce_collected_papers_fixed"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Champs vectorisés**:
|
|
||||||
- ✅ `text` → Vectorisé avec BGE-M3 (1024-dim)
|
|
||||||
- ✅ `concepts` → Vectorisé avec BGE-M3
|
|
||||||
|
|
||||||
**Champs de filtrage**:
|
|
||||||
- `sectionPath` → Pour lier avec Chunks
|
|
||||||
- `level` → Pour hiérarchie (1=chapitre, 2=section, 3=subsection)
|
|
||||||
- `chunksCount` → Pour navigation
|
|
||||||
|
|
||||||
#### Chunk (Fragment de Texte)
|
|
||||||
|
|
||||||
**Fichier**: `schema.py:216-280`
|
|
||||||
|
|
||||||
```python
|
|
||||||
{
|
|
||||||
"text": str, # Contenu du fragment (200-800 chars)
|
|
||||||
"keywords": List[str], # ["sémiose", "triade"]
|
|
||||||
|
|
||||||
"sectionPath": str, # "Peirce: CP 5.314 > La sémiose" (LIEN AVEC SUMMARY)
|
|
||||||
"sectionLevel": int, # 2
|
|
||||||
"chapterTitle": str, # "La sémiose et les catégories"
|
|
||||||
"orderIndex": int, # 42 (position dans le document)
|
|
||||||
"unitType": str, # "argument", "définition", etc.
|
|
||||||
|
|
||||||
"work": {
|
|
||||||
"title": str, # "Collected Papers"
|
|
||||||
"author": str, # "Peirce"
|
|
||||||
},
|
|
||||||
"document": {
|
|
||||||
"sourceId": str, # "peirce_collected_papers_fixed"
|
|
||||||
"edition": str, # "Hartshorne & Weiss"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2.2 Comment le Lien Fonctionne
|
|
||||||
|
|
||||||
**Lien par sectionPath** (chaîne de caractères):
|
|
||||||
|
|
||||||
```python
|
|
||||||
# Recherche dans Summary
|
|
||||||
summary_result = summaries.query.near_text(query="sémiose", limit=3)
|
|
||||||
top_section = summary_result.objects[0].properties['sectionPath']
|
|
||||||
# → "Peirce: CP 5.314 > La sémiose et les catégories"
|
|
||||||
|
|
||||||
# Récupérer tous les Chunks de cette section
|
|
||||||
chunks = client.collections.get("Chunk")
|
|
||||||
chunk_result = chunks.query.fetch_objects(
|
|
||||||
filters=Filter.by_property("sectionPath").like(f"{top_section}*"),
|
|
||||||
limit=100
|
|
||||||
)
|
|
||||||
# → Retourne les 23 chunks appartenant à cette section
|
|
||||||
```
|
|
||||||
|
|
||||||
**Avantages de ce design** (vs cross-references):
|
|
||||||
- ✅ Pas besoin de UUID references
|
|
||||||
- ✅ Requête unique (pas de jointures)
|
|
||||||
- ✅ Filtrage simple avec LIKE ou EQUAL
|
|
||||||
- ✅ Lisible et debuggable
|
|
||||||
|
|
||||||
**Inconvénients**:
|
|
||||||
- ⚠️ Sensible aux typos dans sectionPath
|
|
||||||
- ⚠️ Pas de validation d'intégrité référentielle
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 3. Comment les Summary sont Créés
|
|
||||||
|
|
||||||
### 3.1 Fonction d'Ingestion
|
|
||||||
|
|
||||||
**Fichier**: `utils/weaviate_ingest.py:632-731`
|
|
||||||
|
|
||||||
```python
|
|
||||||
def ingest_summaries(
|
|
||||||
client: WeaviateClient,
|
|
||||||
doc_name: str,
|
|
||||||
toc: List[Dict[str, Any]], # Table des matières
|
|
||||||
summaries_content: Dict[str, str], # ← RÉSUMÉS LLM (actuellement vide !)
|
|
||||||
) -> int:
|
|
||||||
"""Insert section summaries into the Summary collection."""
|
|
||||||
|
|
||||||
summaries_to_insert: List[SummaryObject] = []
|
|
||||||
|
|
||||||
def process_toc(items: List[Dict[str, Any]], parent_path: str = "") -> None:
|
|
||||||
"""Parcourt récursivement la TOC pour créer des Summary."""
|
|
||||||
for item in items:
|
|
||||||
title: str = item.get("title", "")
|
|
||||||
level: int = item.get("level", 1)
|
|
||||||
path: str = f"{parent_path} > {title}" if parent_path else title
|
|
||||||
|
|
||||||
summary_obj: SummaryObject = {
|
|
||||||
"sectionPath": path,
|
|
||||||
"title": title,
|
|
||||||
"level": level,
|
|
||||||
|
|
||||||
# ⚠️ PROBLÈME ICI : Si summaries_content est vide,
|
|
||||||
# on utilise juste le titre comme texte !
|
|
||||||
"text": summaries_content.get(title, title),
|
|
||||||
|
|
||||||
"concepts": item.get("concepts", []),
|
|
||||||
|
|
||||||
# ⚠️ PROBLÈME : Toujours 0, jamais calculé !
|
|
||||||
"chunksCount": 0,
|
|
||||||
|
|
||||||
"document": {
|
|
||||||
"sourceId": doc_name,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
summaries_to_insert.append(summary_obj)
|
|
||||||
|
|
||||||
# Traiter les sous-sections récursivement
|
|
||||||
if "children" in item:
|
|
||||||
process_toc(item["children"], path)
|
|
||||||
|
|
||||||
process_toc(toc)
|
|
||||||
|
|
||||||
# Insertion batch dans Weaviate
|
|
||||||
summary_collection.data.insert_many(summaries_to_insert)
|
|
||||||
return len(summaries_to_insert)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3.2 Appel dans le Pipeline
|
|
||||||
|
|
||||||
**Fichier**: `utils/weaviate_ingest.py:844-845`
|
|
||||||
|
|
||||||
```python
|
|
||||||
# Dans la fonction ingest_document()
|
|
||||||
if ingest_summary_collection and toc:
|
|
||||||
ingest_summaries(client, doc_name, toc, {}) # ← {} = VIDE !
|
|
||||||
```
|
|
||||||
|
|
||||||
**PROBLÈME** : Le dictionnaire `summaries_content` passé est **VIDE** (`{}`).
|
|
||||||
|
|
||||||
**Résultat** : Ligne 686 → `summaries_content.get(title, title)` retourne juste `title` !
|
|
||||||
|
|
||||||
**Exemple**:
|
|
||||||
```python
|
|
||||||
title = "Peirce: CP 5.314"
|
|
||||||
summaries_content = {} # VIDE
|
|
||||||
|
|
||||||
text = summaries_content.get(title, title)
|
|
||||||
# → text = "Peirce: CP 5.314" (car title pas dans dict vide)
|
|
||||||
|
|
||||||
# Attendu:
|
|
||||||
# text = "Ce passage explore la théorie de la sémiose comme processus triadique..."
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3.3 Source de la TOC
|
|
||||||
|
|
||||||
La TOC vient de l'extraction LLM :
|
|
||||||
|
|
||||||
**Fichier**: `utils/llm_toc.py` (étape 5 du pipeline)
|
|
||||||
|
|
||||||
```python
|
|
||||||
def extract_toc_from_markdown(markdown_text: str, ...) -> List[TOCEntry]:
|
|
||||||
"""Extrait la TOC via LLM (Ollama ou Mistral).
|
|
||||||
|
|
||||||
Résultat:
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"title": "Peirce: CP 5.314",
|
|
||||||
"level": 1,
|
|
||||||
"page": null,
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"title": "La sémiose et les catégories",
|
|
||||||
"level": 2,
|
|
||||||
"page": null
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
...
|
|
||||||
]
|
|
||||||
"""
|
|
||||||
```
|
|
||||||
|
|
||||||
**Note**: La TOC contient **seulement les titres**, pas les résumés.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 4. Pourquoi les Summary sont Vides
|
|
||||||
|
|
||||||
### 4.1 Problème #1 : Pas de Génération de Résumés LLM
|
|
||||||
|
|
||||||
**Constat**: Le pipeline PDF ne génère **jamais** de résumés pour les sections.
|
|
||||||
|
|
||||||
**Étapes du pipeline actuel** (`utils/pdf_pipeline.py`):
|
|
||||||
```
|
|
||||||
[1] OCR → Texte brut
|
|
||||||
[2] Markdown → Markdown structuré
|
|
||||||
[3] Images → Extraction images
|
|
||||||
[4] Metadata → Titre, auteur, année
|
|
||||||
[5] TOC → Table des matières (TITRES SEULEMENT)
|
|
||||||
[6] Classify → Classification sections
|
|
||||||
[7] Chunking → Découpage en chunks
|
|
||||||
[8] Cleaning → Nettoyage chunks
|
|
||||||
[9] Validation → Validation + concepts
|
|
||||||
[10] Ingestion → Insertion Weaviate
|
|
||||||
```
|
|
||||||
|
|
||||||
**Manque** : Étape de génération de résumés par section !
|
|
||||||
|
|
||||||
**Ce qui devrait exister** :
|
|
||||||
```
|
|
||||||
[5.5] Summarization → Générer résumé LLM pour chaque section TOC
|
|
||||||
Input: Section text (tous les chunks d'une section)
|
|
||||||
Output: {"Peirce: CP 5.314": "Ce passage explore..."}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4.2 Problème #2 : chunksCount Toujours à 0
|
|
||||||
|
|
||||||
**Constat**: Le champ `chunksCount` est hardcodé à 0.
|
|
||||||
|
|
||||||
**Fichier**: `utils/weaviate_ingest.py:688`
|
|
||||||
|
|
||||||
```python
|
|
||||||
"chunksCount": 0, # ← Hardcodé, jamais calculé !
|
|
||||||
```
|
|
||||||
|
|
||||||
**Ce qui devrait être fait** :
|
|
||||||
|
|
||||||
```python
|
|
||||||
def calculate_chunks_count(chunks: List[Dict], section_path: str) -> int:
|
|
||||||
"""Compte combien de chunks appartiennent à cette section."""
|
|
||||||
count = 0
|
|
||||||
for chunk in chunks:
|
|
||||||
if chunk.get("sectionPath", "").startswith(section_path):
|
|
||||||
count += 1
|
|
||||||
return count
|
|
||||||
|
|
||||||
# Dans process_toc():
|
|
||||||
chunks_count = calculate_chunks_count(all_chunks, path)
|
|
||||||
|
|
||||||
summary_obj: SummaryObject = {
|
|
||||||
...
|
|
||||||
"chunksCount": chunks_count, # ← Calculé dynamiquement
|
|
||||||
...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Pourquoi ce n'est pas fait** :
|
|
||||||
- La fonction `ingest_summaries()` n'a pas accès à la liste des chunks
|
|
||||||
- Les chunks sont insérés APRÈS les summaries dans le pipeline
|
|
||||||
- Ordre incorrect : devrait être Chunks → Summaries (pour compter)
|
|
||||||
|
|
||||||
### 4.3 Problème #3 : Concepts Vides
|
|
||||||
|
|
||||||
**Constat**: Le champ `concepts` est toujours vide.
|
|
||||||
|
|
||||||
**Fichier**: `utils/weaviate_ingest.py:687`
|
|
||||||
|
|
||||||
```python
|
|
||||||
"concepts": item.get("concepts", []), # ← TOC n'a jamais de concepts
|
|
||||||
```
|
|
||||||
|
|
||||||
**Explication**: La TOC extraite par LLM ne contient que `{title, level, page}`, pas de concepts.
|
|
||||||
|
|
||||||
**Ce qui devrait être fait** :
|
|
||||||
|
|
||||||
Les concepts devraient être extraits lors de la génération du résumé :
|
|
||||||
|
|
||||||
```python
|
|
||||||
# Étape 5.5 - Summarization (à créer)
|
|
||||||
def generate_section_summary(section_text: str) -> Dict[str, Any]:
|
|
||||||
"""Génère résumé + concepts via LLM."""
|
|
||||||
|
|
||||||
prompt = f"""Résume cette section et extrais les concepts clés.
|
|
||||||
|
|
||||||
Section:
|
|
||||||
{section_text}
|
|
||||||
|
|
||||||
Réponds en JSON:
|
|
||||||
{{
|
|
||||||
"summary": "Résumé en 100-200 mots...",
|
|
||||||
"concepts": ["concept1", "concept2", ...]
|
|
||||||
}}
|
|
||||||
"""
|
|
||||||
|
|
||||||
response = llm.generate(prompt)
|
|
||||||
return json.loads(response)
|
|
||||||
|
|
||||||
# Résultat:
|
|
||||||
{
|
|
||||||
"summary": "Ce passage explore la théorie de la sémiose...",
|
|
||||||
"concepts": ["sémiose", "triade", "signe", "interprétant", "représentamen"]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 5. Comment Corriger le Problème
|
|
||||||
|
|
||||||
### 5.1 Solution Complète : Ajouter Étape de Summarization
|
|
||||||
|
|
||||||
**Créer nouveau module** : `utils/llm_summarizer.py`
|
|
||||||
|
|
||||||
```python
|
|
||||||
"""LLM-based section summarization for Library RAG.
|
|
||||||
|
|
||||||
Generates summaries and extracts concepts for each section in the TOC.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from typing import Dict, List, Any
|
|
||||||
from utils.llm_structurer import get_llm_client
|
|
||||||
import json
|
|
||||||
|
|
||||||
def generate_summaries_for_toc(
|
|
||||||
toc: List[Dict[str, Any]],
|
|
||||||
chunks: List[Dict[str, Any]],
|
|
||||||
llm_provider: str = "ollama"
|
|
||||||
) -> Dict[str, Dict[str, Any]]:
|
|
||||||
"""Generate LLM summaries for each section in the TOC.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
toc: Table of contents with hierarchical structure.
|
|
||||||
chunks: All document chunks with sectionPath.
|
|
||||||
llm_provider: "ollama" or "mistral".
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Dict mapping section title to {summary, concepts}.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
>>> summaries = generate_summaries_for_toc(toc, chunks)
|
|
||||||
>>> summaries["Peirce: CP 5.314"]
|
|
||||||
{
|
|
||||||
"summary": "Ce passage explore la sémiose...",
|
|
||||||
"concepts": ["sémiose", "triade", "signe"]
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
llm = get_llm_client(llm_provider)
|
|
||||||
summaries_content: Dict[str, Dict[str, Any]] = {}
|
|
||||||
|
|
||||||
def process_section(item: Dict[str, Any], parent_path: str = "") -> None:
|
|
||||||
title = item.get("title", "")
|
|
||||||
path = f"{parent_path} > {title}" if parent_path else title
|
|
||||||
|
|
||||||
# Collecter tous les chunks de cette section
|
|
||||||
section_chunks = [
|
|
||||||
chunk for chunk in chunks
|
|
||||||
if chunk.get("sectionPath", "").startswith(path)
|
|
||||||
]
|
|
||||||
|
|
||||||
if not section_chunks:
|
|
||||||
# Pas de chunks, utiliser juste le titre
|
|
||||||
summaries_content[title] = {
|
|
||||||
"summary": title,
|
|
||||||
"concepts": []
|
|
||||||
}
|
|
||||||
else:
|
|
||||||
# Générer résumé via LLM
|
|
||||||
section_text = "\n\n".join([c.get("text", "") for c in section_chunks[:10]]) # Max 10 chunks
|
|
||||||
|
|
||||||
prompt = f"""Résume cette section philosophique en 100-200 mots et extrais les 5-10 concepts clés.
|
|
||||||
|
|
||||||
Section: {title}
|
|
||||||
|
|
||||||
Texte:
|
|
||||||
{section_text}
|
|
||||||
|
|
||||||
Réponds en JSON:
|
|
||||||
{{
|
|
||||||
"summary": "Résumé de la section...",
|
|
||||||
"concepts": ["concept1", "concept2", ...]
|
|
||||||
}}
|
|
||||||
"""
|
|
||||||
|
|
||||||
try:
|
|
||||||
response = llm.generate(prompt, max_tokens=500)
|
|
||||||
result = json.loads(response)
|
|
||||||
summaries_content[title] = result
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Erreur génération résumé pour {title}: {e}")
|
|
||||||
summaries_content[title] = {
|
|
||||||
"summary": title,
|
|
||||||
"concepts": []
|
|
||||||
}
|
|
||||||
|
|
||||||
# Traiter sous-sections récursivement
|
|
||||||
if "children" in item:
|
|
||||||
for child in item["children"]:
|
|
||||||
process_section(child, path)
|
|
||||||
|
|
||||||
for item in toc:
|
|
||||||
process_section(item)
|
|
||||||
|
|
||||||
return summaries_content
|
|
||||||
```
|
|
||||||
|
|
||||||
**Modifier le pipeline** : `utils/weaviate_ingest.py`
|
|
||||||
|
|
||||||
```python
|
|
||||||
def ingest_document(
|
|
||||||
doc_name: str,
|
|
||||||
chunks: List[Dict[str, Any]],
|
|
||||||
metadata: Dict[str, Any],
|
|
||||||
...,
|
|
||||||
ingest_summary_collection: bool = False,
|
|
||||||
) -> IngestResult:
|
|
||||||
|
|
||||||
# ... (code existant pour chunks)
|
|
||||||
|
|
||||||
# NOUVEAU : Générer résumés APRÈS avoir les chunks
|
|
||||||
if ingest_summary_collection and toc:
|
|
||||||
from utils.llm_summarizer import generate_summaries_for_toc
|
|
||||||
|
|
||||||
# Générer résumés LLM pour chaque section
|
|
||||||
summaries_content = generate_summaries_for_toc(toc, chunks, llm_provider="ollama")
|
|
||||||
|
|
||||||
# Transformer en format pour ingest_summaries
|
|
||||||
summaries_text = {
|
|
||||||
title: content["summary"]
|
|
||||||
for title, content in summaries_content.items()
|
|
||||||
}
|
|
||||||
|
|
||||||
# Ajouter concepts dans la TOC
|
|
||||||
def enrich_toc_with_concepts(items: List[Dict]) -> None:
|
|
||||||
for item in items:
|
|
||||||
title = item.get("title", "")
|
|
||||||
if title in summaries_content:
|
|
||||||
item["concepts"] = summaries_content[title]["concepts"]
|
|
||||||
if "children" in item:
|
|
||||||
enrich_toc_with_concepts(item["children"])
|
|
||||||
|
|
||||||
enrich_toc_with_concepts(toc)
|
|
||||||
|
|
||||||
# Insérer avec vrais résumés
|
|
||||||
ingest_summaries(client, doc_name, toc, summaries_text)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5.2 Solution Rapide : Calculer chunksCount Dynamiquement
|
|
||||||
|
|
||||||
**Modifier** : `utils/weaviate_ingest.py:ingest_summaries()`
|
|
||||||
|
|
||||||
```python
|
|
||||||
def ingest_summaries(
|
|
||||||
client: WeaviateClient,
|
|
||||||
doc_name: str,
|
|
||||||
toc: List[Dict[str, Any]],
|
|
||||||
summaries_content: Dict[str, str],
|
|
||||||
chunks: List[Dict[str, Any]] = [], # ← NOUVEAU paramètre
|
|
||||||
) -> int:
|
|
||||||
|
|
||||||
summaries_to_insert: List[SummaryObject] = []
|
|
||||||
|
|
||||||
def count_chunks_for_section(section_path: str) -> int:
|
|
||||||
"""Compte chunks appartenant à cette section."""
|
|
||||||
count = 0
|
|
||||||
for chunk in chunks:
|
|
||||||
if chunk.get("sectionPath", "").startswith(section_path):
|
|
||||||
count += 1
|
|
||||||
return count
|
|
||||||
|
|
||||||
def process_toc(items: List[Dict[str, Any]], parent_path: str = "") -> None:
|
|
||||||
for item in items:
|
|
||||||
title: str = item.get("title", "")
|
|
||||||
level: int = item.get("level", 1)
|
|
||||||
path: str = f"{parent_path} > {title}" if parent_path else title
|
|
||||||
|
|
||||||
summary_obj: SummaryObject = {
|
|
||||||
"sectionPath": path,
|
|
||||||
"title": title,
|
|
||||||
"level": level,
|
|
||||||
"text": summaries_content.get(title, title),
|
|
||||||
"concepts": item.get("concepts", []),
|
|
||||||
|
|
||||||
# ✅ CORRECTIF : Calculer dynamiquement
|
|
||||||
"chunksCount": count_chunks_for_section(path),
|
|
||||||
|
|
||||||
"document": {
|
|
||||||
"sourceId": doc_name,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
summaries_to_insert.append(summary_obj)
|
|
||||||
|
|
||||||
if "children" in item:
|
|
||||||
process_toc(item["children"], path)
|
|
||||||
|
|
||||||
process_toc(toc)
|
|
||||||
|
|
||||||
# ... (reste du code)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Modifier appel** : `utils/weaviate_ingest.py:844-845`
|
|
||||||
|
|
||||||
```python
|
|
||||||
if ingest_summary_collection and toc:
|
|
||||||
# ✅ Passer les chunks pour calcul de chunksCount
|
|
||||||
ingest_summaries(client, doc_name, toc, {}, chunks)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5.3 Solution Minimale : Ré-injecter avec Vraies Données
|
|
||||||
|
|
||||||
Si vous avez déjà les résumés dans les JSON :
|
|
||||||
|
|
||||||
```python
|
|
||||||
# Script de correction rapide
|
|
||||||
import json
|
|
||||||
import weaviate
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
# Charger le JSON avec les résumés
|
|
||||||
chunks_file = Path("output/peirce_collected_papers_fixed/peirce_collected_papers_fixed_chunks.json")
|
|
||||||
with open(chunks_file, 'r', encoding='utf-8') as f:
|
|
||||||
data = json.load(f)
|
|
||||||
|
|
||||||
# Vérifier s'il y a des résumés
|
|
||||||
if 'summaries' in data:
|
|
||||||
print(f"Trouvé {len(data['summaries'])} résumés dans le JSON")
|
|
||||||
|
|
||||||
# Connecter à Weaviate
|
|
||||||
client = weaviate.connect_to_local()
|
|
||||||
|
|
||||||
# Supprimer anciens Summary
|
|
||||||
summaries = client.collections.get("Summary")
|
|
||||||
summaries.data.delete_many(
|
|
||||||
where=Filter.by_property("document").by_property("sourceId").equal("peirce_collected_papers_fixed")
|
|
||||||
)
|
|
||||||
|
|
||||||
# Réinsérer avec vrais résumés
|
|
||||||
from utils.weaviate_ingest import ingest_summaries
|
|
||||||
|
|
||||||
toc = data['metadata']['toc']
|
|
||||||
chunks = data['chunks']
|
|
||||||
|
|
||||||
# Extraire résumés du JSON
|
|
||||||
summaries_content = {
|
|
||||||
s['title']: s['text']
|
|
||||||
for s in data['summaries']
|
|
||||||
}
|
|
||||||
|
|
||||||
# Réinjecter
|
|
||||||
count = ingest_summaries(client, "peirce_collected_papers_fixed", toc, summaries_content, chunks)
|
|
||||||
print(f"Réinséré {count} résumés")
|
|
||||||
|
|
||||||
client.close()
|
|
||||||
else:
|
|
||||||
print("❌ Pas de résumés dans le JSON - il faut les générer avec LLM")
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 6. Résumé Visual
|
|
||||||
|
|
||||||
```
|
|
||||||
┌─────────────────────────────────────────────────────────────────┐
|
|
||||||
│ PIPELINE ACTUEL (CASSÉ) │
|
|
||||||
└─────────────────────────────────────────────────────────────────┘
|
|
||||||
|
|
||||||
PDF → OCR → Markdown → TOC Extraction (LLM)
|
|
||||||
│
|
|
||||||
└─► toc = [
|
|
||||||
{"title": "Peirce: CP 5.314", "level": 1},
|
|
||||||
{"title": "La sémiose", "level": 2}
|
|
||||||
]
|
|
||||||
|
|
||||||
↓
|
|
||||||
|
|
||||||
Chunking (LLM) → chunks = [
|
|
||||||
{"text": "Un signe...", "sectionPath": "Peirce: CP 5.314 > La sémiose"},
|
|
||||||
{"text": "La sémiose...", "sectionPath": "Peirce: CP 5.314 > La sémiose"},
|
|
||||||
...
|
|
||||||
]
|
|
||||||
|
|
||||||
↓
|
|
||||||
|
|
||||||
Ingestion → ingest_summaries(client, doc_name, toc, {}) ← VIDE !
|
|
||||||
│
|
|
||||||
└─► Summary créés avec:
|
|
||||||
- text: "Peirce: CP 5.314" (juste le titre)
|
|
||||||
- concepts: []
|
|
||||||
- chunksCount: 0
|
|
||||||
|
|
||||||
|
|
||||||
┌─────────────────────────────────────────────────────────────────┐
|
|
||||||
│ PIPELINE CORRIGÉ (ATTENDU) │
|
|
||||||
└─────────────────────────────────────────────────────────────────┘
|
|
||||||
|
|
||||||
PDF → OCR → Markdown → TOC Extraction → Chunking
|
|
||||||
│
|
|
||||||
↓
|
|
||||||
Summarization (LLM) ← NOUVEAU !
|
|
||||||
│
|
|
||||||
└─► summaries_content = {
|
|
||||||
"Peirce: CP 5.314": {
|
|
||||||
"summary": "Ce passage explore...",
|
|
||||||
"concepts": ["sémiose", "triade"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
↓
|
|
||||||
|
|
||||||
Ingestion → ingest_summaries(client, doc_name, toc, summaries_content, chunks)
|
|
||||||
│
|
|
||||||
└─► Summary créés avec:
|
|
||||||
- text: "Ce passage explore la théorie de la sémiose..." ✅
|
|
||||||
- concepts: ["sémiose", "triade", "signe"] ✅
|
|
||||||
- chunksCount: 23 ✅
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 7. Conclusion
|
|
||||||
|
|
||||||
### État Actuel
|
|
||||||
|
|
||||||
**Summary → Chunk** : ❌ LIEN CASSÉ
|
|
||||||
|
|
||||||
| Aspect | Actuel | Attendu | Status |
|
|
||||||
|--------|--------|---------|--------|
|
|
||||||
| **text** | "Peirce: CP 5.314" | "Ce passage explore..." | ❌ Vide |
|
|
||||||
| **concepts** | `[]` | `["sémiose", "triade"]` | ❌ Vide |
|
|
||||||
| **chunksCount** | 0 | 23 | ❌ Faux |
|
|
||||||
| **sectionPath** | ✅ Correct | ✅ Correct | ✅ OK |
|
|
||||||
|
|
||||||
### Lien Théorique vs Réel
|
|
||||||
|
|
||||||
**Théorique** (design prévu):
|
|
||||||
```
|
|
||||||
Summary.sectionPath = "Peirce: CP 5.314 > La sémiose"
|
|
||||||
↓ LIEN
|
|
||||||
Chunk.sectionPath = "Peirce: CP 5.314 > La sémiose"
|
|
||||||
Chunk.sectionPath = "Peirce: CP 5.314 > La sémiose"
|
|
||||||
... (23 chunks)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Réel** (implémentation actuelle):
|
|
||||||
```
|
|
||||||
Summary.sectionPath = "Peirce: CP 5.314" ✅ OK
|
|
||||||
Summary.chunksCount = 0 ❌ FAUX
|
|
||||||
Summary.text = "Peirce: CP 5.314" ❌ VIDE
|
|
||||||
|
|
||||||
Chunk.sectionPath = "Peirce: CP 5.314" ✅ OK
|
|
||||||
Chunk.text = "Un signe, ou representamen..." ✅ OK
|
|
||||||
```
|
|
||||||
|
|
||||||
**LIEN** : ⚠️ Existe techniquement (sectionPath identique) mais inutilisable car Summary vides.
|
|
||||||
|
|
||||||
### Actions Requises
|
|
||||||
|
|
||||||
**Priorité 1** : Générer résumés LLM (créer `llm_summarizer.py`)
|
|
||||||
**Priorité 2** : Calculer `chunksCount` dynamiquement
|
|
||||||
**Priorité 3** : Extraire concepts pour Summary
|
|
||||||
|
|
||||||
**ROI** : Activer recherche hiérarchique Summary → Chunk (+30% précision)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Dernière mise à jour**: 2026-01-03
|
|
||||||
**Auteur**: Analyse du code source
|
|
||||||
**Version**: 1.0
|
|
||||||
@@ -1,280 +0,0 @@
|
|||||||
# Fix - Recherche Hiérarchique
|
|
||||||
|
|
||||||
**Date**: 2026-01-03
|
|
||||||
**Problème**: Mode hiérarchique n'affichait aucun résultat
|
|
||||||
**Statut**: ✅ Résolu et testé
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Problème Identifié
|
|
||||||
|
|
||||||
Le mode hiérarchique retournait **0 résultats** pour toutes les requêtes.
|
|
||||||
|
|
||||||
**Symptôme**:
|
|
||||||
```
|
|
||||||
Mode: 🌳 Hiérarchique
|
|
||||||
Résultat: "Aucun résultat trouvé"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Cause Racine
|
|
||||||
|
|
||||||
**Fichier**: `flask_app.py`
|
|
||||||
**Fonction**: `hierarchical_search()`
|
|
||||||
**Lignes**: 338-344
|
|
||||||
|
|
||||||
### Code Problématique
|
|
||||||
|
|
||||||
```python
|
|
||||||
summaries_result = summary_collection.query.near_text(
|
|
||||||
query=query,
|
|
||||||
limit=sections_limit,
|
|
||||||
return_metadata=wvq.MetadataQuery(distance=True),
|
|
||||||
return_properties=[
|
|
||||||
"sectionPath", "title", "text", "level", "concepts"
|
|
||||||
], # ❌ N'inclut PAS "document" (nested object)
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Problème**: Le paramètre `return_properties` **excluait** le nested object `"document"`.
|
|
||||||
|
|
||||||
### Conséquence
|
|
||||||
|
|
||||||
```python
|
|
||||||
# Ligne 363-366
|
|
||||||
doc_obj = props.get("document") # ← Retourne None ou {}
|
|
||||||
source_id = ""
|
|
||||||
if doc_obj and isinstance(doc_obj, dict):
|
|
||||||
source_id = doc_obj.get("sourceId", "") # ← source_id reste vide
|
|
||||||
|
|
||||||
# Ligne 374
|
|
||||||
"document_source_id": source_id, # ← Vide!
|
|
||||||
|
|
||||||
# Ligne 385-387
|
|
||||||
for section in sections_data:
|
|
||||||
source_id = section["document_source_id"]
|
|
||||||
if not source_id:
|
|
||||||
continue # ← Toutes les sections sont SKIPPÉES!
|
|
||||||
|
|
||||||
# Ligne 410-421
|
|
||||||
if not sections_data:
|
|
||||||
return {
|
|
||||||
"mode": "hierarchical",
|
|
||||||
"sections": [],
|
|
||||||
"results": [],
|
|
||||||
"total_chunks": 0, # ← 0 résultats!
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Résultat**: Toutes les sections étaient filtrées → 0 résultats
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Solution Appliquée
|
|
||||||
|
|
||||||
**Suppression de `return_properties`** pour laisser Weaviate retourner **tous** les properties automatiquement, y compris les nested objects.
|
|
||||||
|
|
||||||
### Code Corrigé
|
|
||||||
|
|
||||||
```python
|
|
||||||
summaries_result = summary_collection.query.near_text(
|
|
||||||
query=query,
|
|
||||||
limit=sections_limit,
|
|
||||||
return_metadata=wvq.MetadataQuery(distance=True),
|
|
||||||
# Note: Don't specify return_properties - let Weaviate return all properties
|
|
||||||
# including nested objects like "document" which we need for source_id
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Changement**: Ligne 342-344 - Suppression du paramètre `return_properties`
|
|
||||||
|
|
||||||
### Pourquoi ça fonctionne?
|
|
||||||
|
|
||||||
En **Weaviate v4**, quand on ne spécifie pas `return_properties`:
|
|
||||||
- ✅ Weaviate retourne **automatiquement** tous les properties
|
|
||||||
- ✅ Les **nested objects** comme `document` sont inclus
|
|
||||||
- ✅ Le `source_id` est correctement récupéré
|
|
||||||
- ✅ Les sections ne sont plus filtrées
|
|
||||||
- ✅ Les résultats s'affichent
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Tests de Validation
|
|
||||||
|
|
||||||
### ✅ Test Automatisé
|
|
||||||
|
|
||||||
**Script**: `test_hierarchical_fix.py`
|
|
||||||
|
|
||||||
```python
|
|
||||||
query = "What is the Turing test?"
|
|
||||||
mode = "hierarchical"
|
|
||||||
```
|
|
||||||
|
|
||||||
**Résultat**:
|
|
||||||
```
|
|
||||||
✅ Mode hiérarchique détecté
|
|
||||||
✅ 13 cartes de passage trouvées
|
|
||||||
✅ 4 groupes de sections
|
|
||||||
✅ Headers de section présents
|
|
||||||
✅ Textes de résumé présents
|
|
||||||
✅ Concepts affichés
|
|
||||||
|
|
||||||
RÉSULTAT: Mode hiérarchique fonctionne!
|
|
||||||
```
|
|
||||||
|
|
||||||
### ✅ Test Manuel
|
|
||||||
|
|
||||||
**URL**: `http://localhost:5000/search?q=What+is+the+Turing+test&mode=hierarchical`
|
|
||||||
|
|
||||||
**Résultat attendu**:
|
|
||||||
- Badge "🌳 Recherche hiérarchique (N sections)"
|
|
||||||
- Groupes de sections avec résumés
|
|
||||||
- Chunks regroupés par section
|
|
||||||
- Concepts affichés
|
|
||||||
- Metadata complète
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Comparaison Avant/Après
|
|
||||||
|
|
||||||
### Avant (Bugué)
|
|
||||||
|
|
||||||
```
|
|
||||||
Query: "What is the Turing test?"
|
|
||||||
Mode: Hiérarchique
|
|
||||||
|
|
||||||
Étape 1 (Summary): 3 sections trouvées ✓
|
|
||||||
Étape 2 (Filter): 0 sections après filtrage ✗
|
|
||||||
(source_id vide → toutes skippées)
|
|
||||||
|
|
||||||
Résultat: "Aucun résultat trouvé" ❌
|
|
||||||
```
|
|
||||||
|
|
||||||
### Après (Corrigé)
|
|
||||||
|
|
||||||
```
|
|
||||||
Query: "What is the Turing test?"
|
|
||||||
Mode: Hiérarchique
|
|
||||||
|
|
||||||
Étape 1 (Summary): 3 sections trouvées ✓
|
|
||||||
Étape 2 (Filter): 3 sections valides ✓
|
|
||||||
(source_id récupéré → sections conservées)
|
|
||||||
Étape 3 (Chunks): 13 chunks trouvés ✓
|
|
||||||
|
|
||||||
Résultat: 4 sections avec 13 passages ✅
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Impact
|
|
||||||
|
|
||||||
### Code
|
|
||||||
- **1 ligne modifiée** (flask_app.py:342-344)
|
|
||||||
- **0 régression** (autres modes inchangés)
|
|
||||||
- **0 effet secondaire**
|
|
||||||
|
|
||||||
### Fonctionnalité
|
|
||||||
- ✅ Mode hiérarchique opérationnel
|
|
||||||
- ✅ Summary → Chunks fonctionnel
|
|
||||||
- ✅ Sections regroupées correctement
|
|
||||||
- ✅ Metadata complète affichée
|
|
||||||
|
|
||||||
### Performance
|
|
||||||
- **Temps de réponse**: Identique (~500ms)
|
|
||||||
- **Qualité résultats**: Excellente
|
|
||||||
- **Visibilité**: Variable (dépend de la requête)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Modes Disponibles (État Final)
|
|
||||||
|
|
||||||
| Mode | Collection | Étapes | Statut | Performance |
|
|
||||||
|------|------------|--------|--------|-------------|
|
|
||||||
| **Auto** | Détection | 1-2 | ✅ OK | Variable |
|
|
||||||
| **Simple** | Chunk | 1 | ✅ OK | 10% visibilité |
|
|
||||||
| **Hiérarchique** | Summary → Chunk | 2 | ✅ **CORRIGÉ** | Variable |
|
|
||||||
| **Summary** | Summary | 1 | ✅ OK | 90% visibilité |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Leçon Apprise
|
|
||||||
|
|
||||||
### ❌ Erreur Commune
|
|
||||||
|
|
||||||
**NE PAS** spécifier `return_properties` quand on a besoin de nested objects:
|
|
||||||
|
|
||||||
```python
|
|
||||||
# MAUVAIS
|
|
||||||
results = collection.query.near_text(
|
|
||||||
query=query,
|
|
||||||
return_properties=["field1", "field2"] # ❌ Exclut nested objects
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
### ✅ Bonne Pratique
|
|
||||||
|
|
||||||
**LAISSER** Weaviate retourner automatiquement tous les properties:
|
|
||||||
|
|
||||||
```python
|
|
||||||
# BON
|
|
||||||
results = collection.query.near_text(
|
|
||||||
query=query,
|
|
||||||
# Pas de return_properties → tous les properties retournés ✓
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Alternative** (si vraiment nécessaire):
|
|
||||||
|
|
||||||
```python
|
|
||||||
# ACCEPTABLE
|
|
||||||
results = collection.query.near_text(
|
|
||||||
query=query,
|
|
||||||
return_properties=["field1", "field2", "nested_object"] # ✓ Inclure nested
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
Mais la **meilleure approche** reste de **ne pas spécifier** `return_properties` quand on utilise des nested objects, pour éviter ce genre de bug.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Vérification Finale
|
|
||||||
|
|
||||||
### Checklist de Test
|
|
||||||
|
|
||||||
- [x] Mode auto-détection fonctionne
|
|
||||||
- [x] Mode simple fonctionne
|
|
||||||
- [x] Mode hiérarchique fonctionne ✅ **CORRIGÉ**
|
|
||||||
- [x] Mode summary fonctionne
|
|
||||||
- [x] Filtres auteur/work fonctionnent
|
|
||||||
- [x] Affichage correct pour tous modes
|
|
||||||
- [x] Pas de régression
|
|
||||||
|
|
||||||
### Commande de Test
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Démarrer Flask
|
|
||||||
python flask_app.py
|
|
||||||
|
|
||||||
# Tester mode hiérarchique
|
|
||||||
curl "http://localhost:5000/search?q=What+is+the+Turing+test&mode=hierarchical"
|
|
||||||
|
|
||||||
# Ou avec script
|
|
||||||
python test_hierarchical_fix.py
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Conclusion
|
|
||||||
|
|
||||||
✅ **Le mode hiérarchique est maintenant complètement fonctionnel.**
|
|
||||||
|
|
||||||
Le bug était subtil mais critique : l'exclusion du nested object `document` par `return_properties` rendait impossible la récupération du `source_id`, ce qui causait le filtrage de toutes les sections.
|
|
||||||
|
|
||||||
La solution simple (supprimer `return_properties`) résout le problème sans effets secondaires.
|
|
||||||
|
|
||||||
**Tous les modes de recherche fonctionnent désormais correctement!**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Fichier modifié**: `flask_app.py` (ligne 342-344)
|
|
||||||
**Tests**: `test_hierarchical_fix.py`
|
|
||||||
**Statut**: ✅ Résolu et validé
|
|
||||||
@@ -1,297 +0,0 @@
|
|||||||
# Intégration Recherche Summary - Résumé
|
|
||||||
|
|
||||||
**Date**: 2026-01-03
|
|
||||||
**Statut**: ✅ Intégration complète et testée
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Fichiers Modifiés/Créés
|
|
||||||
|
|
||||||
### 1. Backend (flask_app.py)
|
|
||||||
**Modifications**:
|
|
||||||
- ✅ Ajout de la fonction `search_summaries_backend()` (lignes 2907-2999)
|
|
||||||
- ✅ Ajout de la route `@app.route("/search/summary")` (lignes 3002-3046)
|
|
||||||
|
|
||||||
**Fonctionnalités**:
|
|
||||||
- Recherche sémantique dans la collection Summary
|
|
||||||
- Filtrage par seuil de similarité configurable
|
|
||||||
- Icônes de documents automatiques (🟣🟢🟡🔵⚪)
|
|
||||||
- Métadonnées riches (auteur, année, concepts, résumé)
|
|
||||||
|
|
||||||
### 2. Template (templates/search_summary.html)
|
|
||||||
**Statut**: ✅ Créé (nouveau fichier)
|
|
||||||
|
|
||||||
**Caractéristiques**:
|
|
||||||
- Interface cohérente avec le design existant
|
|
||||||
- Bannière d'information sur la performance (90% vs 10%)
|
|
||||||
- Cartes de résumés avec dégradés et animations
|
|
||||||
- Badges de concepts clés
|
|
||||||
- Suggestions de recherche pré-remplies
|
|
||||||
- Bouton de bascule vers recherche classique
|
|
||||||
|
|
||||||
### 3. Navigation (templates/base.html)
|
|
||||||
**Modifications**:
|
|
||||||
- ✅ Ajout du lien "Recherche Résumés" dans la sidebar (lignes 709-713)
|
|
||||||
- ✅ Badge "90%" pour indiquer la performance
|
|
||||||
- ✅ Icône 📚 distincte
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Tests de Validation
|
|
||||||
|
|
||||||
### ✅ Tests Fonctionnels (4/4 PASS)
|
|
||||||
|
|
||||||
#### Test 1: Requête IA (Haugeland)
|
|
||||||
```
|
|
||||||
Query: "What is the Turing test?"
|
|
||||||
✅ PASS - Found Haugeland icon 🟣
|
|
||||||
✅ PASS - Results displayed
|
|
||||||
✅ PASS - Similarity scores displayed
|
|
||||||
✅ PASS - Concepts displayed
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Test 2: Requête Vertu (Platon)
|
|
||||||
```
|
|
||||||
Query: "Can virtue be taught?"
|
|
||||||
✅ PASS - Found Platon icon 🟢
|
|
||||||
✅ PASS - Results displayed
|
|
||||||
✅ PASS - Similarity scores displayed
|
|
||||||
✅ PASS - Concepts displayed
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Test 3: Requête Pragmatisme (Tiercelin)
|
|
||||||
```
|
|
||||||
Query: "What is pragmatism according to Peirce?"
|
|
||||||
✅ PASS - Found Tiercelin icon 🟡
|
|
||||||
✅ PASS - Results displayed
|
|
||||||
✅ PASS - Similarity scores displayed
|
|
||||||
✅ PASS - Concepts displayed
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Test 4: Navigation
|
|
||||||
```
|
|
||||||
✅ PASS - Navigation link present
|
|
||||||
✅ PASS - Summary search label found
|
|
||||||
```
|
|
||||||
|
|
||||||
**Résultat Global**: 100% de réussite (12/12 checks passés)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Accès à la Fonctionnalité
|
|
||||||
|
|
||||||
### URL Directe
|
|
||||||
```
|
|
||||||
http://localhost:5000/search/summary
|
|
||||||
```
|
|
||||||
|
|
||||||
### Via Navigation
|
|
||||||
1. Cliquer sur le menu hamburger (☰) en haut à gauche
|
|
||||||
2. Cliquer sur "📚 Recherche Résumés" (badge 90%)
|
|
||||||
3. Entrer une question et rechercher
|
|
||||||
|
|
||||||
### Paramètres URL
|
|
||||||
```
|
|
||||||
/search/summary?q=votre+question&limit=10&min_similarity=0.65
|
|
||||||
```
|
|
||||||
|
|
||||||
**Paramètres disponibles**:
|
|
||||||
- `q` (string): Question de recherche
|
|
||||||
- `limit` (int): Nombre de résultats (5, 10, 15, 20)
|
|
||||||
- `min_similarity` (float): Seuil 0-1 (0.60, 0.65, 0.70, 0.75)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Performance Démontrée
|
|
||||||
|
|
||||||
### Recherche Summary (Nouvelle Interface)
|
|
||||||
- ✅ 90% de visibilité des documents riches
|
|
||||||
- ✅ 100% de précision sur tests (3/3)
|
|
||||||
- ✅ Temps de réponse: ~200-500ms
|
|
||||||
- ✅ Métadonnées riches affichées
|
|
||||||
|
|
||||||
### Recherche Chunk (Ancienne Interface)
|
|
||||||
- ❌ 10% de visibilité des documents riches
|
|
||||||
- ⚠️ Dominée par chunks Peirce (97%)
|
|
||||||
- ✅ Toujours disponible via `/search`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Comparaison Visuelle
|
|
||||||
|
|
||||||
### Nouvelle Interface (Summary)
|
|
||||||
```
|
|
||||||
┌─────────────────────────────────────────┐
|
|
||||||
│ 📚 Recherche par Résumés │
|
|
||||||
│ │
|
|
||||||
│ ┌─────────────────────────────────────┐ │
|
|
||||||
│ │ 🟣 Haugeland - 69.5% similaire │ │
|
|
||||||
│ │ Computers and intelligence │ │
|
|
||||||
│ │ │ │
|
|
||||||
│ │ This section examines Turing's... │ │
|
|
||||||
│ │ │ │
|
|
||||||
│ │ Concepts: Turing test, AI, ... │ │
|
|
||||||
│ │ 📄 1 passage détaillé │ │
|
|
||||||
│ └─────────────────────────────────────┘ │
|
|
||||||
└─────────────────────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
### Ancienne Interface (Chunk)
|
|
||||||
```
|
|
||||||
┌─────────────────────────────────────────┐
|
|
||||||
│ 🔍 Recherche sémantique │
|
|
||||||
│ │
|
|
||||||
│ ┌─────────────────────────────────────┐ │
|
|
||||||
│ │ ⚪ Peirce - 73.5% similaire │ │
|
|
||||||
│ │ "This idea of discrete quantity..." │ │
|
|
||||||
│ │ │ │
|
|
||||||
│ │ Section: CP 4.162 │ │
|
|
||||||
│ └─────────────────────────────────────┘ │
|
|
||||||
│ [4 autres résultats Peirce...] │
|
|
||||||
└─────────────────────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Architecture Technique
|
|
||||||
|
|
||||||
### Backend Flow
|
|
||||||
```
|
|
||||||
User Query
|
|
||||||
↓
|
|
||||||
@app.route("/search/summary")
|
|
||||||
↓
|
|
||||||
search_summaries_backend()
|
|
||||||
↓
|
|
||||||
Weaviate Summary.query.near_text()
|
|
||||||
↓
|
|
||||||
Format results (icons, metadata)
|
|
||||||
↓
|
|
||||||
render_template("search_summary.html")
|
|
||||||
↓
|
|
||||||
HTML Response to Browser
|
|
||||||
```
|
|
||||||
|
|
||||||
### Collection Summary
|
|
||||||
- **Total**: 114 résumés
|
|
||||||
- **Riches**: 106 résumés (>100 chars)
|
|
||||||
- **Vecteurs**: BAAI/bge-m3 (1024-dim)
|
|
||||||
- **Documents**: Tiercelin (51), Haugeland (50), Platon (12), Logique (1)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Utilisation Recommandée
|
|
||||||
|
|
||||||
### Cas d'Usage Summary (Recommandé)
|
|
||||||
- ✅ Questions générales sur un sujet
|
|
||||||
- ✅ Découverte exploratoire
|
|
||||||
- ✅ Vue d'ensemble d'un document/section
|
|
||||||
- ✅ Identification de sections pertinentes
|
|
||||||
|
|
||||||
**Exemples**:
|
|
||||||
- "What is the Turing test?"
|
|
||||||
- "Can virtue be taught?"
|
|
||||||
- "What is pragmatism?"
|
|
||||||
|
|
||||||
### Cas d'Usage Chunk (Ancienne)
|
|
||||||
- Citations précises nécessaires
|
|
||||||
- Recherche très spécifique dans le texte
|
|
||||||
- Analyse détaillée d'un passage
|
|
||||||
|
|
||||||
**Exemples**:
|
|
||||||
- "Exact quote about X"
|
|
||||||
- Requêtes avec mots-clés très précis
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Prochaines Étapes (Optionnel)
|
|
||||||
|
|
||||||
### Court Terme
|
|
||||||
- [ ] Ajouter bouton "Voir chunks détaillés" sur chaque résumé
|
|
||||||
- [ ] Route `/summary/<uuid>/chunks` pour expansion
|
|
||||||
- [ ] Export résultats (JSON/CSV)
|
|
||||||
|
|
||||||
### Moyen Terme
|
|
||||||
- [ ] Mode hybride avec toggle Summary/Chunk
|
|
||||||
- [ ] Filtres par auteur/document
|
|
||||||
- [ ] Historique de recherche
|
|
||||||
- [ ] Sauvegarde de recherches favorites
|
|
||||||
|
|
||||||
### Long Terme
|
|
||||||
- [ ] Suggestions de recherche basées sur l'historique
|
|
||||||
- [ ] Graphe de relations entre concepts
|
|
||||||
- [ ] Visualisation des sections les plus consultées
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Maintenance
|
|
||||||
|
|
||||||
### Dépendances
|
|
||||||
- Flask 3.0+
|
|
||||||
- Weaviate Python client v4
|
|
||||||
- Jinja2 (inclus avec Flask)
|
|
||||||
|
|
||||||
### Monitoring
|
|
||||||
- Logs Flask: Recherches effectuées dans stdout
|
|
||||||
- Weaviate: Métriques via `http://localhost:8080/v1/meta`
|
|
||||||
|
|
||||||
### Mise à Jour
|
|
||||||
Si nouveaux résumés générés:
|
|
||||||
1. Les résumés sont automatiquement vectorisés dans Summary
|
|
||||||
2. Aucune modification de code nécessaire
|
|
||||||
3. Nouveaux résumés apparaissent immédiatement dans recherche
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Support et Débogage
|
|
||||||
|
|
||||||
### Vérifier que Weaviate tourne
|
|
||||||
```bash
|
|
||||||
docker ps | grep weaviate
|
|
||||||
# Devrait montrer: Up X hours
|
|
||||||
```
|
|
||||||
|
|
||||||
### Vérifier les résumés en base
|
|
||||||
```bash
|
|
||||||
python -c "
|
|
||||||
import weaviate
|
|
||||||
client = weaviate.connect_to_local()
|
|
||||||
summaries = client.collections.get('Summary')
|
|
||||||
print(f'Total summaries: {len(list(summaries.iterator()))}')
|
|
||||||
client.close()
|
|
||||||
"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Logs Flask
|
|
||||||
```bash
|
|
||||||
# Le serveur affiche les requêtes dans stdout
|
|
||||||
127.0.0.1 - - [DATE] "GET /search/summary?q=... HTTP/1.1" 200 -
|
|
||||||
```
|
|
||||||
|
|
||||||
### Test Manuel
|
|
||||||
```bash
|
|
||||||
# Test rapide
|
|
||||||
curl "http://localhost:5000/search/summary?q=test&limit=5"
|
|
||||||
# Devrait retourner HTML avec résultats
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Conclusion
|
|
||||||
|
|
||||||
✅ **Intégration complète et fonctionnelle**
|
|
||||||
- Backend: Fonction + Route
|
|
||||||
- Frontend: Template + Navigation
|
|
||||||
- Tests: 100% de réussite
|
|
||||||
- Performance: 90% de visibilité démontrée
|
|
||||||
|
|
||||||
La nouvelle interface de recherche Summary est maintenant disponible dans l'application Flask et offre une expérience utilisateur nettement supérieure pour la découverte de documents philosophiques.
|
|
||||||
|
|
||||||
**Recommandation**: Promouvoir la recherche Summary comme interface principale et garder la recherche Chunk pour les cas d'usage spécifiques.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Auteur**: Claude Sonnet 4.5
|
|
||||||
**Date**: 2026-01-03
|
|
||||||
**Version**: 1.0
|
|
||||||
**Status**: ✅ Production Ready
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,239 +0,0 @@
|
|||||||
# Quickstart - Recherche Summary
|
|
||||||
|
|
||||||
Guide rapide pour utiliser la nouvelle interface de recherche optimisée.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 Démarrage Rapide
|
|
||||||
|
|
||||||
### 1. Démarrer Weaviate (si pas déjà lancé)
|
|
||||||
```bash
|
|
||||||
docker compose up -d
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Démarrer l'application Flask
|
|
||||||
```bash
|
|
||||||
cd generations/library_rag
|
|
||||||
python flask_app.py
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Accéder à l'interface
|
|
||||||
Ouvrir dans le navigateur: **http://localhost:5000**
|
|
||||||
|
|
||||||
### 4. Utiliser la Recherche Summary
|
|
||||||
1. Cliquer sur le menu ☰ (hamburger) en haut à gauche
|
|
||||||
2. Cliquer sur **"📚 Recherche Résumés"** (badge 90%)
|
|
||||||
3. Entrer une question et cliquer sur **"🔍 Rechercher"**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 💡 Exemples de Recherche
|
|
||||||
|
|
||||||
### IA et Philosophie de l'Esprit (Haugeland 🟣)
|
|
||||||
```
|
|
||||||
What is the Turing test?
|
|
||||||
Can machines think?
|
|
||||||
What is a physical symbol system?
|
|
||||||
How do connectionist networks work?
|
|
||||||
```
|
|
||||||
|
|
||||||
**Résultat attendu**: Résumés de Haugeland avec icône 🟣
|
|
||||||
|
|
||||||
### Vertu et Connaissance (Platon 🟢)
|
|
||||||
```
|
|
||||||
Can virtue be taught?
|
|
||||||
What is the theory of recollection?
|
|
||||||
How does Socrates define virtue?
|
|
||||||
```
|
|
||||||
|
|
||||||
**Résultat attendu**: Résumés de Platon (Ménon) avec icône 🟢
|
|
||||||
|
|
||||||
### Pragmatisme et Sémiotique (Tiercelin 🟡)
|
|
||||||
```
|
|
||||||
What is pragmatism according to Peirce?
|
|
||||||
How does thought work as a sign?
|
|
||||||
What is the relationship between doubt and inquiry?
|
|
||||||
```
|
|
||||||
|
|
||||||
**Résultat attendu**: Résumés de Tiercelin avec icône 🟡
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎨 Interface Visuelle
|
|
||||||
|
|
||||||
### Ce que vous verrez:
|
|
||||||
|
|
||||||
```
|
|
||||||
┌──────────────────────────────────────────────────────────┐
|
|
||||||
│ 📚 Recherche par Résumés │
|
|
||||||
│ │
|
|
||||||
│ ┌────────────────────────────────────────────────────┐ │
|
|
||||||
│ │ ✨ Nouvelle interface de recherche optimisée │ │
|
|
||||||
│ │ Performance: [📊 90% de visibilité] vs [📉 10%] │ │
|
|
||||||
│ └────────────────────────────────────────────────────┘ │
|
|
||||||
│ │
|
|
||||||
│ ┌─ Formulaire de recherche ─────────────────────────┐ │
|
|
||||||
│ │ Votre question: [What is the Turing test?] │ │
|
|
||||||
│ │ Nombre: [10 résumés ▼] Seuil: [65% ▼] │ │
|
|
||||||
│ │ [🔍 Rechercher] [Réinitialiser] [🔄 Classique] │ │
|
|
||||||
│ └───────────────────────────────────────────────────┘ │
|
|
||||||
│ │
|
|
||||||
│ 3 résumés trouvés [📚 Recherche par Résumés] │
|
|
||||||
│ │
|
|
||||||
│ ┌─────────────────────────────────────────────────────┐ │
|
|
||||||
│ │ 🟣 [Haugeland] John Haugeland (2023) ⚡ 69.5% │ │
|
|
||||||
│ │ Computers and intelligence │ │
|
|
||||||
│ │ │ │
|
|
||||||
│ │ "This section examines Turing's 1950 prediction... │ │
|
|
||||||
│ │ analyzing the theoretical foundations..." │ │
|
|
||||||
│ │ │ │
|
|
||||||
│ │ Concepts: Turing test | AI | formal function |... │ │
|
|
||||||
│ │ 📄 1 passage détaillé Section: 2.2.3... │ │
|
|
||||||
│ └─────────────────────────────────────────────────────┘ │
|
|
||||||
│ │
|
|
||||||
│ [Plus de résultats...] │
|
|
||||||
└──────────────────────────────────────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 Comparaison des Modes
|
|
||||||
|
|
||||||
| Fonctionnalité | Summary (Nouveau) | Chunk (Ancien) |
|
|
||||||
|----------------|-------------------|----------------|
|
|
||||||
| **Visibilité documents riches** | 90% ✅ | 10% ❌ |
|
|
||||||
| **Vue d'ensemble** | Résumés de sections | Passages courts |
|
|
||||||
| **Métadonnées** | Riches (concepts, auteur) | Basiques |
|
|
||||||
| **Exploration** | Excellente | Difficile |
|
|
||||||
| **Précision citations** | Moyenne | Excellente |
|
|
||||||
| **Temps de réponse** | Rapide (~300ms) | Rapide (~300ms) |
|
|
||||||
|
|
||||||
### Quand utiliser Summary? ✅
|
|
||||||
- Questions générales
|
|
||||||
- Découverte de sujets
|
|
||||||
- Vue d'ensemble d'un document
|
|
||||||
- Identification de sections pertinentes
|
|
||||||
|
|
||||||
### Quand utiliser Chunk? 🔍
|
|
||||||
- Besoin de citations exactes
|
|
||||||
- Recherche très précise
|
|
||||||
- Analyse détaillée d'un passage
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 Paramètres Recommandés
|
|
||||||
|
|
||||||
### Exploration Large
|
|
||||||
```
|
|
||||||
Résultats: 15-20 résumés
|
|
||||||
Seuil: 60-65% (plus large)
|
|
||||||
```
|
|
||||||
**Utilisation**: Découverte de sujets, brainstorming
|
|
||||||
|
|
||||||
### Recherche Précise
|
|
||||||
```
|
|
||||||
Résultats: 5-10 résumés
|
|
||||||
Seuil: 70-75% (très précis)
|
|
||||||
```
|
|
||||||
**Utilisation**: Questions spécifiques, confirmation d'informations
|
|
||||||
|
|
||||||
### Par Défaut (Recommandé)
|
|
||||||
```
|
|
||||||
Résultats: 10 résumés
|
|
||||||
Seuil: 65% (équilibré)
|
|
||||||
```
|
|
||||||
**Utilisation**: Usage général, meilleur compromis
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔧 Troubleshooting
|
|
||||||
|
|
||||||
### "Aucun résumé trouvé"
|
|
||||||
**Solutions**:
|
|
||||||
1. Réduire le seuil de similarité (essayer 60%)
|
|
||||||
2. Reformuler la question en anglais/français
|
|
||||||
3. Utiliser des termes plus généraux
|
|
||||||
4. Vérifier que la question porte sur les documents disponibles
|
|
||||||
|
|
||||||
### Page ne charge pas
|
|
||||||
**Solutions**:
|
|
||||||
1. Vérifier que Flask tourne: `http://localhost:5000`
|
|
||||||
2. Vérifier que Weaviate tourne: `docker ps | grep weaviate`
|
|
||||||
3. Consulter les logs Flask dans le terminal
|
|
||||||
|
|
||||||
### Résultats non pertinents
|
|
||||||
**Solutions**:
|
|
||||||
1. Augmenter le seuil de similarité (essayer 70-75%)
|
|
||||||
2. Réduire le nombre de résultats
|
|
||||||
3. Être plus spécifique dans la question
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📚 Documents Disponibles
|
|
||||||
|
|
||||||
### 🟣 Haugeland - Mind Design III
|
|
||||||
**Sujets**: IA, philosophie de l'esprit, Turing test, réseaux de neurones, computation
|
|
||||||
**Résumés**: 50 sections
|
|
||||||
|
|
||||||
### 🟢 Platon - Ménon
|
|
||||||
**Sujets**: Vertu, connaissance, réminiscence, Socrate, enseignement
|
|
||||||
**Résumés**: 12 sections
|
|
||||||
|
|
||||||
### 🟡 Tiercelin - La Pensée-Signe
|
|
||||||
**Sujets**: Pragmatisme, Peirce, sémiotique, pensée, signes
|
|
||||||
**Résumés**: 51 sections
|
|
||||||
|
|
||||||
### 🔵 Peirce - La Logique de la Science
|
|
||||||
**Sujets**: Croyance, doute, méthode scientifique, fixation des croyances
|
|
||||||
**Résumés**: 1 section
|
|
||||||
|
|
||||||
**Total**: 114 résumés (106 riches) indexés et searchables
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎓 Conseils d'Utilisation
|
|
||||||
|
|
||||||
### 1. Formuler de Bonnes Questions
|
|
||||||
✅ **Bon**: "What is the Turing test and what does it tell us about intelligence?"
|
|
||||||
❌ **Mauvais**: "turing"
|
|
||||||
|
|
||||||
✅ **Bon**: "Can virtue be taught according to Plato?"
|
|
||||||
❌ **Mauvais**: "plato virtue"
|
|
||||||
|
|
||||||
### 2. Explorer les Concepts
|
|
||||||
Cliquer sur les concepts affichés pour voir les thèmes principaux d'une section.
|
|
||||||
|
|
||||||
### 3. Ajuster le Seuil
|
|
||||||
- Trop de résultats non pertinents? → Augmenter le seuil
|
|
||||||
- Pas assez de résultats? → Réduire le seuil
|
|
||||||
|
|
||||||
### 4. Basculer entre Modes
|
|
||||||
Utiliser le bouton "🔄 Recherche classique" pour comparer les résultats entre Summary et Chunk.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 Prochaines Fonctionnalités
|
|
||||||
|
|
||||||
Améliorations prévues:
|
|
||||||
- [ ] Bouton "Voir les passages détaillés" sur chaque résumé
|
|
||||||
- [ ] Filtres par auteur/document
|
|
||||||
- [ ] Historique de recherche
|
|
||||||
- [ ] Export des résultats (JSON/PDF)
|
|
||||||
- [ ] Suggestions de recherches liées
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📞 Support
|
|
||||||
|
|
||||||
- **Documentation complète**: `INTEGRATION_SUMMARY.md`
|
|
||||||
- **Analyse technique**: `ANALYSE_RAG_FINAL.md`
|
|
||||||
- **Guide d'utilisation**: `README_SEARCH.md`
|
|
||||||
- **Tests**: `test_flask_integration.py`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Version**: 1.0
|
|
||||||
**Date**: 2026-01-03
|
|
||||||
**Statut**: ✅ Production Ready
|
|
||||||
|
|
||||||
Bon usage de la recherche optimisée! 🚀
|
|
||||||
@@ -1,188 +0,0 @@
|
|||||||
# Guide d'Utilisation - Interface de Recherche Optimisée
|
|
||||||
|
|
||||||
## Vue d'Ensemble
|
|
||||||
|
|
||||||
L'interface de recherche optimisée utilise la collection **Summary** comme point d'entrée principal, offrant **90% de visibilité** des documents riches vs 10% pour la recherche directe dans Chunks.
|
|
||||||
|
|
||||||
## Performance Démontrée
|
|
||||||
|
|
||||||
### ✅ Tests Réussis
|
|
||||||
|
|
||||||
#### 1. Requêtes sur l'IA (domaine Haugeland)
|
|
||||||
```bash
|
|
||||||
python search_summary_interface.py "What is the Turing test?"
|
|
||||||
```
|
|
||||||
**Résultat**: 7/7 résultats Haugeland (100%)
|
|
||||||
|
|
||||||
#### 2. Requêtes sur la vertu (domaine Platon)
|
|
||||||
```bash
|
|
||||||
python search_summary_interface.py "Can virtue be taught?"
|
|
||||||
```
|
|
||||||
**Résultat**: 6/6 résultats Platon (100%)
|
|
||||||
|
|
||||||
#### 3. Requêtes sur le pragmatisme (domaine Peirce/Tiercelin)
|
|
||||||
```bash
|
|
||||||
python search_summary_interface.py "What is pragmatism according to Peirce?"
|
|
||||||
```
|
|
||||||
**Résultat**: 5/5 résultats Tiercelin (100%)
|
|
||||||
|
|
||||||
### Comparaison avec Recherche Chunk Directe
|
|
||||||
|
|
||||||
| Approche | Visibilité Documents Riches | Performance |
|
|
||||||
|----------|----------------------------|-------------|
|
|
||||||
| **Summary-first** (ce script) | **90%** | ✅ Excellent |
|
|
||||||
| Chunk directe | 10% | ❌ Dominé par Peirce |
|
|
||||||
|
|
||||||
## Utilisation
|
|
||||||
|
|
||||||
### Mode Requête Unique
|
|
||||||
```bash
|
|
||||||
# Requête simple
|
|
||||||
python search_summary_interface.py "Votre question ici"
|
|
||||||
|
|
||||||
# Avec limite de résultats
|
|
||||||
python search_summary_interface.py "What is intelligence?" -n 5
|
|
||||||
|
|
||||||
# Avec seuil de similarité personnalisé
|
|
||||||
python search_summary_interface.py "Can machines think?" -s 0.7
|
|
||||||
```
|
|
||||||
|
|
||||||
### Mode Interactif
|
|
||||||
```bash
|
|
||||||
# Lancer sans arguments
|
|
||||||
python search_summary_interface.py
|
|
||||||
|
|
||||||
# Interface interactive
|
|
||||||
INTERFACE DE RECHERCHE RAG - Collection Summary
|
|
||||||
================================================
|
|
||||||
Mode: Summary-first (90% de visibilité démontrée)
|
|
||||||
Tapez 'quit' pour quitter
|
|
||||||
|
|
||||||
Votre question: What is the Chinese Room argument?
|
|
||||||
[résultats affichés]
|
|
||||||
|
|
||||||
Votre question: Can virtue be taught?
|
|
||||||
[résultats affichés]
|
|
||||||
|
|
||||||
Votre question: quit
|
|
||||||
Au revoir!
|
|
||||||
```
|
|
||||||
|
|
||||||
## Options
|
|
||||||
|
|
||||||
| Option | Court | Défaut | Description |
|
|
||||||
|--------|-------|--------|-------------|
|
|
||||||
| `query` | - | - | Question de recherche (optionnel) |
|
|
||||||
| `--limit` | `-n` | 10 | Nombre maximum de résultats |
|
|
||||||
| `--min-similarity` | `-s` | 0.65 | Seuil de similarité (0-1) |
|
|
||||||
|
|
||||||
## Format des Résultats
|
|
||||||
|
|
||||||
Chaque résultat affiche:
|
|
||||||
- **Icône + Document**: 🟣 Haugeland, 🟢 Platon, 🟡 Tiercelin, 🔵 Logique, ⚪ Peirce
|
|
||||||
- **Similarité**: Score 0-1 et pourcentage
|
|
||||||
- **Titre**: Titre de la section
|
|
||||||
- **Auteur/Année**: Si disponible
|
|
||||||
- **Concepts**: Top 5 concepts clés
|
|
||||||
- **Résumé**: Résumé de la section (max 300 chars)
|
|
||||||
- **Chunks**: Nombre de chunks disponibles pour lecture détaillée
|
|
||||||
|
|
||||||
### Exemple de Sortie
|
|
||||||
```
|
|
||||||
[1] 🟣 Haugeland - Similarité: 0.695 (69.5%)
|
|
||||||
Titre: 2.2.3 Computers and intelligence
|
|
||||||
Auteur: John Haugeland, Carl F. Craver, and Colin Klein (2023.0)
|
|
||||||
Concepts: Turing test, artificial intelligence, formal input/output function, universal machine, computability (+5 autres)
|
|
||||||
Résumé: This section examines Turing's 1950 prediction that computers would achieve human-level intelligence by 2000, analyzing the theoretical foundations underlying this forecast...
|
|
||||||
📄 1 chunk(s) disponible(s) pour lecture détaillée
|
|
||||||
```
|
|
||||||
|
|
||||||
## Fonctionnalités Avancées
|
|
||||||
|
|
||||||
### Récupération des Chunks Détaillés
|
|
||||||
|
|
||||||
Le script inclut la fonction `get_chunks_for_section()` pour récupérer le contenu détaillé:
|
|
||||||
|
|
||||||
```python
|
|
||||||
from search_summary_interface import get_chunks_for_section
|
|
||||||
|
|
||||||
# Après avoir identifié une section intéressante
|
|
||||||
chunks = get_chunks_for_section(
|
|
||||||
document_id="Haugeland_J._Mind_Design_III...",
|
|
||||||
section_path="2.2.3 Computers and intelligence",
|
|
||||||
limit=5
|
|
||||||
)
|
|
||||||
|
|
||||||
for chunk in chunks:
|
|
||||||
print(chunk["text"])
|
|
||||||
```
|
|
||||||
|
|
||||||
## Architecture
|
|
||||||
|
|
||||||
### Collection Summary
|
|
||||||
- 114 résumés total
|
|
||||||
- 106 résumés riches (>100 chars)
|
|
||||||
- Documents: Tiercelin (51), Haugeland (50), Platon (12), Logique (1)
|
|
||||||
|
|
||||||
### Vecteurs
|
|
||||||
- Modèle: BAAI/bge-m3 (1024 dimensions)
|
|
||||||
- Contexte: 8192 tokens
|
|
||||||
- Multilingual: Anglais, Français, Latin, Grec
|
|
||||||
|
|
||||||
### Recherche Sémantique
|
|
||||||
- Méthode: `near_text` (Weaviate)
|
|
||||||
- Distance: Cosine
|
|
||||||
- Métrique: Similarité = 1 - distance
|
|
||||||
|
|
||||||
## Pourquoi Summary-First?
|
|
||||||
|
|
||||||
### Problème des Chunks
|
|
||||||
- 5,068 chunks Peirce sur 5,230 total (97%)
|
|
||||||
- Domination écrasante même sur requêtes spécialisées
|
|
||||||
- Exemple: "What is the Turing test?" → 5/5 chunks Peirce (0/5 Haugeland)
|
|
||||||
|
|
||||||
### Solution Summary
|
|
||||||
- Résumés équilibrés par document
|
|
||||||
- Haute qualité (générés par Claude Sonnet 4.5)
|
|
||||||
- 90% de visibilité prouvée
|
|
||||||
- Concepts et keywords riches
|
|
||||||
|
|
||||||
## Coût et Performance
|
|
||||||
|
|
||||||
### Coût de Génération
|
|
||||||
- Total: $1.23 pour 106 résumés riches
|
|
||||||
- Tiercelin: $0.63 (43 résumés)
|
|
||||||
- Haugeland: $0.44 (50 résumés)
|
|
||||||
- Platon: $0.14 (12 résumés)
|
|
||||||
- Logique: $0.02 (1 résumé)
|
|
||||||
|
|
||||||
### Performance Requêtes
|
|
||||||
- Temps moyen: ~200-500ms par requête
|
|
||||||
- Précision: 90% (documents pertinents dans top 5)
|
|
||||||
- Couverture: Tous les documents riches indexés
|
|
||||||
|
|
||||||
## Prochaines Étapes Possibles
|
|
||||||
|
|
||||||
1. **Interface Web**: Intégrer dans Flask app existante
|
|
||||||
2. **Mode Hybride**: Toggle Summary/Chunk au choix
|
|
||||||
3. **Expansion Chunks**: Fonction "Voir plus" pour lire chunks détaillés
|
|
||||||
4. **Filtres**: Par document, auteur, année, concepts
|
|
||||||
5. **Historique**: Sauvegarde des recherches récentes
|
|
||||||
|
|
||||||
## Fichiers Associés
|
|
||||||
|
|
||||||
- `search_summary_interface.py` - Script principal
|
|
||||||
- `ANALYSE_RAG_FINAL.md` - Analyse complète du système
|
|
||||||
- `test_real_queries.py` - Tests de validation (15 requêtes)
|
|
||||||
- `test_haugeland_ai.py` - Tests spécifiques IA
|
|
||||||
- `test_hierarchical_search.py` - Tests Summary → Chunks
|
|
||||||
|
|
||||||
## Support
|
|
||||||
|
|
||||||
Pour questions ou améliorations, voir `ANALYSE_RAG_FINAL.md` pour le contexte complet.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Date**: 2026-01-03
|
|
||||||
**Version**: 1.0
|
|
||||||
**Status**: ✅ Production-ready
|
|
||||||
@@ -1,372 +0,0 @@
|
|||||||
# Refactorisation - Intégration Summary dans Dropdown
|
|
||||||
|
|
||||||
**Date**: 2026-01-03
|
|
||||||
**Type**: Refactorisation (Option 1)
|
|
||||||
**Statut**: ✅ Complète et testée
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Contexte
|
|
||||||
|
|
||||||
Initialement, j'avais créé une **page séparée** (`/search/summary`) pour la recherche par résumés.
|
|
||||||
|
|
||||||
L'utilisateur a correctement identifié que c'était redondant puisque le mode **hiérarchique** existant fait déjà une recherche en 2 étapes (Summary → Chunks).
|
|
||||||
|
|
||||||
**Solution**: Intégrer "Résumés uniquement" comme option dans le dropdown "Mode de recherche" existant.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Ce qui a été Refactorisé
|
|
||||||
|
|
||||||
### ✅ Backend (`flask_app.py`)
|
|
||||||
|
|
||||||
#### 1. Nouvelle fonction `summary_only_search()`
|
|
||||||
**Emplacement**: Lignes 553-654
|
|
||||||
**Rôle**: Recherche sémantique dans la collection Summary uniquement
|
|
||||||
|
|
||||||
```python
|
|
||||||
def summary_only_search(
|
|
||||||
query: str,
|
|
||||||
limit: int = 10,
|
|
||||||
author_filter: Optional[str] = None,
|
|
||||||
work_filter: Optional[str] = None,
|
|
||||||
) -> List[Dict[str, Any]]:
|
|
||||||
"""Summary-only semantic search (90% visibility)."""
|
|
||||||
```
|
|
||||||
|
|
||||||
**Caractéristiques**:
|
|
||||||
- Recherche dans Summary collection
|
|
||||||
- Filtre par auteur/work (Python-side)
|
|
||||||
- Icônes par document (🟣🟢🟡🔵⚪)
|
|
||||||
- Format compatible avec template existant
|
|
||||||
|
|
||||||
#### 2. Modification `search_passages()`
|
|
||||||
**Ajout**: Support du mode `force_mode="summary"`
|
|
||||||
|
|
||||||
```python
|
|
||||||
if force_mode == "summary":
|
|
||||||
results = summary_only_search(query, limit, author_filter, work_filter)
|
|
||||||
return {
|
|
||||||
"mode": "summary",
|
|
||||||
"results": results,
|
|
||||||
"total_chunks": len(results),
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 3. Suppression
|
|
||||||
- ❌ Route `/search/summary` supprimée
|
|
||||||
- ❌ Fonction `search_summaries_backend()` supprimée
|
|
||||||
- ❌ ~150 lignes de code dupliqué éliminées
|
|
||||||
|
|
||||||
### ✅ Frontend (`templates/search.html`)
|
|
||||||
|
|
||||||
#### 1. Dropdown "Mode de recherche"
|
|
||||||
**Ajout**: Option "Résumés uniquement"
|
|
||||||
|
|
||||||
```html
|
|
||||||
<option value="summary">📚 Résumés uniquement (90% visibilité)</option>
|
|
||||||
```
|
|
||||||
|
|
||||||
**Options disponibles**:
|
|
||||||
- 🤖 Auto-détection (défaut)
|
|
||||||
- 📄 Simple (Chunks)
|
|
||||||
- 🌳 Hiérarchique (Summary → Chunks)
|
|
||||||
- 📚 Résumés uniquement (90% visibilité) ⭐ **NOUVEAU**
|
|
||||||
|
|
||||||
#### 2. Badge de mode
|
|
||||||
**Ajout**: Badge pour mode summary
|
|
||||||
|
|
||||||
```jinja2
|
|
||||||
{% elif results_data.mode == "summary" %}
|
|
||||||
<span class="badge">📚 Résumés uniquement (90% visibilité)</span>
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 3. Affichage des résultats Summary
|
|
||||||
**Ajout**: Bloc spécial pour affichage Summary (lignes 264-316)
|
|
||||||
|
|
||||||
**Caractéristiques**:
|
|
||||||
- Icône de document (🟣🟢🟡🔵⚪)
|
|
||||||
- Titre de section
|
|
||||||
- Résumé du contenu
|
|
||||||
- Concepts clés (top 8)
|
|
||||||
- Nombre de chunks disponibles
|
|
||||||
- Badges auteur/année
|
|
||||||
|
|
||||||
### ✅ Navigation (`templates/base.html`)
|
|
||||||
|
|
||||||
#### Suppression
|
|
||||||
- ❌ Lien "📚 Recherche Résumés" supprimé de la sidebar
|
|
||||||
- ❌ Badge "90%" séparé supprimé
|
|
||||||
|
|
||||||
**Raison**: Tout est maintenant dans le dropdown de `/search`
|
|
||||||
|
|
||||||
### ✅ Templates
|
|
||||||
|
|
||||||
#### Suppression
|
|
||||||
- ❌ `templates/search_summary.html` supprimé (~320 lignes)
|
|
||||||
|
|
||||||
**Raison**: Utilise désormais `templates/search.html` avec mode conditionnel
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Comparaison Avant/Après
|
|
||||||
|
|
||||||
### Avant (Page Séparée)
|
|
||||||
|
|
||||||
**Navigation**:
|
|
||||||
```
|
|
||||||
Sidebar:
|
|
||||||
├── Recherche (/search)
|
|
||||||
└── Recherche Résumés (/search/summary) ← Page séparée
|
|
||||||
```
|
|
||||||
|
|
||||||
**Code**:
|
|
||||||
- Route séparée `/search/summary`
|
|
||||||
- Template séparé `search_summary.html`
|
|
||||||
- Fonction séparée `search_summaries_backend()`
|
|
||||||
- Total: ~470 lignes de code dupliqué
|
|
||||||
|
|
||||||
**UX**:
|
|
||||||
- 2 pages différentes
|
|
||||||
- Navigation confuse
|
|
||||||
- Duplication de fonctionnalités
|
|
||||||
|
|
||||||
### Après (Dropdown Intégré)
|
|
||||||
|
|
||||||
**Navigation**:
|
|
||||||
```
|
|
||||||
Sidebar:
|
|
||||||
└── Recherche (/search)
|
|
||||||
└── Mode: Résumés uniquement (dropdown)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Code**:
|
|
||||||
- 1 seule route `/search`
|
|
||||||
- 1 seul template `search.html`
|
|
||||||
- Fonction `summary_only_search()` intégrée
|
|
||||||
- Réduction: ~470 → ~100 lignes
|
|
||||||
|
|
||||||
**UX**:
|
|
||||||
- 1 seule page
|
|
||||||
- Dropdown clair et intuitif
|
|
||||||
- Cohérence avec architecture existante
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Tests de Validation
|
|
||||||
|
|
||||||
### ✅ Tests Automatisés
|
|
||||||
|
|
||||||
**Script**: `test_summary_dropdown.py`
|
|
||||||
|
|
||||||
```
|
|
||||||
Test 1: What is the Turing test? (mode=summary)
|
|
||||||
✅ Found Haugeland icon 🟣
|
|
||||||
✅ Summary mode badge displayed
|
|
||||||
✅ Results displayed
|
|
||||||
✅ Concepts displayed
|
|
||||||
|
|
||||||
Test 2: Can virtue be taught? (mode=summary)
|
|
||||||
✅ Found Platon icon 🟢
|
|
||||||
✅ Summary mode badge displayed
|
|
||||||
✅ Results displayed
|
|
||||||
✅ Concepts displayed
|
|
||||||
|
|
||||||
Test 3: What is pragmatism? (mode=summary)
|
|
||||||
✅ Found Tiercelin icon 🟡
|
|
||||||
✅ Summary mode badge displayed
|
|
||||||
✅ Results displayed
|
|
||||||
✅ Concepts displayed
|
|
||||||
|
|
||||||
Test 4: Summary option in dropdown
|
|
||||||
✅ Summary option present
|
|
||||||
✅ Summary option label correct
|
|
||||||
```
|
|
||||||
|
|
||||||
**Résultat**: 14/14 tests passés (100%)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Utilisation
|
|
||||||
|
|
||||||
### Via Interface Web
|
|
||||||
|
|
||||||
1. Ouvrir http://localhost:5000/search
|
|
||||||
2. Entrer une question
|
|
||||||
3. **Sélectionner** "📚 Résumés uniquement (90% visibilité)" dans le dropdown
|
|
||||||
4. Cliquer "Rechercher"
|
|
||||||
|
|
||||||
### Via URL
|
|
||||||
|
|
||||||
```
|
|
||||||
http://localhost:5000/search?q=What+is+the+Turing+test&mode=summary&limit=10
|
|
||||||
```
|
|
||||||
|
|
||||||
**Paramètres**:
|
|
||||||
- `q`: Question
|
|
||||||
- `mode=summary`: Force le mode Résumés
|
|
||||||
- `limit`: Nombre de résultats (défaut: 10)
|
|
||||||
- `author`: Filtre par auteur (optionnel)
|
|
||||||
- `work`: Filtre par œuvre (optionnel)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Avantages de la Refactorisation
|
|
||||||
|
|
||||||
### ✅ Code
|
|
||||||
|
|
||||||
- **-370 lignes** de code dupliqué
|
|
||||||
- Architecture plus propre
|
|
||||||
- Maintenance simplifiée
|
|
||||||
- Cohérence avec modes existants
|
|
||||||
|
|
||||||
### ✅ UX
|
|
||||||
|
|
||||||
- Interface unifiée
|
|
||||||
- Dropdown intuitif
|
|
||||||
- Moins de confusion
|
|
||||||
- Cohérence visuelle
|
|
||||||
|
|
||||||
### ✅ Performance
|
|
||||||
|
|
||||||
- Aucun impact (même vitesse)
|
|
||||||
- Même fonctionnalité
|
|
||||||
- 90% de visibilité maintenue
|
|
||||||
|
|
||||||
### ✅ Architecture
|
|
||||||
|
|
||||||
- Respect du pattern existant
|
|
||||||
- Hiérarchie logique: Auto → Simple → Hiérarchique → Summary
|
|
||||||
- Extensible pour futurs modes
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Fichiers Modifiés
|
|
||||||
|
|
||||||
### Backend
|
|
||||||
```
|
|
||||||
flask_app.py
|
|
||||||
├── [+] summary_only_search() (lignes 553-654)
|
|
||||||
├── [~] search_passages() (support mode="summary")
|
|
||||||
└── [-] Route /search/summary supprimée
|
|
||||||
```
|
|
||||||
|
|
||||||
### Frontend
|
|
||||||
```
|
|
||||||
templates/search.html
|
|
||||||
├── [~] Dropdown: +1 option "summary"
|
|
||||||
├── [~] Badge mode: +1 cas "summary"
|
|
||||||
└── [+] Affichage Summary (lignes 264-316)
|
|
||||||
|
|
||||||
templates/base.html
|
|
||||||
└── [-] Lien "Recherche Résumés" supprimé
|
|
||||||
|
|
||||||
templates/search_summary.html
|
|
||||||
└── [❌] Fichier supprimé
|
|
||||||
```
|
|
||||||
|
|
||||||
### Tests
|
|
||||||
```
|
|
||||||
test_summary_dropdown.py
|
|
||||||
└── [+] Nouveau script de tests (14 checks)
|
|
||||||
|
|
||||||
test_flask_integration.py
|
|
||||||
└── [~] Maintenu pour référence (ancien test)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Migration
|
|
||||||
|
|
||||||
### Pour les utilisateurs
|
|
||||||
|
|
||||||
**Aucune action requise**. L'ancienne URL `/search/summary` n'est plus disponible, mais la fonctionnalité existe dans `/search` avec `mode=summary`.
|
|
||||||
|
|
||||||
**Migration automatique des URLs**:
|
|
||||||
```
|
|
||||||
Avant: /search/summary?q=test
|
|
||||||
Après: /search?q=test&mode=summary
|
|
||||||
```
|
|
||||||
|
|
||||||
### Pour le code
|
|
||||||
|
|
||||||
**Aucune migration nécessaire**. La fonction backend `search_passages()` reste identique, seul le paramètre `force_mode` accepte maintenant `"summary"`.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Prochaines Étapes (Optionnel)
|
|
||||||
|
|
||||||
### Court Terme
|
|
||||||
|
|
||||||
1. ✅ Ajouter tooltips sur les options du dropdown
|
|
||||||
2. ✅ Badge "Nouveau" temporaire sur option Summary
|
|
||||||
3. ✅ Analytics pour suivre l'usage par mode
|
|
||||||
|
|
||||||
### Moyen Terme
|
|
||||||
|
|
||||||
1. Intégrer filtres auteur/work dans mode Summary
|
|
||||||
2. Permettre expansion "Voir chunks" depuis un résumé
|
|
||||||
3. Mode hybride "Auto-Summary" (détection intelligente)
|
|
||||||
|
|
||||||
### Long Terme
|
|
||||||
|
|
||||||
1. Apprentissage: mémoriser préférence mode par utilisateur
|
|
||||||
2. Mode "Mixed" (Summary + Chunks dans même résultat)
|
|
||||||
3. Recherche fédérée (Summary || Chunks en parallèle)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Comparaison des Modes
|
|
||||||
|
|
||||||
| Mode | Collection | Étapes | Visibilité | Usage |
|
|
||||||
|------|------------|---------|-----------|-------|
|
|
||||||
| **Simple** | Chunk | 1 | 10% ❌ | Citations précises |
|
|
||||||
| **Hiérarchique** | Summary → Chunk | 2 | Variable | Exploration contextuelle |
|
|
||||||
| **Summary** | Summary | 1 | 90% ✅ | Vue d'ensemble |
|
|
||||||
| **Auto** | Détection | 1-2 | Variable | Défaut recommandé |
|
|
||||||
|
|
||||||
### Quand utiliser Summary?
|
|
||||||
|
|
||||||
✅ Questions générales ("What is X?")
|
|
||||||
✅ Découverte de sujets
|
|
||||||
✅ Vue d'ensemble d'un document
|
|
||||||
✅ Identification de sections pertinentes
|
|
||||||
|
|
||||||
❌ Citations exactes nécessaires
|
|
||||||
❌ Analyse très précise d'un passage
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Conclusion
|
|
||||||
|
|
||||||
### ✅ Objectifs Atteints
|
|
||||||
|
|
||||||
1. ✅ Intégration propre dans dropdown existant
|
|
||||||
2. ✅ Suppression de la page séparée redondante
|
|
||||||
3. ✅ Code plus maintenable (-370 lignes)
|
|
||||||
4. ✅ Tests passants (14/14 - 100%)
|
|
||||||
5. ✅ UX améliorée (interface unifiée)
|
|
||||||
6. ✅ Performance identique (90% visibilité)
|
|
||||||
|
|
||||||
### 📊 Métriques
|
|
||||||
|
|
||||||
- **Lignes de code**: -370 (réduction 79%)
|
|
||||||
- **Fichiers supprimés**: 1 (search_summary.html)
|
|
||||||
- **Tests**: 14/14 passés (100%)
|
|
||||||
- **Routes**: 2 → 1 (simplification)
|
|
||||||
- **Templates**: 2 → 1 (consolidation)
|
|
||||||
|
|
||||||
### 🎯 Résultat
|
|
||||||
|
|
||||||
L'option "Résumés uniquement" est maintenant **parfaitement intégrée** dans le dropdown "Mode de recherche", offrant:
|
|
||||||
- Architecture cohérente avec modes existants
|
|
||||||
- Code plus propre et maintenable
|
|
||||||
- UX simplifiée et intuitive
|
|
||||||
- Performance optimale (90% visibilité)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Auteur**: Claude Sonnet 4.5
|
|
||||||
**Date**: 2026-01-03
|
|
||||||
**Type**: Refactorisation Option 1
|
|
||||||
**Statut**: ✅ Complète et Production-Ready
|
|
||||||
@@ -1,238 +0,0 @@
|
|||||||
# Résumé de Session - Amélioration RAG Library
|
|
||||||
|
|
||||||
**Date**: 2026-01-03
|
|
||||||
**Objectif**: Résoudre le problème de dominance des chunks Peirce sans suppression
|
|
||||||
**Statut**: ✅ Résolu avec implémentation production-ready
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Problème Identifié
|
|
||||||
|
|
||||||
### État Initial
|
|
||||||
- **Collection Chunk**: 5,230 chunks total
|
|
||||||
- Peirce: 5,068 chunks (97%)
|
|
||||||
- Autres: 162 chunks (3%)
|
|
||||||
|
|
||||||
- **Impact**:
|
|
||||||
- Recherche chunk directe: 10% de visibilité pour documents riches
|
|
||||||
- Même sur requêtes ultra-spécifiques (ex: "What is the Turing test?"), Peirce domine 88% des résultats
|
|
||||||
- Haugeland n'apparaît que dans 10% des résultats sur son propre domaine (IA)
|
|
||||||
|
|
||||||
### Contrainte Utilisateur
|
|
||||||
> "NE SUPPRIME PAS LES CHUNKLS D EPEIRCE BORDEL"
|
|
||||||
|
|
||||||
❌ Pas de suppression des chunks Peirce permise
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Solution Implémentée
|
|
||||||
|
|
||||||
### Option A: Summary-First Search Interface ✅
|
|
||||||
|
|
||||||
**Principe**: Utiliser la collection Summary (équilibrée, haute qualité) comme point d'entrée principal au lieu des Chunks.
|
|
||||||
|
|
||||||
**Résultats Prouvés**:
|
|
||||||
- ✅ 90% de visibilité des documents riches
|
|
||||||
- ✅ 100% de précision sur requêtes testées
|
|
||||||
- ✅ Coût additionnel: $0
|
|
||||||
- ✅ Respecte la contrainte (pas de suppression)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Livrables
|
|
||||||
|
|
||||||
### 1. Documentation Complète
|
|
||||||
|
|
||||||
#### `ANALYSE_RAG_FINAL.md`
|
|
||||||
Analyse exhaustive comprenant:
|
|
||||||
- État de la base de données (Summary + Chunk)
|
|
||||||
- Historique complet des travaux ($1.23, 106 résumés)
|
|
||||||
- Tests de performance (15 requêtes réelles)
|
|
||||||
- Comparaison Summary vs Chunk (90% vs 10%)
|
|
||||||
- 3 options de solution détaillées
|
|
||||||
|
|
||||||
#### `README_SEARCH.md`
|
|
||||||
Guide d'utilisation complet:
|
|
||||||
- Exemples d'utilisation (modes unique et interactif)
|
|
||||||
- Options et paramètres
|
|
||||||
- Format des résultats
|
|
||||||
- Architecture technique
|
|
||||||
- Prochaines étapes possibles
|
|
||||||
|
|
||||||
### 2. Implémentation Fonctionnelle
|
|
||||||
|
|
||||||
#### `search_summary_interface.py`
|
|
||||||
Script Python production-ready avec:
|
|
||||||
|
|
||||||
**Fonctionnalités**:
|
|
||||||
- ✅ Mode requête unique: `python search_summary_interface.py "question"`
|
|
||||||
- ✅ Mode interactif: `python search_summary_interface.py`
|
|
||||||
- ✅ Paramètres configurables: `-n` (limit), `-s` (min-similarity)
|
|
||||||
- ✅ Affichage riche: icônes, auteurs, concepts, résumés
|
|
||||||
- ✅ Support multilingue (FR/EN)
|
|
||||||
- ✅ Fonction bonus: récupération chunks détaillés
|
|
||||||
|
|
||||||
**Qualité Code**:
|
|
||||||
- Type hints complets
|
|
||||||
- Docstrings Google-style
|
|
||||||
- Gestion d'erreurs
|
|
||||||
- Encodage Windows UTF-8
|
|
||||||
- Code propre et maintenable
|
|
||||||
|
|
||||||
### 3. Tests de Validation
|
|
||||||
|
|
||||||
#### Tests Exécutés et Validés ✅
|
|
||||||
|
|
||||||
**Test 1 - IA/Haugeland**:
|
|
||||||
```bash
|
|
||||||
python search_summary_interface.py "What is the Turing test?"
|
|
||||||
```
|
|
||||||
Résultat: 7/7 résultats Haugeland (100%)
|
|
||||||
|
|
||||||
**Test 2 - Vertu/Platon**:
|
|
||||||
```bash
|
|
||||||
python search_summary_interface.py "Can virtue be taught?"
|
|
||||||
```
|
|
||||||
Résultat: 6/6 résultats Platon (100%)
|
|
||||||
|
|
||||||
**Test 3 - Pragmatisme/Tiercelin**:
|
|
||||||
```bash
|
|
||||||
python search_summary_interface.py "What is pragmatism according to Peirce?"
|
|
||||||
```
|
|
||||||
Résultat: 5/5 résultats Tiercelin (100%)
|
|
||||||
|
|
||||||
**Conclusion**: ✅ 100% de précision sur tous les domaines testés
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Métriques de Performance
|
|
||||||
|
|
||||||
### Avant (Recherche Chunk Directe)
|
|
||||||
- Visibilité documents riches: 10%
|
|
||||||
- Haugeland sur requêtes IA: 10%
|
|
||||||
- Peirce dominance: 88%
|
|
||||||
- Utilisabilité: ❌ Mauvaise
|
|
||||||
|
|
||||||
### Après (Recherche Summary)
|
|
||||||
- Visibilité documents riches: 90%
|
|
||||||
- Haugeland sur requêtes IA: 100%
|
|
||||||
- Distribution équilibrée: ✅
|
|
||||||
- Utilisabilité: ✅ Excellente
|
|
||||||
|
|
||||||
**Amélioration**: +800% de visibilité
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Architecture de la Solution
|
|
||||||
|
|
||||||
### Base de Données
|
|
||||||
```
|
|
||||||
Summary Collection (114 résumés)
|
|
||||||
├─ Tiercelin: 51 résumés (générés LLM)
|
|
||||||
├─ Haugeland: 50 résumés (générés LLM)
|
|
||||||
├─ Platon: 12 résumés (générés LLM)
|
|
||||||
└─ Logique: 1 résumé (généré LLM)
|
|
||||||
|
|
||||||
Vectorisation: BAAI/bge-m3 (1024-dim, 8192 tokens)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Flux de Recherche
|
|
||||||
```
|
|
||||||
User Query
|
|
||||||
↓
|
|
||||||
Summary Search (near_text)
|
|
||||||
↓
|
|
||||||
Top N résumés pertinents
|
|
||||||
↓
|
|
||||||
Affichage: titre, auteur, concepts, résumé
|
|
||||||
↓
|
|
||||||
[Optionnel] Récupération chunks détaillés
|
|
||||||
```
|
|
||||||
|
|
||||||
### Avantages Techniques
|
|
||||||
- ✅ Aucune modification base de données
|
|
||||||
- ✅ Aucune suppression de données
|
|
||||||
- ✅ Utilise infrastructure existante
|
|
||||||
- ✅ Extensible (peut ajouter mode hybride)
|
|
||||||
- ✅ Maintenable (code simple et clair)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Coûts
|
|
||||||
|
|
||||||
### Coûts de Développement
|
|
||||||
- Génération résumés (déjà effectuée): $1.23
|
|
||||||
- Développement script: $0
|
|
||||||
- Tests et validation: $0
|
|
||||||
- **Total**: $1.23
|
|
||||||
|
|
||||||
### Performance
|
|
||||||
- Temps par requête: ~200-500ms
|
|
||||||
- Charge serveur: Faible
|
|
||||||
- Scalabilité: Excellente
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Fichiers Créés/Modifiés
|
|
||||||
|
|
||||||
### Nouveaux Fichiers ✨
|
|
||||||
1. `ANALYSE_RAG_FINAL.md` - Documentation complète (15 KB)
|
|
||||||
2. `search_summary_interface.py` - Script de recherche (8 KB)
|
|
||||||
3. `README_SEARCH.md` - Guide utilisateur (7 KB)
|
|
||||||
4. `SESSION_SUMMARY.md` - Ce fichier (5 KB)
|
|
||||||
|
|
||||||
### Tests Exécutés ✅
|
|
||||||
1. `test_haugeland_ai.py` - Validation domaine IA
|
|
||||||
2. `test_hierarchical_search.py` - Test Summary → Chunks
|
|
||||||
3. `test_real_queries.py` - 15 requêtes réelles
|
|
||||||
|
|
||||||
**Total**: 4 documents + 1 script + 3 tests validés
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Prochaines Étapes Recommandées
|
|
||||||
|
|
||||||
### Court Terme (Optionnel)
|
|
||||||
1. Intégrer `search_summary_interface.py` dans Flask app
|
|
||||||
2. Ajouter route `/search/summary` avec interface web
|
|
||||||
3. Ajouter bouton "Voir chunks détaillés" pour expansion
|
|
||||||
|
|
||||||
### Moyen Terme (Si Besoin)
|
|
||||||
1. Mode hybride: toggle Summary/Chunk au choix utilisateur
|
|
||||||
2. Filtres avancés: par auteur, année, concepts
|
|
||||||
3. Historique de recherche
|
|
||||||
4. Export résultats (JSON, CSV)
|
|
||||||
|
|
||||||
### Long Terme (Si Nécessaire)
|
|
||||||
1. Régénération résumés Peirce (~$45-50)
|
|
||||||
2. Amélioration recherche hierarchique (si nouvelle version Weaviate)
|
|
||||||
3. Multi-modal: recherche par images de diagrammes
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Conclusion
|
|
||||||
|
|
||||||
### Objectifs Atteints ✅
|
|
||||||
- ✅ Problème de visibilité résolu (10% → 90%)
|
|
||||||
- ✅ Contrainte respectée (pas de suppression Peirce)
|
|
||||||
- ✅ Solution production-ready implémentée
|
|
||||||
- ✅ Documentation complète fournie
|
|
||||||
- ✅ Tests validés sur tous domaines
|
|
||||||
|
|
||||||
### État Final
|
|
||||||
- **Fonctionnel**: ✅ Prêt à l'emploi
|
|
||||||
- **Documenté**: ✅ 4 documents complets
|
|
||||||
- **Testé**: ✅ 100% de précision démontrée
|
|
||||||
- **Maintenable**: ✅ Code propre et clair
|
|
||||||
- **Extensible**: ✅ Facile d'ajouter features
|
|
||||||
|
|
||||||
### Recommandation
|
|
||||||
**Utiliser `search_summary_interface.py` comme interface de recherche principale.**
|
|
||||||
|
|
||||||
La recherche dans Summary offre une expérience utilisateur nettement supérieure avec 90% de visibilité vs 10% pour la recherche chunk directe, tout en respectant l'intégrité des données (pas de suppression).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Signature**: Claude Sonnet 4.5
|
|
||||||
**Date**: 2026-01-03
|
|
||||||
**Status**: ✅ Mission Accomplie
|
|
||||||
@@ -1,133 +0,0 @@
|
|||||||
# Guide d'Installation TTS - Après Redémarrage Windows
|
|
||||||
|
|
||||||
## 📋 Contexte
|
|
||||||
Vous avez installé **Microsoft Visual Studio Build Tools avec composants C++**.
|
|
||||||
Après redémarrage de Windows, ces outils seront actifs et permettront la compilation de TTS.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔄 Étapes Après Redémarrage
|
|
||||||
|
|
||||||
### 1. Vérifier que Visual Studio Build Tools est actif
|
|
||||||
|
|
||||||
Ouvrir un **nouveau** terminal et tester :
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Vérifier que le compilateur C++ est disponible
|
|
||||||
where cl
|
|
||||||
|
|
||||||
# Devrait afficher un chemin comme :
|
|
||||||
# C:\Program Files\Microsoft Visual Studio\...\cl.exe
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Installer TTS (Coqui XTTS v2)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Aller dans le dossier du projet
|
|
||||||
cd C:\GitHub\linear_coding_library_rag\generations\library_rag
|
|
||||||
|
|
||||||
# Installer TTS (cela prendra 5-10 minutes)
|
|
||||||
pip install TTS==0.22.0
|
|
||||||
```
|
|
||||||
|
|
||||||
**Attendu** : Compilation réussie avec "Successfully installed TTS-0.22.0"
|
|
||||||
|
|
||||||
### 3. Vérifier l'installation
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Test d'import
|
|
||||||
python -c "import TTS; print(f'TTS version: {TTS.__version__}')"
|
|
||||||
|
|
||||||
# Devrait afficher : TTS version: 0.22.0
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. Redémarrer Flask et Tester
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Lancer Flask
|
|
||||||
python flask_app.py
|
|
||||||
|
|
||||||
# Aller sur http://localhost:5000/chat
|
|
||||||
# Poser une question
|
|
||||||
# Cliquer sur le bouton "Audio"
|
|
||||||
```
|
|
||||||
|
|
||||||
**Premier lancement** : Le modèle XTTS v2 (~2GB) sera téléchargé automatiquement (5-10 min).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ⚠️ Si TTS échoue encore après redémarrage
|
|
||||||
|
|
||||||
### Solution Alternative : edge-tts (Déjà installé ✅)
|
|
||||||
|
|
||||||
**edge-tts** est déjà installé et fonctionne immédiatement. C'est une excellente alternative avec :
|
|
||||||
- ✅ Voix Microsoft Edge haute qualité
|
|
||||||
- ✅ Support français excellent
|
|
||||||
- ✅ Pas de compilation nécessaire
|
|
||||||
- ✅ Pas besoin de GPU
|
|
||||||
|
|
||||||
**Pour utiliser edge-tts**, il faudra modifier `utils/tts_generator.py`.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 Comparaison des Options
|
|
||||||
|
|
||||||
| Critère | TTS (XTTS v2) | edge-tts |
|
|
||||||
|---------|---------------|----------|
|
|
||||||
| Installation | ⚠️ Complexe (compilation) | ✅ Simple (pip install) |
|
|
||||||
| Qualité | ⭐⭐⭐⭐⭐ Excellente | ⭐⭐⭐⭐⭐ Excellente |
|
|
||||||
| GPU | ✅ Oui (4-6 GB VRAM) | ❌ Non (CPU uniquement) |
|
|
||||||
| Vitesse (100 mots) | 2-5 secondes (GPU) | 3-8 secondes (CPU) |
|
|
||||||
| Offline | ✅ Oui (après download) | ⚠️ Requiert Internet |
|
|
||||||
| Taille modèle | ~2 GB | Aucun téléchargement |
|
|
||||||
| Voix françaises | Oui, naturelles | Oui, Microsoft Azure |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 Recommandation
|
|
||||||
|
|
||||||
1. **Essayer TTS après redémarrage** (pour profiter du GPU)
|
|
||||||
2. **Si échec** : Utiliser edge-tts (déjà installé, fonctionne immédiatement)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 Commandes de Diagnostic
|
|
||||||
|
|
||||||
Si TTS échoue encore :
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Vérifier Python
|
|
||||||
python --version
|
|
||||||
|
|
||||||
# Vérifier pip
|
|
||||||
pip --version
|
|
||||||
|
|
||||||
# Vérifier torch (déjà installé)
|
|
||||||
python -c "import torch; print(f'CUDA: {torch.cuda.is_available()}')"
|
|
||||||
|
|
||||||
# Vérifier Visual Studio
|
|
||||||
where cl
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔧 Fichiers Modifiés
|
|
||||||
|
|
||||||
- ✅ `requirements.txt` - TTS>=0.22.0 ajouté
|
|
||||||
- ✅ `utils/tts_generator.py` - Module TTS créé (pour XTTS v2)
|
|
||||||
- ✅ `flask_app.py` - Route /chat/export-audio ajoutée
|
|
||||||
- ✅ `templates/chat.html` - Bouton Audio ajouté
|
|
||||||
|
|
||||||
**Commit** : `d91abd3` - "Ajout de la fonctionnalité TTS"
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📞 Contact après redémarrage
|
|
||||||
|
|
||||||
Après redémarrage, exécutez simplement :
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pip install TTS==0.22.0
|
|
||||||
```
|
|
||||||
|
|
||||||
Et dites-moi le résultat (succès ou erreur).
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,323 +0,0 @@
|
|||||||
# 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
|
|
||||||
Reference in New Issue
Block a user