ChatGPT dans Jeedom?

Bon, de ce que j’en comprend, c’est exactement ce qu’on a fait. A voir pour modifier un peu le prompt, mais sinon, on est deja bon.

Sinon, j’ai aussi essayé de lui envoyer un snapshot d’une des caméra de surveillance. C’est bluffant l’analyse qu’il arrive a en faire. Avec un peu de contexte, il y a moyen de faire des trucs très sympa. Genre déclencher un scénario sur détection de mouvement ou de personne, qui analyse le snapshot et fait un retour vocal ou via télégram pour annoncer l’événement. Genre : il y a quelqu’un qui ressemble a belle maman devant la porte, planquez vous! :sweat_smile: Je m’y mets dès que j’ai le temps.

3 « J'aime »

Dans la prochaine version de Frigate, on aura cette analyse d’image, ça permettra de bien jouer avec :slight_smile:

Je ne veux pas faire le troll, mais dans la nouvelle version de Home Assistant, ils ont fais un grand pas sur leur IA (ajouté il y a 6 mois), on peut pratiquement tout contrôler via des demandes par écrits ou par la voix. Je me demande si Jeedom est sur le coup pour ne pas rater le coche.

J’ai deja testé et intégré Frigate dans jeedom, mais mon frigate a des problèmes de stabilité avec le dongle Coral. Je ne m’en sers donc plus :frowning:
Par contre, la detection de personne / animaux / voiture de mes camera Reolink fonctionne au poil. :wink:

a man in a suit and tie is sitting in a chair .

Faut déjà leur laisser le temps de rendre jeedom compatible avec la dernière version de debian, après on verra :sweat_smile:

2 « J'aime »

Oui, j’ai vu.
Mais en espérant me tromper, je ne crois pas que l’équipe Jeedom bosse sur une intégration IA.
Bon, par contre, avec ce que j’ai fais, franchement, ca fait le job (action et infos). Donc si un dev est motivé par mettre ce script dans un plugin bien packagé, je suis a sa dispo :wink:

Home Assistant gère nativement les différents LLM du marché ( GPT, Google generative, Claude.ai ) et les IA auto hebergées depuis Juin. Depuis ils n’ont cessé d’améliorer la chose, c’est vraiment bluffant.
Alexa et Google Home ressemblent à des reliques du passé à coté.

Il y a peut être de quoi s’inspirer de leur coté ?

L’intégration avec les caméras montre bien le potentiel:

image

image

je peux aussi pratiquement tout controler avec l’IA que j’ai dev, j’ai aussi montré que je gère aussi les différents LLM du marché comme mentionné par @Linc :wink:

cf mon lien un peu plus haut pour les mini démos

pour les cameras sinon le plus simple est de passer via frigate qui a ajouté de l’IA justement pour analyser les images. plugin-frigate

2 « J'aime »

Une petite beta pour tester? :wink:

j’essaie de partager ça asap, je vous redis ça pas de souci :slight_smile:

4 « J'aime »

Et on voit que sur les screen des cameras, l’exemple date de février 2024, j’imagine même pas les progrès encore depuis (vu la vitesse à laquelle l’IA grand publique avance).

Mouvement déclenché par 6 alpagas, dont un probablement atteint d’un cancer du foie

Ou bien

Mouvement déclenché par une voiture rouge sedan, dont le pneu arrière gauche est seulement gonflé à 1.85 bar avec une usure à 89%.

:sweat_smile:

Pour rappel, il y a deux ans, les IA (génératives) n’étaient même pas accessibles du grand public…
L’ère du Jarvis d’Ironman n’est pas loin !

2 « J'aime »

Bonjour,
Il faudrait déjà que l’IA apprenne à compter : Il n’y a pas 6 « Alpacas » mais 7 ! :sweat_smile:
(Voir 8 avec celui couché au fond mais qui, lui, ne semble pas bouger :wink: )

Tu sais pas, seuls les 6 ont peut être effectivement bougé, d’où le « 6 alpagas ont déclenché la détection de mouvement » :grin:

