Commit Graph

16 Commits

Author SHA1 Message Date
0c8ea8fa48 fix: Correct Work titles and improve LLM metadata extraction
Fixes issue where LLM was copying placeholder instructions from the
prompt template into actual metadata fields.

Changes:
1. Created fix_work_titles.py script to correct existing bad titles
   - Detects patterns like "(si c'est bien...)", "Titre corrigé...", "Auteur à identifier"
   - Extracts correct metadata from chunks JSON files
   - Updates Work entries and associated chunks (44 chunks updated)
   - Fixed 3 Works with placeholder contamination

2. Improved llm_metadata.py prompt to prevent future issues
   - Added explicit INTERDIT/OBLIGATOIRE rules with / markers
   - Replaced placeholder examples with real concrete examples
   - Added two example responses (high confidence + low confidence)
   - Final empty JSON template guides structure without placeholders
   - Reinforced: use "confidence" field for uncertainty, not annotations

Results:
- "A Cartesian critique... (si c'est bien le titre)" → "A Cartesian critique of the artificial intelligence"
- "Titre corrigé si nécessaire (ex: ...)" → "Computationalism and The Case When the Brain Is Not a Computer"
- "Titre de l'article principal (à identifier)" → "Computationalism in the Philosophy of Mind"

All future document uploads will now extract clean metadata without
LLM commentary or placeholder instructions.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-08 23:59:25 +01:00
0c3b6c5fea feat: Auto-create Work entries during document ingestion
Adds automatic Work object creation to ensure all uploaded documents
appear on the /documents page. Previously, chunks were ingested but
Work entries were missing, causing documents to be invisible in the UI.

Changes:
- Add create_or_get_work() function to weaviate_ingest.py
  - Checks for existing Work by sourceId (prevents duplicates)
  - Creates new Work with metadata (title, author, year, pages)
  - Returns UUID for potential future reference
- Integrate Work creation into ingest_document() flow
- Add helper scripts for retroactive fixes and verification:
  - create_missing_works.py: Create Works for already-ingested documents
  - reingest_batch_documents.py: Re-ingest documents after bug fixes
  - check_batch_results.py: Verify batch upload results in Weaviate

This completes the batch upload feature - documents now properly appear
on /documents page immediately after ingestion.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-08 23:34:06 +01:00
b8d94576de fix: Correct Weaviate ingestion for Chunk_v2 schema compatibility
Fixes batch upload ingestion that was failing silently due to schema mismatches:

Schema Fixes:
- Update collection names from "Chunk" to "Chunk_v2"
- Update collection names from "Summary" to "Summary_v2"

Object Structure Fixes:
- Replace nested objects (work: {title, author}) with flat fields
- Use workTitle and workAuthor instead of nested work object
- Add year field to chunks
- Remove document nested object (not used in current schema)
- Disable nested objects validation for flat schema

Impact:
- Batch upload now successfully ingests chunks to Weaviate
- Single-file upload also benefits from fixes
- All new documents will be properly indexed and searchable

Testing:
- Verified with 2-file batch upload (7 + 11 chunks = 18 total)
- Total chunks increased from 5,304 to 5,322
- All chunks properly searchable with workTitle/workAuthor filters

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-08 23:25:36 +01:00
b70b796ef8 feat: Add multi-file batch upload with sequential processing
Implements comprehensive batch upload system with real-time progress tracking:

Backend Infrastructure:
- Add batch_jobs global dict for batch orchestration
- Add BatchFileInfo and BatchJob TypedDicts to utils/types.py
- Create run_batch_sequential() worker function with thread.join() synchronization
- Modify /upload POST route to detect single vs multi-file uploads
- Add 3 batch API routes: /upload/batch/progress, /status, /result
- Add timestamp_to_date Jinja2 template filter

Frontend:
- Update upload.html with 'multiple' attribute and file counter
- Create upload_batch_progress.html: Real-time dashboard with SSE per file
- Create upload_batch_result.html: Final summary with statistics

Architecture:
- Backward compatible: single-file upload unchanged
- Sequential processing: one file after another (respects API limits)
- N parallel SSE connections: one per file for real-time progress
- Polling mechanism to discover job IDs as files start processing
- 1-hour timeout per file with error handling and continuation

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-08 22:41:52 +01:00
7045907173 feat: Optimize chunk sizes with 1000-word limit and overlap
Implemented chunking optimization to resolve oversized chunks and improve
semantic search quality:

