Aller au contenu principal

ChatGPT peut il m'assister partie 1 ?

· 9 minutes de lecture
Stéphane ROBERT
Consultant DevOps

Par nature le DSL Ansible n'est pas un langage de programmation, mais permet plutôt de décrire le résultat souhaité. Le code se trouve en fait dans les modules qui eux sont écrits en Python. Alors est-il possible de demander de l'aide à une Intelligence Artificielle comme celle de ChatGPT ?

Dans ce billet, je vais demander à chatGPT de produire du code Ansible et nous analyserons le résultat. Nous regarderons s'il respecte surtout les bonnes pratiques que j'ai définies dans mon précédent billet.

Utilisation du SDK OpenAI

Je ne vais pas utiliser le chatbot, mais le SDK Python d'OpenAI.

Installation du SDK Python OpenAI

Le SDK est fourni sous la forme d'un package pypi et donc très facilement installable.

pyenv virtualenv 3.10.8 chatgpt
pyenv shell chatgpt
pip install openai rich

J'installe aussi la librairie rich pour rendre les sorties plus sympathiques.

Notre première demande à l'API de ChatGPT

info

Ce service n'est pas gratuit, mais les coûts sont très faibles. Le coût d’utilisation de l’API de ChatGPT est d'un centime de dollars pour 5000 tokens. J'ai lancé environ deux requêtes à ChatGPT et le cout est de 20 cts.

Après avoir créé un compte sur la plateforme OpenAI, il faut demander la création d'un token.

Le code de test de ma demande à ChatGPT

Maintenant le code minimal pour poser une question à chatGPT :

#!/usr/bin/env python3

import os
import sys
import openai
from rich.console import Console
from rich import print
from rich.text import Text
from rich.markdown import Markdown

openai.api_key = os.getenv("OPENAI_KEY")
system_message = "Tu es un expert Ansible."
system_user = sys.argv[1]
print("Demande envoyé à ChatGPT : %s : %s" % (system_message, system_user))
response = openai.ChatCompletion.create(
    model="gpt-3.5-turbo-0301",
    messages=[
        {
            "role": "system",
            "content": system_message,
        },
        {"role": "user", "content": system_user},
    ]
)
response = response["choices"][0]["message"]["content"].replace("'", '"')
console = Console()
print("ChatGPT réponds:")
md = Markdown(response)
console.print(md)
print(response["usage"]["total_tokens"])

Quelques explications :

Dans les messages envoyés, on doit indiquer plusieurs rôles accompagnés de leur contexte :

  • le rôle system permet de définir le comportement de l’assistant. Dans mon cas, je lui indique qu'il est un expert Ansible.
  • le rôle user les questions que vous envoyez à l’API de ChatGPT avec les instructions à fournir à l’assistant.
  • le rôle assistant qui sera utilisé pour garder l'historique d'une conversation.

Ici, je ne tiendrai pas de conversation avec ChatGPT, donc pas d'appel à l'assistant.

On lui pose notre première question

On lui pose la première question :

./test.py "Quelle module Ansible utiliser pour copier un fichier du controler sur la cible avec les droits 755"
Demande envoyé à ChatGPT : Tu es un expert Ansible. : Quelle module Ansible utiliser pour copier un fichier du controler sur la cible avec les
droits 755
ChatGPT réponds:
Pour copier un fichier du controler sur la cible avec les droits 755, vous pouvez utiliser le module "copy" d"Ansible.

Voici un exemple de tâche Ansible utilisant le module "copy" pour copier un fichier nommé "mon_script.sh" du controler vers la cible :

- name: Copier le script sur la cible avec les droits 755
  copy:
    src: /chemin/vers/mon_script.sh
    dest: /chemin/vers/mon_script.sh
    mode: 755

Dans cet exemple, le fichier source est situé sur le controler dans le répertoire "/chemin/vers/" et est nommé "mon_script.sh". Le fichier sera
copié vers la cible dans le même chemin et sera défini avec les droits 755 (rwxr-xr-x).
Tokens utilisés 236

Sympa la réponse non ?

  • Mais il ne respecte pas les bonnes pratiques définies. Comment le guider alors ?
  • Et il est bavard non ? Si on commençait par lui demander que la réponse.

Rendre moins bavard

