Aller au contenu principal

Exercice : construire un chatbot

Mis à jour le 30 juillet 2026

Premier exercice du cours, et le plus formateur : mettez en pratique ce que vous avez appris en construisant un chatbot interactif en ligne de commande. Tout y est déjà — les requêtes, l’historique, les fonctions utilitaires — il ne reste qu’à les assembler en programme complet. C’est précisément cet assemblage qui transforme des notions comprises en réflexes acquis.

Objectif

Créer un programme Python qui :

  1. Accepte les messages de l’utilisateur en boucle
  2. Maintient l’historique de la conversation
  3. Envoie l’historique complet à chaque requête
  4. Affiche les réponses de Claude
  5. Permet de quitter avec “quit” ou “exit”

Le point 3 est le cœur de l’exercice : c’est lui qui vérifie que vous avez intégré la leçon des conversations multi-tours — sans l’historique complet, votre chatbot répondra à chaque message comme s’il était le premier.

Consignes

  • Réutilisez les fonctions add_user_message, add_assistant_message et chat de la leçon précédente
  • Le chatbot doit tourner en continu jusqu’à ce que l’utilisateur décide de quitter
  • Affichez un message d’accueil au démarrage
  • Gérez proprement la sortie

Bonus

Ajoutez un prompt système pour donner une personnalité au chatbot (nous verrons les prompts système en détail dans la prochaine leçon, mais vous pouvez déjà expérimenter avec le paramètre system de messages.create()).


Solution

Essayez d’abord par vous-même avant de regarder la solution — l’exercice ne vaut que par la friction de l’essai. Bloqué plus de vingt minutes ? Regardez la structure de main(), puis refermez et terminez seul.

Voir la solution
from dotenv import load_dotenv
import anthropic

load_dotenv()
client = anthropic.Anthropic()

def add_user_message(conversation, text):
    conversation.append({"role": "user", "content": text})

def add_assistant_message(conversation, text):
    conversation.append({"role": "assistant", "content": text})

def chat(conversation, user_message, system_prompt=None, model="claude-sonnet-5", max_tokens=1024):
    add_user_message(conversation, user_message)

    kwargs = {
        "model": model,
        "max_tokens": max_tokens,
        "messages": conversation
    }

    if system_prompt:
        kwargs["system"] = system_prompt

    response = client.messages.create(**kwargs)

    assistant_text = response.content[0].text
    add_assistant_message(conversation, assistant_text)

    return assistant_text

def main():
    print("=== Chatbot Claude ===")
    print("Tapez 'quit' ou 'exit' pour quitter.\n")

    conversation = []

    # Bonus : prompt système pour donner une personnalité
    system_prompt = (
        "Tu es un assistant sympathique et concis. "
        "Tu réponds en français. "
        "Tu utilisés des exemples concrets quand c'est utile."
    )

    while True:
        user_input = input("Vous : ").strip()

        if not user_input:
            continue

        if user_input.lower() in ("quit", "exit"):
            print("Au revoir !")
            break

        try:
            response = chat(conversation, user_input, system_prompt=system_prompt)
            print(f"\nClaude : {response}\n")
        except Exception as e:
            print(f"\nErreur : {e}\n")

if __name__ == "__main__":
    main()

Trois détails de la solution méritent votre attention. La fonction chat archive la réponse de Claude (add_assistant_message) avant de la retourner — c’est l’étape que les premières versions oublient, et le fil de la conversation se rompt silencieusement. La construction conditionnelle de kwargs n’ajoute system que s’il existe : le pattern des paramètres optionnels que vous reverrez tout au long du cours. Et le try/except autour de l’appel réseau garde le chatbot vivant en cas d’erreur API — une requête ratée s’affiche, elle ne tue pas la session.

Pour aller plus loin

  • Ajoutez un compteur de tokens pour suivre la consommation
  • Sauvegardez l’historique dans un fichier JSON pour reprendre une conversation
  • Ajoutez une commande /reset pour effacer l’historique

Ces trois extensions ne sont pas décoratives : le compteur (via response.usage) vous fera voir le coût croissant des conversations longues, la sauvegarde vous fera manipuler la sérialisation de l’historique, et /reset préfigure la gestion de contexte des applications réelles.

Points clés à retenir

  • L’exercice assemble tout l’acquis : boucle, historique complet, utilitaires réutilisés
  • Le piège classique : oublier d’archiver les réponses de Claude — le contexte se perd sans erreur visible
  • kwargs conditionnel pour les paramètres optionnels : un pattern qui resservira partout
  • Encapsulez l’appel API dans un try/except : une erreur réseau ne doit pas tuer la session
  • Prolongez avec tokens, sauvegarde et /reset — trois pas vers une application réelle