CHUNKING IMPROVEMENTS:
- Added strict 1000-word max limit (vs previous 1500-2000)
- Implemented 100-word overlap between consecutive chunks
- Created llm_chunker_improved.py with overlap functionality
- Added 3 fallback points in llm_chunker.py for robustness

RE-CHUNKING RESULTS:
- Identified and re-chunked 31 oversized chunks (>2000 tokens)
- Split into 92 optimally-sized chunks (max 1995 tokens)
- Preserved all metadata (workTitle, workAuthor, sectionPath, etc.)
- 0 chunks now exceed 2000 tokens (vs 31 before)

VECTORIZATION:
- Created manual vectorization script for chunks without vectors
- Successfully vectorized all 92 new chunks (100% coverage)
- All 5,304 chunks now have BGE-M3 embeddings

DOCKER CONFIGURATION:
- Exposed text2vec-transformers port 8090 for manual vectorization
- Added cluster configuration to fix "No private IP address found"
- Increased worker timeout to 600s for large chunks

TESTING:
- Created comprehensive search quality test suite
- Tests distribution, overlap detection, and semantic search
- Modified to use near_vector() (Chunk_v2 has no vectorizer)

Scripts:
- 08_fix_summaries_properties.py - Add missing Work metadata to summaries
- 09_rechunk_oversized.py - Re-chunk giant chunks with overlap
- 10_test_search_quality.py - Validate search improvements
- 11_vectorize_missing_chunks.py - Manual vectorization via API

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-08 17:37:49 +01:00
04ee3f9e39 feat: Add data quality verification & cleanup scripts
## Data Quality & Cleanup (Priorities 1-6)

Added comprehensive data quality verification and cleanup system:

**Scripts créés**:
- verify_data_quality.py: Analyse qualité complète œuvre par œuvre
- clean_duplicate_documents.py: Nettoyage doublons Documents
- populate_work_collection.py/clean.py: Peuplement Work collection
- fix_chunks_count.py: Correction chunksCount incohérents
- manage_orphan_chunks.py: Gestion chunks orphelins (3 options)
- clean_orphan_works.py: Suppression Works sans chunks
- add_missing_work.py: Création Work manquant
- generate_schema_stats.py: Génération stats auto
- migrate_add_work_collection.py: Migration sûre Work collection

**Documentation**:
- WEAVIATE_GUIDE_COMPLET.md: Guide consolidé complet (600+ lignes)
- WEAVIATE_SCHEMA.md: Référence schéma rapide
- NETTOYAGE_COMPLETE_RAPPORT.md: Rapport nettoyage session
- ANALYSE_QUALITE_DONNEES.md: Analyse qualité initiale
- rapport_qualite_donnees.txt: Output brut vérification

**Résultats nettoyage**:
- Documents: 16 → 9 (7 doublons supprimés)
- Works: 0 → 9 (peuplé + nettoyé)
- Chunks: 5,404 → 5,230 (174 orphelins supprimés)
- chunksCount: Corrigés (231 → 5,230 déclaré = réel)
- Cohérence parfaite: 9 Works = 9 Documents = 9 œuvres

