Docfile commited on
Commit
8c3a64a
·
verified ·
1 Parent(s): 09be1bb

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +162 -104
app.py CHANGED
@@ -293,93 +293,127 @@ def api_francais():
293
  # Prompt utilisateur
294
  user_prompt = f"Sujet: {sujet}\nType: {choix}\nStyle: {style}"
295
 
296
- def generate_stream():
297
- try:
298
- logger.info("Démarrage du streaming de génération...")
299
- content_generated = False
300
- chunk_count = 0
301
-
302
- for chunk in client.models.generate_content_stream(
303
- model=model_name,
304
- contents=[user_prompt],
305
- config=config
306
- ):
307
- chunk_count += 1
308
-
309
- # Vérifier si la réponse a été bloquée
310
- if hasattr(chunk, 'prompt_feedback') and chunk.prompt_feedback:
311
- logger.warning(f"Prompt feedback: {chunk.prompt_feedback}")
312
- if hasattr(chunk.prompt_feedback, 'block_reason'):
313
- yield "data: " + json.dumps({
314
- 'type': 'error',
315
- 'content': f'Contenu bloqué par les filtres de sécurité: {chunk.prompt_feedback.block_reason}'
316
- }) + "\n\n"
317
- return
318
-
319
- if not chunk.candidates:
320
- logger.warning(f"Chunk {chunk_count} sans candidats")
321
- continue
322
-
323
- candidate = chunk.candidates[0]
324
-
325
- # Vérifier le statut du candidat
326
- if hasattr(candidate, 'finish_reason') and candidate.finish_reason:
327
- finish_reason = str(candidate.finish_reason)
328
- if finish_reason != 'STOP' and finish_reason != '0':
329
- logger.warning(f"Génération terminée avec raison: {finish_reason}")
330
- if 'SAFETY' in finish_reason:
331
- yield "data: " + json.dumps({
332
- 'type': 'error',
333
- 'content': 'Contenu bloqué par les filtres de sécurité.'
334
- }) + "\n\n"
335
- return
336
-
337
- if not hasattr(candidate, 'content') or not candidate.content:
338
- logger.warning(f"Chunk {chunk_count} sans contenu")
339
- continue
340
-
341
- if not hasattr(candidate.content, 'parts') or not candidate.content.parts:
342
- logger.warning(f"Chunk {chunk_count} sans parts")
343
- continue
344
-
345
- for part in candidate.content.parts:
346
- if not hasattr(part, 'text') or not part.text:
347
- continue
348
-
349
- content_generated = True
350
-
351
- if hasattr(part, 'thought') and part.thought:
352
- # Pensées du modèle (mode deepthink)
353
- yield "data: " + json.dumps({
354
- 'type': 'thought',
355
- 'content': part.text
356
- }) + "\n\n"
357
- else:
358
- # Réponse principale
359
- yield "data: " + json.dumps({
360
- 'type': 'content',
361
- 'content': part.text
362
- }) + "\n\n"
363
-
364
- logger.info(f"Fin du streaming. Chunks traités: {chunk_count}, Contenu généré: {content_generated}")
365
-
366
- if not content_generated:
367
- logger.error("Aucun contenu n'a été généré!")
368
- yield "data: " + json.dumps({
369
  'type': 'error',
370
- 'content': 'Aucun contenu généré. Le modèle n\'a pas produit de réponse.'
371
- }) + "\n\n"
372
- else:
373
- yield "data: " + json.dumps({'type': 'done'}) + "\n\n"
374
-
375
- except Exception as e:
376
- logger.exception("Erreur pendant la génération de contenu.")
377
- yield "data: " + json.dumps({
378
- 'type': 'error',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
379
  'content': f'Erreur serveur pendant la génération: {str(e)}'
380
- }) + "\n\n"
381
-
382
- return Response(generate_stream(), mimetype='text/event-stream')
 
383
 
384
 
385
  @app.route('/api/etude-texte', methods=['POST'])
