Une maison intelligente doit organiser ses appareils électriques. Mais comment une IA locale peut-elle comprendre les contraintes sans se tromper ? Voici la méthode pas à pas.

Imaginez : il est 18h30, vous rentrez du travail, et votre maison vous demande : « Faut-il lancer le lave-vaisselle maintenant ou plus tard ? »

Derrière cette question simple se cachent des dizaines de contraintes : la machine doit finir avant 6h30 pour le petit-déjeuner, elle fait trop de bruit pour les chambres, et l'électricité coûte cher entre 17h et 20h. Sans compter le chargeur de voiture électrique, le sèche-linge et la machine à laver qui veulent aussi leur tour.

Pour répondre correctement, une intelligence artificielle locale doit d'abord comprendre toutes ces règles. Mais comment s'assurer qu'elle ne se trompe pas ? La réponse s'appelle le structured output : une technique pour forcer l'IA à donner des réponses dans un format précis, comme un tableau bien organisé plutôt qu'un texte libre.

Un structured output ne garantit pas que l'information soit juste, seulement que la réponse soit bien formatée.

POURQUOI UTILISER UNE IA LOCALE POUR VOTRE MAISON CONNECTÉE ?

Les maisons intelligentes regorgent d'appareils qui communiquent entre eux : robots aspirateurs, lave-linge, sèche-linge, chargeurs de voiture électrique. Tous ces appareils ont besoin d'électricité, et leur utilisation doit être optimisée pour éviter de faire sauter les plombs ou de gaspiller de l'énergie.

Quand vous posez une question à votre système domotique, comme « Faut-il lancer le lave-vaisselle maintenant ou plus tard ? », l'IA doit analyser plusieurs éléments :

  • • L'heure actuelle (18h30)
  • • Les contraintes de chaque appareil (le lave-vaisselle doit finir avant 6h30)
  • • Les coûts de l'électricité (0,45 €/kWh entre 17h et 20h)
  • • Les règles de votre maison (un seul appareil à la fois)

Le problème ? Ces informations sont souvent écrites dans des notes ou des logs, comme un journal de bord de la maison. Ces données contiennent des détails personnels (quand vous êtes rentré, quels vêtements sont dans la machine) que vous ne voulez pas envoyer sur Internet. Une IA locale est donc idéale : elle reste sur votre ordinateur ou votre serveur, et ne partage pas vos données avec le cloud.

Mais une fois que l'IA a compris les contraintes, comment lui faire produire une réponse exploitable ? C'est là que le structured output entre en jeu.

COMMENT FONCTIONNE LE STRUCTURED OUTPUT ?

Le structured output est une technique qui permet de forcer une IA à donner une réponse dans un format précis, comme un tableau ou une liste. Au lieu de recevoir un texte libre comme :

« Le lave-vaisselle peut démarrer à 18h30 ou 20h, mais pas après 22h30 parce qu'il est à côté des chambres. Le chargeur de voiture doit finir avant 7h. »

L'IA va produire une réponse structurée, comme un dictionnaire en Python :

{
  "appareils": [
    {
      "nom": "Lave-vaisselle",
      "durée": 90,
      "énergie": 1.2,
      "débutauplus_tôt": "18:30",
      "finauplus_tard": "06:30"
    }
  ]
}

Cette réponse structurée est ensuite facile à lire et à utiliser par un autre programme, comme un système de planification.

Pour mettre en place cette technique, il faut trois choses :

  • • Une bibliothèque de validation comme Pydantic pour définir le format attendu
  • • Un runtime local comme Ollama pour faire tourner l'IA
  • • Un modèle d'IA comme Gemma 4 pour analyser les données

ÉTAPE 1 : DÉFINIR LE FORMAT ATTENDU AVEC PYDANTIC

Avant de poser la question à l'IA, il faut lui dire exactement ce qu'on attend comme réponse. C'est comme donner un formulaire à remplir plutôt qu'une feuille blanche.

Avec Pydantic, on définit un modèle pour chaque type d'information. Par exemple, pour l'heure, on utilise un format précis : HH:MM (heures et minutes).