Elle n’a aucun scrupule à me répondre qu’elle ne peut pas allumer la lumiere de la cuisine parce qu’elle est deja éteinte! :rofl:

1 « J'aime »

Bonjour,

Juste une question basique, comment avez-vous fait pour que dans la réponse (ou la question d’ailleurs) Jeedom ne remplace pas les « et » par « && » ainsi que les « ou » par « || » ?
David

Je n’ai rien fait, mais j’envoie la réponse dans un scénario de notification via un tag.
Ou est ce que tu constates ce remplacement sauvage?

Bonjour,

En fait, j’envoie la réponse dans un virtuel et cette réponse est diffusée sur ma tablette via Jeedom connect.
A priori pas de soucis côté widget donc ca doit être lié à JC…
Je vais ouvrir un post, même si bien sur, j’ai pu régler ces remplacements sauvages facilement en PHP mais ça fait pas très propre ! :upside_down_face:

Salut à tous et un énorme merci pour le travail effectué notamment @fwehrle , je me suis bien éclaté avec vos codes, du coup, je me suis dit autant en faire un scénario à trou pour aider les boulets comme moi qui en chie à comprendre le code, du coup, j’ai bossé avec chat gpt, car il est concerné le machin non ?
J’ai fait deux scénarios, un pour les appels ou je pose une question et où il devra répondre par un texte et un deuxième pour les actions, extrêmement fortement inspirés de vos modèles.

Création d’un virtuel
Tout d’abord, je crée un virtuel a adapté pour les 2 scénarios Celon vos besoins :

Scénario question - réponse

Créer bloc action et mettre tout ce qui suit dedans :
Créer 3 variables :


puis un bloc code :
scenario::setData("jeedom_capteurs", "#[Virtuel Température][Etage - Température][Température]#;#[Virtuel Température][Salon bas - Température][Température]#");

Penser a remplacer les devices que vous voulez fournir à chat gpt par exemple dans mon cas : #[Virtuel Température][Etage - Température][Température]#;#[Virtuel Température][Salon bas - Température][Température]#
Un second bloc code :

$scenario->setLog("🚀 Début du script Assistant Domotique avec GPT-4o.");

// **1️⃣ Vérification de l'environnement PHP**
error_reporting(E_ALL);
ini_set('display_errors', 1);
$scenario->setLog("✅ Test : Environnement PHP chargé avec succès.");

// **2️⃣ Pause pour éviter le bug de récupération des variables Jeedom**
sleep(2);

// **3️⃣ Récupération des variables Jeedom**
$apiKeyGPT = scenario::getData("jeedom_openai_api");
$jeedomCapteurs = scenario::getData("jeedom_capteurs");  // Liste des capteurs sous forme Jeedom
$jeedomQuestion = scenario::getData("jeedom_question");  // Question de l'utilisateur
$jeedomSortieID = scenario::getData("jeedom_sortie");    // Commande où envoyer la réponse

// **4️⃣ Vérification des valeurs**
if (empty($apiKeyGPT) || empty($jeedomCapteurs) || empty($jeedomQuestion) || empty($jeedomSortieID)) {
    $scenario->setLog("❌ Erreur : Une ou plusieurs variables essentielles sont manquantes.");
    exit;
}

// **📌 Log des variables récupérées pour débogage**
$scenario->setLog("📌 API Key : ✅ OK");
$scenario->setLog("📌 Capteurs Jeedom : $jeedomCapteurs");
$scenario->setLog("📌 Question posée : \"$jeedomQuestion\"");
$scenario->setLog("📌 ID de la sortie : $jeedomSortieID");

// **5️⃣ Extraction des données Jeedom**
$capteursArray = explode(";", $jeedomCapteurs);
$capteursData = [];

foreach ($capteursArray as $capteur) {
    $cmd = cmd::byString(trim($capteur));
    if (is_object($cmd) && $cmd->execCmd() !== '') {
        $valeur = $cmd->execCmd();
        $scenario->setLog("✅ Capteur récupéré : {$cmd->getHumanName()} → $valeur");
        $capteursData[] = ["nom" => $cmd->getHumanName(), "valeur" => $valeur];
    } else {
        $scenario->setLog("⚠️ Capteur introuvable ou valeur vide : $capteur");
    }
}

