Retrouvez le code source final produit par cet article ici.
TL;DR
Cet article propose un guide complet pour créer un chatbot interactif en utilisant l'API d'OpenAI et Langchain, en expliquant les principes de base de ce framework pour structurer et enrichir les interactions conversationnelles. Il détaille également la configuration de l'environnement de développement, la gestion sécurisée des clés d'API, et l'utilisation de Langchain pour gérer des flux conversationnels avancés. Enfin, l'article aborde l'intégration du chatbot dans une interface graphique avec Streamlit, offrant une expérience utilisateur fluide et interactive.
Introduction
Le but de cet article est de vous accompagner pas à pas dans la création d’une application interagissant avec des modèles d’IA générative. Nous commencerons par la mise en place d’un environnement de développement Python, en respectant les bonnes pratiques. Ensuite, nous expliquerons les bases de l’interaction avec les modèles de IA générative ainsi que les principes fondamentaux du framework Langchain. Une fois ces fondations posées, nous implémenterons un chatbot simple en utilisant l’API d'OpenAI et le framework Langchain. Enfin, nous intégrerons ce chatbot dans une interface graphique avec Streamlit, pour offrir une expérience utilisateur fluide et interactive.
Prérequis
Pour suivre cet article, vous aurez besoin des éléments suivants :
- Quelques notions d'algorithmique et de programmation en Python.
- Python version 3.11.9.
- Un compte OpenAI pour utiliser leur API.
Nous utiliserons les modèles d'OpenAI pour ce tutoriel, mais vous pouvez éventuellement les remplacer par d'autres modèles similaires selon vos préférences.
Préparer l'environnement de travail
Si vous êtes déjà à l'aise avec Python vous pouvez ignorer cette section.
Créer le projet
Commencez par créer un répertoire pour notre projet :
$ mkdir my_awesome_ai_project
Puis, placez-vous dedans :
$ cd my_awesome_ai_project
Installer la version appropriée de Python avec Pyenv
Pyenv est un outil indispensable pour gérer plusieurs versions de Python sur votre machine. Il vous permet d’installer et de basculer entre différentes versions de Python de manière simple, ce qui est particulièrement utile lorsque vous travaillez sur plusieurs projets nécessitant des versions distinctes.
Pour installer Pyenv, suivez les instructions fournies sur le dépôt GitHub de Pyenv.
Après avoir installé Pyenv, utilisez-le pour installer la version de Python requise pour ce projet :
$ pyenv install 3.11.9
Ensuite, pour vous assurer que cette version est utilisée par défaut dans votre projet, créez un fichier .python-version
à la racine du répertoire du projet avec la version choisie :
3.11.9
Cela garantira que toutes les commandes Python exécutées dans ce répertoire utilisent la bonne version.
Pour vérifier que tout fonctionne correctement, exécutez la commande suivante dans le répertoire du projet :
$ python --version
Vous devriez alors voir la version correcte de Python s’afficher.
Un environnement virtuel
Pour bien débuter vôtre projet, il est essentiel de mettre en place un environnement virtuel Python. Mais qu’est-ce qu’un environnement virtuel Python exactement ? Il s’agit d’un espace isolé qui permet de gérer les dépendances propres à chaque projet, sans interférer avec celles des autres projets présents sur votre machine. Cela garantit un environnement de travail propre et sécurisé, où chaque projet utilise les versions de bibliothèques spécifiques dont il a besoin.
Pour créer un environnement virtuel dans notre projet, exécutez la commande suivante à la racine du projet :
python -m venv .venv
Cette commande crée un dossier .venv
à la racine du projet, qui représente l’environnement virtuel.
Pour activer notre environnement virtuel, il suffit de saisir la commande suivante :
source .venv/bin/activate
Sous Windows, utilisez cette commande :
.venv\Scripts\activate.bat
Pour désactiver l’environnement virtuel, il vous suffit de taper la commande suivante :
deactivate
Gestion des dépendances dans un projet Python
Dans la suite de cet article, vous aurez besoin d’ajouter des dépendances externes à votre projet, c’est-à-dire installer des packages dans votre environnement virtuel. Pour cela, vous utiliserez la commande suivante :
pip install <nom_du_package>
Par exemple, pour installer la bibliothèque requests, vous taperiez :
pip install requests
Une fois que vous aurez installé toutes vos dépendances, il est important de les documenter dans un fichier qui pourra être utilisé ultérieurement pour recréer l’environnement à l’identique. Pour cela, vous allez utiliser la commande :
pip freeze > requirements.txt
Cette commande va générer un fichier requirements.txt qui contiendra la liste complète des packages installés ainsi que leurs versions exactes. Ce fichier est essentiel pour partager votre projet avec d’autres développeurs ou pour déployer votre application, car il permettra à n’importe qui de recréer l’environnement en exécutant la commande suivante :
pip install -r requirements.txt
Cela garantira que toutes les personnes travaillant sur le projet utilisent les mêmes versions de packages, évitant ainsi des problèmes liés à la compatibilité ou aux différences de versions.
Le "Hello World!"
Maintenant que notre projet est correctement configuré, nous allons implémenter un petit programme de test, le fameux “Hello World”. Créez un fichier main.py
à la racine du projet avec le contenu suivant :
def main():
# La fonction main() représente le cœur de notre programme.
# C'est ici que nous définissons les actions principales à exécuter.
print("Hello World!")
# La condition suivante vérifie si ce script est exécuté directement.
# Si c'est le cas, elle appelle la fonction main(). Si le script est importé
# comme module dans un autre fichier, ce bloc ne sera pas exécuté à moins
# d'être explicitement appelé.
if __name__ == "__main__":
main()
Pour exécuter ce script, lancez la commande suivante :
python main.py
L’exécution du script devrait afficher la phrase : “Hello World!”.
Et voilà ! Nous sommes maintenant prêts à commencer. 😄
API OpenAI
Si vous prévoyez d’utiliser un autre modèle que ceux proposés par OpenAI, vous pouvez passer cette section.
Dans cette partie, nous allons voir comment obtenir une clé d’API OpenAI, qui nous permettra d’interagir avec les APIs d’OpenAI.
Commencez par créer un compte sur le site web d’OpenAI et connectez-vous à votre compte via ce lien : ici.
Une fois authentifié, accédez à la section Dashboard/API Keys et créez une nouvelle clé d’API. Copiez la clé générée, car nous en aurons besoin pour la suite.
Il est important de noter que l’utilisation de cette API est payante 💵. Cependant, dans le cadre de cet article, un montant minimal suffira pour couvrir les besoins essentiels et réaliser les tests proposés.
Variable d’environnement
La valeur de cette clé API est confidentielle et ne doit jamais apparaître directement dans votre code source. Pour respecter les bonnes pratiques, vous allez la stocker dans une variable d’environnement, ce qui permettra au script d’y accéder facilement et en toute sécurité.
Pour gérer les variables d’environnement, vous allez utiliser le package dotenv. Installez-le avec la commande suivante :
pip install python-dotenv
N’oubliez pas d’activer l’environnement virtuel Python avant de lancer la commande pip install
. Cela permettra d’installer le package dans l’environnement virtuel du projet.
Une fois le package installé, créez un fichier .env
à la racine du projet. Ce fichier contiendra la valeur de votre clé API :
OPENAI_API_KEY="<YOUR_API_KEY>"
Si vous utilisez un système de versionnement tel que Git, assurez-vous d’ajouter le fichier.env
dans votre.gitignore
pour éviter de le versionner.
Pour accéder à la variable d’environnement, dans le script, il suffit d’utiliser la fonction load_dotenv
au début. Ajoutons cette logique dans le fichier main.py
:
import os
from dotenv import load_dotenv
# Charger les variables d'environnement depuis le fichier .env
load_dotenv()
def main():
# Récupération de la clé API OpenAI depuis les variables d'environnement
openai_api_key: str = os.environ.get("OPENAI_API_KEY")
# Affichage de la clé API (pour tester)
print(openai_api_key)
if __name__ == "__main__":
main()
Le script devrait afficher la valeur de votre clé OpenAI.
Premier contact
Pour interagir avec l’API d’OpenAI, vous allez installer le package openai :
pip install openai
Nous allons utiliser ce package pour appeler l’API d’OpenAI et générer un haïku en utilisant le modèle gpt-4o-mini
. Modifions notre fichier main.py
comme suit :
import os
from dotenv import load_dotenv
from openai import OpenAI
load_dotenv()
def main():
openai_api_key = os.environ.get("OPENAI_API_KEY")
# Configuration du client OpenAI avec la clé API
client = OpenAI(api_key=openai_api_key)
# Création d'une requête pour générer un haïku à partir du modèle gpt-4o-mini
completion = client.chat.completions.create(
# Le modèle à utiliser pour générer la réponse, ici "gpt-4o-mini"
model="gpt-4o-mini",
# Les messages envoyés au modèle, sous forme de liste. Chaque message a un "role" (ici "user")
# et un "content", qui est le texte que nous envoyons au modèle.
messages=[
{"role": "user", "content": "write a haiku about ai"}
],
# Le paramètre temperature ajuste la créativité de la réponse. Une valeur proche de 0
# donne des réponses plus déterministes, tandis qu'une valeur plus élevée (jusqu'à 1)
# permet plus de diversité et d'improvisation dans la réponse.
temperature=0.7
)
# Affichage de la réponse générée par le modèle
print(completion.choices[0].message.content)
if __name__ == "__main__":
main()
En exécutant ce script, l’API OpenAI générera un haïku sur l’intelligence artificielle, que le programme affichera ensuite dans la console.
Nous venons de faire un appel à l’API d’OpenAI de manière simple pour générer un haïku. Cet exemple basique permet de se familiariser avec l’API et de comprendre comment interagir avec les modèle d'OpenAI. Dans la suite de cet article, nous explorerons des interactions plus avancées avec l’API en utilisant Langchain.
LangChain
Si la théorie vous donne mal à la tête 🤯, n’hésitez pas à sauter cette section et rendez-vous directement à la partie où nous implémentons notre chatbot !
Dans ce chapitre, nous allons explorer la bibliothèque Langchain et expliquer ses principes de base.
Pourquoi utiliser LangChain
Langchain est une bibliothèque puissante qui facilite l’intégration de modèles d’IA générative dans des chaînes de processus complexes. Cette bibliothèque est particulièrement utile lorsque vous devez gérer plusieurs étapes dans une interaction entre vos applications et les modèles d’IA.
En utilisant LangChain, vous pouvez non seulement optimiser la gestion de vos interactions avec les API d’IA, mais aussi créer des workflows plus modulaires, permettant d’ajouter de nouvelles fonctionnalités sans complexifier votre code. De plus, LangChain implémente de nombreux outils qui simplifient notre travail et nous évitent de réinventer la roue, nous permettant ainsi de nous concentrer sur l’ajout de valeur spécifique à nos applications.
Principe
LangChain repose sur un principe simple : elle permet de chaîner plusieurs étapes de traitement avec des modèles d’IA de manière fluide et organisée. Le but est de créer des chaînes (d’où le nom “LangChain”) qui lient des modèles d’IA, des flux de données et des fonctionnalités de manière modulaire.
Pour mieux comprendre le fonctionnement de LangChain, nous allons parcourir pas à pas ses concepts clés en les mettant en pratique avec des exemples de code en Python :
1. Les Loaders
Les Loaders sont utilisés pour importer et gérer des données à partir de différentes sources (fichiers, API, etc.). Cela permet d’intégrer rapidement des données externes dans vos workflows, optimisant ainsi l’enrichissement des réponses des modèles d’IA.
Exemple de code :
from langchain_community.document_loaders import TextLoader
# Charger un fichier texte
loader = TextLoader('my_file.txt')
# Charger les documents
documents = loader.load()
# Afficher le nombre de documents chargés
print(f"Nombre de documents chargés : {len(documents)}")
# Afficher le contenu du premier document
print(f"Contenu du document : {documents[0].page_content}")
Ici, nous utilisonsTextLoader
pour charger le contenu demy_file.txt
et l’importer en tant que documents exploitables par LangChain.
2. Les Prompts
Les Prompts sont les instructions que vous envoyez au modèle d’IA. Avec LangChain, vous pouvez personnaliser ces prompts pour correspondre précisément à ce que vous attendez du modèle.
Exemple de code :
from langchain.prompts import PromptTemplate
# Créer un template de prompt
template = "Traduisez le texte suivant en anglais : {text}"
prompt_template = PromptTemplate(
input_variables=["text"],
template=template,
)
# Générer le prompt avec une variable
my_prompt = prompt_template.format(text="Bonjour, comment allez-vous ?")
print(my_prompt)
Ici, nous créons un PromptTemplate
qui prend une variable texte et génère un prompt en insérant cette variable dans le template.
3. Les LLM (Large Language Models)
Les LLMs sont des modèles de langage de grande taille comme GPT d’OpenAI. LangChain intègre directement ces modèles, vous permettant de les appeler pour générer des réponses.
Exemple de code :
import os
from dotenv import load_dotenv
from langchain_openai.llms import OpenAI
load_dotenv()
llm = OpenAI(openai_api_key=os.environ['OPENAI_API_KEY'])
# Générer une réponse à partir d'un prompt
response = llm.invoke(my_prompt)
print(response)
Ici, nous initialisons un modèle LLM d’OpenAI en utilisant notre clé API, puis nous utilisons le prompt généré précédemment pour obtenir une réponse.
4. Les Chaînes
Les Chaînes vous permettent de lier plusieurs étapes dans un même flux de travail. Vous pouvez ainsi construire des workflows plus complexes en combinant prompts, modèles et autres fonctionnalités.
Exemple de code :
# Créer une chaîne qui combine le prompt et le modèle LLM
chain = prompt_template | llm
# Exécuter la chaîne avec une entrée
resultat = chain.invoke({"text": "Bonjour, comment allez-vous ?"})
print(resultat)
Ici, nous créons une chaine qui combine notre prompt et le modèle LLM, puis nous exécutons la chaîne avec une entrée spécifique pour obtenir le résultat.
5. La Mémoire
La Mémoire dans LangChain offre la possibilité de gérer le contexte dans une conversation, en gardant une trace des messages précédents. Cela permet de créer des chatbots ou assistants plus intelligents, capables de se souvenir des interactions passées pour offrir une expérience utilisateur plus cohérente.
Exemple de code :
from langchain_community.chat_message_histories import ChatMessageHistory
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage
# Créer une instance de ChatMessageHistory pour suivre l'historique des messages de la conversation
history = ChatMessageHistory()
# Ajouter un message système à l'historique, qui définit le comportement de l'assistant
history.add_message(SystemMessage(content="You are a helpful assistant. Answer all questions to the best of your ability."))
# Ajouter un message humain à l'historique, représentant l'entrée de l'utilisateur dans la conversation
history.add_message(HumanMessage(content="Hi!"))
# Ajouter un message de l'IA à l'historique, représentant la réponse de l'assistant
history.add_message(AIMessage(content="Hello! How can I help you?"))
# Afficher la liste des messages dans l'historique de la conversation
print(history.messages)
Ici, ChatMessageHistory
est utilisé pour stocker l’historique des échanges. Chaque message du système, de l’utilisateur ou de l’IA est ajouté à cet historique, permettant ainsi de préserver le contexte de la conversation pour les interactions futures.
En combinant ces éléments, LangChain vous permet de construire des workflows complexes et modulaires, intégrant des modèles d’IA de manière fluide. Que ce soit pour traiter des données, générer du texte, ou créer des assistants conversationnels intelligents, LangChain offre une structure flexible pour vos projets d’IA.
Création d’un Chatbot
Nous arrivons enfin à la partie tant attendue ! Ici, nous allons mettre en pratique ce que nous avons vu précédemment pour implémenter un simple chatbot en utilisant la bibliothèque LangChain et l’API d’OpenAI.
Note : Si vous souhaitez utiliser un autre modèle, vous pouvez consulter la documentation officielle de LangChain pour savoir comment le changer facilement.
Installation des dépendances
Commençant par installer les packages nécessaires en exécutant la commande suivante :
pip install langchain langchain_openai langchain-community
Modification du fichier main.py
Ensuite, modifions le fichier main.py
pour qu’il ressemble à ceci :
import os
from dotenv import load_dotenv
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.messages import SystemMessage
from langchain_community.chat_message_histories import ChatMessageHistory
from langchain_openai import ChatOpenAI
# Charge les variables d'environnement depuis un fichier .env
load_dotenv()
# Récupère la clé API OpenAI depuis les variables d'environnement
openai_api_key = os.getenv("OPENAI_API_KEY")
# Crée un modèle de prompt de conversation avec des messages
prompt = ChatPromptTemplate.from_messages(
[
# Message système pour définir le rôle de l'assistant
SystemMessage("You are a helpful assistant. Answer all questions to the best of your ability."),
# Placeholder pour les messages à remplir dynamiquement
MessagesPlaceholder(variable_name="messages"),
]
)
# Initialise le modèle GPT-4 avec la clé API et définit la température pour ajuster la créativité
llm = ChatOpenAI(api_key=openai_api_key, model="gpt-4o-mini", temperature=0.7)
# Crée une chaîne de traitement combinant le prompt et le modèle LLM
chain = prompt | llm
# Crée un historique des messages de chat pour suivre la conversation
chat_history = ChatMessageHistory()
# Fonction principale qui gère la conversation avec l'assistant
def main():
# Boucle infinie pour maintenir une conversation continue avec l'utilisateur
while True:
# Demande l'entrée de l'utilisateur
user_input = input("You: ")
# Ajoute le message de l'utilisateur à l'historique de la conversation
chat_history.add_user_message(user_input)
# Utilise le modèle pour générer une réponse en fonction de l'historique des messages
response = chain.invoke({"messages": chat_history.messages})
# Affiche la réponse de l'assistant
print("Assistant:", response.content)
# Ajoute la réponse de l'assistant à l'historique des messages
chat_history.add_ai_message(response.content)
# Point d'entrée du programme, appelle la fonction main
if __name__ == "__main__":
main()
En lançant notre script main.py
nous allons pouvoir interagir avec le chatbot.
Bonus 🎁: Interface graphique
Dans cette partie bonus, nous allons voir comment ajouter une interface graphique simple et élégante pour interagir avec le chatbot de manière plus conviviale.
Nous utiliserons la bibliothèque Streamlit pour créer rapidement une interface graphique fonctionnelle.
Mais avant cela, on va approter quelques modifications à notre code source pour mieux le structurer.
Refactorisation du code
Création du module chatbot_core
Nous allons structurer notre code en créant un nouveau fichier chatbot_core.py
qui contiendra le cœur du chatbot sous forme de module :
import os
from dotenv import load_dotenv
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.messages import SystemMessage
from langchain_community.chat_message_histories import ChatMessageHistory
from langchain_openai import ChatOpenAI
class ChatbotCore:
def __init__(
self,
openai_api_key=None,
system_prompt="You are a helpful assistant. Answer all questions to the best of your ability.",
model="gpt-4o-mini",
temperature=0.7,
):
if openai_api_key is None:
load_dotenv()
openai_api_key = os.getenv("OPENAI_API_KEY")
self.api_key = openai_api_key
self.prompt = ChatPromptTemplate.from_messages(
[ SystemMessage(system_prompt),
MessagesPlaceholder(variable_name="messages"),
]
)
# Configurer le modèle de langage
self.llm = ChatOpenAI(
api_key=self.api_key, model=model, temperature=temperature
)
self.chain = self.prompt | self.llm
# Initialiser l'historique de conversation
self.chat_history = ChatMessageHistory()
def send_message(self, message):
"""
Send a message to the chatbot and receive the response.
Args:
message (str): The message to send to the chatbot.
Returns:
str: The chatbot's response.
"""
self.chat_history.add_user_message(message)
response = self.chain.invoke({"messages": self.chat_history.messages})
self.chat_history.add_ai_message(response.content)
return response.content
def get_history(self):
"""
Access the conversation history.
Returns:
list: A list of conversation messages.
"""
return self.chat_history.messages
Nous avons encapsulé la logique du chatbot dans une classe ChatbotCore
qui expose des méthodes utiles pour interagir avec le chatbot.
Mise à jour du fichier main.py
Voici comment utiliser cette classe dans main.py
:
from chatbot_core import (ChatbotCore)
def main():
chatbot_core = ChatbotCore()
while True:
user_input = input("You: ")
response = chatbot_core.send_message(user_input)
print("Assistant:", response)
if __name__ == "__main__":
main()
Maintenant qu'on a un code source propre et modulaire. On va entamer la partie d'interface graphique.
Implementation de l'interface graphique
Installons Streamlit avec la commande suivante :
pip install streamlit
Ensuite, créez un fichier chatbot_interface.py
pour implémenter l’interface :
import streamlit as st
from chatbot_core import ChatbotCore
# Définition du titre de l'application dans l'interface Streamlit
st.title("💬 Chatbot")
# Ajout d'une légende sous le titre pour décrire l'application
st.caption("🚀 A Streamlit chatbot powered by OpenAI")
# Vérifie si un objet 'chatbot' existe dans l'état de session, sinon en crée un nouveau
if "chatbot" not in st.session_state:
# Création d'une instance de ChatbotCore dans l'état de session
st.session_state.chatbot = ChatbotCore()
# Affichage de l'historique des messages du chatbot (messages utilisateurs et assistants)
for msg in st.session_state.chatbot.get_history():
# Affiche un message selon s'il s'agit d'un utilisateur ou d'un assistant
st.chat_message("user" if msg.type == "human" else "assistant").write(msg.content)
# Vérifie si l'utilisateur a entré un message dans l'interface
if prompt := st.chat_input():
# Affiche le message de l'utilisateur dans l'interface
st.chat_message("user").write(prompt)
# Envoie le message à l'instance du chatbot et obtient la réponse
response = st.session_state.chatbot.send_message(prompt)
# Affiche la réponse du chatbot dans l'interface
st.chat_message("assistant").write(response)
Pour lancer l’interface graphique, exécutez cette commande :
streamlit run chatbot.py
Conclusion
Ce guide vous a permis de découvrir les bases des modèles d'IA générative et de créer un chatbot interactif. Pour aller plus loin, les Retrieval-augmented generation (RAG) et les Agents AI représentent une évolution prometteuse de ce que nous avons réalisé ici. Ces technologies peuvent enrichir les interactions et offrir des solutions encore plus sophistiquées. De plus, vous pouvez également explorer comment déployer votre application Streamlit pour la rendre accessible en ligne.
Nous espérons que cet article vous a inspiré pour continuer à explorer et développer des applications basées sur l'IA. Bonne continuation !