from typing import Annotated
from pydantic import BaseModel, Field

ClockTime = Annotated[
    str,
    Field(
        min_length=5,
        max_length=5,
        description="Heure au format HH:MM.",
    ),
]

Ensuite, on définit un modèle pour chaque appareil à planifier :

class AppareilAPlanifier(BaseModel):
    nom_appareil: str
    durée_minutes: int
    énergie_kwh: float
    débutauplus_tôt: ClockTime
    finauplus_tard: ClockTime | None

Et enfin, le modèle principal qui regroupe toutes les informations nécessaires au planificateur :

class ContextePlanification(BaseModel):
    heure_actuelle: ClockTime
    appareil_principal: str
    appareilsàplanifier: list[AppareilAPlanifier]

Ce modèle contient :

  • • L'heure actuelle (18:30)
  • • L'appareil concerné par la question (le lave-vaisselle)
  • • La liste des appareils qui restent à planifier

Avec cette structure, l'IA sait exactement ce qu'elle doit extraire des notes de la maison.

ÉTAPE 2 : INSTALLER OLLAMA POUR FAIRE TOURNER L'IA LOCALE

Pour faire tourner une IA locale, il faut un outil comme Ollama. C'est un logiciel qui permet de télécharger et d'exécuter des modèles d'IA directement sur son ordinateur.

Sur Windows, l'installation se fait en une ligne de commande :

winget install Ollama.Ollama

Sur macOS ou Linux, il suffit d'exécuter :

curl -fsSL https://ollama.com/install.sh | sh

Une fois Ollama installé, on télécharge le modèle d'IA Gemma 4 (version 4B, la plus légère) :

ollama pull gemma4:e4b

Enfin, on installe les bibliothèques Python nécessaires :

pip install ollama pydantic

ÉTAPE 3 : CRÉER UNE FONCTION POUR POSER LA QUESTION À L'IA

Maintenant, il faut une fonction qui envoie la question à l'IA et récupère la réponse structurée. Cette fonction prend trois arguments :

  • • Le modèle Pydantic (le format attendu)
  • • Les instructions pour l'IA (ce qu'elle doit faire)
  • • La question ou les données à analyser
import ollama

def poserquestionàlia_locale(schema, instructions, question):
    réponse = ollama.chat(
        model="gemma4:e4b",
        messages=[
            {"role": "system", "content": instructions},
            {"role": "user", "content": question},
        ],
        think="medium",
        format=schema.modeljsonschema(),
    )
    return schema.modelvalidatejson(réponse.message.content)

Cette fonction utilise ollama.chat pour discuter avec l'IA. Le paramètre format force l'IA à répondre dans le format JSON attendu, grâce au schéma défini par Pydantic.

ÉTAPE 4 : POSER LA QUESTION ET RÉCUPÉRER LA RÉPONSE

La question est simple : « Faut-il lancer le lave-vaisselle maintenant ou plus tard ? »

Les données à analyser sont les notes de la maison, qui contiennent toutes les contraintes. Voici un extrait :

Il est actuellement 18:30.

Le robot aspirateur a terminé son passage dans la cuisine à 16:10 et est retourné à sa base. Plus de passage n'est nécessaire aujourd'hui.

Le lave-vaisselle peut démarrer au plus tôt à 18:30. Un cycle dure 90 minutes et consomme environ 1,2 kWh. Il doit être terminé avant le petit-déjeuner à 06:30. Comme il est à côté des chambres, il doit s'arrêter avant 22:30.

Le chargeur de voiture électrique peut démarrer au plus tôt à 18:30. La recharge dure 120 minutes et consomme environ 14 kWh. La voiture doit être chargée avant le départ du conducteur à 07:00.

Le sèche-linge peut démarrer au plus tôt à 19:00. Un cycle dure 75 minutes et consomme environ 3,2 kWh. Il contient la tenue de football, qui doit être sèche avant 23:00. Le sèche-linge est trop bruyant en soirée, donc il doit s'arrêter avant 21:30.

La machine à laver peut démarrer au plus tôt à 20:00. Un cycle dure 60 minutes et consomme environ 0,9 kWh. Elle contient les vêtements de travail pour demain et doit être terminée avant 05:30.

