KJ24 commited on
Commit
1aff8d3
·
verified ·
1 Parent(s): 48dc9ed

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +190 -80
app.py CHANGED
@@ -1,16 +1,16 @@
1
  """
2
- app.py v4.0 CORRIGÉ - FastAPI pour Chunking Sémantique Intelligent
3
 
4
- CORRECTIONS MAJEURES v4.0:
5
- Import SmartChunkerPipeline au lieu de ChunkingPipeline
6
- Méthodes corrigées (process_text au lieu de process_text_sync)
7
- Health check v4.0 avec nouvelles méthodes
8
- Gestion erreurs améliorée
 
9
  ✅ Optimisations HF Space gratuit renforcées
10
  ✅ Variables d'environnement sécurisées
11
  """
12
 
13
-
14
  import os
15
  import logging
16
  import time
@@ -30,14 +30,21 @@ logging.basicConfig(
30
  )
31
  logger = logging.getLogger(__name__)
32
 
33
- # ✅ CORRECTION: Import SmartChunkerPipeline v4.0
34
  try:
35
- from chunker_pipeline import SmartChunkerPipeline # Import corrigé
36
  from schemas import ChunkRequest, ChunkResponse, ChunkMetadata
37
- logger.info("✅ Modules de chunking v4.0 importés avec succès")
38
  except ImportError as e:
39
  logger.error(f"❌ Erreur import modules chunking: {e}")
40
- raise
 
 
 
 
 
 
 
41
 
42
  # ✅ Configuration sécurisée variables d'environnement HF Space
43
  os.environ["TOKENIZERS_PARALLELISM"] = "false"
@@ -46,11 +53,14 @@ os.environ["TRANSFORMERS_VERBOSITY"] = "error"
46
  os.environ["HF_HOME"] = "/app/cache/huggingface"
47
  os.environ["TRANSFORMERS_CACHE"] = "/app/cache/transformers"
48
 
49
- # Initialisation FastAPI avec optimisations v4.0
 
 
 
50
  app = FastAPI(
51
- title="Chunking Sémantique Intelligent API v4.0",
52
- description="API de découpage récursif hiérarchique avec parentalité - Powered by Chonkie + HuggingFace",
53
- version="4.0.0",
54
  docs_url="/docs",
55
  redoc_url="/redoc"
56
  )
@@ -64,7 +74,7 @@ app.add_middleware(
64
  allow_headers=["*"],
65
  )
66
 
67
- # ✅ Instance globale pipeline v4.0 (chargée une seule fois)
68
  pipeline = None
69
  executor = ThreadPoolExecutor(max_workers=1) # HF Space gratuit = 1 worker max
70
 
@@ -82,44 +92,59 @@ async def catch_exceptions_middleware(request: Request, call_next):
82
  content={
83
  "error": "Erreur interne du serveur",
84
  "detail": str(e),
85
- "timestamp": time.time()
 
86
  }
87
  )
88
 
89
  @app.on_event("startup")
90
  async def startup_event():
91
- """✅ Initialisation pipeline v4.0 au démarrage"""
92
  global pipeline
93
  try:
94
- logger.info("🚀 Initialisation SmartChunkerPipeline v4.0...")
95
 
96
- # ✅ CORRECTION: SmartChunkerPipeline au lieu de ChunkingPipeline
97
  pipeline = SmartChunkerPipeline()
98
  await pipeline.initialize()
99
 