@@ -454,30 +488,54 @@ def api_etude_texte():
454
 
455
  logger.info("Démarrage de l'analyse d'images...")
456
 
457
- for chunk in client.models.generate_content_stream(
 
458
  model=STANDARD_MODEL_NAME,
459
  contents=content,
460
  config=config
461
- ):
462
- if not chunk.candidates:
463
- continue
464
-
465
- for part in chunk.candidates[0].content.parts:
466
- if part.text:
467
- yield "data: " + json.dumps({
468
- 'type': 'content',
469
- 'content': part.text
470
- }) + "\n\n"
471
-
472
- logger.info("Fin de l'analyse d'images.")
473
- yield "data: " + json.dumps({'type': 'done'}) + "\n\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
474
 
475
  except Exception as e:
476
  logger.exception("Erreur pendant l'analyse d'images.")
477
- yield "data: " + json.dumps({
478
- 'type': 'error',
479
- 'content': f"Erreur serveur pendant l'analyse: {str(e)}"
480
- }) + "\n\n"
 
 
 
 
481
 
482
  finally:
483
  # Nettoyer les fichiers uploadés après traitement
@@ -485,7 +543,7 @@ def api_etude_texte():
485
  file_manager.cleanup_file(file_id)
486
  logger.info("Fichiers temporaires nettoyés.")
487
 
488
- return Response(generate_analysis(), mimetype='text/event-stream')
489
 
490
 
491
  @app.route('/health')
 
293
  # Prompt utilisateur
294
  user_prompt = f"Sujet: {sujet}\nType: {choix}\nStyle: {style}"
295
 
296
+ try:
297
+ logger.info("Démarrage de la génération...")
298
+
299
+ # Génération sans streaming
300
+ response = client.models.generate_content(
301
+ model=model_name,
302
+ contents=[user_prompt],
303
+ config=config
304
+ )
305
+
306
+ # Vérifier si la réponse a été bloquée
307
+ if hasattr(response, 'prompt_feedback') and response.prompt_feedback:
308
+ logger.warning(f"Prompt feedback: {response.prompt_feedback}")
309
+ if hasattr(response.prompt_feedback, 'block_reason'):
310
+ return Response(
311
+ json.dumps({
312
+ 'type': 'error',
313
+ 'content': f'Contenu bloqué par les filtres de sécurité: {response.prompt_feedback.block_reason}'
314
+ }),
315
+ mimetype='application/json',
316
+ status=400
317
+ )
318
+
319
+ # Vérifier les candidats
320
+ if not response.candidates:
321
+ logger.error("Aucun candidat dans la réponse")
322
+ return Response(
323
+ json.dumps({
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
324
  'type': 'error',
325
+ 'content': 'Aucune réponse générée par le modèle.'
326
+ }),
327
+ mimetype='application/json',
328
+ status=500
329
+ )
330
+
331
+ candidate = response.candidates[0]
332
+
333
+ # Vérifier le statut du candidat
334
+ if hasattr(candidate, 'finish_reason') and candidate.finish_reason:
335
+ finish_reason = str(candidate.finish_reason)
336
+ if 'SAFETY' in finish_reason:
337
+ logger.warning(f"Contenu bloqué: {finish_reason}")
338
+ return Response(
339
+ json.dumps({
340
+ 'type': 'error',
341
+ 'content': 'Contenu bloqué par les filtres de sécurité.'
342
+ }),
343
+ mimetype='application/json',
344
+ status=400
345
+ )
346
+
347
+ # Extraire le texte
348
+ if not hasattr(candidate, 'content') or not candidate.content:
349
+ logger.error("Pas de contenu dans le candidat")
350
+ return Response(
351
+ json.dumps({
352
+ 'type': 'error',
353
+ 'content': 'Aucun contenu généré.'
354
+ }),
355
+ mimetype='application/json',
356
+ status=500
357
+ )
358
+
359
+ if not hasattr(candidate.content, 'parts') or not candidate.content.parts:
360
+ logger.error("Pas de parts dans le contenu")
361
+ return Response(
362
+ json.dumps({
363
+ 'type': 'error',
364
+ 'content': 'Aucun contenu généré.'
365
+ }),
366
+ mimetype='application/json',
367
+ status=500
368
+ )
369
+
370
+ # Récupérer tout le texte
371
+ full_text = ""
372
+ thoughts = ""
373
+
374
+ for part in candidate.content.parts:
375
+ if hasattr(part, 'text') and part.text:
376
+ if hasattr(part, 'thought') and part.thought and use_deepthink:
377
+ thoughts += part.text + "\n"
378
+ else:
379
+ full_text += part.text
380
+
381
+ if not full_text:
382
+ logger.error("Aucun texte dans les parts")
383
+ return Response(
384
+ json.dumps({
385
+ 'type': 'error',
386
+ 'content': 'Aucun contenu textuel généré.'
387
+ }),
388
+ mimetype='application/json',
389
+ status=500
390
+ )
391
+
392
+ logger.info(f"Génération réussie. Longueur: {len(full_text)} caractères")
393
+
394
+ result = {
395
+ 'type': 'success',
396
+ 'content': full_text
397
+ }
398
+
399
+ if thoughts and use_deepthink:
400
+ result['thoughts'] = thoughts
401
+
402
+ return Response(
403
+ json.dumps(result),
404
+ mimetype='application/json'
405
+ )
406
+
407
+ except Exception as e:
408
+ logger.exception("Erreur pendant la génération de contenu.")
409
+ return Response(
410
+ json.dumps({
411
+ 'type': 'error',
412
  'content': f'Erreur serveur pendant la génération: {str(e)}'
413
+ }),
414
+ mimetype='application/json',
415
+ status=500
416
+ )
417
 