Un passage de robot aspirateur dans la cuisine prend 45 minutes et consomme environ 0,2 kWh. Le passage le plus tôt était à 15:00.

Le contrôleur énergétique de la maison n'autorise qu'un seul appareil flexible à fonctionner à la fois.

L'électricité coûte 0,45 €/kWh de 17:00 à 20:00, 0,22 € de 20:00 à 00:00, 0,12 € de 00:00 à 06:00, et 0,25 € de 06:00 à 17:00.

On prépare les instructions pour l'IA : « Convertis les notes fournies en un contexte de planification structuré. Ne propose pas de planning, extrais simplement les faits. »

Ensuite, on envoie tout à l'IA :

réponse = poserquestionàlia_locale(
    ContextePlanification,
    "Convertis les notes fournies en un contexte de planification structuré. Ne propose pas de planning, extrais simplement les faits.",
    question + "\n\n" + notes_maison
)

La réponse de l'IA est un objet Python structuré, prêt à être utilisé par un autre programme.

LE PROBLÈME : L'IA SE TROMPE TOUJOURS

Quand on exécute ce code, l'IA répond avec une structure valide, mais avec des erreurs de contenu. Voici ce qu'elle retourne :

ContextePlanification

["Lave-vaisselle", "Chargeur de voiture électrique", "Machine à laver", "Robot aspirateur (Passage cuisine)"]

Le problème ? Le robot aspirateur a déjà fait son travail à 16h10. Il n'a pas besoin d'être planifié. Pourtant, l'IA l'a inclus dans la liste. Pourquoi ?

Parce que le structured output ne garantit que la forme de la réponse, pas son contenu. L'IA a suivi le format demandé, mais a mal interprété les données. Elle a cru que le robot aspirateur devait encore passer, alors que les notes disaient clairement qu'il avait terminé.

C'est un piège classique : une IA locale comme Gemma 4 est petite et peu puissante. Lui demander de faire trop de choses en même temps (comprendre les contraintes, filtrer les appareils inutiles, et structurer la réponse) la fait souvent échouer.

Un modèle local comme Gemma 4 peut facilement se tromper quand on lui demande trop de travail d'un coup.

LA SOLUTION : DÉCOMPOSER LA TÂCHE EN PLUSIEURS ÉTAPES

Pour éviter les erreurs, il faut simplifier le travail de l'IA. Au lieu de tout lui demander en une seule fois, on divise la tâche en deux étapes :

  1. D'abord, on lui demande de déterminer quels appareils ont vraiment besoin d'être planifiés.
  2. Ensuite, on lui demande d'extraire les détails précis pour ces appareils.

Étape 1 : Déterminer le périmètre de planification

On crée un nouveau modèle Pydantic, plus simple, pour identifier les appareils concernés :

class PérimètrePlanification(BaseModel):
    appareil_principal: str
    appareilsàplanifier: list[str]

Et les instructions correspondantes :

INSTRUCTIONS_PÉRIMÈTRE = """
Identifie l'appareil principal et les appareils de la maison qui ont encore besoin d'être planifiés.
Ne propose pas de planning, extrais simplement les faits.
"""

On envoie la question et les notes à l'IA avec ce nouveau modèle :

périmètre = poserquestionàlia_locale(
    PérimètrePlanification,
    INSTRUCTIONS_PÉRIMÈTRE,
    question + "\n\n" + notes_maison
)

Cette fois, la réponse est correcte :

{
  "appareil_principal": "Lave-vaisselle",
  "appareilsàplanifier": [
    "Lave-vaisselle",
    "Chargeur de voiture électrique",
    "Machine à laver"
  ]
}

Le robot aspirateur a disparu de la liste. L'IA a bien compris qu'il n'avait plus besoin d'être planifié.

Étape 2 : Extraire les détails pour les appareils sélectionnés

Maintenant qu'on sait quels appareils ont besoin d'être planifiés, on peut demander à l'IA d'extraire les détails précis pour ces appareils seulement. On utilise le même modèle ContextePlanification que précédemment.

