La recherche en IA te passionne ?
Les papers et avancées qui comptent, expliqués simplement, chaque soir. Gratuit.
Inclus dès l'inscription : notre sélection des meilleurs guides & comparatifs IA.
Choisis ton rythme
Gratuit · Pas de spam · Désabonnement en 1 clic
LangGraph : Une nouvelle ère pour les systèmes IA
Avec l'évolution rapide des grands modèles de langage (LLMs), les développeurs ne se contentent plus de créer de simples chatbots. Ils s'aventurent désormais dans la conception de systèmes capables de raisonner, de prendre des décisions, d'utiliser divers outils, de récupérer des informations, d'interagir avec des API et même de collaborer avec d'autres agents IA. Cette complexité croissante pose un défi majeur : comment coordonner et gérer efficacement ce flux d'intelligence ? C'est précisément pour répondre à cette question que LangGraph a été conçu.
LangGraph se positionne au cœur de cette révolution en offrant un cadre robuste pour construire des flux de travail IA qui sont non seulement contrôlables mais aussi prêts pour la production. Il permet aux développeurs de définir précisément comment les agents IA doivent penser, prendre des décisions, interagir avec des outils et progresser à travers des tâches complexes. Alors que LangChain se concentre sur la connexion des composants IA, LangGraph se spécialise dans l'orchestration du comportement de ces composants au fil du temps.
LangGraph est le fruit du travail de l'équipe derrière LangChain, et il permet aux développeurs de modéliser des applications IA sous forme de graphes, facilitant ainsi la gestion des processus décisionnels.
Comprendre les graphes d'agents
Pour illustrer le fonctionnement de LangGraph, envisageons un graphe simple composé de trois nœuds et d'une arête conditionnelle. Imaginez un processus de livraison de nourriture : chaque nœud représente une tâche ou une action spécifique. Par exemple :
- Recevoir la commande est un nœud.
- Préparer la nourriture est un autre nœud.
- Livrer la nourriture est un troisième nœud.
Chaque fois qu'une tâche est accomplie, on se trouve à un nœud. Les arêtes, quant à elles, sont les chemins qui indiquent au système la prochaine étape à suivre. Par exemple :
- Recevoir la commande ↓ Préparer la nourriture ↓ Livrer la nourriture
Ces flèches représentent les arêtes. Elles ne réalisent aucun travail par elles-mêmes mais indiquent simplement la direction à suivre après chaque étape. Pensez à une arête comme à une route reliant deux villes, où les villes sont les nœuds et la route est l'arête.
L'état est l'information qui circule tout au long du processus. Par exemple, lorsqu'un client passe une commande, les détails de cette commande (comme le type de pizza, l'adresse de livraison, et le nom du client) circulent avec elle à travers les différentes étapes du processus.
Construire un agent simple : l'importance de l'état
L'état peut être perçu comme la mémoire partagée du graphe. C'est l'information qui se déplace à travers le flux de travail, passant d'un nœud à l'autre. Chaque nœud a la capacité de lire cet état, de le mettre à jour et de transmettre la version mise à jour au nœud suivant. Dans notre exemple, l'état contient une seule information appelée graph_state.
Pour définir l'état du graphe, nous utilisons la classe TypedDict du module typing de Python, qui fournit des indices de type pour les clés.
from typing_extensions import TypedDict
class State(TypedDict):
graph_state: str
Les nœuds : les ouvriers du graphe
Un nœud est essentiellement une fonction qui exécute une tâche. Lorsqu'un nœud est activé, il reçoit l'état actuel, effectue une opération sur celui-ci, et retourne un état mis à jour. On peut comparer un nœud à un ouvrier dans une usine qui reçoit un colis (l'état), le modifie, puis le transmet.
Le premier argument positionnel d'un nœud est l'état, tel que défini précédemment. Chaque nœud peut accéder à la clé graph_state avec state['graph_state'] et retourne une nouvelle valeur pour cette clé. Par défaut, la nouvelle valeur retournée par chaque nœud remplace la valeur précédente de l'état.
def node_1(state):
print("---Nœud 1---")
return {"graph_state": state['graph_state'] + "Je suis"}
def node_2(state):
print("---Nœud 2---")
return {"graph_state": state['graph_state'] + "heureux !"}
def node_3(state):
print("---Nœud 3---")
return {"graph_state": state['graph_state'] + "triste !"}
Arêtes : les connexions entre les nœuds
Une arête est simplement une connexion entre des nœuds, indiquant au graphe la prochaine étape après qu'un nœud ait terminé son travail. Une arête normale suit un chemin fixe, mais une arête conditionnelle agit comme un point de décision, permettant au graphe de choisir le chemin en fonction de l'état actuel.
Par exemple, après avoir analysé des données, le graphe pourrait se demander : « Ai-je suffisamment d'informations ? » Si la réponse est oui, il passe à l'étape suivante, sinon, il revient à une étape antérieure pour collecter plus de données.
Les arêtes conditionnelles sont mises en œuvre sous forme de fonctions qui déterminent le prochain nœud à visiter en fonction de certaines logiques.
import random
from typing import Literal
def decide_mood(state) -> Literal["node_2", "node_3"]:
user_input = state['graph_state'] # Ici, faisons simplement un tirage au sort entre les nœuds 2 et 3
if random.random() < 0.5: # 50% du temps, nous retournons le Nœud 2
return "node_2"
return "node_3" # 50% du temps, nous retournons le Nœud 3
Construction et exécution du graphe
Pour construire le graphe, nous utilisons la classe StateGraph. Après avoir initialisé un StateGraph avec la classe State, nous ajoutons nos nœuds et arêtes. Le Nœud START est un nœud spécial qui envoie l'entrée utilisateur au graphe, indiquant où commencer, tandis que le Nœud END représente un nœud terminal. Enfin, nous compilons notre graphe pour effectuer quelques vérifications de base sur sa structure.
from IPython.display import Image, display
from langgraph.graph import StateGraph, START, END
# Construire le Graphe
builder = StateGraph(state)
builder.add_node("node_1", node_1)
builder.add_node("node_2", node_2)
builder.add_node("node_3", node_3)
# Logique
builder.add_edge(START, "node_1")
builder.add_conditional_edges("node_1", decide_mood)
builder.add_edge("node_2", END)
builder.add_edge("node_3", END)
# Ajouter
graph = builder.compile()
# Voir
display(Image(graph.get_graph().draw_mermaid_png()))
Le graphe compilé implémente le protocole exécutable, fournissant un moyen standard d'exécuter les composants de LangChain. La méthode invoke permet de lancer l'exécution du graphe en utilisant un dictionnaire d'entrée initial.
LangGraph offre ainsi une approche innovante pour orchestrer des systèmes IA complexes, rendant les processus plus intelligents et adaptatifs.


