Préparer le projet 01
On crée un nouveau projet Python avec son venv. Si tu ne te souviens plus comment, relis le tuto sur les environnements virtuels.
mkdir chatbot-ollama
cd chatbot-ollama
# Créer et activer le venv
python -m venv venv # Windows
python3 -m venv venv # macOS / Linux
venv\Scripts\activate # Windows
source venv/bin/activate # macOS / Linux
# Installer la bibliothèque officielle Ollama pour Python
pip install ollama
La bibliothèque ollama est l'interface Python officielle pour parler à Ollama. Elle simplifie les appels API qu'on a vus dans le tuto précédent.
Premier appel au modèle 02
Crée un fichier chatbot.py. On commence simple — un seul message, une seule réponse :
import ollama # on importe la bibliothèque qu'on vient d'installer
# La fonction chat() prend un modèle et une liste de messages.
# Chaque message est un dictionnaire avec deux clés :
# "role" : "user" (l'utilisateur) ou "assistant" (le modèle)
# "content" : le texte du message
reponse = ollama.chat(
model="gemma4:e2b",
messages=[
{"role": "user", "content": "Bonjour ! Qui es-tu ?"}
]
)
# La réponse est un objet. Le texte généré est dans :
# reponse.message.content
print(reponse.message.content)
python chatbot.py
Le modèle répond. Mais là, c'est un programme qui envoie un message fixe et s'arrête. On veut une vraie conversation.
L'historique de conversation 03
Pour qu'un LLM se souvienne de ce qu'on a dit précédemment, il faut lui envoyer tout l'historique de la conversation à chaque requête. Les LLM n'ont pas de mémoire intrinsèque — ils ne voient que les messages qu'on leur passe.
Concrètement, on maintient une liste historique et on y ajoute chaque message (utilisateur et assistant) au fur et à mesure :
import ollama
# L'historique démarre vide. On peut aussi y mettre un "system prompt"
# pour donner des instructions globales au modèle.
historique = [
{
"role": "system",
"content": (
"Tu es un assistant en français, sympathique et concis. "
"Tu réponds toujours en français, même si on te parle dans une autre langue."
)
}
]
print("=== Chatbot Ollama (gemma4:e2b) ===")
print("Tape 'quitter' pour terminer.\n")
while True: # une boucle infinie — on continue jusqu'à ce que l'utilisateur quitte
# 1. Demander un message à l'utilisateur
message_utilisateur = input("Toi : ").strip()
# 2. Permettre de quitter proprement
if message_utilisateur.lower() in ["quitter", "exit", "bye", "q"]:
print("Au revoir !")
break # sort de la boucle while
# 3. Ne rien faire si l'utilisateur n'a rien tapé
if not message_utilisateur:
continue # passe à l'itération suivante de la boucle
# 4. Ajouter le message de l'utilisateur à l'historique
historique.append({
"role": "user",
"content": message_utilisateur
})
# 5. Envoyer TOUT l'historique au modèle
reponse = ollama.chat(
model="gemma4:e2b",
messages=historique
)
# 6. Extraire le texte de la réponse
texte_reponse = reponse.message.content
# 7. Ajouter la réponse de l'assistant à l'historique
historique.append({
"role": "assistant",
"content": texte_reponse
})
# 8. Afficher la réponse
print(f"\nAssistant : {texte_reponse}\n")
Le while True: crée une boucle infinie — le programme continue indéfiniment jusqu'à ce qu'on rencontre un break. C'est le pattern classique pour une interface en ligne de commande interactive.
Lance le programme et teste une vraie conversation en plusieurs échanges. Remarque que le modèle se souvient de ce que tu as dit au début — c'est grâce à l'historique qu'on lui passe.
Afficher la réponse en temps réel (streaming) 04
Pour l'instant, le programme attend que le modèle ait tout généré avant d'afficher quoi que ce soit. C'est frustrant pour les longues réponses. On peut activer le streaming pour afficher le texte mot par mot, comme ChatGPT :
import ollama
import sys # pour flush le buffer d'affichage
historique = [
{
"role": "system",
"content": (
"Tu es un assistant en français, sympathique et concis. "
"Tu réponds toujours en français."
)
}
]
print("=== Chatbot Ollama (gemma4:e2b) ===")
print("Tape 'quitter' pour terminer.\n")
while True:
message_utilisateur = input("Toi : ").strip()
if message_utilisateur.lower() in ["quitter", "exit", "bye", "q"]:
print("Au revoir !")
break
if not message_utilisateur:
continue
historique.append({"role": "user", "content": message_utilisateur})
print("Assistant : ", end="", flush=True) # afficher sans saut de ligne
texte_complet = "" # on accumule le texte pour l'historique
# stream=True active le streaming
for chunk in ollama.chat(model="gemma4:e2b", messages=historique, stream=True):
morceau = chunk.message.content
print(morceau, end="", flush=True) # afficher sans saut de ligne
texte_complet += morceau # accumuler
print("\n") # saut de ligne à la fin de la réponse
historique.append({"role": "assistant", "content": texte_complet})
end="" dans print() empêche le saut de ligne automatique. flush=True force Python à afficher immédiatement sans attendre de remplir son buffer interne. Ces deux options ensemble permettent l'affichage progressif.
Gérer les erreurs proprement 05
Que se passe-t-il si Ollama n'est pas lancé, ou si le modèle n'existe pas ? Le programme plante avec une erreur cryptique. On peut gérer ça proprement avec try/except :
# Remplace le bloc "for chunk in ollama.chat..." par ceci :
try:
print("Assistant : ", end="", flush=True)
texte_complet = ""
for chunk in ollama.chat(model="gemma4:e2b", messages=historique, stream=True):
morceau = chunk.message.content
print(morceau, end="", flush=True)
texte_complet += morceau
print("\n")
historique.append({"role": "assistant", "content": texte_complet})
except Exception as erreur:
# Si quelque chose se passe mal, on affiche un message clair
print(f"\n[Erreur] Impossible de contacter Ollama : {erreur}")
print("Vérifie qu'Ollama est bien lancé sur ta machine.\n")
# On retire le dernier message utilisateur de l'historique
# car la réponse n'a pas été générée
historique.pop()
Ton chatbot est maintenant robuste et agréable à utiliser. Dans le tuto suivant, on va plus loin : on crée un agent capable d'appeler de vraies fonctions Python pour récupérer des données réelles.