Un chatbot simple, par correspondance de mots-clés, 100% côté client — sans API ni coût. Essayez "salut", "apps", "labo" ou "aide".
Cette page est un chatbot minimal qui tourne entièrement dans le navigateur. Aucun appel réseau, aucune clé d'API, aucun coût par requête: le fichier JavaScript fait deux kilooctets et contient à la fois la logique et la totalité des réponses.
On écrit un message, il apparaît à droite, et la réponse arrive à gauche après un court délai. Les sujets qu'il connaît sont au nombre de six: les salutations, mes applications, le contenu du Labo, une demande d'aide, un remerciement, et une question sur son identité. Tout le reste tombe sur une réponse de repli.
Le cœur tient dans un tableau nommé RULES. Chaque entrée est un objet avec deux champs:
keywords, une liste de chaînes à repérer, et reply, la réponse à servir.
Six règles couvrent tout le vocabulaire de la démo.
La fonction reply() met le message en minuscules, puis parcourt les règles dans l'ordre du
tableau. Pour chacune, elle teste chaque mot-clé avec indexOf(). Le premier mot-clé trouvé
n'importe où dans la chaîne gagne, et la fonction retourne immédiatement. S'il n'y a aucune
correspondance, elle retourne FALLBACK, qui ramène l'utilisateur vers les sujets connus.
Ce choix a deux conséquences, et elles comptent. Premièrement, indexOf() cherche une
sous-chaîne, pas un mot: la règle bâtie sur « app » se déclenche aussi sur « rapport » ou
« apparence ». Deuxièmement, l'ordre du tableau est une priorité implicite. Un message qui contient
à la fois « bonjour » et « labo » reçoit toujours la salutation, parce qu'elle est déclarée en premier.
L'affichage passe par addMessage(), qui crée un élément, lui donne la classe du locuteur,
puis écrit le texte avec textContent plutôt qu'avec innerHTML. C'est
délibéré: si quelqu'un tape des balises, elles s'affichent comme du texte au lieu d'être interprétées.
Ensuite je force le défilement de la boîte de messages jusqu'en bas pour que la dernière bulle reste
visible. Le délai de 350 millisecondes avant la réponse est un simple setTimeout: il ne
sert à rien techniquement, la réponse est prête tout de suite, mais sans lui l'échange paraît cassé
plutôt que rapide.
Il faut être honnête sur ce que ça vaut. Une table de mots-clés n'est pas un modèle de langue et n'en approche pas. Elle ne comprend rien: ni les fautes de frappe, ni les accents manquants, ni la négation — « je ne veux pas d'aide » déclenche exactement la même réponse que « aide ». Elle n'a aucune mémoire du tour précédent, donc pas de conversation au sens propre. Et chaque nouveau sujet demande une ligne de code de plus, alors que la couverture réelle, elle, progresse beaucoup plus lentement.
Ce que ça m'a appris est ailleurs. L'exercice met à plat la boucle que n'importe quel système conversationnel doit fermer: recevoir une entrée, la normaliser, choisir une réponse, l'afficher, garder l'interface lisible pendant que l'historique s'allonge. Ces morceaux-là ne changent pas si on remplace le tableau par un appel à un modèle; seule la fonction qui choisit la réponse change.
Je retrouve la même division dans mon travail en intégration vidéo. Sur un décodeur, la logique métier bouge sans arrêt d'une version à l'autre, mais la plomberie autour — recevoir l'événement, valider, rendre à l'écran — reste la même. C'est elle qu'il vaut la peine de construire proprement en premier.