**Modifications code**:
- schema.py: Ajout Work collection avec vectorisation
- utils/weaviate_ingest.py: Support Work ingestion
- utils/word_pipeline.py: Désactivation concepts (problème .lower())
- utils/word_toc_extractor.py: Métadonnées Word correctes
- .gitignore: Exclusion fichiers temporaires (*.wav, output/*, NUL)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-01 11:57:26 +01:00
845ffb4b06 Fix: Métadonnées Word correctes + désactivation concepts
Problèmes corrigés:
1. TITRE INCORRECT → Maintenant utilise TITRE: de la première page
2. CONCEPTS EN FRANÇAIS → Désactivé l'enrichissement LLM

Avant:
- Titre: "An Historical Sketch..." (mauvais, titre du chapitre)
- Concepts: ['immuabilité des espèces', 'création séparée'] (français)
- Résultat: 3/37 chunks ingérés dans Weaviate

Après:
- Titre: "On the Origin of Species BY MEANS OF..." (correct!)
- Concepts: [] (vides, pas de problème d'encoding)
- Résultat: 14/37 chunks ingérés (mieux mais pas parfait)

Changements word_pipeline.py:

1. STEP 5 - Métadonnées simplifiées (ligne 241-262):
   - Supprimé l'appel à extract_metadata() du LLM
   - Utilise directement raw_meta de extract_word_metadata()
   - Le LLM prenait le titre du chapitre au lieu du livre

2. STEP 9 - Désactivé enrichissement concepts (ligne 410-423):
   - Skip enrich_chunks_with_concepts()
   - Raison: LLM génère concepts en FRANÇAIS pour texte ANGLAIS
   - Accents français causent échecs Weaviate

Note TOC:
Le document n'a que 2 Heading 2, donc la TOC est limitée.
C'est normal pour un extrait de 10 pages.

Reste à investiguer: Pourquoi 14/37 au lieu de 37/37 chunks?

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-30 23:39:41 +01:00
b928352e36 Fix: Appel correct à ingest_document() pour Word
Corrections finales word_pipeline.py:

1. Signature ingest_document() corrigée:
   AVANT:
   - document_source_id=doc_name   (paramètre inexistant)

   APRÈS:
   - doc_name=doc_name
   - metadata=metadata
   - language=metadata.get("language", "unknown")
   - toc=toc_flat
   - hierarchy=None  # Word n'a pas de hiérarchie page
   - pages=0  # Word n'a pas de pages

2. Message callback corrigé:
   AVANT:
   - ingestion_result.get('chunks_ingested', 0)   (champ inexistant)

   APRÈS:
   - ingestion_result.get('count', 0)   (champ réel)

Test réussi complet:
 48 paragraphes extraits
 2 headings détectés
 37 chunks créés
 37 chunks nettoyés
 37 chunks validés
 37 chunks ingérés dans Weaviate
 Coût OCR: €0.0000 (pas d'OCR pour Word!)
 Document indexé et recherchable

Le pipeline Word est maintenant 100% fonctionnel de bout en bout.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-30 22:49:13 +01:00
0800f74bd7 Fix: clean_chunk attend str, pas dict
Problème:
- Erreur: "expected string or bytes-like object, got 'dict'"
- À l'étape "Chunk Cleaning", on passait chunk (dict) au lieu de chunk["text"] (str)

Correction word_pipeline.py (ligne 434):
AVANT:
```python
cleaned = clean_chunk(chunk)  # chunk est un dict!
```

APRÈS:
```python
text: str = chunk.get("text", "")
cleaned_text = clean_chunk(text, use_llm=False)
if is_chunk_valid(cleaned_text, min_chars=30, min_words=8):
    chunk["text"] = cleaned_text
    cleaned_chunks.append(chunk)
```

Pattern copié depuis pdf_pipeline.py:765-771 où la même logique
extrait le texte, le nettoie, puis met à jour le dict.

Test réussi:
 48 paragraphes extraits
 37 chunks créés
 Nettoyage OK
 Validation OK
 Pipeline complet fonctionnel avec Mistral API

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-30 22:39:41 +01:00
19713f22d6 Fix: Pipeline Word + UI simplifiée pour upload
Corrections word_pipeline.py:
- Gestion robuste des erreurs LLM (fallback vers métadonnées Word)
- Correction: s["section_type"] -> s.get("type") pour classification
- Correction: "section_type" -> "type" dans fallback (use_llm=False)
- Ajout try/except pour extract_metadata avec fallback automatique
- Métadonnées Word utilisées si LLM échoue ou retourne None

Refonte upload.html (interface simplifiée):
- UI claire avec 2 options principales (LLM + Weaviate)
- Options PDF masquées automatiquement pour Word/Markdown
- Encart vert "Fichier Word détecté" s'affiche automatiquement
- Encart orange "Fichier Markdown détecté" ajouté
- Options avancées repliables (<details>)
- Pipeline adaptatif selon le type de fichier
- Support .md ajouté (oublié dans version précédente)

Problème résolu:
 AVANT: Trop d'options partout, confus pour l'utilisateur
 APRÈS: Interface simple, 2 cases à cocher, reste pré-configuré

Usage recommandé:
1. Sélectionner fichier (.pdf, .docx, .md)
2. Les options s'adaptent automatiquement
3. Cliquer sur "🚀 Analyser le document"

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-30 22:34:28 +01:00
4823fd1b10 Fix: Gestion robuste des valeurs None dans .lower()
Problème:
- AttributeError: 'NoneType' object has no attribute 'lower'
- Se produisait quand section.get("title") retournait None au lieu de ""

Corrections:
- llm_classifier.py:
  * is_excluded_section(): (section.get("title") or "").lower()
  * filter_indexable_sections(): (s.get("chapterTitle") or "").lower()
  * validate_classified_sections(): Idem pour chapter_title et section_title

- llm_validator.py:
  * apply_corrections(): Ajout de vérification "if title and ..."

- llm_chat.py:
  * call_llm(): Ajout d'une exception si provider est None/vide

Pattern de correction:
  AVANT: section.get("title", "").lower()  # Échoue si None
  APRÈS: (section.get("title") or "").lower()  # Sûr avec None

Raison:
.get(key, default) retourne le default SEULEMENT si la clé n'existe pas.
Si la clé existe avec valeur None, .get() retourne None, pas le default!

Donc: {"title": None}.get("title", "") -> None (pas "")

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-30 22:26:29 +01:00
4de645145a Ajout pipeline Word (.docx) pour ingestion RAG
Nouveaux modules (3 fichiers, ~850 lignes):
- word_processor.py: Extraction contenu Word (texte, headings, images, métadonnées)
- word_toc_extractor.py: Construction TOC hiérarchique depuis styles Heading
- word_pipeline.py: Orchestrateur complet réutilisant modules LLM existants

Fonctionnalités:
- Extraction native Word (pas d'OCR, économie ~0.003€/page)
- Support Heading 1-9 pour TOC hiérarchique
- Section paths compatibles Weaviate (1, 1.1, 1.2, etc.)
- Métadonnées depuis propriétés Word + extraction paragraphes
- Markdown compatible avec pipeline existant
- Extraction images inline
- Réutilise 100% des modules LLM (metadata, classifier, chunker, cleaner, validator)

Pipeline testé:
- Fichier exemple: "On the origin - 10 pages.docx"
- 48 paragraphes, 2 headings extraits
- 37 chunks créés
- Output: markdown + JSON chunks

Architecture:
1. Extraction Word → 2. Markdown → 3. TOC → 4-9. Modules LLM réutilisés → 10. Weaviate

Prochaine étape: Intégration Flask (route upload Word)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-30 21:58:43 +01:00
f2303569b5 Ajout nettoyage markdown pour TTS audio
- Nouvelle fonction _clean_markdown() pour supprimer le formatage markdown
- Supprime headers (#), bold (**), italic (*), code blocks (```)
- Supprime liens [text](url), citations (>), marqueurs de listes (-)
- Nettoie les espaces multiples pour un texte propre
- Évite la lecture à voix haute des caractères markdown
- Tests validés: tous les patterns markdown correctement nettoyés

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-30 19:35:01 +01:00
d91abd3566 Ajout de la fonctionnalité TTS (Text-to-Speech) avec XTTS v2
- Ajout de TTS>=0.22.0 aux dépendances
- Création du module utils/tts_generator.py avec Coqui XTTS v2
  * Support GPU avec mixed precision (FP16)
  * Lazy loading avec singleton pattern
  * Chunking automatique pour textes longs
  * Support multilingue (fr, en, es, de, etc.)
- Ajout de la route /chat/export-audio dans flask_app.py
- Ajout du bouton Audio dans chat.html (côté Word/PDF)
- Génération audio WAV téléchargeable depuis les réponses

Optimisé pour GPU 4070 (8GB VRAM) : utilise 4-6GB, génération rapide
Qualité : voix naturelle française avec prosodie expressive

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-30 14:31:30 +01:00
b835cd13ea Ajout des fonctionnalités d'export Word et PDF pour le chat RAG
- Ajout de python-docx et reportlab aux dépendances
- Création du module utils/word_exporter.py pour l'export Word
- Création du module utils/pdf_exporter.py pour l'export PDF
- Ajout des routes /chat/export-word et /chat/export-pdf dans flask_app.py
- Ajout des boutons d'export (Word et PDF) dans chat.html
- Les boutons apparaissent après chaque réponse de l'assistant
- Support des questions reformulées avec question originale

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-30 14:02:11 +01:00
d2f7165120 Add Library RAG project and cleanup root directory
- Add complete Library RAG application (Flask + MCP server)
  - PDF processing pipeline with OCR and LLM extraction
  - Weaviate vector database integration (BGE-M3 embeddings)
  - Flask web interface with search and document management
  - MCP server for Claude Desktop integration
  - Comprehensive test suite (134 tests)

- Clean up root directory
  - Remove obsolete documentation files
  - Remove backup and temporary files
  - Update autonomous agent configuration

- Update prompts
  - Enhance initializer bis prompt with better instructions

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-30 11:57:12 +01:00