Aller au contenu principal

Agent météo complet

Construire un agent météo de A à Z

Dans cette leçon, vous allez assembler toutes les connaissances acquises pour construire un agent météo complet. Cet agent illustre le cycle complet du function calling : définition des outils, gestion multi-tour, traitement des erreurs et réponse en langage naturel.

Architecture de l’agent

L’agent météo dispose de trois outils :

  1. get_weather — obtenir la météo actuelle d’une ville
  2. get_forecast — obtenir les prévisions sur plusieurs jours
  3. get_alerts — vérifier les alertes météo actives
import json
from openai import OpenAI

client = OpenAI(
    api_key="votre-cle-xai",
    base_url="https://api.x.ai/v1"
)

tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "Obtenir la météo actuelle d'une ville. "
                          "Retourne température, humidité, vent et conditions.",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {
                        "type": "string",
                        "description": "Nom de la ville (ex: Paris, Lyon, Marseille)"
                    },
                    "unit": {
                        "type": "string",
                        "enum": ["celsius", "fahrenheit"],
                        "default": "celsius"
                    }
                },
                "required": ["city"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "get_forecast",
            "description": "Obtenir les prévisions météo sur plusieurs jours. "
                          "Retourne les conditions jour par jour.",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {
                        "type": "string",
                        "description": "Nom de la ville"
                    },
                    "days": {
                        "type": "integer",
                        "description": "Nombre de jours de prévision (1-7)",
                        "default": 3
                    }
                },
                "required": ["city"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "get_alerts",
            "description": "Vérifier les alertes météo actives (tempêtes, canicule, "
                          "inondations) pour une ville ou une région.",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {
                        "type": "string",
                        "description": "Nom de la ville ou de la région"
                    }
                },
                "required": ["city"]
            }
        }
    }
]

Implémentation des fonctions

En production, ces fonctions appelleraient une vraie API météo. Ici, nous simulons les réponses :

def get_weather(city, unit="celsius"):
    # En production : appel à OpenWeatherMap, WeatherAPI, etc.
    data = {
        "Paris": {"temp": 18, "humidity": 65, "wind": 12, "conditions": "Nuageux"},
        "Lyon": {"temp": 21, "humidity": 55, "wind": 8, "conditions": "Ensoleillé"},
        "Marseille": {"temp": 24, "humidity": 70, "wind": 15, "conditions": "Dégagé"},
    }
    result = data.get(city, {"error": f"Ville {city} non trouvée"})
    if "error" not in result:
        result["city"] = city
        result["unit"] = unit
    return result

def get_forecast(city, days=3):
    return {
        "city": city,
        "forecast": [
            {"day": f"J+{i+1}", "temp_max": 20+i, "temp_min": 12+i,
             "conditions": "Variable"}
            for i in range(days)
        ]
    }

def get_alerts(city):
    alerts = {
        "Marseille": [{"type": "Vent fort", "severity": "orange",
                       "message": "Rafales jusqu'à 90 km/h prévues"}],
    }
    return {"city": city, "alerts": alerts.get(city, [])}

La boucle principale de l’agent

def execute_function(name, args):
    functions = {
        "get_weather": get_weather,
        "get_forecast": get_forecast,
        "get_alerts": get_alerts,
    }
    fn = functions.get(name)
    if not fn:
        return {"error": f"Fonction {name} inconnue"}
    try:
        return fn(**args)
    except Exception as e:
        return {"error": str(e)}

def weather_agent(user_message):
    messages = [
        {
            "role": "system",
            "content": "Vous êtes un assistant météo expert. "
                       "Utilisez les outils disponibles pour fournir "
                       "des informations météo précises. Vérifiez "
                       "toujours les alertes quand on vous demande "
                       "la météo d'une ville."
        },
        {"role": "user", "content": user_message}
    ]

    for _ in range(5):  # Max 5 tours
        response = client.chat.completions.create(
            model="grok-3",
            messages=messages,
            tools=tools
        )

        message = response.choices[0].message
        messages.append(message)

        if not message.tool_calls:
            return message.content

        for tc in message.tool_calls:
            args = json.loads(tc.function.arguments)
            print(f"  → Appel : {tc.function.name}({args})")
            result = execute_function(tc.function.name, args)
            messages.append({
                "role": "tool",
                "tool_call_id": tc.id,
                "content": json.dumps(result, ensure_ascii=False)
            })

    return "Désolé, trop de tours nécessaires."

Tester l’agent

# Test 1 : question simple
print(weather_agent("Quel temps fait-il à Paris ?"))

# Test 2 : prévisions
print(weather_agent("Donne-moi les prévisions pour Lyon sur 5 jours"))

# Test 3 : multi-villes (appels parallèles)
print(weather_agent("Compare la météo entre Paris, Lyon et Marseille"))

# Test 4 : question complexe
print(weather_agent("Je pars à Marseille ce weekend, que me conseilles-tu ?"))

Le test 3 déclenche des appels parallèles : le modèle appelle get_weather trois fois simultanément. Le test 4 est le plus intéressant — le modèle devrait appeler get_forecast ET get_alerts pour Marseille, puis synthétiser les résultats en conseils pratiques.

Améliorations possibles

Pour un agent production-ready, ajoutez :

  • Cache : ne pas rappeler l’API météo pour la même ville dans les 10 minutes
  • Géocodage : convertir les noms de ville en coordonnées pour plus de précision
  • Historique : sauvegarder les préférences utilisateur (unités, villes favorites)
  • Internationalisation : supporter les noms de ville dans toutes les langues

Points clés à retenir

  • Un agent complet combine plusieurs outils avec des responsabilités distinctes
  • Le system prompt guide le comportement du modèle (vérifier les alertes systématiquement)
  • La boucle multi-tour avec max_iterations évite les boucles infinies
  • Le dispatcher execute_function centralise l’exécution et la gestion d’erreurs
  • Testez avec des requêtes variées : simples, multi-villes, complexes
  • En production, ajoutez cache, géocodage et historique utilisateur