418
 
419
  @app.route('/api/etude-texte', methods=['POST'])
 
488
 
489
  logger.info("Démarrage de l'analyse d'images...")
490
 
491
+ # Génération sans streaming
492
+ response = client.models.generate_content(
493
  model=STANDARD_MODEL_NAME,
494
  contents=content,
495
  config=config
496
+ )
497
+
498
+ # Vérifier les erreurs
499
+ if not response.candidates:
500
+ raise ValueError("Aucun candidat dans la réponse")
501
+
502
+ candidate = response.candidates[0]
503
+
504
+ if not hasattr(candidate, 'content') or not candidate.content:
505
+ raise ValueError("Pas de contenu dans le candidat")
506
+
507
+ if not hasattr(candidate.content, 'parts') or not candidate.content.parts:
508
+ raise ValueError("Pas de parts dans le contenu")
509
+
510
+ # Récupérer le texte
511
+ full_text = ""
512
+ for part in candidate.content.parts:
513
+ if hasattr(part, 'text') and part.text:
514
+ full_text += part.text
515
+
516
+ if not full_text:
517
+ raise ValueError("Aucun texte généré")
518
+
519
+ logger.info(f"Analyse réussie. Longueur: {len(full_text)} caractères")
520
+
521
+ return Response(
522
+ json.dumps({
523
+ 'type': 'success',
524
+ 'content': full_text
525
+ }),
526
+ mimetype='application/json'
527
+ )
528
 
529
  except Exception as e:
530
  logger.exception("Erreur pendant l'analyse d'images.")
531
+ return Response(
532
+ json.dumps({
533
+ 'type': 'error',
534
+ 'content': f"Erreur serveur pendant l'analyse: {str(e)}"
535
+ }),
536
+ mimetype='application/json',
537
+ status=500
538
+ )
539
 
540
  finally:
541
  # Nettoyer les fichiers uploadés après traitement
 
543
  file_manager.cleanup_file(file_id)
544
  logger.info("Fichiers temporaires nettoyés.")
545
 
546
+ return generate_analysis()
547
 
548
 
549
  @app.route('/health')