Buckets:

HuggingFaceDocBuilder's picture
download
raw
65.9 kB
<meta charset="utf-8" /><meta name="hf:doc:metadata" content="{&quot;title&quot;:&quot;Construire votre premier LangGraph&quot;,&quot;local&quot;:&quot;construire-votre-premier-langgraph&quot;,&quot;sections&quot;:[{&quot;title&quot;:&quot;Notre workflow&quot;,&quot;local&quot;:&quot;notre-workflow&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Configuration de notre environnement&quot;,&quot;local&quot;:&quot;configuration-de-notre-environnement&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Étape 1 : Définir notre état&quot;,&quot;local&quot;:&quot;étape-1--définir-notre-état&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Étape 2 : Définir nos nœuds&quot;,&quot;local&quot;:&quot;étape-2--définir-nos-nœuds&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Étape 3 : Définir notre logique de routage&quot;,&quot;local&quot;:&quot;étape-3--définir-notre-logique-de-routage&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Étape 4 : Créer le StateGraph et définir les arêtes&quot;,&quot;local&quot;:&quot;étape-4--créer-le-stategraph-et-définir-les-arêtes&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Étape 5 : Exécuter l’application&quot;,&quot;local&quot;:&quot;étape-5--exécuter-lapplication&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Étape 6 : Inspecter notre agent trieur d’email avec Langfuse 📡&quot;,&quot;local&quot;:&quot;étape-6--inspecter-notre-agent-trieur-demail-avec-langfuse-&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Visualiser notre graphe&quot;,&quot;local&quot;:&quot;visualiser-notre-graphe&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Ce que nous avons construit&quot;,&quot;local&quot;:&quot;ce-que-nous-avons-construit&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Points clés à retenir&quot;,&quot;local&quot;:&quot;points-clés-à-retenir&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Et maintenant ?&quot;,&quot;local&quot;:&quot;et-maintenant-&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2}],&quot;depth&quot;:1}">
<link href="/docs/agents-course/pr_673/fr/_app/immutable/assets/0.e3b0c442.css" rel="modulepreload">
<link rel="modulepreload" href="/docs/agents-course/pr_673/fr/_app/immutable/entry/start.6a3cabb6.js">
<link rel="modulepreload" href="/docs/agents-course/pr_673/fr/_app/immutable/chunks/scheduler.505acc25.js">
<link rel="modulepreload" href="/docs/agents-course/pr_673/fr/_app/immutable/chunks/singletons.f87ed60a.js">
<link rel="modulepreload" href="/docs/agents-course/pr_673/fr/_app/immutable/chunks/index.001f95d5.js">
<link rel="modulepreload" href="/docs/agents-course/pr_673/fr/_app/immutable/chunks/paths.cc8cef00.js">
<link rel="modulepreload" href="/docs/agents-course/pr_673/fr/_app/immutable/entry/app.bbc296eb.js">
<link rel="modulepreload" href="/docs/agents-course/pr_673/fr/_app/immutable/chunks/preload-helper.f888915a.js">
<link rel="modulepreload" href="/docs/agents-course/pr_673/fr/_app/immutable/chunks/index.b1175496.js">
<link rel="modulepreload" href="/docs/agents-course/pr_673/fr/_app/immutable/nodes/0.8f31a791.js">
<link rel="modulepreload" href="/docs/agents-course/pr_673/fr/_app/immutable/chunks/each.e59479a4.js">
<link rel="modulepreload" href="/docs/agents-course/pr_673/fr/_app/immutable/nodes/40.d5928c0e.js">
<link rel="modulepreload" href="/docs/agents-course/pr_673/fr/_app/immutable/chunks/Heading.aedc5b40.js">
<link rel="modulepreload" href="/docs/agents-course/pr_673/fr/_app/immutable/chunks/MermaidChart.svelte_svelte_type_style_lang.11cb69c9.js">
<link rel="modulepreload" href="/docs/agents-course/pr_673/fr/_app/immutable/chunks/CodeBlock.91f006af.js"><!-- HEAD_svelte-u9bgzb_START --><meta name="hf:doc:metadata" content="{&quot;title&quot;:&quot;Construire votre premier LangGraph&quot;,&quot;local&quot;:&quot;construire-votre-premier-langgraph&quot;,&quot;sections&quot;:[{&quot;title&quot;:&quot;Notre workflow&quot;,&quot;local&quot;:&quot;notre-workflow&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Configuration de notre environnement&quot;,&quot;local&quot;:&quot;configuration-de-notre-environnement&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Étape 1 : Définir notre état&quot;,&quot;local&quot;:&quot;étape-1--définir-notre-état&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Étape 2 : Définir nos nœuds&quot;,&quot;local&quot;:&quot;étape-2--définir-nos-nœuds&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Étape 3 : Définir notre logique de routage&quot;,&quot;local&quot;:&quot;étape-3--définir-notre-logique-de-routage&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Étape 4 : Créer le StateGraph et définir les arêtes&quot;,&quot;local&quot;:&quot;étape-4--créer-le-stategraph-et-définir-les-arêtes&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Étape 5 : Exécuter l’application&quot;,&quot;local&quot;:&quot;étape-5--exécuter-lapplication&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Étape 6 : Inspecter notre agent trieur d’email avec Langfuse 📡&quot;,&quot;local&quot;:&quot;étape-6--inspecter-notre-agent-trieur-demail-avec-langfuse-&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Visualiser notre graphe&quot;,&quot;local&quot;:&quot;visualiser-notre-graphe&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Ce que nous avons construit&quot;,&quot;local&quot;:&quot;ce-que-nous-avons-construit&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Points clés à retenir&quot;,&quot;local&quot;:&quot;points-clés-à-retenir&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Et maintenant ?&quot;,&quot;local&quot;:&quot;et-maintenant-&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2}],&quot;depth&quot;:1}"><!-- HEAD_svelte-u9bgzb_END --> <p></p> <div class="items-center shrink-0 min-w-[100px] max-sm:min-w-[50px] justify-end ml-auto flex" style="float: right; margin-left: 10px; display: inline-flex; position: relative; z-index: 10;"><div class="inline-flex rounded-md max-sm:rounded-sm"><button class="inline-flex items-center gap-1 h-7 max-sm:h-7 px-2 max-sm:px-1.5 text-sm font-medium text-gray-800 border border-r-0 rounded-l-md max-sm:rounded-l-sm border-gray-200 bg-white hover:shadow-inner dark:border-gray-850 dark:bg-gray-950 dark:text-gray-200 dark:hover:bg-gray-800" aria-live="polite"><span class="inline-flex items-center justify-center rounded-md p-0.5 max-sm:p-0 hover:text-gray-800 dark:hover:text-gray-200"><svg class="sm:size-3.5 size-3" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg></span> <span>Copy page</span></button> <button class="inline-flex items-center justify-center w-6 max-sm:w-5 h-7 max-sm:h-7 disabled:pointer-events-none text-sm text-gray-500 hover:text-gray-700 dark:hover:text-white rounded-r-md max-sm:rounded-r-sm border border-l transition border-gray-200 bg-white hover:shadow-inner dark:border-gray-850 dark:bg-gray-950 dark:text-gray-200 dark:hover:bg-gray-800" aria-haspopup="menu" aria-expanded="false" aria-label="Open copy menu"><svg class="transition-transform text-gray-400 overflow-visible sm:size-3.5 size-3 rotate-0" width="1em" height="1em" viewBox="0 0 12 7" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M1 1L6 6L11 1" stroke="currentColor"></path></svg></button></div> </div> <h1 class="relative group"><a id="construire-votre-premier-langgraph" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#construire-votre-premier-langgraph"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Construire votre premier LangGraph</span></h1> <p data-svelte-h="svelte-joxdvp">Maintenant que nous comprenons les composants de base, mettons-les en pratique en construisant notre premier graphe fonctionnel. Nous implémenterons le système de traitement des emails reçus par Alfred, où il doit :</p> <ol data-svelte-h="svelte-d8d9yj"><li>Lire les emails entrants</li> <li>Les classifier comme spam ou légitimes</li> <li>Rédiger une réponse préliminaire pour les emails légitimes</li> <li>Envoyer les informations à M. Wayne quand c’est légitime (affichage seulement)</li></ol> <p data-svelte-h="svelte-zv1y8r">Cet exemple démontre comment structurer un <em>workflow</em> avec LangGraph qui implique une prise de décision basée sur LLM. Bien que cela ne puisse pas être considéré comme un agent car aucun outil n’est impliqué, cette section se concentre plus sur l’apprentissage du <em>framework</em> LangGraph que sur les agents.</p> <blockquote class="tip" data-svelte-h="svelte-179ghm9"><p>Vous pouvez suivre le code dans <a href="https://huggingface.co/agents-course/notebooks/blob/main/fr/unit2/langgraph/mail_sorting.ipynb" target="_blank">ce <i>notebook</i></a> que vous pouvez exécuter avec Google Colab.</p></blockquote> <h2 class="relative group"><a id="notre-workflow" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#notre-workflow"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Notre workflow</span></h2> <p data-svelte-h="svelte-klwm00">Voici le <em>workflow</em> que nous allons construire :</p> <img src="https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/LangGraph/first_graph.png" alt="First LangGraph"> <h2 class="relative group"><a id="configuration-de-notre-environnement" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#configuration-de-notre-environnement"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Configuration de notre environnement</span></h2> <p data-svelte-h="svelte-86hspx">Tout d’abord, installons les <em>packages</em> requis :</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START -->%pip install langgraph langchain_openai<!-- HTML_TAG_END --></pre></div> <p data-svelte-h="svelte-1o6mwvs">Ensuite, importons les modules nécessaires :</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START --><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> TypedDict, <span class="hljs-type">List</span>, <span class="hljs-type">Dict</span>, <span class="hljs-type">Any</span>, <span class="hljs-type">Optional</span>
<span class="hljs-keyword">from</span> langgraph.graph <span class="hljs-keyword">import</span> StateGraph, START, END
<span class="hljs-keyword">from</span> langchain_openai <span class="hljs-keyword">import</span> ChatOpenAI
<span class="hljs-keyword">from</span> langchain_core.messages <span class="hljs-keyword">import</span> HumanMessage<!-- HTML_TAG_END --></pre></div> <h2 class="relative group"><a id="étape-1--définir-notre-état" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#étape-1--définir-notre-état"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Étape 1 : Définir notre état</span></h2> <p data-svelte-h="svelte-zwio3t">Définissons quelles informations Alfred doit suivre pendant le <em>workflow</em> de traitement des emails :</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START --><span class="hljs-keyword">class</span> <span class="hljs-title class_">EmailState</span>(<span class="hljs-title class_ inherited__">TypedDict</span>):
<span class="hljs-comment"># L&#x27;email en cours de traitement</span>
email: <span class="hljs-type">Dict</span>[<span class="hljs-built_in">str</span>, <span class="hljs-type">Any</span>] <span class="hljs-comment"># Contient sujet, expéditeur, corps, etc.</span>
<span class="hljs-comment"># Catégorie de l&#x27;email (enquête, plainte, etc.)</span>
email_category: <span class="hljs-type">Optional</span>[<span class="hljs-built_in">str</span>]
<span class="hljs-comment"># Raison pourquoi l&#x27;email a été marqué comme spam</span>
spam_reason: <span class="hljs-type">Optional</span>[<span class="hljs-built_in">str</span>]
<span class="hljs-comment"># Analyse et décisions</span>
is_spam: <span class="hljs-type">Optional</span>[<span class="hljs-built_in">bool</span>]
<span class="hljs-comment"># Génération de réponse</span>
email_draft: <span class="hljs-type">Optional</span>[<span class="hljs-built_in">str</span>]
<span class="hljs-comment"># Métadonnées de traitement</span>
messages: <span class="hljs-type">List</span>[<span class="hljs-type">Dict</span>[<span class="hljs-built_in">str</span>, <span class="hljs-type">Any</span>]] <span class="hljs-comment"># Suivre la conversation avec le LLM pour l&#x27;analyse</span><!-- HTML_TAG_END --></pre></div> <blockquote data-svelte-h="svelte-1ngenq0"><p>💡 <strong>Astuce :</strong> Rendez votre état suffisamment complet pour suivre toutes les informations importantes, mais évitez de l’encombrer avec des détails inutiles.</p></blockquote> <h2 class="relative group"><a id="étape-2--définir-nos-nœuds" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#étape-2--définir-nos-nœuds"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Étape 2 : Définir nos nœuds</span></h2> <p data-svelte-h="svelte-1r9d606">Maintenant, créons les fonctions de traitement qui formeront nos nœuds :</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START --><span class="hljs-comment"># Initialiser notre LLM</span>
model = ChatOpenAI(temperature=<span class="hljs-number">0</span>)
<span class="hljs-keyword">def</span> <span class="hljs-title function_">read_email</span>(<span class="hljs-params">state: EmailState</span>):
<span class="hljs-string">&quot;&quot;&quot;Alfred lit et enregistre l&#x27;email entrant&quot;&quot;&quot;</span>
email = state[<span class="hljs-string">&quot;email&quot;</span>]
<span class="hljs-comment"># Ici nous pourrions faire un prétraitement initial</span>
<span class="hljs-built_in">print</span>(<span class="hljs-string">f&quot;Alfred traite un email de <span class="hljs-subst">{email[<span class="hljs-string">&#x27;sender&#x27;</span>]}</span> avec le sujet : <span class="hljs-subst">{email[<span class="hljs-string">&#x27;subject&#x27;</span>]}</span>&quot;</span>)
<span class="hljs-comment"># Aucun changement d&#x27;état nécessaire ici</span>
<span class="hljs-keyword">return</span> {}
<span class="hljs-keyword">def</span> <span class="hljs-title function_">classify_email</span>(<span class="hljs-params">state: EmailState</span>):
<span class="hljs-string">&quot;&quot;&quot;Alfred utilise un LLM pour déterminer si l&#x27;email est spam ou légitime&quot;&quot;&quot;</span>
email = state[<span class="hljs-string">&quot;email&quot;</span>]
<span class="hljs-comment"># Préparer notre prompt pour le LLM</span>
prompt = <span class="hljs-string">f&quot;&quot;&quot;
En tant qu&#x27;Alfred le majordome, analysez cet email et déterminez s&#x27;il s&#x27;agit de spam ou s&#x27;il est légitime.
email :
De : <span class="hljs-subst">{email[<span class="hljs-string">&#x27;sender&#x27;</span>]}</span>
Sujet : <span class="hljs-subst">{email[<span class="hljs-string">&#x27;subject&#x27;</span>]}</span>
Corps : <span class="hljs-subst">{email[<span class="hljs-string">&#x27;body&#x27;</span>]}</span>
Premièrement, détermine si cet email est du spam. S&#x27;il s&#x27;agit de spam, explique pourquoi.
S&#x27;il est légitime, catégorise-le (enquête, plainte, remerciement, etc.).
&quot;&quot;&quot;</span>
<span class="hljs-comment"># Appeler le LLM</span>
messages = [HumanMessage(content=prompt)]
response = model.invoke(messages)
<span class="hljs-comment"># Logique simple pour analyser la réponse (dans une vraie app, vous voudriez un parsing plus robuste)</span>
response_text = response.content.lower()
is_spam = <span class="hljs-string">&quot;spam&quot;</span> <span class="hljs-keyword">in</span> response_text <span class="hljs-keyword">and</span> <span class="hljs-string">&quot;not spam&quot;</span> <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> response_text
<span class="hljs-comment"># Extraire une raison si c&#x27;est du spam</span>
spam_reason = <span class="hljs-literal">None</span>
<span class="hljs-keyword">if</span> is_spam <span class="hljs-keyword">and</span> <span class="hljs-string">&quot;reason:&quot;</span> <span class="hljs-keyword">in</span> response_text:
spam_reason = response_text.split(<span class="hljs-string">&quot;reason:&quot;</span>)[<span class="hljs-number">1</span>].strip()
<span class="hljs-comment"># Déterminer la catégorie si légitime</span>
email_category = <span class="hljs-literal">None</span>
<span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> is_spam:
categories = [<span class="hljs-string">&quot;inquiry&quot;</span>, <span class="hljs-string">&quot;complaint&quot;</span>, <span class="hljs-string">&quot;thank you&quot;</span>, <span class="hljs-string">&quot;request&quot;</span>, <span class="hljs-string">&quot;information&quot;</span>]
<span class="hljs-keyword">for</span> category <span class="hljs-keyword">in</span> categories:
<span class="hljs-keyword">if</span> category <span class="hljs-keyword">in</span> response_text:
email_category = category
<span class="hljs-keyword">break</span>
<span class="hljs-comment"># Mettre à jour les messages pour le suivi</span>
new_messages = state.get(<span class="hljs-string">&quot;messages&quot;</span>, []) + [
{<span class="hljs-string">&quot;role&quot;</span>: <span class="hljs-string">&quot;user&quot;</span>, <span class="hljs-string">&quot;content&quot;</span>: prompt},
{<span class="hljs-string">&quot;role&quot;</span>: <span class="hljs-string">&quot;assistant&quot;</span>, <span class="hljs-string">&quot;content&quot;</span>: response.content}
]
<span class="hljs-comment"># Retourner les mises à jour d&#x27;état</span>
<span class="hljs-keyword">return</span> {
<span class="hljs-string">&quot;is_spam&quot;</span>: is_spam,
<span class="hljs-string">&quot;spam_reason&quot;</span>: spam_reason,
<span class="hljs-string">&quot;email_category&quot;</span>: email_category,
<span class="hljs-string">&quot;messages&quot;</span>: new_messages
}
<span class="hljs-keyword">def</span> <span class="hljs-title function_">handle_spam</span>(<span class="hljs-params">state: EmailState</span>):
<span class="hljs-string">&quot;&quot;&quot;Alfred rejette l&#x27;email spam avec une note explicative&quot;&quot;&quot;</span>
<span class="hljs-built_in">print</span>(<span class="hljs-string">f&quot;Alfred a marqué l&#x27;email comme spam. Raison : <span class="hljs-subst">{state[<span class="hljs-string">&#x27;spam_reason&#x27;</span>]}</span>&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;L&#x27;email a été déplacé dans le dossier spam.&quot;</span>)
<span class="hljs-comment"># Nous avons fini de traiter cet email</span>
<span class="hljs-keyword">return</span> {}
<span class="hljs-keyword">def</span> <span class="hljs-title function_">draft_response</span>(<span class="hljs-params">state: EmailState</span>):
<span class="hljs-string">&quot;&quot;&quot;Alfred rédige une réponse préliminaire pour les emails légitimes&quot;&quot;&quot;</span>
email = state[<span class="hljs-string">&quot;email&quot;</span>]
category = state[<span class="hljs-string">&quot;email_category&quot;</span>] <span class="hljs-keyword">or</span> <span class="hljs-string">&quot;general&quot;</span>
<span class="hljs-comment"># Préparer notre prompt pour le LLM</span>
prompt = <span class="hljs-string">f&quot;&quot;&quot;
En tant qu&#x27;Alfred le majordome, rédige une réponse préliminaire polie à cet email.
email :
De : <span class="hljs-subst">{email[<span class="hljs-string">&#x27;sender&#x27;</span>]}</span>
Sujet : <span class="hljs-subst">{email[<span class="hljs-string">&#x27;subject&#x27;</span>]}</span>
Corps : <span class="hljs-subst">{email[<span class="hljs-string">&#x27;body&#x27;</span>]}</span>
Cet email a été catégorisé comme : <span class="hljs-subst">{category}</span>
Rédige une réponse brève et professionnelle que M. Hugg peut réviser et personnaliser avant l&#x27;envoi.
&quot;&quot;&quot;</span>
<span class="hljs-comment"># Appeler le LLM</span>
messages = [HumanMessage(content=prompt)]
response = model.invoke(messages)
<span class="hljs-comment"># Mettre à jour les messages pour le suivi</span>
new_messages = state.get(<span class="hljs-string">&quot;messages&quot;</span>, []) + [
{<span class="hljs-string">&quot;role&quot;</span>: <span class="hljs-string">&quot;user&quot;</span>, <span class="hljs-string">&quot;content&quot;</span>: prompt},
{<span class="hljs-string">&quot;role&quot;</span>: <span class="hljs-string">&quot;assistant&quot;</span>, <span class="hljs-string">&quot;content&quot;</span>: response.content}
]
<span class="hljs-comment"># Retourner les mises à jour d&#x27;état</span>
<span class="hljs-keyword">return</span> {
<span class="hljs-string">&quot;email_draft&quot;</span>: response.content,
<span class="hljs-string">&quot;messages&quot;</span>: new_messages
}
<span class="hljs-keyword">def</span> <span class="hljs-title function_">notify_mr_hugg</span>(<span class="hljs-params">state: EmailState</span>):
<span class="hljs-string">&quot;&quot;&quot;Alfred informe M. Hugg de l&#x27;email et présente le brouillon de réponse&quot;&quot;&quot;</span>
email = state[<span class="hljs-string">&quot;email&quot;</span>]
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;\n&quot;</span> + <span class="hljs-string">&quot;=&quot;</span>*<span class="hljs-number">50</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">f&quot;Monsieur, vous avez reçu un email de <span class="hljs-subst">{email[<span class="hljs-string">&#x27;sender&#x27;</span>]}</span>.&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">f&quot;Sujet : <span class="hljs-subst">{email[<span class="hljs-string">&#x27;subject&#x27;</span>]}</span>&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">f&quot;Catégorie : <span class="hljs-subst">{state[<span class="hljs-string">&#x27;email_category&#x27;</span>]}</span>&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;\nJ&#x27;ai préparé un brouillon de réponse pour votre révision :&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;-&quot;</span>*<span class="hljs-number">50</span>)
<span class="hljs-built_in">print</span>(state[<span class="hljs-string">&quot;email_draft&quot;</span>])
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;=&quot;</span>*<span class="hljs-number">50</span> + <span class="hljs-string">&quot;\n&quot;</span>)
<span class="hljs-comment"># Nous avons fini de traiter cet email</span>
<span class="hljs-keyword">return</span> {}<!-- HTML_TAG_END --></pre></div> <h2 class="relative group"><a id="étape-3--définir-notre-logique-de-routage" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#étape-3--définir-notre-logique-de-routage"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Étape 3 : Définir notre logique de routage</span></h2> <p data-svelte-h="svelte-vnm3qe">Nous avons besoin d’une fonction pour déterminer quel chemin prendre après la classification :</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START --><span class="hljs-keyword">def</span> <span class="hljs-title function_">route_email</span>(<span class="hljs-params">state: EmailState</span>) -&gt; <span class="hljs-built_in">str</span>:
<span class="hljs-string">&quot;&quot;&quot;Déterminer la prochaine étape basée sur la classification en spam&quot;&quot;&quot;</span>
<span class="hljs-keyword">if</span> state[<span class="hljs-string">&quot;is_spam&quot;</span>]:
<span class="hljs-keyword">return</span> <span class="hljs-string">&quot;spam&quot;</span>
<span class="hljs-keyword">else</span>:
<span class="hljs-keyword">return</span> <span class="hljs-string">&quot;legitimate&quot;</span><!-- HTML_TAG_END --></pre></div> <blockquote data-svelte-h="svelte-1u2eq3s"><p>💡 <strong>Note :</strong> Cette fonction de routage est appelée par LangGraph pour déterminer quelle arête suivre après le nœud de classification. La valeur de retour doit correspondre à l’une des clés dans notre mappage d’arêtes conditionnelles.</p></blockquote> <h2 class="relative group"><a id="étape-4--créer-le-stategraph-et-définir-les-arêtes" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#étape-4--créer-le-stategraph-et-définir-les-arêtes"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Étape 4 : Créer le StateGraph et définir les arêtes</span></h2> <p data-svelte-h="svelte-1y957er">Maintenant nous connectons tout ensemble :</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START --><span class="hljs-comment"># Créer le graphe</span>
email_graph = StateGraph(EmailState)
<span class="hljs-comment"># Ajouter les nœuds</span>
email_graph.add_node(<span class="hljs-string">&quot;read_email&quot;</span>, read_email)
email_graph.add_node(<span class="hljs-string">&quot;classify_email&quot;</span>, classify_email)
email_graph.add_node(<span class="hljs-string">&quot;handle_spam&quot;</span>, handle_spam)
email_graph.add_node(<span class="hljs-string">&quot;draft_response&quot;</span>, draft_response)
email_graph.add_node(<span class="hljs-string">&quot;notify_mr_hugg&quot;</span>, notify_mr_hugg)
<span class="hljs-comment"># Commencer les arêtes</span>
email_graph.add_edge(START, <span class="hljs-string">&quot;read_email&quot;</span>)
<span class="hljs-comment"># Ajouter les arêtes - définir le flux</span>
email_graph.add_edge(<span class="hljs-string">&quot;read_email&quot;</span>, <span class="hljs-string">&quot;classify_email&quot;</span>)
<span class="hljs-comment"># Ajouter l&#x27;embranchement conditionnel depuis classify_email</span>
email_graph.add_conditional_edges(
<span class="hljs-string">&quot;classify_email&quot;</span>,
route_email,
{
<span class="hljs-string">&quot;spam&quot;</span>: <span class="hljs-string">&quot;handle_spam&quot;</span>,
<span class="hljs-string">&quot;legitimate&quot;</span>: <span class="hljs-string">&quot;draft_response&quot;</span>
}
)
<span class="hljs-comment"># Ajouter les arêtes finales</span>
email_graph.add_edge(<span class="hljs-string">&quot;handle_spam&quot;</span>, END)
email_graph.add_edge(<span class="hljs-string">&quot;draft_response&quot;</span>, <span class="hljs-string">&quot;notify_mr_hugg&quot;</span>)
email_graph.add_edge(<span class="hljs-string">&quot;notify_mr_hugg&quot;</span>, END)
<span class="hljs-comment"># Compiler le graphe</span>
compiled_graph = email_graph.<span class="hljs-built_in">compile</span>()<!-- HTML_TAG_END --></pre></div> <p data-svelte-h="svelte-1wjyxp5">Remarquez comment nous utilisons le nœud spécial <code>END</code> fourni par LangGraph. Cela indique les états terminaux où le <em>workflow</em> se termine.</p> <h2 class="relative group"><a id="étape-5--exécuter-lapplication" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#étape-5--exécuter-lapplication"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Étape 5 : Exécuter l’application</span></h2> <p data-svelte-h="svelte-oq767u">Testons notre graphe avec un email légitime et un email spam :</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START --><span class="hljs-comment"># Exemple d&#x27;email légitime</span>
legitimate_email = {
<span class="hljs-string">&quot;sender&quot;</span>: <span class="hljs-string">&quot;john.smith@example.com&quot;</span>,
<span class="hljs-string">&quot;subject&quot;</span>: <span class="hljs-string">&quot;Question sur vos services&quot;</span>,
<span class="hljs-string">&quot;body&quot;</span>: <span class="hljs-string">&quot;Cher M. Hugg, J&#x27;ai été référé à vous par un collègue et je suis intéressé à en savoir plus sur vos services de conseil. Pourrions-nous programmer un appel la semaine prochaine ? Meilleures salutations, John Smith&quot;</span>
}
<span class="hljs-comment"># Exemple d&#x27;email spam</span>
spam_email = {
<span class="hljs-string">&quot;sender&quot;</span>: <span class="hljs-string">&quot;winner@lottery-intl.com&quot;</span>,
<span class="hljs-string">&quot;subject&quot;</span>: <span class="hljs-string">&quot;VOUS AVEZ GAGNÉ 5 000 000 $ !!!&quot;</span>,
<span class="hljs-string">&quot;body&quot;</span>: <span class="hljs-string">&quot;FÉLICITATIONS ! Vous avez été sélectionné comme gagnant de notre loterie internationale ! Pour réclamer votre prix de 5 000 000 $, veuillez nous envoyer vos coordonnées bancaires et des frais de traitement de 100 $.&quot;</span>
}
<span class="hljs-comment"># Traiter l&#x27;email légitime</span>
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;\nTraitement de l&#x27;email légitime...&quot;</span>)
legitimate_result = compiled_graph.invoke({
<span class="hljs-string">&quot;email&quot;</span>: legitimate_email,
<span class="hljs-string">&quot;is_spam&quot;</span>: <span class="hljs-literal">None</span>,
<span class="hljs-string">&quot;spam_reason&quot;</span>: <span class="hljs-literal">None</span>,
<span class="hljs-string">&quot;email_category&quot;</span>: <span class="hljs-literal">None</span>,
<span class="hljs-string">&quot;email_draft&quot;</span>: <span class="hljs-literal">None</span>,
<span class="hljs-string">&quot;messages&quot;</span>: []
})
<span class="hljs-comment"># Traiter l&#x27;email spam</span>
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;\nTraitement de l&#x27;email spam...&quot;</span>)
spam_result = compiled_graph.invoke({
<span class="hljs-string">&quot;email&quot;</span>: spam_email,
<span class="hljs-string">&quot;is_spam&quot;</span>: <span class="hljs-literal">None</span>,
<span class="hljs-string">&quot;spam_reason&quot;</span>: <span class="hljs-literal">None</span>,
<span class="hljs-string">&quot;email_category&quot;</span>: <span class="hljs-literal">None</span>,
<span class="hljs-string">&quot;email_draft&quot;</span>: <span class="hljs-literal">None</span>,
<span class="hljs-string">&quot;messages&quot;</span>: []
})<!-- HTML_TAG_END --></pre></div> <h2 class="relative group"><a id="étape-6--inspecter-notre-agent-trieur-demail-avec-langfuse-" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#étape-6--inspecter-notre-agent-trieur-demail-avec-langfuse-"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Étape 6 : Inspecter notre agent trieur d’email avec Langfuse 📡</span></h2> <p data-svelte-h="svelte-y4amsa">Alors qu’Alfred peaufine l’agent trieur d’email, il se lasse de déboguer ses exécutions. Les agents, par nature, sont imprévisibles et difficiles à inspecter. Mais comme il vise à construire l’agent de détection de spam ultime et à le déployer en production, il a besoin d’une traçabilité robuste pour le <em>monitoring</em> et l’analyse futurs.</p> <p data-svelte-h="svelte-vgvz2k">Pour cela, Alfred peut utiliser un outil d’observabilité comme <a href="https://langfuse.com/" rel="nofollow">Langfuse</a> pour tracer et monitorer l’agent.</p> <p data-svelte-h="svelte-uhpw4h">Premièrement, nous installons Langfuse avec pip :</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START -->%pip install -q langfuse<!-- HTML_TAG_END --></pre></div> <p data-svelte-h="svelte-alijlj">Deuxièmement, nous installons LangChain avec pip (LangChain est requis car nous utilisons LangFuse) :</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START -->%pip install langchain<!-- HTML_TAG_END --></pre></div> <p data-svelte-h="svelte-1yo6vsj">Ensuite, nous ajoutons les clés API LangFuse et l’adresse de l’hôte comme variables d’environnement. Vous pouvez obtenir vos identifiants LangFuse en vous inscrivant sur <a href="https://cloud.langfuse.com" rel="nofollow">LangFuse Cloud</a> ou en <a href="https://langfuse.com/self-hosting" rel="nofollow">auto-hébergeant LangFuse</a>.</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START --><span class="hljs-keyword">import</span> os
<span class="hljs-comment"># Obtenez les clés pour votre projet depuis la page des paramètres du projet : https://cloud.langfuse.com</span>
os.environ[<span class="hljs-string">&quot;LANGFUSE_PUBLIC_KEY&quot;</span>] = <span class="hljs-string">&quot;pk-lf-...&quot;</span>
os.environ[<span class="hljs-string">&quot;LANGFUSE_SECRET_KEY&quot;</span>] = <span class="hljs-string">&quot;sk-lf-...&quot;</span>
os.environ[<span class="hljs-string">&quot;LANGFUSE_HOST&quot;</span>] = <span class="hljs-string">&quot;https://cloud.langfuse.com&quot;</span> <span class="hljs-comment"># 🇪🇺 région EU</span>
<span class="hljs-comment"># os.environ[&quot;LANGFUSE_HOST&quot;] = &quot;https://us.cloud.langfuse.com&quot; # 🇺🇸 région US</span><!-- HTML_TAG_END --></pre></div> <p data-svelte-h="svelte-13dikqx">Ensuite, nous configurons le <a href="https://langfuse.com/docs/integrations/langchain/tracing#add-langfuse-to-your-langchain-application" rel="nofollow">LangFuse <code>callback_handler</code></a> et instrumentons l’agent en ajoutant le <code>langfuse_callback</code> à l’invocation du graphe : <code>config={&quot;callbacks&quot;: [langfuse_handler]}</code>.</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START --><span class="hljs-keyword">from</span> langfuse.langchain <span class="hljs-keyword">import</span> CallbackHandler
<span class="hljs-comment"># Initialiser le CallbackHandler Langfuse pour LangGraph/Langchain (traçage)</span>
langfuse_handler = CallbackHandler()
<span class="hljs-comment"># Traiter l&#x27;email légitime</span>
legitimate_result = compiled_graph.invoke(
<span class="hljs-built_in">input</span>={<span class="hljs-string">&quot;email&quot;</span>: legitimate_email, <span class="hljs-string">&quot;is_spam&quot;</span>: <span class="hljs-literal">None</span>, <span class="hljs-string">&quot;spam_reason&quot;</span>: <span class="hljs-literal">None</span>, <span class="hljs-string">&quot;email_category&quot;</span>: <span class="hljs-literal">None</span>, <span class="hljs-string">&quot;draft_response&quot;</span>: <span class="hljs-literal">None</span>, <span class="hljs-string">&quot;messages&quot;</span>: []},
config={<span class="hljs-string">&quot;callbacks&quot;</span>: [langfuse_handler]}
)<!-- HTML_TAG_END --></pre></div> <p data-svelte-h="svelte-1tphwqw">Alfred est maintenant connecté 🔌 ! Les exécutions de LangGraph sont enregistrées dans LangFuse, lui donnant une visibilité complète sur le comportement de l’agent. Avec cette configuration, il est prêt à revisiter les exécutions précédentes et à affiner encore plus son agent de tri de courrier.</p> <p data-svelte-h="svelte-3rgcl6"><img src="https://langfuse.com/images/cookbook/huggingface-agent-course/langgraph-trace-legit.png" alt="Example trace in Langfuse"></p> <p data-svelte-h="svelte-ujuql6"><em><a href="https://cloud.langfuse.com/project/cloramnkj0002jz088vzn1ja4/traces/f5d6d72e-20af-4357-b232-af44c3728a7b?timestamp=2025-03-17T10%3A13%3A28.413Z&observation=6997ba69-043f-4f77-9445-700a033afba1" rel="nofollow">Lien public vers la trace avec l’email légitime</a></em></p> <h2 class="relative group"><a id="visualiser-notre-graphe" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#visualiser-notre-graphe"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Visualiser notre graphe</span></h2> <p data-svelte-h="svelte-mw5vba">LangGraph nous permet de visualiser notre <em>workflow</em> pour mieux comprendre et déboguer sa structure :</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START -->compiled_graph.get_graph().draw_mermaid_png()<!-- HTML_TAG_END --></pre></div> <img src="https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/LangGraph/mail_flow.png" alt="Mail LangGraph"> <p data-svelte-h="svelte-v54btz">Cela produit une représentation visuelle montrant comment nos nœuds sont connectés et les chemins conditionnels qui peuvent être pris.</p> <h2 class="relative group"><a id="ce-que-nous-avons-construit" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#ce-que-nous-avons-construit"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Ce que nous avons construit</span></h2> <p data-svelte-h="svelte-1gki4s6">Nous avons créé un <em>workflow</em> complet de traitement des emails qui :</p> <ol data-svelte-h="svelte-khkzyp"><li>Prend un email entrant</li> <li>Utilise un LLM pour le classifier comme spam ou légitime</li> <li>Gère le spam en le rejetant</li> <li>Pour les emails légitimes, rédige une réponse et informe M. Hugg</li></ol> <p data-svelte-h="svelte-1fawh0f">Cela démontre la puissance de LangGraph pour orchestrer des <em>workflows</em> complexes avec des LLM tout en maintenant un flux clair et structuré.</p> <h2 class="relative group"><a id="points-clés-à-retenir" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#points-clés-à-retenir"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Points clés à retenir</span></h2> <ul data-svelte-h="svelte-2wb9vm"><li><strong>Gestion d’état</strong> : Nous avons défini un état complet pour suivre tous les aspects du traitement des emails</li> <li><strong>Implémentation de nœuds</strong> : Nous avons créé des nœuds fonctionnels qui interagissent avec un LLM</li> <li><strong>Routage conditionnel</strong> : Nous avons implémenté une logique d’embranchement basée sur la classification des emails</li> <li><strong>États terminaux</strong> : Nous avons utilisé le nœud <em>END</em> pour marquer les points d’achèvement dans notre <em>workflow</em></li></ul> <h2 class="relative group"><a id="et-maintenant-" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#et-maintenant-"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Et maintenant ?</span></h2> <p data-svelte-h="svelte-9gepeu">Dans la prochaine section, nous explorerons des fonctionnalités plus avancées de LangGraph, y compris la gestion de l’interaction humaine dans le <em>workflow</em> et l’implémentation d’une logique d’embranchement plus complexe basée sur plusieurs conditions.</p> <a class="!text-gray-400 !no-underline text-sm flex items-center not-prose mt-4" href="https://github.com/huggingface/agents-course/blob/main/units/fr/unit2/langgraph/first_graph.mdx" target="_blank"><svg class="mr-1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M31,16l-7,7l-1.41-1.41L28.17,16l-5.58-5.59L24,9l7,7z"></path><path d="M1,16l7-7l1.41,1.41L3.83,16l5.58,5.59L8,23l-7-7z"></path><path d="M12.419,25.484L17.639,6.552l1.932,0.518L14.351,26.002z"></path></svg> <span data-svelte-h="svelte-zjs2n5"><span class="underline">Update</span> on GitHub</span></a> <p></p>
<script>
{
__sveltekit_1b31nyx = {
assets: "/docs/agents-course/pr_673/fr",
base: "/docs/agents-course/pr_673/fr",
env: {}
};
const element = document.currentScript.parentElement;
const data = [null,null];
Promise.all([
import("/docs/agents-course/pr_673/fr/_app/immutable/entry/start.6a3cabb6.js"),
import("/docs/agents-course/pr_673/fr/_app/immutable/entry/app.bbc296eb.js")
]).then(([kit, app]) => {
kit.start(app, element, {
node_ids: [0, 40],
data,
form: null,
error: null
});
});
}
</script>

Xet Storage Details

Size:
65.9 kB
·
Xet hash:
84940d7abddf079a3331301fab5e2e743d490aa3ab6ff051d7952670a933ed1f

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.