malaknihed commited on
Commit
907d6a2
·
verified ·
1 Parent(s): 7e482f5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +166 -36
app.py CHANGED
@@ -1,16 +1,26 @@
1
  from fastapi import FastAPI, File, UploadFile, Form
2
  from fastapi.responses import JSONResponse, RedirectResponse
3
  from fastapi.staticfiles import StaticFiles
4
- from fastapi.middleware.cors import CORSMiddleware
5
- from transformers import pipeline
6
  import shutil
7
  import os
8
  import logging
 
9
  from PyPDF2 import PdfReader
10
  import docx
11
- from PIL import Image
12
- #h
13
- from pydantic import BaseModel
 
 
 
 
 
 
 
 
 
 
14
 
15
  # Configuration du logging
16
  logging.basicConfig(level=logging.INFO)
@@ -29,13 +39,13 @@ app.add_middleware(
29
  UPLOAD_DIR = "uploads"
30
  os.makedirs(UPLOAD_DIR, exist_ok=True)
31
 
32
- # Chargement des modèles
33
  try:
34
- qa_pipeline = pipeline("question-answering", model="deepset/roberta-base-squad2")
35
- logging.info("✅ Modèle QA chargé avec succès !")
36
  except Exception as e:
37
- qa_pipeline = None
38
- logging.error(f"❌ Erreur chargement modèle QA : {e}")
39
 
40
  try:
41
  image_captioning = pipeline("image-to-text", model="nlpconnect/vit-gpt2-image-captioning")
@@ -44,60 +54,180 @@ except Exception as e:
44
  image_captioning = None
45
  logging.error(f"❌ Erreur chargement modèle image : {e}")
46
 
47
- # Fonction pour extraire du texte d'un document
48
- def extract_text_from_file(file_path):
 
 
 
 
 
 
 
 
 
49
  text = ""
50
- if file_path.endswith(".txt"):
51
  with open(file_path, "r", encoding="utf-8") as f:
52
  text = f.read()
53
- elif file_path.endswith(".pdf"):
54
  try:
55
  reader = PdfReader(file_path)
56
  text = "\n".join([page.extract_text() or "" for page in reader.pages]).strip()
57
  except Exception as e:
58
  logging.error(f"❌ Erreur lecture PDF : {e}")
59
- elif file_path.endswith(".docx"):
 
60
  try:
61
  doc = docx.Document(file_path)
62
  text = "\n".join([para.text for para in doc.paragraphs]).strip()
63
  except Exception as e:
64
  logging.error(f"❌ Erreur lecture DOCX : {e}")
65
- return text
 
 
66
 
67
- @app.post("/qa/document/")
68
- async def question_answering_document(file: UploadFile = File(...), question: str = Form(...)):
69
- file_path = os.path.join(UPLOAD_DIR, file.filename)
70
- with open(file_path, "wb") as buffer:
71
- shutil.copyfileobj(file.file, buffer)
72
-
73
- text = extract_text_from_file(file_path)
74
  if not text:
75
- return JSONResponse(content={"error": "Le fichier ne contient pas de texte lisible"}, status_code=400)
76
-
 
 
 
 
 
77
  try:
78
- answer = qa_pipeline(question=question, context=text)
79
- return JSONResponse(content={"answer": answer["answer"]})
80
  except Exception as e:
81
- logging.error(f"❌ Erreur lors du QA : {e}")
82
- return JSONResponse(content={"error": "Échec du Question Answering"}, status_code=500)
 
 
 
 
 
83
 
84
- @app.post("/qa/image/")
85
- async def question_answering_image(file: UploadFile = File(...)):
86
  file_path = os.path.join(UPLOAD_DIR, file.filename)
87
  with open(file_path, "wb") as buffer:
88
  shutil.copyfileobj(file.file, buffer)
89
-
90
  try:
91
- with Image.open(file_path) as img:
92
  caption = image_captioning(img)[0]["generated_text"]
93
  return JSONResponse(content={"caption": caption})
94
  except Exception as e:
95
- logging.error(f"❌ Erreur analyse image : {e}")
96
  return JSONResponse(content={"error": "Échec de l'analyse de l'image"}, status_code=400)
 
 
 
 
 
 
 
 
 
 
 
 
 
97
 
98
- # Montage des fichiers statiques
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  app.mount("/", StaticFiles(directory="static", html=True), name="static")
100
 
 
 
 
101
  @app.get("/")
102
  async def root():
103
- return RedirectResponse(url="/index.html")
 
1
  from fastapi import FastAPI, File, UploadFile, Form
2
  from fastapi.responses import JSONResponse, RedirectResponse
3
  from fastapi.staticfiles import StaticFiles
4
+ from transformers import pipeline, M2M100ForConditionalGeneration, M2M100Tokenizer
 
5
  import shutil
6
  import os
7
  import logging
8
+ from fastapi.middleware.cors import CORSMiddleware
9
  from PyPDF2 import PdfReader
10
  import docx
11
+ from PIL import Image # Pour ouvrir les images avant analyse
12
+ from transformers import MarianMTModel, MarianTokenizer
13
+ import os
14
+ import fitz
15
+ from transformers import M2M100ForConditionalGeneration, M2M100Tokenizer
16
+
17
+ import logging
18
+ import openpyxl
19
+ import io
20
+ from docx import Document
21
+ from pptx import Presentation
22
+ from fastapi.responses import JSONResponse
23
+
24
 
25
  # Configuration du logging
26
  logging.basicConfig(level=logging.INFO)
 
39
  UPLOAD_DIR = "uploads"
40
  os.makedirs(UPLOAD_DIR, exist_ok=True)
41
 
42
+ # 🔹 Charger les modèles avec gestion des erreurs
43
  try:
44
+ summarizer = pipeline("summarization", model="facebook/bart-large-cnn")
45
+ logging.info("✅ Modèle de résumé chargé avec succès !")
46
  except Exception as e:
47
+ summarizer = None
48
+ logging.error(f"❌ Erreur chargement modèle résumé : {e}")
49
 
50
  try:
51
  image_captioning = pipeline("image-to-text", model="nlpconnect/vit-gpt2-image-captioning")
 
54
  image_captioning = None
55
  logging.error(f"❌ Erreur chargement modèle image : {e}")
56
 
57
+ # 🔹 Chargement du modèle de traduction
58
+
59
+ # ✅ Déclare les routes AVANT le montage des fichiers statiques
60
+ @app.post("/summarize/")
61
+ async def summarize_document(file: UploadFile = File(...)):
62
+ logging.info(f"📂 Requête reçue - Fichier : {file.filename}")
63
+
64
+ file_path = os.path.join(UPLOAD_DIR, file.filename)
65
+ with open(file_path, "wb") as buffer:
66
+ shutil.copyfileobj(file.file, buffer)
67
+
68
  text = ""
69
+ if file.filename.endswith(".txt"):
70
  with open(file_path, "r", encoding="utf-8") as f:
71
  text = f.read()
72
+ elif file.filename.endswith(".pdf"):
73
  try:
74
  reader = PdfReader(file_path)
75
  text = "\n".join([page.extract_text() or "" for page in reader.pages]).strip()
76
  except Exception as e:
77
  logging.error(f"❌ Erreur lecture PDF : {e}")
78
+ return JSONResponse(content={"error": "Impossible de lire le PDF"}, status_code=400)
79
+ elif file.filename.endswith(".docx"):
80
  try:
81
  doc = docx.Document(file_path)
82
  text = "\n".join([para.text for para in doc.paragraphs]).strip()
83
  except Exception as e:
84
  logging.error(f"❌ Erreur lecture DOCX : {e}")
85
+ return JSONResponse(content={"error": "Impossible de lire le fichier DOCX"}, status_code=400)
86
+ else:
87
+ return JSONResponse(content={"error": "Format de fichier non supporté"}, status_code=400)
88
 
 
 
 
 
 
 
 
89
  if not text:
90
+ logging.error(" Le fichier ne contient pas de texte lisible")
91
+ return JSONResponse(content={"error": "Le fichier est vide ou non lisible"}, status_code=400)
92
+
93
+ # Tronquer le texte pour éviter l'erreur "IndexError: index out of range"
94
+ max_input_length = 1024 # Limite du modèle
95
+ text = text[:max_input_length] # Tronquer le texte s'il est trop long
96
+
97
  try:
98
+ summary = summarizer(text, max_length=150, min_length=50, do_sample=False)[0]["summary_text"]
99
+ return JSONResponse(content={"summary": summary})
100
  except Exception as e:
101
+ logging.error(f"❌ Erreur lors du résumé : {e}")
102
+ return JSONResponse(content={"error": "Échec du résumé. Texte trop long ou format invalide."}, status_code=500)
103
+
104
+
105
+ @app.post("/interpret/")
106
+ async def interpret_image(file: UploadFile = File(...)):
107
+ logging.info(f"📂 Requête reçue - Image : {file.filename}")
108
 
 
 
109
  file_path = os.path.join(UPLOAD_DIR, file.filename)
110
  with open(file_path, "wb") as buffer:
111
  shutil.copyfileobj(file.file, buffer)
112
+
113
  try:
114
+ with Image.open(file_path) as img: # Charger l'image correctement
115
  caption = image_captioning(img)[0]["generated_text"]
116
  return JSONResponse(content={"caption": caption})
117
  except Exception as e:
118
+ logging.error(f"❌ Erreur interprétation image : {e}")
119
  return JSONResponse(content={"error": "Échec de l'analyse de l'image"}, status_code=400)
120
+
121
+
122
+
123
+
124
+ # 🔹 Chargement du modèle de traduction
125
+ try:
126
+ model_name = "facebook/m2m100_418M"
127
+ tokenizer = M2M100Tokenizer.from_pretrained(model_name)
128
+ model = M2M100ForConditionalGeneration.from_pretrained(model_name)
129
+ logging.info("✅ Modèle de traduction chargé avec succès !")
130
+ except Exception as e:
131
+ logging.error(f"❌ Erreur chargement modèle de traduction : {e}")
132
+ model, tokenizer = None, None
133
 
134
+
135
+ def extract_text_from_pdf(file):
136
+ """Extrait le texte d'un fichier PDF."""
137
+ doc = fitz.open(stream=file.file.read(), filetype="pdf")
138
+ text = "\n".join([page.get_text() for page in doc])
139
+ return text.strip()
140
+
141
+
142
+ def extract_text_from_docx(file):
143
+ """Extrait le texte d'un fichier DOCX."""
144
+ doc = Document(io.BytesIO(file.file.read()))
145
+ text = "\n".join([para.text for para in doc.paragraphs])
146
+ return text.strip()
147
+
148
+
149
+ def extract_text_from_pptx(file):
150
+ """Extrait le texte d'un fichier PPTX."""
151
+ prs = Presentation(io.BytesIO(file.file.read()))
152
+ text = []
153
+ for slide in prs.slides:
154
+ for shape in slide.shapes:
155
+ if hasattr(shape, "text"):
156
+ text.append(shape.text)
157
+ return "\n".join(text).strip()
158
+
159
+
160
+ def extract_text_from_excel(file):
161
+ """Extrait le texte d'un fichier Excel (XLSX)."""
162
+ try:
163
+ print("📥 Début extraction texte depuis Excel...")
164
+ wb = openpyxl.load_workbook(io.BytesIO(file.file.read()), data_only=True)
165
+ print("✅ Fichier Excel chargé avec succès !")
166
+
167
+ text = []
168
+ for sheet in wb.worksheets:
169
+ print(f"📄 Feuille trouvée : {sheet.title}")
170
+ for row in sheet.iter_rows(values_only=True):
171
+ text.extend([str(cell) for cell in row if cell])
172
+
173
+ extracted_text = "\n".join(text).strip()
174
+ print(f"✅ Texte extrait (début) : {extracted_text[:100]}...")
175
+ return extracted_text
176
+ except Exception as e:
177
+ print(f"❌ Erreur lors de l'extraction du fichier Excel : {e}")
178
+ return None
179
+
180
+
181
+
182
+ @app.post("/translate/")
183
+ async def translate_document(file: UploadFile = File(...), target_lang: str = Form(...)):
184
+ """API pour traduocire un dument."""
185
+ try:
186
+ logging.info(f"📥 Fichier reçu : {file.filename}")
187
+ logging.info(f"🌍 Langue cible reçue : {target_lang}")
188
+
189
+ if model is None or tokenizer is None:
190
+ return JSONResponse(status_code=500, content={"error": "Modèle de traduction non chargé"})
191
+
192
+ # Extraction du texte en fonction du type de fichier
193
+ if file.filename.endswith(".pdf"):
194
+ text = extract_text_from_pdf(file)
195
+ elif file.filename.endswith(".docx"):
196
+ text = extract_text_from_docx(file)
197
+ elif file.filename.endswith(".pptx"):
198
+ text = extract_text_from_pptx(file)
199
+ elif file.filename.endswith(".xlsx"):
200
+ text = extract_text_from_excel(file)
201
+ else:
202
+ return JSONResponse(status_code=400, content={"error": "Format non supporté"})
203
+
204
+ logging.info(f"📜 Texte extrait : {text[:50]}...") # Affiche un extrait du texte
205
+
206
+ if not text:
207
+ return JSONResponse(status_code=400, content={"error": "Aucun texte trouvé dans le document"})
208
+
209
+ # Traduire le texte
210
+ tokenizer.src_lang = "fr"
211
+ encoded_text = tokenizer(text, return_tensors="pt", padding=True, truncation=True)
212
+
213
+ generated_tokens = model.generate(**encoded_text, forced_bos_token_id=tokenizer.get_lang_id(target_lang))
214
+ translated_text = tokenizer.batch_decode(generated_tokens, skip_special_tokens=True)[0]
215
+
216
+ logging.info(f"✅ Traduction réussie : {translated_text[:50]}...") # Affiche un extrait de la traduction
217
+
218
+ return {"translated_text": translated_text}
219
+
220
+ except Exception as e:
221
+ logging.error(f"❌ Erreur lors de la traduction : {e}")
222
+ return JSONResponse(status_code=500, content={"error": "Échec de la traduction"})
223
+
224
+
225
+ # ✅ Déplace ici le montage des fichiers statiques
226
  app.mount("/", StaticFiles(directory="static", html=True), name="static")
227
 
228
+
229
+
230
+ # Redirection vers index.html
231
  @app.get("/")
232
  async def root():
233
+ return RedirectResponse(url="/index.html")