if (empty($capteursData)) {
    $scenario->setLog("❌ Erreur : Aucune donnée récupérée de Jeedom.");
    exit;
}

// **6️⃣ Reformulation explicite du prompt pour OpenAI**
$prompt = "Tu es un assistant domotique Jeedom qui analyse les relevés des capteurs et répond aux questions de l'utilisateur.\n\n";

$prompt .= "**📊 Capteurs détectés et relevés actuels :**\n";
foreach ($capteursData as $data) {
    $prompt .= "- **{$data['nom']}** : {$data['valeur']}°C\n";
}

$prompt .= "\n⚠️ **Attention : Certains nombres dans la question peuvent être des identifiants et ne sont pas des capteurs.**\n";
$prompt .= "Tu dois ignorer tout chiffre qui ne correspond pas à un relevé de capteur.\n\n";

$prompt .= "**💡 Question posée par l'utilisateur :** \"$jeedomQuestion\"\n\n";
$prompt .= "**Ta mission :**\n";
$prompt .= "- Compare les relevés des capteurs.\n";
$prompt .= "- Réponds en **UNE seule phrase claire et directe**.\n";
$prompt .= "- Donne **l'information essentielle** sans analyser des nombres inutiles.\n\n";
$prompt .= "**Exemple de réponse correcte :**\n";
$prompt .= "- \"Le salon est l'endroit le plus chaud avec 19.8°C.\"\n";
$prompt .= "- \"Aucun relevé ne permet de répondre précisément à cette question.\"\n";

$prompt .= "\n**Réponds maintenant :**";


$scenario->setLog("📩 Envoi du prompt à OpenAI...");

// **7️⃣ Préparation de la requête OpenAI**
$data = [
    "model" => "gpt-4o",
    "messages" => [
        ["role" => "system", "content" => "Tu es un assistant domotique qui analyse les relevés des capteurs et réponds aux questions de manière directe et pertinente."],
        ["role" => "user", "content" => $prompt]
    ],
    "max_tokens" => 200,
    "temperature" => 0.6
];

$jsonPayload = json_encode($data, JSON_UNESCAPED_UNICODE);
if ($jsonPayload === false) {
    $scenario->setLog("❌ Erreur : JSON mal formé avant envoi à OpenAI.");
    exit;
}

// **8️⃣ Envoi à OpenAI**
$openaiUrl = "https://api.openai.com/v1/chat/completions";

$options = [
    "http" => [
        "header" => "Content-Type: application/json\r\n" . "Authorization: Bearer " . $apiKeyGPT . "\r\n",
        "method"  => "POST",
        "content" => $jsonPayload,
        "timeout" => 10
    ]
];

$context = stream_context_create($options);
$response = @file_get_contents($openaiUrl, false, $context);

// **9️⃣ Gestion de la réponse OpenAI**
$chatgptResponse = "Erreur : Aucune réponse générée.";
if ($response !== FALSE) {
    $responseData = json_decode($response, true);
    if (isset($responseData['choices'][0]['message']['content'])) {
        $chatgptResponse = trim($responseData['choices'][0]['message']['content']);
    } else {
        $scenario->setLog("❌ Réponse OpenAI invalide : " . print_r($responseData, true));
    }
} else {
    $scenario->setLog("❌ Erreur OpenAI : L'API n'a pas répondu.");
    exit;
}

// **🔟 Envoi de la réponse vers Jeedom**
$cmdSortie = cmd::byId($jeedomSortieID);
if (is_object($cmdSortie)) {
    $cmdSortie->event($chatgptResponse);
    $scenario->setLog("✅ Réponse envoyée à l'action message ID $jeedomSortieID : $chatgptResponse");
} else {
    $scenario->setLog("⚠️ Erreur : Commande ID $jeedomSortieID introuvable.");
}

// **🔚 Fin du script**
$scenario->setLog("🔚 Fin du script Assistant Domotique.");

Coté mode d’emploi :
:dart: Comment utiliser ce scénario ?

