10 KiB
Analyse comparative des projets AIagent2 et llm_lab-test
1. Différences structurelles entre les deux projets
Structure de AIagent2 (ancien projet)
AIagent2/
├── llm_classes/
│ ├── __init__.py
│ ├── llm.py (classe abstraite de base)
│ ├── mistral.py
│ ├── ollama.py
│ ├── deepseek.py
│ ├── perplexity.py
│ ├── deepl.py
│ ├── rag.py
│ ├── llama_vision.py
│ ├── agents.py (classe Agent abstraite et implémentations)
│ ├── example.py
│ ├── example_vision.py
│ └── requirements.txt
├── images/
└── JSON/
Structure de llm_lab-test (nouveau projet)
llm_lab-test/
├── core/
│ ├── base_llm.py (classe abstraite de base)
│ ├── factory.py (pattern Factory pour instancier les LLM)
│ ├── mistral7b.py
│ └── llama_vision90b.py
├── agents/
│ └── roles.py (définition des rôles d'agents)
├── utils/
├── tests/
├── config/
├── prompts/
├── outputs/
└── logs/
Principales différences
-
Organisation structurelle:
- AIagent2: Organisation plus plate avec toutes les classes LLM et agents dans le même package
- llm_lab-test: Structure plus modulaire avec séparation claire entre core (modèles) et agents (rôles)
-
Patron de conception:
- AIagent2: Utilise principalement l'héritage avec classes abstraites
- llm_lab-test: Utilise le pattern Factory pour créer les instances LLM et séparation entre modèles et rôles
-
Gestion des configurations:
- AIagent2: Configuration intégrée dans les classes
- llm_lab-test: Configuration externalisée dans un dossier dédié et séparation des rôles
-
Logging et sorties:
- AIagent2: Gestion interne dans les classes
- llm_lab-test: Dossiers dédiés pour les logs et les sorties
2. Analyse de la classe abstraite Agent dans AIagent2
Structure de la classe Agent
Dans l'ancien projet AIagent2, une classe abstraite Agent a été définie comme base pour tous les agents spécialisés. Cette approche suit le principe de conception orienté objet où une classe de base définit l'interface commune et les comportements partagés.
class Agent:
"""
Classe de base pour tous les agents
"""
def __init__(self, nom: str = "Agent"):
self.nom: str = nom
self.historique: List[Dict[str, Any]] = []
def ajouter_historique(self, action: str, input_data: Any, output_data: Any) -> None:
# Implémentation commune
def obtenir_historique(self) -> List[Dict[str, Any]]:
# Implémentation commune
def executer(self, *args, **kwargs) -> Any:
# Méthode abstraite que chaque agent doit implémenter
raise NotImplementedError("Chaque agent doit implémenter sa propre méthode executer()")
Agents spécialisés implémentés
Trois agents spécialisés héritent de cette classe abstraite :
- AgentAnalyseImage - Spécialisé dans l'analyse d'images avec LlamaVision
- AgentAnalyseJSON - Spécialisé dans l'analyse de données JSON
- AgentQuestionReponse - Spécialisé dans le processus de questions/réponses
Intérêt de cette approche
- Cohérence d'interface : Tous les agents partagent la même interface de base (
executer()) - Code réutilisable : Les fonctionnalités communes comme la gestion de l'historique sont implémentées une seule fois
- Extensibilité : Facile d'ajouter de nouveaux types d'agents en héritant de la classe de base
- Polymorphisme : Possibilité de traiter différents agents de manière uniforme
- Traçabilité : Gestion unifiée de l'historique des actions et résultats
3. Analyse des classes LLM dans les deux projets
Classes LLM dans AIagent2
Le projet AIagent2 comporte plusieurs classes pour différents modèles LLM, toutes héritant d'une classe abstraite LLM :
- Mistral - Intégration avec l'API Mistral
- Ollama - Intégration avec Ollama pour les modèles locaux
- DeepSeek - Intégration avec l'API DeepSeek
- Perplexity - Intégration avec l'API Perplexity
- DeepL - Intégration avec l'API DeepL pour la traduction
- RAG - Système de Retrieval Augmented Generation
- LlamaVision - Intégration avec Llama Vision 3.2 pour l'analyse d'images
Toutes ces classes partagent une interface commune définie par la classe abstraite LLM, qui inclut des méthodes comme Interroger(), LLM_POST(), etc.
Classes LLM dans llm_lab-test
Le nouveau projet utilise une approche similaire mais plus simplifiée :
- BaseLLM - Classe de base abstraite
- Mistral7B - Implémentation pour Mistral 7B
- LlamaVision90B - Implémentation pour Llama Vision 90B
La différence principale est la séparation entre les modèles et les rôles (agents), qui sont définis dans un fichier séparé.
Comparaison des implémentations LlamaVision
LlamaVision dans AIagent2
- Plus de paramètres configurables (température, top_k, top_p, mirostat, etc.)
- Support intégré pour les images et données JSON
- Méthodes pour la fusion des résultats avec JSON
- Gestion détaillée des erreurs
LlamaVision90B dans llm_lab-test
- Implémentation plus simple
- Moins de paramètres configurables
- Support pour la traduction automatique
- Structure plus légère
4. Recommandations pour le nouveau projet
Intégration de la classe Agent dans llm_lab-test
L'approche avec une classe abstraite Agent présente des avantages significatifs qui pourraient être bénéfiques pour le nouveau projet sans perturber son fonctionnement actuel.
Voici comment elle pourrait être implémentée :
# Proposition pour agents/base_agent.py
from datetime import datetime
from typing import Dict, List, Any, Optional
class Agent:
"""Classe de base pour tous les agents d'analyse"""
def __init__(self, nom: str = "Agent"):
self.nom = nom
self.historique = []
def ajouter_historique(self, action: str, input_data: Any, output_data: Any) -> None:
"""Ajoute une entrée dans l'historique de l'agent"""
self.historique.append({
"timestamp": datetime.now().isoformat(),
"action": action,
"input": str(input_data)[:500],
"output": str(output_data)[:500]
})
def obtenir_historique(self) -> List[Dict[str, Any]]:
"""Retourne l'historique complet de l'agent"""
return self.historique
def executer(self, *args, **kwargs) -> Any:
"""Méthode abstraite à implémenter dans les classes dérivées"""
raise NotImplementedError("Chaque agent doit implémenter sa propre méthode executer()")
Adaptation de LlamaVision90B avec plus de paramètres
Le modèle LlamaVision90B du nouveau projet pourrait bénéficier des paramètres supplémentaires disponibles dans l'ancien projet :
# Proposition de mise à jour pour core/llama_vision90b.py
class LlamaVision90B(BaseLLM):
def __init__(self):
model_name = "llama3.2-vision:90b"
engine = "Ollama"
self.api_url = "http://217.182.105.173:11434/api/chat"
default_params = {
# Paramètres existants
"temperature": 0.3,
"top_p": 1.0,
"top_k": 40,
"repeat_penalty": 1.1,
"num_predict": 512,
"num_ctx": 4096,
# Nouveaux paramètres inspirés de l'ancien projet
"mirostat": 0,
"mirostat_eta": 0.1,
"mirostat_tau": 5.0,
"seed": 0,
"stop": [],
"min_p": 0.0,
# Paramètres existants
"format": "json",
"stream": False,
"raw": False,
"keep_alive": "5m"
}
super().__init__(model_name=model_name, engine=engine, base_params=default_params)
# Support pour les données JSON associées
self.json_data = {}
def set_json_data(self, json_data: Dict[str, Any]) -> bool:
"""Définit les données JSON à associer à l'image"""
try:
self.json_data = json_data
return True
except Exception as e:
print(f"Erreur lors de la définition des données JSON: {e}")
return False
# [...] Reste de l'implémentation
Création d'une classe Mistral compatible avec l'ancien projet
# Proposition pour core/mistral_api.py
from core.base_llm import BaseLLM
import requests
import json
class MistralAPI(BaseLLM):
"""Intégration avec l'API Mistral (similaire à la classe Mistral de l'ancien projet)"""
def __init__(self):
model_name = "mistral-large-latest"
engine = "MistralAPI"
self.api_url = "https://api.mistral.ai/v1/chat/completions"
self.api_key = "VOTRE_CLE_API" # À remplacer par la clé réelle ou une variable d'environnement
default_params = {
"temperature": 0.7,
"top_p": 0.9,
"max_tokens": 1024,
"presence_penalty": 0,
"frequency_penalty": 0,
"stop": []
}
super().__init__(model_name=model_name, engine=engine, base_params=default_params)
def generate(self, user_prompt):
prompt = self._format_prompt(user_prompt)
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {self.api_key}"
}
payload = {
"model": self.model,
"messages": [
{"role": "system", "content": self.system_prompt},
{"role": "user", "content": user_prompt}
],
"temperature": self.params.get("temperature", 0.7),
"top_p": self.params.get("top_p", 0.9),
"max_tokens": self.params.get("max_tokens", 1024)
}
response = requests.post(self.api_url, headers=headers, json=payload)
if not response.ok:
raise Exception(f"Erreur API Mistral: {response.status_code} - {response.text}")
result_data = response.json()
result_text = result_data.get("choices", [{}])[0].get("message", {}).get("content", "")
return self._log_result(user_prompt, result_text)