On prépare un nouveau prompt avec la liste des appareils sélectionnés :

INSTRUCTIONS_DÉTAILS = """
Convertis les notes fournies en un contexte de planification structuré pour les appareils sélectionnés.
Ne propose pas de planning, extrais simplement les faits.
"""

prompt_détails = f"""
Appareils sélectionnés:
{périmètre.appareilsàplanifier}

Question de l'utilisateur:
{question}

Notes de la maison:
{notes_maison}
"""

contextedétaillé = poserquestionàlialocale(
    ContextePlanification,
    INSTRUCTIONS_DÉTAILS,
    prompt_détails
)

Cette fois, la réponse est parfaite :

{
  "heure_actuelle": "18:30",
  "appareil_principal": "Lave-vaisselle",
  "appareilsàplanifier": [
    {
      "nom_appareil": "Lave-vaisselle",
      "durée_minutes": 90,
      "énergie_kwh": 1.2,
      "débutauplus_tôt": "18:30",
      "finauplus_tard": "06:30"
    },
    {
      "nom_appareil": "Chargeur de voiture électrique",
      "durée_minutes": 120,
      "énergie_kwh": 14.0,
      "débutauplus_tôt": "18:30",
      "finauplus_tard": "07:00"
    },
    {
      "nom_appareil": "Machine à laver",
      "durée_minutes": 60,
      "énergie_kwh": 0.9,
      "débutauplus_tôt": "20:00",
      "finauplus_tard": "05:30"
    }
  ]
}

Tous les appareils sont corrects, les contraintes sont respectées, et les informations personnelles (comme le linge dans la machine) ont été filtrées.

CE QU'IL FAUT RETENIR : LES 3 RÈGLES D'OR

Un structured output ne garantit pas que l'information soit juste, seulement que la réponse soit bien formatée.

Voici les trois leçons à retenir quand on utilise une IA locale pour structurer des données :

1. Le format ne garantit pas le contenu

Même si l'IA répond dans le bon format, elle peut se tromper sur les données. C'est comme remplir un formulaire : si vous écrivez n'importe quoi dans les cases, le formulaire sera toujours valide, mais les informations seront fausses.

Pour éviter ça, il faut vérifier les résultats et, si possible, décomposer la tâche en étapes plus simples.

2. Une IA locale est limitée

Les modèles comme Gemma 4 sont petits et peu puissants. Leur force est de rester privés et rapides, mais leur faiblesse est de mal comprendre des instructions complexes. Si on leur demande trop de travail en une seule fois, elles échouent.

La solution ? Diviser la tâche en étapes claires et donner à l'IA une seule instruction à la fois.

3. Le structured output est un outil, pas une solution magique

Cette technique permet de forcer une IA à donner une réponse structurée, mais elle ne garantit pas que la réponse soit correcte. C'est un outil pour automatiser des tâches répétitives, pas pour remplacer la réflexion humaine.

POUR ALLER PLUS LOIN : QUELQUES RESSOURCES UTILES

Si vous voulez approfondir le sujet, voici quelques ressources qui pourraient vous intéresser :

  • • Un framework pour mesurer la qualité de récupération dans les agents utilisant le Model Context Protocol
  • • Une méthode pour générer des exemples de prompts de manière systématique, du choix aléatoire à la Génération organisée
  • • Un guide pour surmonter les limites des IA avec la vérification formelle

Ces ressources montrent que le structured output n'est qu'une partie de l'équation. Pour créer des applications vraiment utiles avec les IA, il faut aussi savoir comment poser les bonnes questions, comment valider les réponses, et comment intégrer l'IA dans un workflow plus large.

En résumé, une IA locale peut être un excellent outil pour organiser votre maison connectée, à condition de bien comprendre ses limites et de structurer vos demandes. Avec cette méthode, vous éviterez les erreurs et optimiserez l'utilisation de vos appareils électriques.

Sources :
  • Towards Data Science

L'indépendance de CLODCO est votre garantie.

Pour que l'actualité de l'IA reste sans filtre et sans concession, votre soutien est indispensable. Votre contribution est le seul moteur de notre liberté éditoriale.

Soutenir CLODCO