# Tutoriel Complet : Créer et Utiliser des Agents LLM Dynamiques avec Ollama, Python, CLI, Streamlit et Cursor --- ## Objectif - **Obsidian** (notes, organisation) - **Cursor** (code, développement) - **Streamlit** (interface utilisateur graphique) - **CLI** (ligne de commande) Chaque agent peut : - Être instancié avec un **modèle différent** (mistral, codellama, etc.) - Avoir un **rôle personnalisé** défini dynamiquement à l'appel - Utiliser des **paramètres avancés** comme temperature, top_p, top_k - Travailler en **mode synchrone ou asynchrone** --- ## I. Architecture des fichiers ```bash llm_agents/ ├── ollama_interface.py # Interface générique avec Ollama ├── base_agent.py # Classe d'agent configurable ├── agent_factory.py # Création d'agents depuis JSON ├── agent_router.py # Routage intelligent selon le contenu ├── cli.py # Interface terminale (CLI) ├── streamlit_app.py # Interface Streamlit dynamique ├── main.py # Démo complète ├── profiles.json # Profils agents (modèles, rôles) └── agents/ # Agents spécialisés (optionnel) ``` --- ## II. Interface avec Ollama (ollama_interface.py) ```python import requests class OllamaInterface: def __init__(self, model, **params): self.model = model self.api_url = "http://localhost:11434/api/generate" self.params = params def generate(self, prompt): payload = {"model": self.model, "prompt": prompt, **self.params} try: response = requests.post(self.api_url, json=payload) response.raise_for_status() return response.json().get("response", "") except Exception as e: return f"[Erreur Ollama] {e}" ``` --- ## III. Classe de base des agents (base_agent.py) ```python import logging from ollama_interface import OllamaInterface class BaseAgent: def __init__(self, name, model, system_prompt="", async_mode=False, enable_logging=True, **params): self.name = name self.system_prompt = system_prompt.strip() self.async_mode = async_mode self.enable_logging = enable_logging self.llm = OllamaInterface(model=model, **params) self.history = [] if enable_logging: logging.basicConfig( filename=f"{self.name}.log", level=logging.INFO, format="%(asctime)s [%(name)s] %(message)s", datefmt="%Y-%m-%d %H:%M:%S" ) def set_role(self, prompt_system): self.system_prompt = prompt_system.strip() def build_prompt(self, user_input): return f"{self.system_prompt}\n\n{user_input}" if self.system_prompt else user_input def log(self, prompt, response): if self.enable_logging: logging.getLogger(self.name).info(f"Prompt:\n{prompt}\nRéponse:\n{response}\n") def process(self, user_input): prompt = self.build_prompt(user_input) response = self.llm.generate(prompt) self.log(prompt, response) self.history.append((prompt, response)) return response ``` --- ## IV. Création d'agents dynamiques avec des rôles ```python from base_agent import BaseAgent agent1 = BaseAgent("AnalyseurNote", model="mistral") agent1.set_role("Tu analyses les notes markdown pour en extraire la structure.") agent2 = BaseAgent("Correcteur", model="mistral") agent2.set_role("Tu corriges l'orthographe et mets en page le texte Markdown.") note = "ceci est une not mal structuré avec des errurs" print(agent1.process(note)) print(agent2.process(note)) ``` --- ## V. AgentRouter — routage intelligent selon le contenu ```python class AgentRouter: def __init__(self, agents): self.agents = {agent.name.lower(): agent for agent in agents} def route(self, prompt): if "code" in prompt.lower(): return self.agents["codeoptimizer"].process(prompt) elif "note" in prompt.lower() or "obsidian" in prompt.lower(): return self.agents["analyseurnote"].process(prompt) else: return self.agents["correcteur"].process(prompt) ``` --- ## VI. Exemple avec plusieurs agents dynamiques (main.py) ```python from base_agent import BaseAgent analyse = BaseAgent("analyseur", model="mistral") analyse.set_role("Tu es un expert Obsidian. Analyse les notes et suggère des améliorations.") optimiseur = BaseAgent("codeoptimizer", model="codellama:13b-python") optimiseur.set_role("Tu es un assistant Python. Améliore le code donné.") texte = "Voici une note mal formée sur FastAPI" code = "def app(): return None" print(analyse.process(texte)) print(optimiseur.process(code)) ``` --- ## VII. Interface CLI (cli.py) ```python from base_agent import BaseAgent name = input("Nom de l'agent : ") model = input("Modèle Ollama (ex: mistral) : ") role = input("Décris le rôle de l'agent : ") agent = BaseAgent(name=name, model=model) agent.set_role(role) while True: prompt = input("\nPrompt > ") if prompt in ["exit", "quit"]: break print(agent.process(prompt)) ``` --- ## VIII. Interface Streamlit (streamlit_app.py) ```python import streamlit as st from base_agent import BaseAgent st.title("Créateur d'agents LLM dynamiques") name = st.text_input("Nom de l'agent") model = st.text_input("Modèle Ollama", value="mistral") role = st.text_area("Prompt système (rôle)") prompt = st.text_area("Message utilisateur") if st.button("Créer et exécuter"): agent = BaseAgent(name=name, model=model) agent.set_role(role) st.write(agent.process(prompt)) ``` --- ## IX. Exemple de configuration JSON (profiles.json) ```json { "agents": [ { "name": "ObsidianNoteur", "model": "mistral", "system_prompt": "Tu aides à structurer des notes Markdown.", "temperature": 0.6 }, { "name": "PythonHelper", "model": "codellama:13b-python", "system_prompt": "Tu améliores du code Python.", "temperature": 0.4 } ] } ``` --- ## Conclusion Tu disposes maintenant : - D'une **base agent dynamique** et paramétrable - De **rôles personnalisables** via `set_role()` - D'exemples concrets dans Obsidian, Cursor, CLI et Streamlit