100
- # Test santé initial
101
- health = await pipeline.health_check_v4()
102
- logger.info(f"✅ Pipeline v4.0 initialisé - Status: {health['status']}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
 
104
- # Log informations configuration
105
- config_info = await pipeline.get_config_info_v4()
106
- logger.info(f"⚙️ LLM: {config_info['models']['llm_model']}")
107
- logger.info(f"🧬 Embedding: {config_info['models']['embedding_model']}")
108
- logger.info(f"🦛 Chonkie: {config_info['models']['chonkie_available']}")
109
 
110
  except Exception as e:
111
- logger.error(f"❌ Erreur initialisation pipeline v4.0: {e}")
112
  raise
113
 
114
  @app.on_event("shutdown")
115
  async def shutdown_event():
116
- """✅ Nettoyage à l'arrêt optimisé v4.0"""
117
  global pipeline, executor
118
  try:
119
  logger.info("🛑 Arrêt du service - nettoyage en cours...")
120
 
121
  if pipeline:
122
- await pipeline.cleanup()
 
 
 
 
123
 
124
  if executor:
125
  executor.shutdown(wait=True)
@@ -127,20 +152,22 @@ async def shutdown_event():
127
  # Nettoyage mémoire final
128
  gc.collect()
129
 
130
- logger.info("✅ Nettoyage terminé")
131
 
132
  except Exception as e:
133
  logger.error(f"⚠️ Erreur lors du nettoyage: {e}")
134
 
135
  @app.get("/")
136
  async def root():
137
- """Point d'entrée racine avec informations service v4.0"""
138
  return {
139
  "service": "Chunking Sémantique Intelligent API",
140
- "version": "4.0.0",
141
  "status": "running",
 
142
  "features": [
143
  "Chunking sémantique avec Chonkie",
 
144
  "Hiérarchie récursive intelligente",
145
  "Relations bidirectionnelles",
146
  "Export Obsidian [[Titre]], id",
@@ -152,68 +179,119 @@ async def root():
152
  "GET /health - Vérification santé",
153
  "GET /config - Configuration système",
154
  "POST /chunk - Chunking principal",
155
- "POST /chunk-batch - Chunking par lots"
 
156
  ],
157
- "documentation": "/docs"
 
 
 
 
 
158
  }
159
 
160
  @app.get("/health")
161
  async def health_check():
162
- """✅ Vérification santé complète v4.0"""
163
  try:
164
  if pipeline is None:
165
  return {
166
  "status": "error",
167
  "message": "Pipeline non initialisé",
168
- "version": "4.0.0",
169
  "timestamp": time.time()
170
  }
171
 
172
- # ✅ CORRECTION: health_check_v4 au lieu de quick_health_check
173
- health_result = await pipeline.health_check_v4()
 
174
 
175
- # Ajout informations mémoire
176
- memory_info = pipeline.get_memory_usage_v4()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
 
178
  return {
179
  **health_result,
180
  "memory_info": memory_info,
181
- "version": "4.0.0"
 
182
  }
183
 
184
  except Exception as e:
185
- logger.error(f"❌ Erreur health check: {e}")
186
  return {
187
  "status": "error",
188
  "message": f"Erreur health check: {str(e)}",
189
- "version": "4.0.0",
190
  "timestamp": time.time()
191
  }
192
 
193
  @app.get("/config")
194
  async def get_config():
195
- """✅ NOUVEAU: Informations configuration système v4.0"""
196
  try:
197
  if pipeline is None:
198
  raise HTTPException(status_code=503, detail="Pipeline non initialisé")
199
 
200
- config_info = await pipeline.get_config_info_v4()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
201
  return {
202
  **config_info,
203
- "api_version": "4.0.0",
204
- "timestamp": time.time()
 
205
  }
206
 
207
  except Exception as e:
208
- logger.error(f"❌ Erreur récupération config: {e}")
209
  raise HTTPException(status_code=500, detail=f"Erreur config: {str(e)}")
210
 
211
  @app.post("/chunk", response_model=ChunkResponse)
212
  async def chunk_text(request: ChunkRequest):
213
  """
214
- ✅ Point d'entrée principal chunking sémantique intelligent v4.0
215
 
216
- Traitement récursif hiérarchique avec:
 
217
  - Chonkie SemanticChunker + RecursiveChunker
218
  - Relations bidirectionnelles complètes
219
  - Export Obsidian format [[Titre]], id
@@ -225,7 +303,7 @@ async def chunk_text(request: ChunkRequest):
225
  start_time = time.time()
226
 
227
  try:
228
- logger.info(f"📝 Début chunking v4.0: {request.titre or 'Sans titre'}")
229
 
230
  # Validation entrées renforcée
231
  if not request.text or len(request.text.strip()) < 10:
@@ -240,11 +318,24 @@ async def chunk_text(request: ChunkRequest):
240
  detail="Texte trop long (max 500,000 caractères pour Space gratuit)"
241
  )
242
 
243
- # ✅ CORRECTION: process_text (async) au lieu de process_text_sync
244
- result = await pipeline.process_text(request)
 
 
 
 
 
 
 
 
 
 
 
 
 
245
 
246
  processing_time = time.time() - start_time
247
- logger.info(f"✅ Chunking v4.0 terminé: {result.total_chunks} chunks en {processing_time:.2f}s")
248
 
249
  return result
250
 
@@ -252,11 +343,14 @@ async def chunk_text(request: ChunkRequest):
252
  # Re-lever les HTTPException sans modification
253
  raise
254
  except Exception as e:
255
- logger.error(f"❌ Erreur chunking v4.0: {str(e)}")
256
 
257
- # Nettoyage mémoire en cas d'erreur
258
  try:
259
- await pipeline._cleanup_memory_v4()
 
 
 
260
  except:
261
  pass
262
 
@@ -264,12 +358,12 @@ async def chunk_text(request: ChunkRequest):
264
 
265
  raise HTTPException(
266
  status_code=500,
267
- detail=f"Erreur traitement chunking v4.0: {str(e)}"
268
  )
269
 
270
  @app.post("/chunk-batch")
271
  async def chunk_batch(requests: List[ChunkRequest]):
272
- """✅ Traitement par lots optimisé v4.0 (limité HF Space gratuit)"""
273
 
274
  # Validation limite batch pour Space gratuit
275
  max_batch_size = 3
@@ -286,12 +380,18 @@ async def chunk_batch(requests: List[ChunkRequest]):
286
  results = []
287
 
288
  try:
289
- logger.info(f"📦 Début chunking batch v4.0: {len(requests)} textes")
290
 
291
  for idx, request in enumerate(requests):
292
  try:
293
- # Traitement individuel avec gestion erreurs
294
- result = await pipeline.process_text(request)
 
 
 
 
 
 
295
  results.append({
296
  "success": True,
297
  "index": idx,
@@ -313,11 +413,12 @@ async def chunk_batch(requests: List[ChunkRequest]):
313
 
314
  # Nettoyage mémoire après batch
315
  try:
316
- await pipeline._cleanup_memory_v4()
 
317
  except:
318
  pass
319
 
320
- logger.info(f"✅ Batch v4.0 terminé: {len(successful_results)}/{len(requests)} succès en {total_time:.2f}s")
321
 
322
  return {
323
  "results": results,
@@ -325,57 +426,65 @@ async def chunk_batch(requests: List[ChunkRequest]):
325
  "successful": len(successful_results),
326
  "failed": len(requests) - len(successful_results),
327
  "total_processing_time": total_time,
328
- "version": "4.0.0"
329
  }
330
 
331
  except Exception as e:
332
- logger.error(f"❌ Erreur chunking batch v4.0: {e}")
333
  gc.collect()
334
  raise HTTPException(
335
  status_code=500,
336
- detail=f"Erreur traitement batch v4.0: {str(e)}"
337
  )
338
 
339
- # ✅ NOUVEAU: Endpoint test pour validation déploiement
340
  @app.post("/test")
341
  async def test_chunking():
342
- """Endpoint de test pour validation déploiement v4.0"""
343
  if pipeline is None:
344
  raise HTTPException(status_code=503, detail="Pipeline non initialisé")
345
 
346
  try:
347
  # Test avec texte simple
348
  test_request = ChunkRequest(
349
- text="Ceci est un test de chunking sémantique intelligent v4.0. "
350
- "Le système utilise Chonkie pour le découpage sémantique. "
 
351
  "Il génère des relations hiérarchiques bidirectionnelles. "
352
  "L'export Obsidian utilise le format [[Titre]], id. "
353
  "Les agents IA reçoivent une base de connaissance structurée.",
354
- titre="Test Chunking v4.0",
355
- source_id="test_v4",
356
  include_metadata=True
357
  )
358
 
359
- result = await pipeline.process_text(test_request)
 
 
 
 
 
360
 
361
  return {
362
  "test_status": "success",
363
  "chunks_generated": result.total_chunks,
364
  "processing_time": result.processing_time,
365
  "features_tested": [
 
366
  "Chunking sémantique Chonkie",
367
  "Relations hiérarchiques",
368
  "Export Obsidian",
369
  "Base connaissance agents"
370
  ],
371
- "version": "4.0.0"
 
372
  }
373
 
374
  except Exception as e:
375
- logger.error(f"❌ Erreur test chunking v4.0: {e}")
376
  raise HTTPException(
377
  status_code=500,
378
- detail=f"Test échoué v4.0: {str(e)}"
379
  )
380
 
381
  # ✅ Gestion erreur 404 personnalisée
@@ -388,7 +497,8 @@ async def not_found_handler(request: Request, exc):
388
  "message": f"L'endpoint {request.url.path} n'existe pas",
389
  "available_endpoints": ["/", "/health", "/config", "/chunk", "/chunk-batch", "/test"],
390
  "documentation": "/docs",
391
- "version": "4.0.0"
 
392
  }
393
  )
394
 
 
1
  """
2
+ app.py v5.0 ADAPTÉ - FastAPI pour Chunking Sémantique Intelligent
3
 
4
+ ADAPTATIONS MAJEURES v5.0:
5
+ Compatible avec LlamaIndex moderne modulaire (llama-index-core)
6
+ Import SmartChunkerPipeline adapté pour nouvelle architecture
7
+ Méthodes corrigées pour nouvelle structure
8
+ Health check v5.0 avec support modulaire
9
+ ✅ Gestion erreurs améliorée pour compatibilité
10
  ✅ Optimisations HF Space gratuit renforcées
11
  ✅ Variables d'environnement sécurisées
12
  """
13
 
 
14
  import os
15
  import logging
16
  import time
 
30
  )
31
  logger = logging.getLogger(__name__)
32
 
33
+ # ✅ ADAPTATION: Import SmartChunkerPipeline v5.0 avec fallback
34
  try:
35
+ from chunker_pipeline import SmartChunkerPipeline # Version moderne
36
  from schemas import ChunkRequest, ChunkResponse, ChunkMetadata
37
+ logger.info("✅ Modules de chunking v5.0 importés avec succès (LlamaIndex moderne)")
38
  except ImportError as e:
39
  logger.error(f"❌ Erreur import modules chunking: {e}")
40
+ # Fallback pour tests
41
+ try:
42
+ from pipeline import ChunkingPipeline as SmartChunkerPipeline
43
+ from schemas import ChunkRequest, ChunkResponse, ChunkMetadata
44
+ logger.warning("⚠️ Utilisation pipeline fallback - fonctionnalités limitées")
45
+ except ImportError as e2:
46
+ logger.error(f"❌ Erreur import fallback: {e2}")
47
+ raise
48
 
49
  # ✅ Configuration sécurisée variables d'environnement HF Space
50
  os.environ["TOKENIZERS_PARALLELISM"] = "false"
 
53
  os.environ["HF_HOME"] = "/app/cache/huggingface"
54
  os.environ["TRANSFORMERS_CACHE"] = "/app/cache/transformers"
55
 
56
+ # NOUVEAU: Configuration spécifique LlamaIndex moderne
57
+ os.environ["LLAMA_INDEX_CACHE_DIR"] = "/app/cache/llamaindex"
58
+
59
+ # Initialisation FastAPI avec optimisations v5.0
60
  app = FastAPI(
61
+ title="Chunking Sémantique Intelligent API v5.0",
62
+ description="API de découpage récursif hiérarchique avec parentalité - Powered by LlamaIndex Moderne + Chonkie",
63
+ version="5.0.0",
64
  docs_url="/docs",
65
  redoc_url="/redoc"
66
  )
 
74
  allow_headers=["*"],
75
  )
76
 
77
+ # ✅ Instance globale pipeline v5.0 (chargée une seule fois)
78
  pipeline = None
79
  executor = ThreadPoolExecutor(max_workers=1) # HF Space gratuit = 1 worker max
80
 
 
92
  content={
93
  "error": "Erreur interne du serveur",
94
  "detail": str(e),
95
+ "timestamp": time.time(),
96
+ "version": "5.0.0"
97
  }
98
  )
99
 
100
  @app.on_event("startup")
101
  async def startup_event():
102
+ """✅ Initialisation pipeline v5.0 au démarrage avec LlamaIndex moderne"""
103
  global pipeline
104
  try:
105
+ logger.info("🚀 Initialisation SmartChunkerPipeline v5.0 (LlamaIndex moderne)...")
106
 
107
+ # ✅ ADAPTATION: SmartChunkerPipeline avec support modulaire
108
  pipeline = SmartChunkerPipeline()
109
  await pipeline.initialize()
110
 
111
+ # Test santé initial avec méthodes adaptatives
112
+ try:
113
+ health = await pipeline.health_check_v4()
114
+ logger.info(f"✅ Pipeline v5.0 initialisé - Status: {health['status']}")
115
+ except AttributeError:
116
+ # Fallback pour anciennes méthodes
117
+ health = await pipeline.get_health_status() if hasattr(pipeline, 'get_health_status') else {"status": "unknown"}
118
+ logger.info(f"✅ Pipeline v5.0 initialisé - Status: {health.get('status', 'initialized')}")
119
+
120
+ # Log informations configuration avec fallback
121
+ try:
122
+ config_info = await pipeline.get_config_info_v4()
123
+ logger.info(f"⚙️ LLM: {config_info.get('models', {}).get('llm_model', 'N/A')}")
124
+ logger.info(f"🧬 Embedding: {config_info.get('models', {}).get('embedding_model', 'N/A')}")
125
+ logger.info(f"🦛 Chonkie: {config_info.get('models', {}).get('chonkie_available', False)}")
126
+ except AttributeError:
127
+ logger.info("⚙️ Configuration détaillée non disponible (mode fallback)")
128
 
129
+ logger.info("🔧 LlamaIndex moderne modulaire configuré")
 
 
 
 
130
 
131
  except Exception as e:
132
+ logger.error(f"❌ Erreur initialisation pipeline v5.0: {e}")
133
  raise
134
 
135
  @app.on_event("shutdown")
136
  async def shutdown_event():
137
+ """✅ Nettoyage à l'arrêt optimisé v5.0"""
138
  global pipeline, executor
139
  try:
140
  logger.info("🛑 Arrêt du service - nettoyage en cours...")
141
 
142
  if pipeline:
143
+ # Nettoyage adaptatif selon les méthodes disponibles
144
+ if hasattr(pipeline, 'cleanup'):
145
+ await pipeline.cleanup()
146
+ elif hasattr(pipeline, '_cleanup_memory_v4'):
147
+ await pipeline._cleanup_memory_v4()
148
 
149
  if executor:
150
  executor.shutdown(wait=True)
 
152
  # Nettoyage mémoire final
153
  gc.collect()
154
 
155
+ logger.info("✅ Nettoyage v5.0 terminé")
156
 
157
  except Exception as e:
158
  logger.error(f"⚠️ Erreur lors du nettoyage: {e}")
159
 
160
  @app.get("/")
161
  async def root():
162
+ """Point d'entrée racine avec informations service v5.0"""
163
  return {
164
  "service": "Chunking Sémantique Intelligent API",
165
+ "version": "5.0.0",
166
  "status": "running",
167
+ "architecture": "LlamaIndex Moderne Modulaire",
168
  "features": [
169
  "Chunking sémantique avec Chonkie",
170
+ "LlamaIndex moderne (llama-index-core)",
171
  "Hiérarchie récursive intelligente",
172
  "Relations bidirectionnelles",
173
  "Export Obsidian [[Titre]], id",
 
179
  "GET /health - Vérification santé",
180
  "GET /config - Configuration système",
181
  "POST /chunk - Chunking principal",
182
+ "POST /chunk-batch - Chunking par lots",
183
+ "POST /test - Test de fonctionnement"
184
  ],
185
+ "documentation": "/docs",
186
+ "compatible_with": [
187
+ "llama-index-core (moderne)",
188
+ "llama-index-embeddings-huggingface",
189
+ "chonkie >= 0.1.0"
190
+ ]
191
  }
192
 
193
  @app.get("/health")
194
  async def health_check():
195
+ """✅ Vérification santé complète v5.0 avec fallbacks adaptatifs"""
196
  try:
197
  if pipeline is None:
198
  return {
199
  "status": "error",
200
  "message": "Pipeline non initialisé",
201
+ "version": "5.0.0",
202
  "timestamp": time.time()
203
  }
204
 
205
+ # ✅ ADAPTATION: Health check avec fallbacks multiples
206
+ health_result = None
207
+ memory_info = None
208
 
209
+ # Tentative méthode v4.0
210
+ try:
211
+ health_result = await pipeline.health_check_v4()
212
+ except AttributeError:
213
+ # Fallback méthode alternative
214
+ try:
215
+ health_result = await pipeline.get_health_status()
216
+ except AttributeError:
217
+ # Fallback basique
218
+ health_result = {
219
+ "status": "running",
220
+ "checks": {"initialization": True},
221
+ "version": "5.0.0"
222
+ }
223
+
224
+ # Tentative récupération mémoire
225
+ try:
226
+ memory_info = pipeline.get_memory_usage_v4()
227
+ except AttributeError:
228
+ try:
229
+ memory_info = pipeline.get_memory_usage()
230
+ except AttributeError:
231
+ memory_info = {"status": "monitoring_unavailable"}
232
 
233
  return {
234
  **health_result,
235
  "memory_info": memory_info,
236
+ "version": "5.0.0",
237
+ "architecture": "LlamaIndex Moderne"
238
  }
239
 
240
  except Exception as e:
241
+ logger.error(f"❌ Erreur health check v5.0: {e}")
242
  return {
243
  "status": "error",
244
  "message": f"Erreur health check: {str(e)}",
245
+ "version": "5.0.0",
246
  "timestamp": time.time()
247
  }
248
 
249
  @app.get("/config")
250
  async def get_config():
251
+ """✅ Informations configuration système v5.0 avec adaptation modulaire"""
252
  try:
253
  if pipeline is None:
254
  raise HTTPException(status_code=503, detail="Pipeline non initialisé")
255
 
256
+ # ADAPTATION: Configuration avec fallbacks
257
+ config_info = {}
258
+
259
+ try:
260
+ config_info = await pipeline.get_config_info_v4()
261
+ except AttributeError:
262
+ # Fallback configuration basique
263
+ config_info = {
264
+ "version": "5.0.0",
265
+ "architecture": "LlamaIndex Moderne Modulaire",
266
+ "models": {
267
+ "llm_available": hasattr(pipeline, 'llm'),
268
+ "embedding_available": hasattr(pipeline, 'embed_model'),
269
+ "chonkie_available": hasattr(pipeline, 'chonkie_semantic')
270
+ },
271
+ "chunking_config": {
272
+ "pipeline_type": "SmartChunkerPipeline",
273
+ "initialized": pipeline._is_initialized if hasattr(pipeline, '_is_initialized') else True
274
+ }
275
+ }
276
+
277
  return {
278
  **config_info,
279
+ "api_version": "5.0.0",
280
+ "timestamp": time.time(),
281
+ "llamaindex_architecture": "moderne_modulaire"
282
  }
283
 
284
  except Exception as e:
285
+ logger.error(f"❌ Erreur récupération config v5.0: {e}")
286
  raise HTTPException(status_code=500, detail=f"Erreur config: {str(e)}")
287
 
288
  @app.post("/chunk", response_model=ChunkResponse)
289
  async def chunk_text(request: ChunkRequest):
290
  """
291
+ ✅ Point d'entrée principal chunking sémantique intelligent v5.0
292
 
293
+ Traitement récursif hiérarchique avec LlamaIndex moderne:
294
+ - llama-index-core + llama-index-embeddings-huggingface
295
  - Chonkie SemanticChunker + RecursiveChunker
296
  - Relations bidirectionnelles complètes
297
  - Export Obsidian format [[Titre]], id
 
303
  start_time = time.time()
304
 
305
  try:
306
+ logger.info(f"📝 Début chunking v5.0: {request.titre or 'Sans titre'}")
307
 
308
  # Validation entrées renforcée
309
  if not request.text or len(request.text.strip()) < 10:
 
318
  detail="Texte trop long (max 500,000 caractères pour Space gratuit)"
319
  )
320
 
321
+ # ✅ ADAPTATION: Appel méthode avec fallbacks
322
+ result = None
323
+
324
+ # Tentative méthode v4.0
325
+ try:
326
+ result = await pipeline.process_text(request)
327
+ except AttributeError:
328
+ # Fallback méthode alternative
329
+ try:
330
+ result = await pipeline.process_text_sync(request)
331
+ except AttributeError:
332
+ raise HTTPException(
333
+ status_code=500,
334
+ detail="Méthode de traitement non disponible dans cette version du pipeline"
335
+ )
336
 
337
  processing_time = time.time() - start_time
338
+ logger.info(f"✅ Chunking v5.0 terminé: {result.total_chunks} chunks en {processing_time:.2f}s")
339
 
340
  return result
341
 
 
343
  # Re-lever les HTTPException sans modification
344
  raise
345
  except Exception as e:
346
+ logger.error(f"❌ Erreur chunking v5.0: {str(e)}")
347
 
348
+ # Nettoyage mémoire en cas d'erreur avec fallback
349
  try:
350
+ if hasattr(pipeline, '_cleanup_memory_v4'):
351
+ await pipeline._cleanup_memory_v4()
352
+ elif hasattr(pipeline, '_cleanup_memory'):
353
+ await pipeline._cleanup_memory()
354
  except:
355
  pass
356
 
 
358
 
359
  raise HTTPException(
360
  status_code=500,
361
+ detail=f"Erreur traitement chunking v5.0: {str(e)}"
362
  )
363
 
364
  @app.post("/chunk-batch")
365
  async def chunk_batch(requests: List[ChunkRequest]):
366
+ """✅ Traitement par lots optimisé v5.0 (limité HF Space gratuit)"""
367
 
368
  # Validation limite batch pour Space gratuit
369
  max_batch_size = 3
 
380
  results = []
381
 
382
  try:
383
+ logger.info(f"📦 Début chunking batch v5.0: {len(requests)} textes")
384
 
385
  for idx, request in enumerate(requests):
386
  try:
387
+ # Traitement individuel avec méthodes adaptatives
388
+ result = None
389
+
390
+ try:
391
+ result = await pipeline.process_text(request)
392
+ except AttributeError:
393
+ result = await pipeline.process_text_sync(request)
394
+
395
  results.append({
396
  "success": True,
397
  "index": idx,
 
413
 
414
  # Nettoyage mémoire après batch
415
  try:
416
+ if hasattr(pipeline, '_cleanup_memory_v4'):
417
+ await pipeline._cleanup_memory_v4()
418
  except:
419
  pass
420
 
421
+ logger.info(f"✅ Batch v5.0 terminé: {len(successful_results)}/{len(requests)} succès en {total_time:.2f}s")
422
 
423
  return {
424
  "results": results,
 
426
  "successful": len(successful_results),
427
  "failed": len(requests) - len(successful_results),
428
  "total_processing_time": total_time,
429
+ "version": "5.0.0"
430
  }
431
 
432
  except Exception as e:
433
+ logger.error(f"❌ Erreur chunking batch v5.0: {e}")
434
  gc.collect()
435
  raise HTTPException(
436
  status_code=500,
437
+ detail=f"Erreur traitement batch v5.0: {str(e)}"
438
  )
439
 
440
+ # ✅ Endpoint test adapté pour v5.0
441
  @app.post("/test")
442
  async def test_chunking():
443
+ """Endpoint de test pour validation déploiement v5.0"""
444
  if pipeline is None:
445
  raise HTTPException(status_code=503, detail="Pipeline non initialisé")
446
 
447
  try:
448
  # Test avec texte simple
449
  test_request = ChunkRequest(
450
+ text="Ceci est un test de chunking sémantique intelligent v5.0. "
451
+ "Le système utilise LlamaIndex moderne avec llama-index-core. "
452
+ "Il intègre Chonkie pour le découpage sémantique avancé. "
453
  "Il génère des relations hiérarchiques bidirectionnelles. "
454
  "L'export Obsidian utilise le format [[Titre]], id. "
455
  "Les agents IA reçoivent une base de connaissance structurée.",
456
+ titre="Test Chunking v5.0",
457
+ source_id="test_v5",
458
  include_metadata=True
459
  )
460
 
461
+ # Test avec méthodes adaptatives
462
+ result = None
463
+ try:
464
+ result = await pipeline.process_text(test_request)
465
+ except AttributeError:
466
+ result = await pipeline.process_text_sync(test_request)
467
 
468
  return {
469
  "test_status": "success",
470
  "chunks_generated": result.total_chunks,
471
  "processing_time": result.processing_time,
472
  "features_tested": [
473
+ "LlamaIndex moderne (llama-index-core)",
474
  "Chunking sémantique Chonkie",
475
  "Relations hiérarchiques",
476
  "Export Obsidian",
477
  "Base connaissance agents"
478
  ],
479
+ "version": "5.0.0",
480
+ "architecture": "LlamaIndex Moderne Modulaire"
481
  }
482
 
483
  except Exception as e:
484
+ logger.error(f"❌ Erreur test chunking v5.0: {e}")
485
  raise HTTPException(
486
  status_code=500,
487
+ detail=f"Test échoué v5.0: {str(e)}"
488
  )
489
 
490
  # ✅ Gestion erreur 404 personnalisée
 
497
  "message": f"L'endpoint {request.url.path} n'existe pas",
498
  "available_endpoints": ["/", "/health", "/config", "/chunk", "/chunk-batch", "/test"],
499
  "documentation": "/docs",
500
+ "version": "5.0.0",
501
+ "architecture": "LlamaIndex Moderne"
502
  }
503
  )
504