""" Évaluation comparative des capacités MCP de plusieurs modèles LLM Compare Qwen2.5-0.5B, Qwen3-0.6B, et Gemma-3-1B pour les tâches MCP """ import sys import os import json import time # Ajouter le chemin pour les imports sys.path.append(os.path.dirname(os.path.abspath(__file__))) def initialize_model(model_path, model_name): """Initialiser un modèle spécifique""" try: from llama_cpp import Llama print(f"🔄 Initialisation de {model_name}...") llm = Llama( model_path=model_path, n_ctx=2048, n_threads=2, verbose=False ) print(f"✅ {model_name} initialisé avec succès") return llm except Exception as e: print(f"❌ Erreur d'initialisation de {model_name}: {e}") return None def run_mcp_test(llm, model_name, test): """Exécuter un test MCP sur un modèle spécifique""" try: start_time = time.time() # Utiliser le chat template messages = [ {"role": "system", "content": "Tu es un assistant IA spécialisé dans les jeux RTS et le protocole MCP. Réponds avec des objets JSON valides."}, {"role": "user", "content": test['prompt']} ] response = llm.create_chat_completion( messages=messages, max_tokens=300, temperature=0.1 ) response_time = time.time() - start_time # Extraire le texte de la réponse if response and 'choices' in response and len(response['choices']) > 0: response_text = response['choices'][0]['message']['content'] else: # Fallback simple_response = llm(test['prompt'], max_tokens=300, temperature=0.1) response_text = simple_response['choices'][0]['text'] if 'choices' in simple_response else str(simple_response) # Analyser la réponse score = analyze_mcp_response(response_text, test) return { 'model': model_name, 'test': test['name'], 'response': response_text, 'response_time': response_time, 'score': score, 'success': score >= 5 } except Exception as e: return { 'model': model_name, 'test': test['name'], 'error': str(e), 'score': 0, 'success': False } def analyze_mcp_response(response, test_config): """Analyser la réponse MCP et la noter""" if not response or response.strip() == "": return 0 score = 0 # Vérifier la structure JSON try: json_data = json.loads(response) score += 3 # JSON valide # Vérifier la présence d'outils MCP if 'tool' in json_data: score += 2 if 'args' in json_data: score += 1 except json.JSONDecodeError: # Vérifier les patterns dans le texte mcp_tools = ["get_game_state", "move_units", "attack_unit", "build_building"] tools_found = [tool for tool in mcp_tools if tool in response] if tools_found: score += 2 if any(param in response for param in ['unit_ids', 'target_x', 'target_y']): score += 1 # Vérifier la cohérence sémantique if 'game' in response.lower() or 'rts' in response.lower(): score += 1 # Vérifier la pertinence par rapport au test if 'expected_tool' in test_config: if test_config['expected_tool'] in response: score += 2 elif test_config.get('expected_complex'): if any(word in response.lower() for word in ['sequence', 'steps', 'build', 'defend']): score += 2 elif test_config.get('expected_clarification'): if any(word in response.lower() for word in ['clarify', 'coordinates', 'which', 'ambiguous']): score += 2 return min(score, 10) def run_comparative_evaluation(): """Exécuter l'évaluation comparative des trois modèles""" print("🔍 ÉVALUATION COMPARATIVE DES CAPACITÉS MCP") print("=" * 70) # Définir les modèles à tester models = [ { 'name': 'Qwen2.5-0.5B', 'path': 'qwen2.5-0.5b-instruct-q4_0.gguf' }, { 'name': 'Qwen3-0.6B', 'path': 'Qwen3-0.6B-Q8_0.gguf' }, { 'name': 'Gemma-3-1B', 'path': 'google_gemma-3-1b-it-qat-Q4_0.gguf' } ] # Tests MCP tests = [ { "name": "Compréhension MCP de base", "prompt": """Tu es un assistant IA qui contrôle un jeu RTS via MCP (Model Context Protocol). Outils MCP disponibles: - get_game_state(): Obtenir l'état actuel du jeu - move_units(unit_ids, target_x, target_y): Déplacer des unités Commande utilisateur: "Montre-moi l'état du jeu" Réponds avec un objet JSON contenant l'appel d'outil MCP à exécuter. """, "expected_tool": "get_game_state" }, { "name": "Traduction d'action simple", "prompt": """Tu es un assistant IA qui contrôle un jeu RTS via MCP. Outils MCP disponibles: - move_units(unit_ids, target_x, target_y): Déplacer des unités Commande utilisateur: "Déplace mon infanterie vers la position 150, 200" Réponds avec un objet JSON contenant l'appel d'outil avec les paramètres extraits. """, "expected_tool": "move_units" }, { "name": "Extraction de paramètres complexes", "prompt": """Tu es un assistant IA qui contrôle un jeu RTS via MCP. Outils MCP disponibles: - move_units(unit_ids, target_x, target_y): Déplacer des unités Commande utilisateur: "Déplace les tanks 1, 3 et 7 vers les coordonnées 120, 80" Extrais les paramètres et réponds avec un objet JSON d'appel d'outil. """, "expected_tool": "move_units" }, { "name": "Planification stratégique", "prompt": """Tu es un assistant IA qui contrôle un jeu RTS via MCP. Outils MCP disponibles: - get_game_state(): Obtenir l'état du jeu - move_units(): Déplacer des unités - attack_unit(): Attaquer l'ennemi - build_building(): Construire un bâtiment Commande utilisateur: "Construis une base près du minerai et défends-la" Décompose cette stratégie en une séquence d'actions MCP. """, "expected_complex": True }, { "name": "Gestion d'ambiguïté", "prompt": """Tu es un assistant IA qui contrôle un jeu RTS via MCP. Outils MCP disponibles: - move_units(unit_ids, target_x, target_y): Déplacer des unités Commande utilisateur: "Déplace mes unités vers la base ennemie" Comment gérerais-tu cette instruction ambiguë? """, "expected_clarification": True } ] # Initialiser les modèles initialized_models = {} for model in models: if os.path.exists(model['path']): llm = initialize_model(model['path'], model['name']) if llm: initialized_models[model['name']] = llm else: print(f"❌ Fichier modèle non trouvé: {model['path']}") if not initialized_models: print("❌ Aucun modèle n'a pu être initialisé") return print(f"\n🚀 {len(initialized_models)} modèle(s) initialisé(s) sur {len(models)}") # Exécuter les tests sur chaque modèle all_results = [] for model_name, llm in initialized_models.items(): print(f"\n🧪 TESTS AVEC {model_name}") print("=" * 50) model_results = [] for test in tests: print(f"\n📋 Test: {test['name']}") result = run_mcp_test(llm, model_name, test) model_results.append(result) if result.get('success', False): print(f"✅ Score: {result['score']}/10 | Temps: {result['response_time']:.2f}s") else: print(f"❌ Erreur: {result.get('error', 'Unknown error')}") all_results.append(result) # Générer le rapport comparatif generate_comparative_report(initialized_models.keys(), all_results, tests) def generate_comparative_report(model_names, results, tests): """Générer un rapport comparatif complet""" print("\n" + "=" * 70) print("📊 RAPPORT COMPARATIF DES MODÈLES") print("=" * 70) # Organiser les résultats par modèle model_results = {name: [] for name in model_names} for result in results: if 'model' in result: model_results[result['model']].append(result) # Statistiques par modèle print(f"\n📈 STATISTIQUES PAR MODÈLE:") model_scores = {} for model_name in model_names: results_list = model_results[model_name] if results_list: successful_tests = [r for r in results_list if r.get('success', False)] total_score = sum(r.get('score', 0) for r in results_list) avg_score = total_score / len(results_list) avg_time = sum(r.get('response_time', 0) for r in results_list) / len(results_list) model_scores[model_name] = { 'avg_score': avg_score, 'success_rate': len(successful_tests) / len(results_list), 'avg_time': avg_time } print(f"\n🔹 {model_name}:") print(f" Score moyen: {avg_score:.1f}/10") print(f" Taux de réussite: {len(successful_tests)}/{len(results_list)} ({len(successful_tests)/len(results_list)*100:.0f}%)") print(f" Temps moyen: {avg_time:.2f}s") # Comparaison directe print(f"\n🏆 CLASSEMENT:") sorted_models = sorted(model_scores.items(), key=lambda x: x[1]['avg_score'], reverse=True) for i, (model_name, scores) in enumerate(sorted_models, 1): print(f" {i}. {model_name}: {scores['avg_score']:.1f}/10") # Analyse par type de test print(f"\n🧪 ANALYSE PAR TYPE DE TEST:") for test in tests: test_name = test['name'] print(f"\n🔸 {test_name}:") test_results = [r for r in results if r.get('test') == test_name] for model_name in model_names: model_test_results = [r for r in test_results if r.get('model') == model_name] if model_test_results: avg_score = sum(r.get('score', 0) for r in model_test_results) / len(model_test_results) print(f" {model_name}: {avg_score:.1f}/10") # Recommandations print(f"\n💡 RECOMMANDATIONS:") best_model = sorted_models[0][0] best_score = sorted_models[0][1]['avg_score'] if best_score >= 7: print(f"✅ {best_model} est EXCELLENT pour les tâches MCP") print(f" Utilisation recommandée pour la production") elif best_score >= 5: print(f"👍 {best_model} est BON pour les tâches MCP") print(f" Utilisation recommandée avec validation") else: print(f"⚠️ {best_model} est LIMITÉ pour les tâches MCP") print(f" Amélioration nécessaire avant utilisation") # Performance vs taille print(f"\n⚖️ PERFORMANCE VS TAILLE:") for model_name, scores in model_scores.items(): efficiency = scores['avg_score'] / scores['avg_time'] if scores['avg_time'] > 0 else 0 print(f" {model_name}: {efficiency:.2f} score/seconde") # Sauvegarder les résultats comparative_results = { 'model_scores': model_scores, 'detailed_results': results, 'ranking': sorted_models } with open("comparative_mcp_evaluation.json", "w", encoding="utf-8") as f: json.dump(comparative_results, f, indent=2, ensure_ascii=False) print(f"\n📄 Résultats détaillés sauvegardés dans: comparative_mcp_evaluation.json") if __name__ == "__main__": run_comparative_evaluation()