Thermomètre ancien sur un mur en bois, illustration du tool calling LLM pour la météo

Donner la météo en temps réel à un chatbot avec le tool calling

Mon chatbot répond bien à partir de sa base de connaissances, mais il ne sait pas quelle température il fait en ce moment. Quand un visiteur demande « il fait combien de degrés ? », le modèle invente un chiffre sans hésiter. Pour lui donner accès à des données en direct, j’ai utilisé le tool calling LLM.

Le principe du tool calling LLM

Avec le tool calling LLM, le modèle ne va pas chercher la météo lui-même. On lui donne un outil, et c’est lui qui décide de l’appeler quand la question porte sur le temps qu’il fait. L’outil interroge une API en temps réel et renvoie des valeurs structurées : un texte de prévision, la température de l’air et un indice de chaleur (le WBGT), qui mesure la chaleur ressentie avec le soleil, l’humidité et le vent, pas seulement la température de l’air.

Une consigne courte demande au modèle de répondre uniquement à partir de ces valeurs, et de ne jamais les inventer. L’outil récupère des données fraîches à chaque appel, sans cache.

const weatherTool = tool(
  async () => fetchWeather(),
  {
    name: 'get_current_weather',
    description: `Renvoie la météo en direct : prévision, température de l'air et indice de chaleur.
      À utiliser dès que l'utilisateur demande le temps qu'il fait, la température ou la chaleur.
      Ne jamais inventer ces valeurs, toujours appeler cet outil.`,
    schema: z.object({}),
  },
);

Où l’outil se branche dans le RAG

Le point clé : la recherche dans la base de connaissances est elle-même un outil. On donne au modèle une seule liste d’outils, qui contient à la fois la recherche documentaire (le RAG) et l’outil météo. C’est le modèle qui choisit lequel appeler : la recherche pour une question de fond, l’outil météo pour une question en direct.

On lie la liste au modèle avec bindTools. Le modèle ne répond pas par du texte, il renvoie le nom de l’outil à appeler et ses arguments. Le framework exécute l’outil qui porte ce nom, récupère le résultat, et le modèle rédige la réponse finale à partir de là.

// La recherche dans la base est un outil parmi d'autres.
const tools = [
  retrievalTool, // le RAG : embed puis recherche vectorielle
  weatherTool,   // les données en direct
];

// Le modèle voit les deux et appelle celui qui colle à la question.
const result = await llm.bindTools(tools).invoke(question);

Répondre se fait en deux temps : d’abord on récupère l’info, ensuite le modèle rédige la réponse. L’outil ne touche qu’au premier temps, il change juste l’endroit où on va chercher l’info. Pour une question de fond, on la cherche dans la base ; pour la météo, on la demande à l’API. Le modèle, lui, rédige toujours de la même façon, à partir de ce qu’on a récupéré.

Le petit piège : lire une valeur par sa position

L’API renvoie la température et l’indice de chaleur dans le même tableau. La version naïve les lit par position : le premier élément, puis le second. Le jour où l’API change l’ordre des deux valeurs, le chatbot annonce l’indice de chaleur à la place de la température, sans la moindre erreur visible.

La correction : repérer chaque valeur par son libellé, jamais par sa position.

async function fetchWeather() {
  const { data } = await axios.get(WEATHER_ENDPOINT);
  const measures = data.elements.measures;

  return {
    airTemperature: pickMeasure(measures, false),
    heatIndex: pickMeasure(measures, true),
  };
}

// On repère la bonne valeur par son libellé, pas par sa position dans le tableau.
function pickMeasure(measures, wantHeatIndex) {
  const measure = measures.find((m) => isHeatIndex(m) === wantHeatIndex);
  if (!measure || measure.is_valid === false) {
    return null;
  }
  return { value: Math.round(measure.value * 10) / 10, unit: measure.unit };
}

function isHeatIndex(measure) {
  return `${measure.title}`.toLowerCase().includes('wbgt');
}

Et quand une valeur manque, on respecte le drapeau is_valid renvoyé par l’API : on renvoie null et le modèle répond « pas de donnée pour le moment » plutôt qu’un zéro inventé. C’est tout ce qu’il faut pour un premier outil de tool calling LLM fiable.

Laisser un commentaire