En fait, c'est assez simple. Il suffit d'ajouter dans le contexte `system.

system_message = "Tu es un expert Ansible. Ne commente pas la réponse!"

On relance :

ChatGPT réponds:
Le module Ansible à utiliser est copy. Il faut définir les options src, dest et mode pour copier le fichier avec les droits 755. Voici un exemple de tâche Ansible qui utilise le module copy :

- name: Copier un fichier avec les droits 755
  copy:
    src: /chemin/vers/fichier
    dest: /chemin/vers/destination
    mode: "0755"
Tokens utilisés 154

Mince, il ne peut s'empêcher de parler. Par contre, vous remarquez que du coup, on a utilisé moins de tokens.

Lui demander de répondre en JSON

On peut lui demander de la formater la réponse en JSON, plus simple à interpréter que du yaml. On modifie notre contexte system :

system_message = "Tu es un expert Ansible. Réponds en JSON. Ne commente pas la réponse! JSON:"

On relance :

./test.py "Quelle module Ansible utiliser pour copier un fichier du controler sur la cible avec les droits 755"
Demande envoyé à ChatGPT : Tu es un expert Ansible. Réponds en JSON. Ne commente pas la réponse! JSON: : Quelle module Ansible utiliser pour copier un fichier du controler sur la cible avec les droits 755
ChatGPT réponds:
{"module": "copy", "src": "/chemin/vers/fichier/source", "dest":"/chemin/vers/fichier/destination", "mode":"0755"}
Tokens utilisés 94

Cette fois, c'est la bonne. Pas de commentaire juste un JSON, mais inexploitable.

Demander à ChatGPT de respecter les bonnes pratiques

Je suis un adepte de l'utilisation des FQCN Ansible. Le module copy doit être invoqué avec ansible.builtin.copy.

On modifie cette fois notre demande user :

./test.py "Quelle module Ansible utiliser pour copier un fichier du controler sur la cible avec les droits 755. Utilise les FQCN des modules Ansible "
Demande envoyé à ChatGPT : Tu es un expert Ansible. Réponds en JSON. Ne commente pas la réponse! JSON: : Quelle module Ansible utiliser pour copier un fichier du controler sur la cible avec les droits 755. Utilise les FQCN des modules Ansible
ChatGPT réponds:
{ "module": "ansible.builtin.copy", "args": { "src": "chemin/du/fichier/src", "dest": "chemin/du/fichier/dest", "mode": "755" } }
Tokens utilisés 123

Pas génial car inexpoitable : il a mis modules. C'est de ma faute, il faut lui dire de créer des taches.

Demander à chatGPT de produire un ensemble de taches

Allez on lui demande d'écrire les taches Ansible pour installer les packages net-tools et nginx, ensuite de copier notre fichier :

./test.py "Ecris des taches Ansible pour installer les packages net-tools, nginx avec le module package puis copier un fichier du controler sur la cible avec les droits 755. Utilise les FQCN des modules Ansible "
Demande envoyé à ChatGPT : Tu es un expert Ansible. Réponds en JSON en utilisant les FQCN Ansible. Ne commente pas la réponse! JSON: : Ecris des
taches Ansible pour installer les packages net-tools, nginx avec le module package puis copier un fichier du controler sur la cible avec les droits
755. Utilise les FQCN des modules Ansible
ChatGPT réponds:
{
    "tasks": [
        {
            "name": "Installer net-tools",
            "package": {
                "name": "net-tools",
                "state": "present"
            }
        },
        {
            "name": "Installer nginx",
            "package": {
                "name": "nginx",
                "state": "present"
            }
        },
        {
            "name": "Copier fichier avec droits 755",
            "copy": {
                "src": "/chemin/vers/fichier",
                "dest": "/destination/fichier",
                "mode": "755"
            }
        }
    ]
}
Tokens utilisés 226

Pas mal du tout non ? Mince, il a oublié de respecter ma demande d'utilisation d'un FQCN.

Je relance dés fois que :

{
  "hosts": "cible",
  "tasks": [
    {
      "name": "Installation des packages net-tools et nginx",
      "package": {
        "name": ["net-tools", "nginx"],
        "state": "present"
      }
    },
    {
      "name": "Copie du fichier du controler avec les droits 755",
      "copy": {
        "src": "/chemin/du/fichier",
        "dest": "/chemin/de/destination",
        "mode": "0755"
      }
    }
  ]
}

Cette fois, il m'a créé un playbook avec deux taches dont deux installations de packages avec le module yum et non plus apt.

Ajustement de la température

Il existe un réglage qui permet de contrôler le côté créativité de chatGPT, c'est la température. Une température à 0 rend le moteur déterministe, ce qui signifie qu'il retournera toujours la même sortie pour une demande donnée. Tandis qu'avec une valeur de 1, il prendra plus de liberté.

Notre code devient :

response = openai.ChatCompletion.create(
    model="gpt-3.5-turbo-0301",
    messages=[
        {
            "role": "system",
            "content": system_message,
        },
        {"role": "user", "content": system_user},
    ],
    temperature = 0
)

On relance plusieurs fois :

./test.py "Ecris des taches Ansible pour installer les packages net-tools, nginx avec le module package puis copier un fichier du controler sur la cible avec les droits 755. Utilise les FQCN des modules Ansible "
Demande envoyé à ChatGPT : Tu es un expert Ansible. Réponds en JSON en utilisant les FQCN Ansible. Ne commente pas la réponse! JSON: : Ecris des taches Ansible pour installer les
packages net-tools, nginx avec le module package puis copier un fichier du controler sur la cible avec les droits 755. Utilise les FQCN des modules Ansible
ChatGPT réponds:
{
  "tasks": [
    {
      "name": "Install net-tools package",
      "package": {
        "name": "net-tools",
        "state": "present"
      }
    },
    {
      "name": "Install nginx package",
      "package": {
        "name": "nginx",
        "state": "present"
      }
    },
    {
      "name": "Copy file with 755 permissions",
      "copy": {
        "src": "/path/to/local/file",
        "dest": "/path/to/remote/file",
        "mode": "0755"
      }
    }
  ]
}
Tokens utilisés 228

Je l'ai relancé une dizaine de fois et à chaque fois, il a retourné le même résultat.

Conclusion

Vous remarquez que :

  • le code retourné n'est pas forcément le plus optimisé
  • qu'il est compliqué de lui demander de respecter les bonnes pratiques Ansible.

Dans tous mes tests, je pensais avoir résolu mon problème pour un cas d'usage, mais si je relance sur une question précédente. Bim ça ne fonctionne plus ?

Mais alors comment l'exploiter pour obtenir des réponses plus fiables ?

C'est à partir de ce constat que je me suis dit. Pourquoi lui demander plusieurs tâches ? Pourquoi pas lui fournir un template avec les options attendues ?

Ce sera la seconde partie de ce sujet. Je vais utiliser mon système de génération de snippets vscode pour ajouter à ma demande un template du module demandé.

La suite est publiée.