Introduction
Dans le précédent article, nous avons construit notre premier chatbot en utilisant LangGraph. Le graphe était volontairement simple :
DÉBUT → Chatbot → FIN
Chaque message suivait exactement le même chemin. Peu importe ce que l'utilisateur demandait, le chatbot envoyait toujours la conversation directement au modèle de langage. Bien que ce soit un excellent point de départ, les applications d'IA dans le monde réel se comportent rarement de cette manière. Imaginez que nous construisons un chatbot pour Hiwa AI.
Certaines questions sont liées à l'entreprise :
- Quels services Hiwa AI propose-t-il ?
- Où se trouve Hiwa AI ?
- Comment puis-je contacter Hiwa AI ?
D'autres questions n'ont aucun rapport avec l'entreprise :
- Qui a gagné la Coupe du Monde ?
- Dis-moi une blague.
- Quel temps fait-il aujourd'hui ?
Idéalement, notre chatbot devrait reconnaître l'intention de l'utilisateur avant de décider de la prochaine action.
Dans cet article, nous allons étendre notre chatbot avec deux concepts importants de LangGraph :
- Classification d'intention — déterminer le sujet de la demande de l'utilisateur.
- Routage Conditionnel — choisir un chemin d'exécution différent en fonction de cette intention.
Bien que nous maintiendrons le graphe relativement petit, ces deux concepts constituent la base de nombreux systèmes d'IA en production.

Comprendre la Classification des Intentions
La classification d'intention est le processus d'identification de ce que l'utilisateur cherche à accomplir. Au lieu de générer immédiatement une réponse, le chatbot analyse d'abord le message de l'utilisateur et l'assigne à une catégorie. Pour notre chatbot, nous utiliserons uniquement deux catégories :
- questions connexes – concernant Hiwa AI.
- sans rapport – tout le reste.
Par exemple :
Question, Intention
- Quels produits Hiwa AI propose-t-elle ? : connexe,
- Où est situé Hiwa AI ? : connexe,START → Chatbot → END
Dis-moi une blague.
- Qui a inventé Python ? : sans rapport
Au lieu de tenter de répondre à chaque question, notre chatbot détermine d'abord à quelle catégorie la question appartient. Cette étape supplémentaire permet au graphe de prendre des décisions plus intelligentes par la suite.
Comprendre le routage conditionnel
Dans l'article précédent, l'exécution suivait toujours le même chemin. Il n'y avait pas de prise de décision. Le routage conditionnel change cela. Au lieu d'exécuter toujours le nœud suivant, LangGraph peut inspecter l'état actuel et décider où l'exécution doit se poursuivre.
Notre nouveau graphe ressemble à ceci :

