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