#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Script simple pour tester directement l'API Mistral Large. Ce script permet de diagnostiquer si le problème vient de l'API ou de notre application. """ import os import sys import json import logging import requests from datetime import datetime # Configuration du logging logging.basicConfig( level=logging.DEBUG, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', handlers=[ logging.StreamHandler(sys.stdout) ] ) logger = logging.getLogger("test_mistral_api") # Clés API à tester API_KEYS = [ "2iGzTzE9csRQ9IoASoUjplHwEjA200Vh", # Clé actuelle dans MistralLarge "sk-d359d9236ca84a5986f889631832d1e6" # Clé utilisée dans list_mistral_models.py ] def test_api_key(api_key): """Test si la clé API est valide en listant les modèles disponibles.""" url = "https://api.mistral.ai/v1/models" headers = { "Authorization": f"Bearer {api_key}" } try: logger.info(f"Test de la clé API: {api_key[:5]}...{api_key[-5:]}") response = requests.get(url, headers=headers) logger.info(f"Code de statut: {response.status_code}") if response.status_code == 200: logger.info("La clé API est valide!") try: models = response.json().get('data', []) logger.info(f"Modèles disponibles: {[model.get('id') for model in models]}") return True except Exception as e: logger.error(f"Erreur lors du parsing de la réponse: {e}") logger.error(f"Réponse brute: {response.text}") return False else: logger.error(f"Erreur API: {response.status_code}") logger.error(f"Réponse d'erreur: {response.text}") return False except Exception as e: logger.error(f"Exception lors du test de la clé API: {e}") return False def test_direct_chat_completion(api_key): """Test directement l'endpoint chat/completions.""" url = "https://api.mistral.ai/v1/chat/completions" headers = { "Content-Type": "application/json", "Authorization": f"Bearer {api_key}" } data = { "model": "mistral-large-latest", "messages": [ {"role": "system", "content": "Tu es un assistant utile."}, {"role": "user", "content": "Dis simplement 'API FONCTIONNE' sans rien ajouter."} ], "temperature": 0.1, "max_tokens": 100 } try: logger.info(f"Test d'appel direct à chat/completions avec la clé: {api_key[:5]}...{api_key[-5:]}") response = requests.post(url, headers=headers, json=data) logger.info(f"Code de statut: {response.status_code}") if response.status_code in [200, 201]: try: result = response.json() message = result.get("choices", [{}])[0].get("message", {}).get("content", "") logger.info(f"Réponse: {message}") return True except Exception as e: logger.error(f"Erreur lors du parsing de la réponse: {e}") logger.error(f"Réponse brute: {response.text}") return False else: logger.error(f"Erreur API: {response.status_code}") logger.error(f"Réponse d'erreur: {response.text}") return False except Exception as e: logger.error(f"Exception lors de l'appel direct: {e}") return False # Essayer d'importer la classe MistralLarge try: from llm_classes.mistral_large import MistralLarge logger.info("Module MistralLarge importé avec succès") except ImportError as e: logger.error(f"Impossible d'importer MistralLarge: {e}") sys.exit(1) def test_simple_prompt(): """Test avec un prompt simple pour vérifier que l'API répond.""" try: logger.info("Initialisation du modèle Mistral Large...") model = MistralLarge() logger.info("Modèle initialisé avec succès") # Afficher la clé API utilisée api_key = model.cleAPI() logger.info(f"Clé API utilisée: {api_key[:5]}...{api_key[-5:]}") # Prompt simple pour tester la connexion prompt = "Réponds uniquement avec le texte 'API MISTRAL FONCTIONNE' sans rien ajouter d'autre." logger.info(f"Envoi du prompt simple: {prompt}") start_time = datetime.now() response = model.interroger(prompt) end_time = datetime.now() duration = (end_time - start_time).total_seconds() logger.info(f"Réponse reçue en {duration} secondes") if response: logger.info(f"Réponse complète: {response}") # Vérifier si la réponse contient une erreur API if "erreur" in response.lower() or "error" in response.lower(): logger.error("La réponse contient une erreur") logger.error(f"Détails de l'erreur: {response}") return False return True else: logger.error("Réponse vide reçue") return False except Exception as e: logger.error(f"Erreur lors du test avec prompt simple: {e}") import traceback logger.error(traceback.format_exc()) return False def test_json_prompt(): """Test avec un prompt demandant un JSON pour vérifier si c'est le format qui pose problème.""" try: logger.info("Initialisation du modèle Mistral Large...") model = MistralLarge() logger.info("Modèle initialisé avec succès") # Prompt demandant un JSON simple prompt = """ Réponds uniquement avec un JSON valide au format suivant, sans aucun texte avant ou après: { "test": "réussi", "timestamp": "heure actuelle", "message": "API Mistral fonctionne correctement" } """ logger.info(f"Envoi du prompt JSON: {prompt}") start_time = datetime.now() response = model.interroger(prompt) end_time = datetime.now() duration = (end_time - start_time).total_seconds() logger.info(f"Réponse reçue en {duration} secondes") if response: logger.info(f"Réponse complète: {response}") # Vérifier si la réponse contient une erreur API if "erreur" in response.lower() or "error" in response.lower(): logger.error("La réponse contient une erreur") logger.error(f"Détails de l'erreur: {response}") return False # Essayer de parser le JSON try: # Chercher un bloc de code JSON import re match = re.search(r"```(?:json)?\s*([\s\S]*?)\s*```", response) if match: response_cleaned = match.group(1).strip() logger.info(f"JSON trouvé dans un bloc de code Markdown") else: response_cleaned = response json_response = json.loads(response_cleaned) logger.info(f"JSON valide reçu: {json.dumps(json_response, indent=2)}") return True except json.JSONDecodeError as e: logger.error(f"Réponse reçue mais JSON invalide: {e}") return False else: logger.error("Réponse vide reçue") return False except Exception as e: logger.error(f"Erreur lors du test avec prompt JSON: {e}") import traceback logger.error(traceback.format_exc()) return False def dump_model_info(): """Affiche les informations sur le modèle et sa configuration.""" try: model = MistralLarge() logger.info("Informations sur le modèle:") # Récupérer et afficher les attributs du modèle for attr_name in dir(model): if not attr_name.startswith('_'): # Ignorer les attributs privés try: attr_value = getattr(model, attr_name) # N'afficher que les attributs simples, pas les méthodes if not callable(attr_value): logger.info(f" {attr_name}: {attr_value}") except Exception as e: logger.warning(f" Impossible d'accéder à {attr_name}: {e}") # Afficher les méthodes disponibles methods = [m for m in dir(model) if not m.startswith('_') and callable(getattr(model, m))] logger.info(f"Méthodes disponibles: {', '.join(methods)}") return True except Exception as e: logger.error(f"Erreur lors de la récupération des informations du modèle: {e}") return False def main(): """Fonction principale exécutant les tests.""" logger.info("=== DÉBUT DES TESTS API MISTRAL ===") logger.info("=== TEST DES CLÉS API ===") for api_key in API_KEYS: test_api_key(api_key) test_direct_chat_completion(api_key) logger.info("\n=== INFORMATIONS SUR LE MODÈLE ===") dump_model_info() logger.info("\n=== TEST AVEC PROMPT SIMPLE ===") test_simple = test_simple_prompt() logger.info("\n=== TEST AVEC PROMPT JSON ===") test_json = test_json_prompt() logger.info("\n=== RÉSULTATS DES TESTS ===") logger.info(f"Test simple: {'RÉUSSI' if test_simple else 'ÉCHEC'}") logger.info(f"Test JSON: {'RÉUSSI' if test_json else 'ÉCHEC'}") logger.info("=== FIN DES TESTS ===") return 0 if test_simple and test_json else 1 if __name__ == "__main__": sys.exit(main())