- Introduction
- Mais c’est un peu trop gros pour juste des petits usages non ?
- C’est cool ça, mais c’est déjà utilisable en production ?
- Et on fait comment pour l’utiliser ?
- Conclusion
Introduction Link to heading
Avant de parler de Prompty, il faut que je te parle un peu de Promptflow. C’est une suite d’outil de développement pour interagir avec des LLMs facilement pour créer des applis AI. Le principe de fonctionnement utilise des flows, comme le nom l’indique. On détermine une suite d’action à faire lors d’une requête via un fichier YAML sous forme de DAG combiné avec du code Python et des fichiers Markdown propulsé par Jinja. Il est également possible depuis peu de faire des flows uniquement avec du code Python via des classes ou des fonctions, des flex flow, mais ce n’est pas le sujet d’aujourd’hui.
Même si c’est un projet développé par Microsoft et disponible sur leur plateforme AI, il est relativement facile de se détacher d’Azure et de le faire tourner où on veut via un container docker ou un exécutable.
Mais c’est un peu trop gros pour juste des petits usages non ? Link to heading
Oui, c’est vrai, si on veut simplement faire un appel à OpenAI en utilisant un template simple. Et c’est là que Prompty intervient ! Tout se fait dans un fichier qui combine du Markdown et un frontmatter en YAML. On garde la puissance du moteur de template Jinja avec la simplicité de définir sa connexion et ses variables.
Ensuite, on peut utiliser ce fichier avec le CLI de Promptflow ou bien un petit bout de code Python qui est intégrable où on veut.
C’est cool ça, mais c’est déjà utilisable en production ? Link to heading
Alors, c’est encore en preview, je ferais attention avant de l’envisager en production. La fonctionnalité est sortie fin avril, rien ne nous garantit qu’il n’y aura pas de grosses modifications dans le futur. Cependant, Prompty ne fait rien de magique en soi, il permet simplement de gagner du temps de développement pour interagir avec des LLMs. Si le projet est abandonné, ou quoi que ce soit, il sera toujours temps de remplacer le Prompty par du code Python entièrement, même si cela prendra un peu de temps à mettre en place.
Et on fait comment pour l’utiliser ? Link to heading
Puisque tu sembles impatient, on va commencer à rentrer dans le vif du sujet ! Je vais t’expliquer comment créer ton premier Prompty depuis 0 et on va voir pour augmenter la complexité (et donc le fun) au fur et à mesure. Tu es prêt ?
Prérequis Link to heading
Pour commencer, il te faut un accès à Python. Le site de Promptflow recommandait la version 3.9 jusqu’à il y a quelques semaines, mais tu peux choisir n’importe quelle version supérieure à 3.8. Si tu veux suivre de bonnes pratiques et éviter de potentielles onflits avec d’autres packages, tu peux créer un environnement virtuel avec venv ou conda
python -m venv prompty
# Linux/MacOS
source prompty/bin/activate
# Windows
prompty\Scripts\activate
Ensuite, il faut installer promptflow pour avoir accès au CLI.
pip install promptflow
Testons si le CLI est bien installé et est accessible.
pf --version
Si tout est bon, tu devrais voir la version des différents packages de promptflow s’afficher.
Création de son premier Prompty Link to heading
Maintenant, il est temps de créer son premier fichier .prompty
. Il s’agit d’un type de fichier reconnu par Promptflow qui combine du Markdown avec un front-matter et le format Jinja.
Créer un fichier hello-world.prompty
avec le contenu suivant :
---
name: "Hello World"
description: "Un simple hello world propulsé par GPT"
model:
api: chat
configuration:
type: openai
model: gpt-3.5-turbo
api_key: ${env:OPENAI_API_KEY}
parameters:
max_tokens: 128
temperature: 1.4
inputs:
first_name:
type: string
last_name:
type: string
tone:
type: string
sample:
first_name: John
last_name: Doe
tone: cérémonieux
---
system:
Tu es un assistant qui salue les gens. Tu vas ajouter une touche d'originalité pour chaque personne. Tu dois avoir un ton "{{tone}}".
Ton seul rôle est de saluer les gens. Tu ne dois pas répondre à des questions ou faire des commentaires sur autre chose.
La personne s'appelle "{{first_name}} {{last_name}}".
On va décortiquer un peu le contenu du fichier pour mieux comprendre ce qu’on fait.
Tout d’abord, nous avons le front matter qui respecte la syntaxe YAML. Il est défini entre les deux ---
. Il contient des informations nécéssaires et par défaut pour faire tourner notre Prompty. Voici les différentes informations que l’on peut y mettre :
name
: Le nom de notre Promptydescription
: Une description pour savoir ce que fait notre Promptymodel
: Les informations pour de connection à l’API d’openAI ou Azure OpenAI et les paramètres du modèle.api
: Le type d’API à utiliser (pour le momentchat
)configuration
: Les informations pour se connecter à l’API d’OpenAItype
: Pour le moment, seulopenai
etazure-openai
sont supportés.model
: Le nom du modèle (openai uniquement)api_key
: La clé d’API pour se connecterbase_url
: Optionnel, l’URL de base pour se connecter à l’API (openai uniquement).azure_deployment
: Le nom du déploiement sur Azure OpenAI (azure-openai uniquement)api_version
: La version de l’API à utiliser (azure-openai uniquement)azure_endpoint
: L’URL de l’API (azure-openai uniquement)
parameters
: Les paramètres pour le modèle. Ici, les 2 plus souvent utilisés,max_tokens
ettemperature
.max_tokens
: Le nombre de tokens à générer au maximum pour la réponsetemperature
: La température pour générer la réponse. Plus la température est élevée, plus la réponse sera “créative/folle”. Plus elle s’approche de 0, plus elle sera reproductible.
inputs
: Les différentes variables que l’on peut passer à notre modèle. Ici, on a 3 variables,first_name
,last_name
ettone
.type
: Le type de la variable.
outputs
: Optionnel, les champs de sorties du JSON si on utilise leresponse_format
:json_object
. Il fonctionne comme le champinputs
.sample
: Un exemple de données qui seront utilisées par défaut.
Ensuite, nous pouvons écrire notre prompt en Markdown. Le prompt est assez court et se compose que d’un bloc system
. Il va décrire le comportement du modèle et lui apporter les informations nécessaires pour répondre à la demande. Ici, on demande simplement au modèle de saluer quelqu’un en étant original.
Il y a 3 blocs principaux disponibles : system
, user
et assistant
. Le bloc tool
n’est pas supporté pour le moment. Fais attention à bien avoir un passage à la ligne après le :
pour que le bloc soit reconnu.
Si tu regardes bien le contenu du markdown, tu peux voir des expressions Jinja. C’est ce qui va permettre d’utiliser les inputs que nous avons définis dans le frontmatter de notre Prompty. Pour uniquement utiliser une variable, il suffit de la mettre entre {{
et }}
. Le reste de la syntaxe Jinja est disponible ici : https://jinja.palletsprojects.com/en/3.1.x/templates/
Connexion avec OpenAi Link to heading
Maintenant que nous avons un prompty il manque les informations de connexion pour l’API d’OpenAI. Tu peux obtenir une clé en cliquant ici. Tu peux également utiliser une ressource Azure Open AI, mais je ne décrirai pas la procédure ici.
Une fois que tu as ta clé d’API, tu peux ajouter la variable d’environnement OPENAI_API_KEY
avec la valeur de ta clé.
# Powershell
$env:OPENAI_API_KEY = "ta_clé"
# Bash
export OPENAI_API_KEY="ta_clé"
(Alternative) Connexion avec une API compatible OpenAI Link to heading
Si tu ne souhaites pas utiliser OpenAI, ni Azure OpenAI. Tu peux simplement utiliser un autre fournisseur compatible avec l’API d’OpenAI ou utiliser un modèle Open Source sur ta machine grâce à ollama ou LM Studio par exemple.
La seule chose à ajouter dans ton frontmatter est base_url
dans model.configuration
. Voici un example pour Ollama:
# ... Ta configuration
model:
api: chat
configuration:
type: openai
model: phi-3 # Non utilisé
api_key: "Non utilisé"
base_url: "http://localhost:11434/"
# ...
Tu peux remplacer http://localhost:11434/
par ${env:OPENAI_BASE_URL}
pour utiliser une variable d’environnement si tu préfères. Cela te permet de facilement changer l’URL sans avoir à modifier le fichier. Et même d’utiliser OpenAI par la suite avec https://api.openai.com/v1
comme valeur (Attention à ton nom de modèle).
Tester son Prompty Link to heading
Maintenant que tout est en place, il est temps d’obtenir notre premier résultat avec la commande suivante :
pf flow test --flow hello-world.prompty
Si tu cliques sur le lien de la réponse avant la réponse, tu peux voir les étapes qu’il y a eues avant d’arriver à la réponse et obtenir plus de détail. Ce n’est pas vraiment utile pour un Prompty, mais pour un Promptflow plus complexe, cela peut être très utile.
Modifier les inputs Link to heading
Maintenant que le premier test est passé, on peut s’amuser avec les variables d’entrée via le flag --inputs
Par Exemple:
pf flow test --flow hello-world.prompty --inputs first_name=Victor last_name=Santelé tone=amusé
(Promis, j’ai pas triché sur le résultat)
Utilisation en Chat Link to heading
Maintenant qu’on a un peu jouer avec des entrées simples, on va pousser un peu plus loin la logique pour permettre d’intéragir avec notre Prompty comme un chat. En gardant l’historique de la conversation en gros.
Il ne faut pas oublier que l’API d’OpenAI (et la majorité des LLMs) fonctionne en “stateless”, c’est-à-dire qu’il ne garde pas en mémoire les précédentes réponses. Pour chaque interaction, il faut envoyer l’ensemble de la conversation dans le contexte pour qu’il puisse répondre correctement.
Pour cela, on va créer un nouveau fichier chat.prompty
avec le contenu suivant :
---
name: "Auteur de mail"
description: "Chatbot pour aider à la rédaction d'un mail."
model:
api: chat
configuration:
type: openai
model: gpt-3.5-turbo
api_key: ${env:OPENAI_API_KEY}
parameters:
max_tokens: 256
temperature: 1.4
inputs:
question:
type: string
is_chat_input: true
chat_history:
is_chat_history: true
type: list
default: []
sample:
question:
chat_history: []
---
system:
Tu es un assistant bienveillant. Tu vas aider l'utilisateur a écrire un mail. Tu as besoin d'un minimum d'information pour commencer: le nom du destinataire, le sujet, un résumé du contenu et le ton du message. Tu peux demander ces informations à l'utilisateur en posant des questions. Tu peux aussi donner des conseils pour écrire un mail efficace. Quand tu as toutes les informations, rédiges le mail en respectant les demandes de l'utilisateur.
{% for message in chat_history %}
{{ message.author }}:
{{ message.content }}
{% endfor %}
user:
{{ question }}
Tu peux ensuite tester le chat avec la commande :
pf flow test --flow chat.prompty --interactive
--ui
Qu’est-ce qui a changé par rapport à notre hello world ? Déjà, dans les paramtres, on a modifié les inputs pour avoir la question de l’utilisateur et l’historique de la conversation.
On a également précisé que question
est une entrée de chat avec is_chat_input: true
et que chat_history
est un… historique de chat grâce à is_chat_history: true
. Cela permet à promptflow de comprendre quels champs correspond à un message dans le chat et où stocker l’historique.
Mais, je ne venais pas de dire que les requêtes sont stateless?
Et oui, c’est bien le cas! La mention is_chat_history:true
n’est utile que lors des tests interactifs. C’est une aide pour le développeur simplement. En production, il faudra gérer nous-mêmes l’historique de la conversation sous la forme suivante :
[
{ "author": "user", "content": "Bonjour" },
{ "author": "assistant", "content": "Bonjour, comment puis-je vous aider ?" }
]
Voici ce que ça peut donner :
Si tu es habitué à Azure Ai, tu ne seras pas perdu dans l’interface. Comme on peut le voir dans la capture d’écran, il a continué de me poser des questions pour obtenir les informations requises pour m’aider à rédiger mon e-mail. Grâce à l’historique, il a pu garder dans son contexte les informations que je lui ai données.
Intégration dans un script Python Link to heading
Maintenant que tu as les bases pour créer un Prompty, tu peux l’intégrer dans n’importe quel script Python.
Pour cela, il faut charger le fichier .prompty
depuis la classe Prompty
de promptflow.core
et l"utiliser avec les bons inputs
.
Commence par créer un fichier python run.py
:
from promptflow.core import Prompty
prompty = Prompty("hello-world.prompty")
response = prompty(first_name="John", last_name="Doe", tone="drôle")
Maintenant tu as les bases pour faire les Prompty que tu souhaites!
Conclusion Link to heading
On a pu découvrir pas mal de fonctionnalités de Prompty et Promptflow. J’ai essayé de rester simple sans oublier de détail pour que ça puisse être accessible à un maximum de monde.
J’espère que je t’ai donné l’envie de tester Prompty et de découvrir le reste des fonctionnalités de Promptflow. Je vais publier un autre article bientôt pour présenter des fonctionnalités un peu plus avancées et on va finir par maîtriser toutes les possibilités de Promptflow ensemble!
On se revoit vite ! 😎