Notez qu'il existe désormais deux chemins d'exécution possibles. Le chemin suivi par le graphe dépend entièrement du résultat de la classification d'intention.
Étape 1 : Extension de l'état
Notre premier chatbot devait uniquement se souvenir de l'historique de la conversation. Désormais, il doit également mémoriser l'intention de l'utilisateur.
from typing import Literal
from langgraph.graph import MessagesState
class State(MessagesState):
user_intent: Literal["related", "unrelated"]Au lieu de créer un tout nouvel état, nous héritons de MessagesState. MessagesState contient déjà tout ce qui est nécessaire pour stocker l'historique des conversations. Nous l'étendons simplement avec un autre champ appelé user_intent. Plus tard, notre graphe utilisera cette valeur pour décider quel nœud doit s'exécuter ensuite.
Étape 2 : Définir une réponse structurée
Le modèle de langage doit classer le message de l'utilisateur. Au lieu de demander au modèle de renvoyer du texte brut, nous lui demanderons de renvoyer un objet structuré.
from typing import Literal
from pydantic import BaseModel
class UserIntent(BaseModel):
user_intent: Literal["related", "unrelated"]
reasoning: strEnsuite, nous indiquons au modèle de langage de toujours retourner cette structure.
structured_llm = llm.with_structured_output(UserIntent)Maintenant, au lieu de générer quelque chose comme ceci :
Je pense que cette question est liée à Hiwa AI parce que...
le modèle renvoie un objet comme :
UserIntent(
user_intent="related",
reasoning="The user is asking about the company's services."
)Cette approche est beaucoup plus facile à utiliser car notre application reçoit des données structurées au lieu de texte libre.
Étape 3 : Création du nœud de classification d'intention
Maintenant, nous pouvons créer notre premier nœud.
from langchain_core.messages import SystemMessage
INTENT_SYSTEM = """ Determine whether the user's question is related to Hiwa AI. Return: - related - unrelated """Le nœud lui-même est très petit.
def find_out_intent(state: State):
result = structured_llm.invoke(
[SystemMessage(content=INTENT_SYSTEM)] + state["messages"]
)
return { "user_intent": result.user_intent }Le nœud reçoit l'historique de la conversation. Il demande au modèle de langage de classer le dernier message de l'utilisateur. Enfin, il stocke la classification dans l'état du graphe. Remarquez que ce nœud ne répond pas à la question de l'utilisateur. Sa seule responsabilité est de déterminer l'intention de l'utilisateur. Garder chaque nœud concentré sur une seule tâche rend le graphe plus facile à comprendre et à maintenir.
Étape 4 : Prendre une décision
Maintenant que le graphe connaît l'intention de l'utilisateur, il peut décider de la prochaine action. Cette décision est prise par une fonction Python standard.
from typing import Literal
from langgraph.graph import END
def should_continue( state: State,) -> Literal["chatbot", END]:
if state["user_intent"] == "related":
return "chatbot"
return ENDSi la question concerne Hiwa AI, le graphe continue vers le nœud du chatbot. Sinon, l'exécution se termine immédiatement. Cette fonction est appelée fonction de routage car son seul rôle est de décider quel nœud doit s'exécuter ensuite.
Étape 5 : Création du nœud de chatbot
Notre nœud de chatbot est presque identique à celui de l'article précédent.
def chatbot(state: State):
response = llm.invoke(state["messages"])
return {"messages": [response]}La seule différence est que ce nœud n'est plus exécuté pour chaque message utilisateur. Il ne s'exécute que si la fonction de routage détermine que la question est liée à Hiwa AI.
Étape 6 : Construction du graphe
Enfin, nous connectons tous les éléments ensemble.
from langgraph.graph import StateGraph, START, END
builder = StateGraph(State)
builder.add_node("find_out_intent", find_out_intent)
builder.add_node("chatbot", chatbot)
builder.add_edge(START, "find_out_intent")
builder.add_conditional_edges("find_out_intent", should_continue, ["chatbot", END])
builder.add_edge("chatbot", END)
graph = builder.compile()La majeure partie de ce code devrait sembler familière par rapport à l'article précédent.
Le seul nouveau concept est :
from langgraph.graph import StateGraph, START, END
builder = StateGraph(State)
builder.add_node("find_out_intent", find_out_intent)
builder.add_node("chatbot", chatbot)
builder.add_edge(START, "find_out_intent")
builder.add_conditional_edges(
"find_out_intent",
should_continue,
["chatbot", END]
)
builder.add_edge("chatbot", END)
graph = builder.compile()
def chatbot(state: State):
response = llm.invoke(state["messages"])
return {"messages": [response]}La seule différence est que ce nœud n'est plus exécuté pour chaque message utilisateur. Il ne s'exécute que si la fonction de routage détermine que la question est liée à Hiwa AI.
Étape 6 : Construction du graphe
Enfin, nous connectons tout ensemble.
from langgraph.graph import StateGraph, START, END
builder = StateGraph(State)
builder.add_node("find_out_intent", find_out_intent)
builder.add_node("chatbot", chatbot)
builder.add_edge(START, "find_out_intent")
builder.add_conditional_edges("find_out_intent", should_continue, ["chatbot", END])
builder.add_edge("chatbot", END)
graph = builder.compile()La majeure partie de ce code devrait sembler familière par rapport à l'article précédent. Le seul nouveau concept est :
builder.add_conditional_edges( "find_out_intent", should_continue, ["chatbot", END])Au lieu de toujours connecter un nœud directement à un autre, nous indiquons à LangGraph d'exécuter la fonction should_continue(). La valeur renvoyée par cette fonction détermine quel bord du graphe est suivi.
C'est l'une des fonctionnalités qui rend LangGraph si puissant. Au lieu d'écrire des instructions if imbriquées dans votre application, vous modélisez directement votre processus de prise de décision sous forme de graphe.
À mesure que votre application se développe, vous ajoutez simplement plus de nœuds et plus de logique de routage tout en gardant chaque composant petit et ciblé.
Et ensuite ?
Notre chatbot peut désormais prendre des décisions avant de générer une réponse. Cependant, il présente encore une limitation majeure.
Même lorsqu'une question concerne Hiwa AI, le modèle de langage ne possède aucune connaissance du site web de l'entreprise.
Dans le prochain article, nous résoudrons ce problème en introduisant le Retrieval-Augmented Generation (RAG). Nous construirons une base de connaissances à partir du site web de Hiwa AI, récupérerons les informations les plus pertinentes pour chaque question, et fournirons ce contexte au modèle de langage avant qu'il ne génère sa réponse.