jeedom_capteurs = par exemple : #[Virtuel][Salon][Température]#;#[Divers][Meteo][Condition]#
jeedom_openai_api = ta clé API OpenAI
jeedom_question = ID de ta question
jeedom_sortie = ID du message où afficher la réponse

1 « J'aime »

Scénario question-action

On crée un bloc actionpuis on met tout ce qui suit dedans
Créer 4 variables :


puis on crée un bloc code :

$scenario->setLog("🚀 Début du script Assistant Domotique avec GPT-4o.");

// **1️⃣ Vérification de l'environnement PHP**
error_reporting(E_ALL);
ini_set('display_errors', 1);
$scenario->setLog("✅ Test : Environnement PHP chargé avec succès.");

// **2️⃣ Récupération des variables dynamiques**
sleep(2); // Pause pour s'assurer que les variables sont bien disponibles

$openaiApiKey  = scenario::getData("jeedom_openai_api");
$cmdAskId      = scenario::getData("jeedom_question");
$pieceId       = scenario::getData("jeedom_piece");
$cmdReponseId  = scenario::getData("jeedom_sortie");

$scenario->setLog("📌 API Key récupérée : " . (empty($openaiApiKey) ? "❌ Manquante" : "✅ OK"));
$scenario->setLog("📌 Commande utilisateur ID : " . (empty($cmdAskId) ? "❌ Manquante" : $cmdAskId));
$scenario->setLog("📌 Pièce ID : " . (empty($pieceId) ? "❌ Manquante" : $pieceId));
$scenario->setLog("📌 Commande de réponse ID : " . (empty($cmdReponseId) ? "❌ Manquante" : $cmdReponseId));

// **📌 Vérification des variables obligatoires**
if (empty($openaiApiKey) || empty($cmdAskId) || empty($pieceId) || empty($cmdReponseId)) {
    $scenario->setLog("❌ Erreur : Une ou plusieurs variables essentielles sont manquantes.");
    exit;
}

// **3️⃣ Récupération de la commande utilisateur**
$cmdAsk = cmd::byId((int)$cmdAskId);
$questionUtilisateur = (is_object($cmdAsk) && $cmdAsk->execCmd() !== '') ? $cmdAsk->execCmd() : "";

if (empty($questionUtilisateur)) {
    $scenario->setLog("⚠️ Aucune commande reçue !");
    exit;
}
$scenario->setLog("📩 Commande utilisateur : $questionUtilisateur");

// **4️⃣ Récupération des équipements de la pièce**
$objet = jeeObject::byId((int)$pieceId);

if (!is_object($objet)) {
    $scenario->setLog("❌ Erreur : Aucun objet trouvé pour l'ID $pieceId.");
    exit;
}
$scenario->setLog("✅ Pièce détectée : " . $objet->getName());

// **5️⃣ Récupération des équipements actionnables**
$equipements = $objet->getEqLogic(true);
$equipementsActionnables = [];

foreach ($equipements as $equipement) {
    if ($equipement->getIsEnable() && $equipement->getIsVisible()) {
        foreach ($equipement->getCmd() as $cmd) {
            if ($cmd->getIsVisible() == 1 && $cmd->getType() == "action") {
                $equipementsActionnables[] = [
                    "nom" => $equipement->getName(),
                    "commande" => $cmd->getName(),
                    "id" => $cmd->getId()
                ];
                $scenario->setLog("✅ Équipement actionnable détecté : " . $equipement->getName() . " - Commande : " . $cmd->getName());
            }
        }
    }
}

if (empty($equipementsActionnables)) {
    $scenario->setLog("❌ Aucun équipement actionnable détecté !");
    exit;
}

// **6️⃣ Encodage JSON des équipements pour OpenAI**
$equipementsJson = json_encode($equipementsActionnables, JSON_UNESCAPED_UNICODE);
if (!$equipementsJson || $equipementsJson == "null") {
    $scenario->setLog("❌ Erreur JSON : les équipements ne sont pas envoyés à GPT.");
    exit;
}
$scenario->setLog("📊 Envoi des équipements détectés à GPT : " . $equipementsJson);

