Update app.py
Browse files
app.py
CHANGED
@@ -175,90 +175,62 @@ def root():
|
|
175 |
"""Sert la page HTML principale."""
|
176 |
return render_template('index.html')
|
177 |
|
|
|
178 |
@app.route('/api/history', methods=['GET'])
|
179 |
def get_history():
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
# Préparer l'historique pour l'affichage (contient déjà le HTML pour l'assistant)
|
185 |
-
display_history = [
|
186 |
-
{'role': msg.get('role', 'unknown'), 'text': msg.get('text', '')}
|
187 |
-
for msg in session.get('chat_history', [])
|
188 |
-
]
|
189 |
-
print(f"API: Récupération de l'historique ({len(display_history)} messages)")
|
190 |
-
return jsonify({'success': True, 'history': display_history})
|
191 |
|
192 |
@app.route('/api/chat', methods=['POST'])
|
193 |
def chat_api():
|
194 |
-
"""Gère les nouvelles requêtes de chat via AJAX."""
|
195 |
-
if not GEMINI_CONFIGURED:
|
196 |
-
print("API ERREUR: Tentative d'appel à /api/chat sans configuration Gemini valide.")
|
197 |
-
return jsonify({'success': False, 'error': "Le service IA n'est pas configuré correctement."}), 503 # Service Unavailable
|
198 |
-
|
199 |
# Récupération des données du formulaire
|
200 |
prompt = request.form.get('prompt', '').strip()
|
201 |
-
use_web_search_str = request.form.get('web_search', 'false')
|
202 |
use_web_search = use_web_search_str.lower() == 'true'
|
203 |
file = request.files.get('file')
|
204 |
-
use_advanced_str = request.form.get('advanced_reasoning', 'false')
|
205 |
use_advanced = use_advanced_str.lower() == 'true'
|
206 |
|
207 |
-
# Validation simple
|
208 |
if not prompt and not file:
|
209 |
return jsonify({'success': False, 'error': 'Veuillez fournir un message ou un fichier.'}), 400
|
210 |
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
|
|
|
|
|
|
|
|
|
|
216 |
|
217 |
-
|
218 |
-
|
219 |
-
|
|
|
220 |
|
221 |
-
|
222 |
-
|
223 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
224 |
|
225 |
-
# --- Gestion de l'upload de fichier ---
|
226 |
-
if file and file.filename != '':
|
227 |
-
if allowed_file(file.filename):
|
228 |
-
try:
|
229 |
-
filename = secure_filename(file.filename)
|
230 |
-
filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
|
231 |
-
file.save(filepath)
|
232 |
-
filepath_to_delete = filepath # Marquer pour suppression
|
233 |
-
uploaded_filename = filename
|
234 |
-
print(f"Fichier '{filename}' sauvegardé temporairement dans '{filepath}'")
|
235 |
-
|
236 |
-
# Détecter le MimeType pour Gemini
|
237 |
-
mime_type = mimetypes.guess_type(filepath)[0]
|
238 |
-
if not mime_type:
|
239 |
-
mime_type = 'application/octet-stream' # Fallback
|
240 |
-
print(f"AVERTISSEMENT: Impossible de deviner le MimeType pour '{filename}', utilisation de '{mime_type}'.")
|
241 |
-
|
242 |
-
# Uploader vers Google AI (peut prendre du temps)
|
243 |
-
print(f"Upload du fichier vers Google AI (MimeType: {mime_type})...")
|
244 |
-
# Note: L'API upload_file est générique et ne dépend pas du modèle Flash/Pro
|
245 |
-
uploaded_gemini_file = genai.upload_file(path=filepath, mime_type=mime_type)
|
246 |
-
print(f"Fichier '{uploaded_gemini_file.name}' uploadé avec succès vers Google AI.")
|
247 |
-
|
248 |
-
except Exception as e:
|
249 |
-
print(f"ERREUR Critique lors du traitement/upload du fichier '{filename}': {e}")
|
250 |
-
# Supprimer le fichier local même en cas d'erreur d'upload Gemini
|
251 |
-
if filepath_to_delete and os.path.exists(filepath_to_delete):
|
252 |
-
try:
|
253 |
-
os.remove(filepath_to_delete)
|
254 |
-
print(f"Fichier temporaire '{filepath_to_delete}' supprimé après erreur.")
|
255 |
-
except OSError as del_e:
|
256 |
-
print(f"Erreur lors de la suppression du fichier temporaire après erreur: {del_e}")
|
257 |
-
# Renvoyer une erreur claire au client
|
258 |
-
return jsonify({'success': False, 'error': f"Erreur lors du traitement du fichier: {e}"}), 500
|
259 |
-
else:
|
260 |
-
print(f"ERREUR: Type de fichier non autorisé: {file.filename}")
|
261 |
-
return jsonify({'success': False, 'error': f"Type de fichier non autorisé. Extensions permises: {', '.join(ALLOWED_EXTENSIONS)}"}), 400
|
262 |
|
263 |
# --- Préparation du message utilisateur pour l'historique et Gemini ---
|
264 |
# Texte brut pour Gemini (et pour l'historique interne)
|
|
|
175 |
"""Sert la page HTML principale."""
|
176 |
return render_template('index.html')
|
177 |
|
178 |
+
|
179 |
@app.route('/api/history', methods=['GET'])
|
180 |
def get_history():
|
181 |
+
# Retourne toujours un historique vide
|
182 |
+
return jsonify({'success': True, 'history': []})
|
183 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
184 |
|
185 |
@app.route('/api/chat', methods=['POST'])
|
186 |
def chat_api():
|
|
|
|
|
|
|
|
|
|
|
187 |
# Récupération des données du formulaire
|
188 |
prompt = request.form.get('prompt', '').strip()
|
189 |
+
use_web_search_str = request.form.get('web_search', 'false')
|
190 |
use_web_search = use_web_search_str.lower() == 'true'
|
191 |
file = request.files.get('file')
|
192 |
+
use_advanced_str = request.form.get('advanced_reasoning', 'false')
|
193 |
use_advanced = use_advanced_str.lower() == 'true'
|
194 |
|
|
|
195 |
if not prompt and not file:
|
196 |
return jsonify({'success': False, 'error': 'Veuillez fournir un message ou un fichier.'}), 400
|
197 |
|
198 |
+
# Gestion éventuelle de l'upload de fichier et recherche web...
|
199 |
+
# Préparation du prompt pour Gemini, etc.
|
200 |
+
raw_user_text = prompt
|
201 |
+
final_prompt_for_gemini = raw_user_text
|
202 |
+
if use_web_search and raw_user_text:
|
203 |
+
search_data = perform_web_search(raw_user_text)
|
204 |
+
if search_data:
|
205 |
+
formatted_results = format_search_results(search_data)
|
206 |
+
final_prompt_for_gemini = f"""Voici la question originale de l'utilisateur:
|
207 |
+
"{raw_user_text}"
|
208 |
|
209 |
+
J'ai effectué une recherche web et voici les informations pertinentes trouvées:
|
210 |
+
--- DEBUT RESULTATS WEB ---
|
211 |
+
{formatted_results}
|
212 |
+
--- FIN RESULTATS WEB ---
|
213 |
|
214 |
+
En te basant sur ces informations ET sur ta connaissance générale, fournis une réponse complète et bien structurée à la question originale de l'utilisateur."""
|
215 |
+
|
216 |
+
# Préparation des parts pour l'appel Gemini
|
217 |
+
current_gemini_parts = [final_prompt_for_gemini]
|
218 |
+
# (Gestion de fichier si applicable...)
|
219 |
+
|
220 |
+
try:
|
221 |
+
# Appel à Gemini avec current_gemini_parts et sans historique précédent
|
222 |
+
active_model = genai.GenerativeModel(
|
223 |
+
model_name=MODEL_PRO if use_advanced else MODEL_FLASH,
|
224 |
+
safety_settings=SAFETY_SETTINGS,
|
225 |
+
system_instruction=SYSTEM_INSTRUCTION
|
226 |
+
)
|
227 |
+
response = active_model.generate_content(current_gemini_parts)
|
228 |
+
response_text_raw = response.text
|
229 |
+
response_html = markdown.markdown(response_text_raw, extensions=['fenced_code', 'tables', 'nl2br'])
|
230 |
+
return jsonify({'success': True, 'message': response_html})
|
231 |
+
except Exception as e:
|
232 |
+
return jsonify({'success': False, 'error': f"Erreur interne: {e}"}), 500
|
233 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
234 |
|
235 |
# --- Préparation du message utilisateur pour l'historique et Gemini ---
|
236 |
# Texte brut pour Gemini (et pour l'historique interne)
|