Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -1,9 +1,9 @@
|
|
1 |
from flask import Flask, render_template, request, jsonify
|
2 |
import os
|
3 |
import tempfile
|
4 |
-
from PIL import Image
|
5 |
from google import genai
|
6 |
-
from google.genai import types
|
7 |
import uuid
|
8 |
|
9 |
app = Flask(__name__)
|
@@ -13,15 +13,18 @@ app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 # 16 MB max upload
|
|
13 |
# Ensure upload directory exists
|
14 |
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)
|
15 |
|
16 |
-
# Google Gemini API setup
|
17 |
def init_gemini():
|
18 |
api_key = os.environ.get('GOOGLE_API_KEY')
|
19 |
if not api_key:
|
20 |
print("WARNING: GOOGLE_API_KEY environment variable not set")
|
21 |
return None
|
22 |
-
|
|
|
|
|
|
|
23 |
|
24 |
-
client = init_gemini()
|
25 |
|
26 |
# Prompts for analysis
|
27 |
ICONOGRAPHIC_PROMPT = """
|
@@ -157,48 +160,53 @@ Et voici le plan :
|
|
157 |
|
158 |
* **Opinion personnelle** (Donner son avis personnel)
|
159 |
* **Ressentis / Sentiments** (J'ai eu des sentiments mitigés à propos de......... / Ce que j'ai ressenti...)
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
"""
|
164 |
|
165 |
-
|
166 |
-
|
|
|
|
|
|
|
167 |
try:
|
168 |
-
if not client:
|
169 |
-
return "
|
170 |
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
183 |
|
184 |
-
|
185 |
-
|
186 |
-
text_content = f.read()
|
187 |
-
|
188 |
-
response = client.models.generate_content(
|
189 |
-
model="gemini-2.5-flash-preview-04-17",
|
190 |
-
contents=[text_content, TEXT_PROMPT],
|
191 |
-
config=types.GenerateContentConfig(
|
192 |
-
thinking_config=types.ThinkingConfig(
|
193 |
-
thinking_budget=8000
|
194 |
-
)
|
195 |
-
),
|
196 |
-
)
|
197 |
return response.candidates[0].content.parts[0].text.strip()
|
|
|
|
|
|
|
|
|
198 |
|
199 |
except Exception as e:
|
200 |
-
print(f"Error generating response: ")
|
201 |
-
|
|
|
|
|
|
|
|
|
|
|
202 |
|
203 |
@app.route('/')
|
204 |
def index():
|
@@ -207,28 +215,64 @@ def index():
|
|
207 |
@app.route('/upload', methods=['POST'])
|
208 |
def upload_file():
|
209 |
if 'file' not in request.files:
|
210 |
-
return jsonify({'error': '
|
211 |
|
212 |
file = request.files['file']
|
213 |
-
|
|
|
214 |
|
215 |
if file.filename == '':
|
216 |
-
return jsonify({'error': '
|
217 |
|
218 |
if file:
|
219 |
-
#
|
220 |
-
filename = f"{uuid.uuid4()}_{file.filename}"
|
221 |
file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
|
222 |
-
file.save(file_path)
|
223 |
-
|
224 |
-
# Generate analysis
|
225 |
-
analysis = generate_response(file_path, file_type)
|
226 |
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
'
|
231 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
232 |
|
233 |
if __name__ == '__main__':
|
234 |
app.run(debug=True)
|
|
|
1 |
from flask import Flask, render_template, request, jsonify
|
2 |
import os
|
3 |
import tempfile
|
4 |
+
from PIL import Image # Make sure Pillow is installed: pip install Pillow
|
5 |
from google import genai
|
6 |
+
from google.genai import types # Important pour thinking_config
|
7 |
import uuid
|
8 |
|
9 |
app = Flask(__name__)
|
|
|
13 |
# Ensure upload directory exists
|
14 |
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)
|
15 |
|
16 |
+
# Google Gemini API setup (ancienne méthode)
|
17 |
def init_gemini():
|
18 |
api_key = os.environ.get('GOOGLE_API_KEY')
|
19 |
if not api_key:
|
20 |
print("WARNING: GOOGLE_API_KEY environment variable not set")
|
21 |
return None
|
22 |
+
# Note: genai.configure(api_key=api_key) n'est pas nécessaire si on utilise genai.Client()
|
23 |
+
# Cependant, cela ne fait pas de mal de le laisser si d'autres parties du code s'y attendent.
|
24 |
+
# genai.configure(api_key=api_key)
|
25 |
+
return genai.Client(api_key=api_key) # Retourne une instance du client
|
26 |
|
27 |
+
client = init_gemini() # Store the client instance
|
28 |
|
29 |
# Prompts for analysis
|
30 |
ICONOGRAPHIC_PROMPT = """
|
|
|
160 |
|
161 |
* **Opinion personnelle** (Donner son avis personnel)
|
162 |
* **Ressentis / Sentiments** (J'ai eu des sentiments mitigés à propos de......... / Ce que j'ai ressenti...)
|
|
|
|
|
|
|
163 |
"""
|
164 |
|
165 |
+
# Nom du modèle utilisé précédemment
|
166 |
+
MODEL_NAME = "gemini-2.5-flash-preview-04-17" # Ou le modèle que vous utilisiez
|
167 |
+
|
168 |
+
def generate_response(file_path, file_type_option):
|
169 |
+
"""Generate response using Gemini API based on file type option (ancienne méthode d'appel)"""
|
170 |
try:
|
171 |
+
if not client: # Vérifie si le client a été initialisé
|
172 |
+
return "Erreur: Le client Google API n'a pas été configuré correctement."
|
173 |
|
174 |
+
image_data = Image.open(file_path) # Les deux options utilisent une image comme entrée
|
175 |
+
|
176 |
+
prompt_to_use = ""
|
177 |
+
if file_type_option == 'image': # Méthodologie iconographique
|
178 |
+
prompt_to_use = ICONOGRAPHIC_PROMPT
|
179 |
+
elif file_type_option == 'text_method_image_input': # Méthodologie textuelle (avec image en entrée)
|
180 |
+
prompt_to_use = TEXT_PROMPT
|
181 |
+
else:
|
182 |
+
return "Erreur: Type d'analyse non reconnu."
|
183 |
+
|
184 |
+
response = client.models.generate_content( # Utilisation de client.models.generate_content
|
185 |
+
model=MODEL_NAME, # Spécifier le modèle ici
|
186 |
+
contents=[image_data, prompt_to_use],
|
187 |
+
config=types.GenerateContentConfig(
|
188 |
+
thinking_config=types.ThinkingConfig(
|
189 |
+
thinking_budget=8000 # Conserve la configuration thinking_budget
|
190 |
+
)
|
191 |
+
),
|
192 |
+
)
|
193 |
|
194 |
+
# Accéder au texte de la réponse comme dans la version originale
|
195 |
+
if response.candidates and response.candidates[0].content and response.candidates[0].content.parts:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
196 |
return response.candidates[0].content.parts[0].text.strip()
|
197 |
+
else:
|
198 |
+
# Gérer le cas où la réponse n'a pas la structure attendue
|
199 |
+
print(f"Réponse inattendue de l'API Gemini: {response}")
|
200 |
+
return "Erreur: La réponse de l'API Gemini n'a pas pu être traitée."
|
201 |
|
202 |
except Exception as e:
|
203 |
+
print(f"Error generating response: {e}")
|
204 |
+
# Vous pouvez ajouter une gestion d'erreur plus spécifique ici si nécessaire
|
205 |
+
if "API_KEY_INVALID" in str(e):
|
206 |
+
return "Erreur: Clé API Google invalide ou non autorisée."
|
207 |
+
if "billing account" in str(e).lower():
|
208 |
+
return "Erreur: Problème de facturation avec le compte Google Cloud. Veuillez vérifier votre compte."
|
209 |
+
return f"Erreur lors de l'analyse: {str(e)}"
|
210 |
|
211 |
@app.route('/')
|
212 |
def index():
|
|
|
215 |
@app.route('/upload', methods=['POST'])
|
216 |
def upload_file():
|
217 |
if 'file' not in request.files:
|
218 |
+
return jsonify({'success': False, 'error': 'Aucun fichier reçu'}), 400
|
219 |
|
220 |
file = request.files['file']
|
221 |
+
# 'fileType' indique maintenant la méthodologie ('image' ou 'text_method_image_input')
|
222 |
+
file_type_option = request.form.get('fileType', 'image')
|
223 |
|
224 |
if file.filename == '':
|
225 |
+
return jsonify({'success': False, 'error': 'Aucun fichier sélectionné'}), 400
|
226 |
|
227 |
if file:
|
228 |
+
# Générer un nom de fichier unique
|
229 |
+
filename = f"{uuid.uuid4()}_{os.path.splitext(file.filename)[0]}{os.path.splitext(file.filename)[1]}"
|
230 |
file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
|
|
|
|
|
|
|
|
|
231 |
|
232 |
+
try:
|
233 |
+
file.save(file_path)
|
234 |
+
|
235 |
+
# S'assurer que le fichier est une image avant de continuer
|
236 |
+
try:
|
237 |
+
img_check = Image.open(file_path)
|
238 |
+
img_check.verify() # Vérifie si c'est une image
|
239 |
+
img_check.close() # Important de fermer le fichier après vérification
|
240 |
+
# Réouvrir pour l'envoi à l'API car verify() peut corrompre certains formats
|
241 |
+
# Image.open(file_path) sera fait dans generate_response
|
242 |
+
except Exception as img_err:
|
243 |
+
if os.path.exists(file_path):
|
244 |
+
os.remove(file_path) # Nettoyer le fichier invalide
|
245 |
+
print(f"Invalid image file uploaded: {img_err}")
|
246 |
+
return jsonify({'success': False, 'error': 'Le fichier téléversé n\'est pas une image valide.'}), 400
|
247 |
+
|
248 |
+
analysis = generate_response(file_path, file_type_option)
|
249 |
+
|
250 |
+
# Vérifier si l'analyse a retourné une erreur
|
251 |
+
if analysis.startswith("Erreur:"):
|
252 |
+
# Ne pas supprimer le fichier immédiatement si l'analyse a échoué,
|
253 |
+
# l'utilisateur pourrait vouloir réessayer ou le voir.
|
254 |
+
return jsonify({'success': False, 'error': analysis}), 500
|
255 |
+
|
256 |
+
return jsonify({
|
257 |
+
'success': True,
|
258 |
+
'file_url': f"/static/uploads/{filename}", # Utile si vous voulez que l'utilisateur voie l'image téléversée
|
259 |
+
'analysis': analysis
|
260 |
+
})
|
261 |
+
except Exception as e:
|
262 |
+
print(f"Error in upload_file: {e}")
|
263 |
+
if os.path.exists(file_path): # Nettoyer si un fichier a été sauvegardé mais une erreur est survenue
|
264 |
+
try:
|
265 |
+
os.remove(file_path)
|
266 |
+
except Exception as e_rem:
|
267 |
+
print(f"Could not remove file {file_path}: {e_rem}")
|
268 |
+
return jsonify({'success': False, 'error': f'Une erreur serveur est survenue: {str(e)}'}), 500
|
269 |
+
# finally:
|
270 |
+
# Optionnel : nettoyer le fichier téléversé après traitement.
|
271 |
+
# if os.path.exists(file_path):
|
272 |
+
# try:
|
273 |
+
# os.remove(file_path)
|
274 |
+
# except Exception as e:
|
275 |
+
# print(f"Error removing uploaded file {file_path}: {e}")
|
276 |
|
277 |
if __name__ == '__main__':
|
278 |
app.run(debug=True)
|