// **7️⃣ Envoi à GPT-4o**
$data = [
    "model" => "gpt-4o",
    "messages" => [
        ["role" => "system", "content" => "Tu es un assistant domotique Jeedom intelligent. Analyse et exécute les demandes en fonction des équipements disponibles."],
        ["role" => "system", "content" => "Réponds TOUJOURS sous la forme d'un JSON contenant : 'question', 'response', 'id', 'mode' (action ou info)."],
        ["role" => "user", "content" => "Voici les équipements disponibles dans la pièce ID $pieceId : " . $equipementsJson],
        ["role" => "user", "content" => "Commande utilisateur : " . $questionUtilisateur]
    ],
    "max_tokens" => 200,
    "temperature" => 0.5
];

$options = [
    "http" => [
        "header" => "Content-Type: application/json\r\n" . "Authorization: Bearer " . $openaiApiKey . "\r\n",
        "method"  => "POST",
        "content" => json_encode($data),
        "timeout" => 10
    ]
];

$context = stream_context_create($options);
$response = @file_get_contents("https://api.openai.com/v1/chat/completions", false, $context);

// **8️⃣ Vérification de la réponse GPT-4o**
if ($response === FALSE) {
    $scenario->setLog("❌ Erreur OpenAI : L'API n'a pas répondu.");
    exit;
}

$responseData = json_decode($response, true);
if (!isset($responseData['choices'][0]['message']['content'])) {
    $scenario->setLog("❌ Réponse OpenAI invalide : " . print_r($responseData, true));
    exit;
}

// **🔹 Suppression des balises `json` dans la réponse**
$chatgptResponse = trim($responseData['choices'][0]['message']['content']);
$chatgptResponse = str_replace(["```json", "```"], "", $chatgptResponse);
$chatgptResponse = trim($chatgptResponse);

$scenario->setLog("✅ Réponse GPT après nettoyage : " . $chatgptResponse);

// **9️⃣ Exécution de la commande si action détectée**
$reponseJson = json_decode($chatgptResponse, true);

if (isset($reponseJson['id']) && $reponseJson['mode'] == "action") {
    $cmdIds = $reponseJson['id'];

    if (is_array($cmdIds)) {
        foreach ($cmdIds as $cmdId) {
            $cmd = cmd::byId((int)$cmdId);
            if (is_object($cmd)) {
                $cmd->execCmd();
                $scenario->setLog("✅ Exécution de la commande ID $cmdId : " . $cmd->getHumanName());
            } else {
                $scenario->setLog("❌ Échec : ID de commande inexistant ($cmdId)");
            }
        }
    } elseif (is_numeric($cmdIds)) {
        $cmd = cmd::byId((int)$cmdIds);
        if (is_object($cmd)) {
            $cmd->execCmd();
            $scenario->setLog("✅ Exécution de la commande ID $cmdIds : " . $cmd->getHumanName());
        } else {
            $scenario->setLog("❌ Échec : ID de commande inexistant ($cmdIds)");
        }
    } else {
        $scenario->setLog("⚠️ Aucun ID valide retourné par GPT.");
    }
}

// **🔟 Envoi de la réponse dans Jeedom**
$cmdReponse = cmd::byId((int)$cmdReponseId);
if (is_object($cmdReponse)) {
    $cmdReponse->event($reponseJson['response']);
    $scenario->setLog("✅ Réponse envoyée à l'ID $cmdReponseId : " . $reponseJson['response']);
} else {
    $scenario->setLog("❌ Erreur : Impossible d'envoyer la réponse (ID $cmdReponseId).");
}

// **🔚 Fin du script**
$scenario->setLog("🔚 Fin du script Assistant Domotique.");

Mode d’emploi

:dart: Comment utiliser ce scénario d’action ?

  • jeedom_openai_api = Ta clé API OpenAI
  • jeedom_commande = ID de la commande utilisateur (ex: question posée via un assistant vocal ou une interaction)
  • jeedom_piece = ID de la pièce Jeedom contenant les équipements à contrôler
  • jeedom_sortie = ID du message où afficher la réponse
1 « J'aime »