Dans la continuité du projet précédent, nous allons explorer l'abstraction des assistants d'OpenAI.
Les assistants sont l'équivalent "code" des GPTs sur l'interface graphique de ChatGPT.
Les assistants, basés sur les modèles OpenAI (comme GPT-3.5 Turbo ou GPT-4), sont des agents conversationnels préconfigurés. Ils peuvent être fournis par OpenAI, comme ChatGPT ou DALL·E, ou créés par n'importe quel utilisateur (comme un GPT sur l'interface publique).
Les threads représentent des conversations entre un assistant et un utilisateur. Ils servent d'historique et peuvent être repris ultérieurement.
Les messages regroupent à la fois ceux des utilisateurs (messages utilisateur) et ceux de l'assistant (messages assistant). Ils sont contenus dans le thread.
Les runs représentent les échanges entre l'assistant et l'utilisateur. Exemple d'un déroulement de run : L'utilisateur écrit un message -> le message est envoyé -> l'assistant traite le message et génère une réponse -> un événement de réponse est déclenché, contenant à la fois le message de l'utilisateur et la réponse de l'assistant.
C'est aussi durant le déroulement d'une run que le modèle peut décider d'effectuer un appel vers un outil.
Les tools (outils) sont des fonctions ou des capacités supplémentaires que l'assistant peut utiliser pour accomplir des tâches spécifiques. Par exemple, un assistant peut utiliser un outil pour chercher des informations en ligne, créer des images, manipuler des fichiers, ou même exécuter du code.
Il existe de nombreux avantages à utiliser les assistants plutôt que la version simplifiée, comme vu dans la partie 1 du tutoriel précédent. Nous pouvons préconfigurer un comportement, un ton, ou une fonctionnalité spécifique, et nous pouvons également conserver un historique des discussions passées.
Nous allons d'abord voir comment mettre en place un échange avec un assistant, dans un contexte non sécurisé.
1- prérequis et setup
Les prérequis sont les mêmes que dans le tutoriel précédent : https://robinmoretti.eu/comment-creer-un-chatbot-avec-lapi-openai-non-securise-pour-la-production-part-1/. Il est donc nécessaire d'avoir consulté ce tutoriel au préalable.
Nous allons reprendre les étapes :
- Étape 1 : Création d'un projet avec ViteJS
- Étape 2 : Installation de l'API OpenAI
- Étape 4 : Ajout d'une entrée utilisateur
Voici le code qui en résulte ainsi que l'architecture du projet :
2 - Configuration et implémentation d'un assistant
Comme vu précédemment, un assistant est une version préconfigurée du modèle. Il est, par définition, destiné à remplir une fonctionnalité précise. Nous allons donc en définir un.
Dans cet exemple, je vais orienter l'assistant vers une fonctionnalité qui me sera utile : un assistant d'écriture et un correcteur avec lequel je peux échanger.
Nous devons tout d'abord créer un assistant. Pour cela, nous avons deux possibilités :
Création dynamique via le code :
let assistant = client.beta.assistants.create({
name: "écrivaint assistant",
instructions: "Tu es un écrivain et correcteur assistant. Corrige et propose des améliorations au texte proposé.",
model: "gpt-3.5-turbo",
})
À chaque exécution de ce code, un nouvel assistant sera créé et enregistré dans la base de données d'OpenAI. Vous pouvez retrouver les assistants créés dans l'interface dédiée à l'API ici : https://platform.openai.com/assistants.
- Vous pouvez également pré-créer un assistant via l'interface dédiée à l'API en suivant ce lien : https://platform.openai.com/assistants.
- Ensuite, vous pourrez retrouver cet assistant directement via le code.
- Dans notre code, au lieu d'utiliser la fonction de création d'un nouvel assistant, nous allons utiliser celle qui permet de retrouver un assistant déjà existant via son ID, que vous pouvez obtenir dans l'interface dédiée.
let assistant = await getAssistantById("asst_Igbsx74rrKaqOaaesliqZ3YU");
async function getAssistantById(assistantId) {
const myAssistant = await openIA.beta.assistants.retrieve(assistantId);
console.log("myAssistant =", myAssistant);
return myAssistant;
}
Le log dans la console du navigateur devrait vous afficher quelque chose de similaire à ceci :
async
et await
sont très importants ici. Ils nous permettent de mettre en attente certaines parties du code sans pour autant bloquer le fonctionnement global de notre site. Je vous recommande vivement d'approfondir cette notion si vous ne la maîtrisez pas encore. Vous pouvez consulter ce tutoriel utile pour en apprendre davantage : Async/Await sur javascript.info.Les mots-clés `async` et `await` sont très importants ici. Ils nous permettent de mettre en attente certaines parties du code sans pour autant bloquer le fonctionnement global de notre site. Je vous recommande vivement d'approfondir cette notion si vous ne la maîtrisez pas encore. Vous pouvez consulter ce tutoriel utile pour en apprendre davantage : [Async/Await sur javascript.info](https://fr.javascript.info/async-await).Une fois que l'assistant est créé et disponible nous allons devoir :
- créer un thread
- ajout d'un message au thread
- envoie du message et afficher la réponse de l'assistant à la fin de l'excécution d'un run
1. Création du Thread
let thread = await openia.beta.threads.create();
Jusqu'ici, rien de compliqué.
2. Ajout d'un message au thread
Nous allons ajouter un message utilisateur dans le thread. Plus tard, nous ferons en sorte que ce texte provienne d'un champ de saisie utilisateur (input). Pour le moment, testons en statique pour vérifier que cela fonctionne correctement.
let newMessage = await openai.beta.threads.messages.create(
thread.id,
{
role: "user",
content: "Je suis dislexique et dis aurtographik. I'm begging yoou, aide moi."
}
);
3. Exécution du run
Cette fois-ci, nous avons deux choix : avec streaming ou sans. Le streaming correspond à l'affichage progressif des lettres de la réponse de l'assistant.
sendMessage();
async function sendMessage() {
await openia.beta.threads.messages.create(
thread.id,
{
role: "user",
content: "Je suis dislexique et dis aurtographik. I'm beggin yoou, aide moi."
}
);
const run = openia.beta.threads.runs.stream(thread.id, {
assistant_id: assistant.id
})
.on('textCreated', () => {
// Événement déclenché lorsque les premiers tokens de réponse sont reçus.
// Nous pouvons donc créer un élément HTML qui contiendra la réponse ici.
let responseElement = document.createElement("div");
responseElement.classList.add("response");
responseElement.innerHTML = "Assistant : <br/>"
// Ajoutons cet élément au DOM.
document.getElementById("messages-container").appendChild(responseElement);
})
.on('textDelta', (textDelta) => {
// Événement déclenché lorsque les tokens suivants de la réponse sont reçus.
// Retrouvons l'élément précédemment ajouté au DOM.
let responseElement = document.querySelector("#messages-container .response:last-child");
// Ajoutons à la suite les tokens suivants reçus.
responseElement.innerHTML += textDelta.value;
});
}
Normalement, vous devriez voir la réponse de l'assistant apparaître dans votre navigateur.
Maintenant que la configuration est faite nous allons pouvoir connecter à l'interface ce code précédemment réalisé.
3. Connexion avec l'interface
De la même manière que dans le tutoriel précédent, nous allons ajouter un événement au clic du bouton, récupérer le texte contenu dans l'input, et l'envoyer comme message à l'assistant. Ce texte sera passé en paramètre à la fonction sendMessage
.
document.getElementById("send-message-button").addEventListener("click", () => {
let inputText = document.getElementById("text-input-to-gpt").value; // récupère l'input textuel contenu dans le html
document.getElementById("text-input-to-gpt").value = ""; // vide l'input
sendMessage(inputText); // envoie la demande à chatgpt dans la fonction précédemment faite
})
Nous devons ensuite modifier légèrement la fonction sendMessage
pour ajouter un paramètre, et remplacer le texte "Je suis dislexique et dis aurtographik. I'm beggin yoou, aide moi." par le paramètre créé.
async function sendMessage(textMessage) {
await openia.beta.threads.messages.create(
thread.id,
{
role: "user",
content: textMessage
}
);
Nous devons également supprimer la ligne sendMessage();
afin qu'elle ne s'exécute pas automatiquement au chargement de la page.
Enfin, j'ajoute une ligne de CSS pour rendre les messages plus lisibles.
#messages-container > div{
margin-bottom: 1rem;
}
Voilà, c'est terminé. Si tout c'est bien passé, vous savez utiliser un assistant avec l'api d'OpenIA.
Vous pouvez retrouver le code complet et fonctionnel ici.
Dans la prochaine partie, nous allons expérimenter en créant une conversation autonome entre deux assistants.
La bise, Tchouss !
o(@)o