import{s as jt,a as yt,n as ct,o as wt}from"../chunks/scheduler.505acc25.js";import{S as mt,i as ot,e,s as n,c as p,h as It,a as U,d as t,b as M,f as it,g as T,j as J,k as hl,l as Ct,m as a,n as y,t as i,o as j,p as c}from"../chunks/index.b1175496.js";import{C as ut,H as w}from"../chunks/Heading.eda51538.js";import{C as m}from"../chunks/CodeBlock.9d480d26.js";import{E as rt}from"../chunks/MermaidChart.svelte_svelte_type_style_lang.ea377ea6.js";function ht(As){let o,Bl,gl,Vl,C,dl,u,Ql,r,Fs="现在我们已经理解了基本构建模块，让我们通过构建第一个功能图来实践。我们将实现 Alfred 的邮件处理系统，他需要：",Nl,h,Zs="<li>阅读 incoming emails</li> <li>将其分类为 spam 或 legitimate</li> <li>为 legitimate 邮件起草初步响应</li> <li>当邮件合法时向 Mr. Wayne 发送信息（仅打印）</li>",fl,g,Es="这个示例演示了如何使用 LangGraph 构建涉及基于 LLM 决策的工作流程结构。虽然这不能算是真正的 Agent（因为没有涉及工具），但本节更侧重于学习 LangGraph 框架而非 Agents。",Sl,I,Gs='<p>你可以在 <a href="https://huggingface.co/agents-course/notebooks/resolve/main/unit2/langgraph/mail_sorting.ipynb" target="_blank">这个 notebook</a> 中查看完整代码，并通过 Google Colab 运行。</p>',Al,b,Fl,B,Rs="这是我们将要构建的工作流程：",Zl,V,Ws,El,d,Gl,Q,qs="首先安装必要的包：",Rl,N,Wl,f,ks="接下来，让我们导入必要的模块：",ql,S,kl,A,Yl,F,Ys="让我们定义 Alfred 在电子邮件处理工作流程中需要跟踪哪些信息：",_l,Z,$l,E,_s="<p>💡 <strong>提示：</strong>让您的状态足够全面，以跟踪所有重要信息，但避免用不必要的细节使其变得臃肿。</p>",zl,G,Xl,R,$s="现在，让我们创建将形成我们节点的处理函数：",xl,W,vl,q,Ol,k,zs="我们需要一个函数来确定分类后要采取哪条路径：",Hl,Y,Ll,_,Xs="<p>💡 <strong>注意：</strong> LangGraph 调用此路由函数来确定在分类节点之后要跟随哪条边。返回值必须与我们的条件边映射中的一个键匹配。</p>",Dl,$,Kl,z,xs="现在我们将所有内容连接在一起：",Pl,X,ls,x,vs="注意我们如何使用 LangGraph 提供的特殊“END”节点。这表示工作流完成的终端状态。",ss,v,ts,O,Os="让我们用一封合法的电子邮件和一封垃圾邮件来测试我们的图表：",as,H,ns,L,Ms,D,Hs="随着 Alfred 对主分类智能体进行微调，他越来越厌倦调试其运行。智能体本质上是不可预测的，难以检查。但由于他的目标是构建终极垃圾邮件检测智能体并将其部署到生产中，因此他需要强大的可追溯性以供将来监控和分析。",es,K,Ls='为此，Alfred 可以使用可观察性工具（例如 <a href="https://langfuse.com/" rel="nofollow">Langfuse</a>）来跟踪和监控智能体。',Us,P,Ds="首先，我们 pip install Langfuse：",Js,ll,ps,sl,Ks='接下来，我们将 Langfuse API 密钥和主机地址添加为环境变量。您可以通过注册 <a href="https://cloud.langfuse.com" rel="nofollow">Langfuse Cloud</a> 或 <a href="https://langfuse.com/self-hosting" rel="nofollow">self-host Langfuse</a> 获取 Langfuse 凭据。',Ts,tl,ys,al,Ps='然后，我们配置 <a href="https://langfuse.com/docs/integrations/langchain/tracing#add-langfuse-to-your-langchain-application" rel="nofollow">Langfuse <code>callback_handler</code></a>，并通过将 <code>langfuse_callback</code> 添加到图的调用来检测智能体：<code>config={&quot;callbacks&quot;: [langfuse_handler]}</code>。',is,nl,js,Ml,lt="Alfred 现已连接 🔌！LangGraph 的运行记录在 Langfuse 中，使他能够全面了解智能体的行为。通过此设置，他可以重新查看之前的运行并进一步完善他的邮件分类智能体。",cs,el,st='<img src="https://langfuse.com/images/cookbook/huggingface-agent-course/langgraph-trace-legit.png" alt="Langfuse 中的示例跟踪"/>',ws,Ul,tt='<em><a href="https://cloud.langfuse.com/project/cloramnkj0002jz088vzn1ja4/traces/f5d6d72e-20af-4357-b232-af44c3728a7b?timestamp=2025-03-17T10%3A13%3A28.413Z&amp;observation=6997ba69-043f-4f77-9445-700a033afba1" rel="nofollow">带有合法电子邮件的跟踪的公共链接</a></em>',ms,Jl,os,pl,at="LangGraph 允许我们可视化我们的工作流程，以便更好地理解和调试其结构：",Is,Tl,Cs,yl,nt,us,il,Mt="这会产生一个可视化表示，显示我们的节点如何连接以及可以采取的条件路径。",rs,jl,hs,cl,et="我们创建了一个完整的电子邮件处理工作流程：",gs,wl,Ut="<li>接收传入的电子邮件</li> <li>使用 LLM 将其分类为垃圾邮件或合法邮件</li> <li>通过丢弃垃圾邮件来处理垃圾邮件</li> <li>对于合法电子邮件，起草回复并通知 Mr. Hugg</li>",bs,ml,Jt="这展示了 LangGraph 使用 LLM 编排复杂工作流程同时保持清晰、结构化流程的强大功能。",Bs,ol,Vs,Il,pt="<li><strong>状态管理</strong>：我们定义了全面的状态来跟踪电子邮件处理的所有方面</li> <li><strong>节点实现</strong>：我们创建了与 LLM 交互的功能节点</li> <li><strong>条件路由</strong>：我们根据电子邮件分类实现了分支逻辑</li> <li><strong>终端状态</strong>：我们使用 END 节点标记工作流程中的完成点</li>",ds,Cl,Qs,ul,Tt="在下一部分中，我们将探索 LangGraph 的更多高级功能，包括处理工作流中的人机交互以及根据多种条件实现更复杂的分支逻辑。",Ns,rl,fs,bl,Ss;return C=new ut({props:{containerStyle:"float: right; margin-left: 10px; display: inline-flex; position: relative; z-index: 10;"}}),u=new w({props:{title:"构建你的第一个 LangGraph",local:"构建你的第一个-langgraph",headingTag:"h1"}}),b=new w({props:{title:"工作流程",local:"工作流程",headingTag:"h2"}}),d=new w({props:{title:"环境设置",local:"环境设置",headingTag:"h2"}}),N=new m({props:{code:"JTI1cGlwJTIwaW5zdGFsbCUyMGxhbmdncmFwaCUyMGxhbmdjaGFpbl9vcGVuYWk=",highlighted:"%pip install langgraph langchain_openai",wrap:!1}}),S=new m({props:{code:"aW1wb3J0JTIwb3MlMEFmcm9tJTIwdHlwaW5nJTIwaW1wb3J0JTIwVHlwZWREaWN0JTJDJTIwTGlzdCUyQyUyMERpY3QlMkMlMjBBbnklMkMlMjBPcHRpb25hbCUwQWZyb20lMjBsYW5nZ3JhcGguZ3JhcGglMjBpbXBvcnQlMjBTdGF0ZUdyYXBoJTJDJTIwRU5EJTBBZnJvbSUyMGxhbmdjaGFpbl9vcGVuYWklMjBpbXBvcnQlMjBDaGF0T3BlbkFJJTBBZnJvbSUyMGxhbmdjaGFpbl9jb3JlLm1lc3NhZ2VzJTIwaW1wb3J0JTIwSHVtYW5NZXNzYWdlJTJDJTIwQUlNZXNzYWdl",highlighted:`<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, 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, AIMessage`,wrap:!1}}),A=new w({props:{title:"步骤 1：定义我们的状态",local:"步骤-1定义我们的状态",headingTag:"h2"}}),Z=new m({props:{code:"Y2xhc3MlMjBFbWFpbFN0YXRlKFR5cGVkRGljdCklM0ElMEElMjAlMjAlMjAlMjAlMjMlMjAlRTYlQUQlQTMlRTUlOUMlQTglRTUlQTQlODQlRTclOTAlODYlRTclOUElODQlRTclOTQlQjUlRTUlQUQlOTAlRTklODIlQUUlRTQlQkIlQjYlMEElMjAlMjAlMjAlMjBlbWFpbCUzQSUyMERpY3QlNUJzdHIlMkMlMjBBbnklNUQlMjAlMjAlMjMlMjAlRTUlOEMlODUlRTUlOTAlQUIlRTQlQjglQkIlRTklQTIlOTglRTMlODAlODElRTUlOEYlOTElRTQlQkIlQjYlRTQlQkElQkElRTMlODAlODElRTYlQUQlQTMlRTYlOTYlODclRTclQUQlODklRTMlODAlODIlMEElMjAlMjAlMjAlMjAlMEElMjAlMjAlMjAlMjAlMjMlMjAlRTUlODglODYlRTYlOUUlOTAlRTQlQjglOEUlRTUlODYlQjMlRTclQUQlOTYlMEElMjAlMjAlMjAlMjBpc19zcGFtJTNBJTIwT3B0aW9uYWwlNUJib29sJTVEJTBBJTIwJTIwJTIwJTIwJTBBJTIwJTIwJTIwJTIwJTIzJTIwJUU1JTkzJThEJUU1JUJBJTk0JUU3JTk0JTlGJUU2JTg4JTkwJTBBJTIwJTIwJTIwJTIwZHJhZnRfcmVzcG9uc2UlM0ElMjBPcHRpb25hbCU1QnN0ciU1RCUwQSUyMCUyMCUyMCUyMCUwQSUyMCUyMCUyMCUyMCUyMyUyMCVFNSVBNCU4NCVFNyU5MCU4NiVFNSU4NSU4MyVFNiU5NSVCMCVFNiU4RCVBRSUwQSUyMCUyMCUyMCUyMG1lc3NhZ2VzJTNBJTIwTGlzdCU1QkRpY3QlNUJzdHIlMkMlMjBBbnklNUQlNUQlMjAlMjAlMjMlMjAlRTglQjclOUYlRTglQjglQUElRTQlQjglOEUlMjBMTE0lMjAlRTclOUElODQlRTUlQUYlQjklRTglQUYlOUQlRTQlQkIlQTUlRTglQkYlOUIlRTglQTElOEMlRTUlODglODYlRTYlOUUlOTA=",highlighted:`<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"># 正在处理的电子邮件</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"># 包含主题、发件人、正文等。</span>
    
    <span class="hljs-comment"># 分析与决策</span>
    is_spam: <span class="hljs-type">Optional</span>[<span class="hljs-built_in">bool</span>]
    
    <span class="hljs-comment"># 响应生成</span>
    draft_response: <span class="hljs-type">Optional</span>[<span class="hljs-built_in">str</span>]
    
    <span class="hljs-comment"># 处理元数据</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"># 跟踪与 LLM 的对话以进行分析</span>`,wrap:!1}}),G=new w({props:{title:"第 2 步：定义我们的节点",local:"第-2-步定义我们的节点",headingTag:"h2"}}),W=new m({props:{code:" ",highlighted:`<span class="hljs-comment"># Initialize our 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 reads and logs the incoming email&quot;&quot;&quot;</span>
    email = state[<span class="hljs-string">&quot;email&quot;</span>]
    
    <span class="hljs-comment"># 在这里我们可能会做一些初步的预处理</span>
    <span class="hljs-built_in">print</span>(<span class="hljs-string">f&quot;Alfred is processing an email from <span class="hljs-subst">{email[<span class="hljs-string">&#x27;sender&#x27;</span>]}</span> with subject: <span class="hljs-subst">{email[<span class="hljs-string">&#x27;subject&#x27;</span>]}</span>&quot;</span>)
    
    <span class="hljs-comment"># 这里不需要更改状态</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 uses an LLM to determine if the email is spam or legitimate&quot;&quot;&quot;</span>
    email = state[<span class="hljs-string">&quot;email&quot;</span>]
    
    <span class="hljs-comment"># 为 LLM 准备提示</span>
    prompt = <span class="hljs-string">f&quot;&quot;&quot;
    As Alfred the butler, analyze this email and determine if it is spam or legitimate.
    
    Email:
    From: <span class="hljs-subst">{email[<span class="hljs-string">&#x27;sender&#x27;</span>]}</span>
    Subject: <span class="hljs-subst">{email[<span class="hljs-string">&#x27;subject&#x27;</span>]}</span>
    Body: <span class="hljs-subst">{email[<span class="hljs-string">&#x27;body&#x27;</span>]}</span>
    
    First, determine if this email is spam. If it is spam, explain why.
    If it is legitimate, categorize it (inquiry, complaint, thank you, etc.).
    &quot;&quot;&quot;</span>
    
    <span class="hljs-comment"># Call the LLM</span>
    messages = [HumanMessage(content=prompt)]
    response = model.invoke(messages)
    
    <span class="hljs-comment"># 解析响应的简单逻辑（在实际应用中，您需要更强大的解析）</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"># 如果是垃圾邮件，请提取原因</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"># 确定类别是否合法</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"># 更新消息以进行追踪</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"># 返回状态更新</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 discards spam email with a note&quot;&quot;&quot;</span>
    <span class="hljs-built_in">print</span>(<span class="hljs-string">f&quot;Alfred has marked the email as spam. Reason: <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;The email has been moved to the spam folder.&quot;</span>)
    
    <span class="hljs-comment"># 我们已处理完这封电子邮件</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 drafts a preliminary response for legitimate emails&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"># 为 LLM 准备提示词</span>
    prompt = <span class="hljs-string">f&quot;&quot;&quot;
    As Alfred the butler, draft a polite preliminary response to this email.
    
    Email:
    From: <span class="hljs-subst">{email[<span class="hljs-string">&#x27;sender&#x27;</span>]}</span>
    Subject: <span class="hljs-subst">{email[<span class="hljs-string">&#x27;subject&#x27;</span>]}</span>
    Body: <span class="hljs-subst">{email[<span class="hljs-string">&#x27;body&#x27;</span>]}</span>
    
    This email has been categorized as: <span class="hljs-subst">{category}</span>
    
    Draft a brief, professional response that Mr. Hugg can review and personalize before sending.
    &quot;&quot;&quot;</span>
    
    <span class="hljs-comment"># Call the LLM</span>
    messages = [HumanMessage(content=prompt)]
    response = model.invoke(messages)
    
    <span class="hljs-comment"># 更新消息以进行追踪</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"># 返回状态更新</span>
    <span class="hljs-keyword">return</span> {
        <span class="hljs-string">&quot;draft_response&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 notifies Mr. Hugg about the email and presents the draft response&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;Sir, you&#x27;ve received an email from <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;Subject: <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;Category: <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;\\nI&#x27;ve prepared a draft response for your review:&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;draft_response&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"># 我们已处理完这封电子邮件</span>
    <span class="hljs-keyword">return</span> {}`,wrap:!1}}),q=new w({props:{title:"步骤 3：定义我们的路由逻辑",local:"步骤-3定义我们的路由逻辑",headingTag:"h2"}}),Y=new m({props:{code:"ZGVmJTIwcm91dGVfZW1haWwoc3RhdGUlM0ElMjBFbWFpbFN0YXRlKSUyMC0lM0UlMjBzdHIlM0ElMEElMjAlMjAlMjAlMjAlMjIlMjIlMjJEZXRlcm1pbmUlMjB0aGUlMjBuZXh0JTIwc3RlcCUyMGJhc2VkJTIwb24lMjBzcGFtJTIwY2xhc3NpZmljYXRpb24lMjIlMjIlMjIlMEElMjAlMjAlMjAlMjBpZiUyMHN0YXRlJTVCJTIyaXNfc3BhbSUyMiU1RCUzQSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMHJldHVybiUyMCUyMnNwYW0lMjIlMEElMjAlMjAlMjAlMjBlbHNlJTNBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwcmV0dXJuJTIwJTIybGVnaXRpbWF0ZSUyMg==",highlighted:`<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;Determine the next step based on spam classification&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>`,wrap:!1}}),$=new w({props:{title:"步骤 4：创建 StateGraph 并定义边",local:"步骤-4创建-stategraph-并定义边",headingTag:"h2"}}),X=new m({props:{code:"JTIzJTIwJUU1JTg4JTlCJUU1JUJCJUJBJTIwZ3JhcGglMEFlbWFpbF9ncmFwaCUyMCUzRCUyMFN0YXRlR3JhcGgoRW1haWxTdGF0ZSklMEElMEElMjMlMjAlRTYlQjclQkIlRTUlOEElQTAlMjBub2RlcyUwQWVtYWlsX2dyYXBoLmFkZF9ub2RlKCUyMnJlYWRfZW1haWwlMjIlMkMlMjByZWFkX2VtYWlsKSUwQWVtYWlsX2dyYXBoLmFkZF9ub2RlKCUyMmNsYXNzaWZ5X2VtYWlsJTIyJTJDJTIwY2xhc3NpZnlfZW1haWwpJTBBZW1haWxfZ3JhcGguYWRkX25vZGUoJTIyaGFuZGxlX3NwYW0lMjIlMkMlMjBoYW5kbGVfc3BhbSklMEFlbWFpbF9ncmFwaC5hZGRfbm9kZSglMjJkcmFmdF9yZXNwb25zZSUyMiUyQyUyMGRyYWZ0X3Jlc3BvbnNlKSUwQWVtYWlsX2dyYXBoLmFkZF9ub2RlKCUyMm5vdGlmeV9tcl9odWdnJTIyJTJDJTIwbm90aWZ5X21yX2h1Z2cpJTBBJTBBJTIzJTIwJUU2JUI3JUJCJUU1JThBJUEwJTIwZWRnZXMlMjAtJTIwJUU1JUFFJTlBJUU0JUI5JTg5JUU2JUI1JTgxJUU3JUE4JThCJTBBZW1haWxfZ3JhcGguYWRkX2VkZ2UoJTIycmVhZF9lbWFpbCUyMiUyQyUyMCUyMmNsYXNzaWZ5X2VtYWlsJTIyKSUwQSUwQSUyMyUyMCVFNCVCQiU4RSUyMGNsYXNzaWZ5X2VtYWlsJTIwJUU2JUI3JUJCJUU1JThBJUEwJUU2JTlEJUExJUU0JUJCJUI2JUU1JTg4JTg2JUU2JTk0JUFGJTBBZW1haWxfZ3JhcGguYWRkX2NvbmRpdGlvbmFsX2VkZ2VzKCUwQSUyMCUyMCUyMCUyMCUyMmNsYXNzaWZ5X2VtYWlsJTIyJTJDJTBBJTIwJTIwJTIwJTIwcm91dGVfZW1haWwlMkMlMEElMjAlMjAlMjAlMjAlN0IlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjJzcGFtJTIyJTNBJTIwJTIyaGFuZGxlX3NwYW0lMjIlMkMlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjJsZWdpdGltYXRlJTIyJTNBJTIwJTIyZHJhZnRfcmVzcG9uc2UlMjIlMEElMjAlMjAlMjAlMjAlN0QlMEEpJTBBJTBBJTIzJTIwJUU2JUI3JUJCJUU1JThBJUEwJUU2JTlDJTgwJUU1JTkwJThFJUU3JTlBJTg0JTIwZWRnZXMlMEFlbWFpbF9ncmFwaC5hZGRfZWRnZSglMjJoYW5kbGVfc3BhbSUyMiUyQyUyMEVORCklMEFlbWFpbF9ncmFwaC5hZGRfZWRnZSglMjJkcmFmdF9yZXNwb25zZSUyMiUyQyUyMCUyMm5vdGlmeV9tcl9odWdnJTIyKSUwQWVtYWlsX2dyYXBoLmFkZF9lZGdlKCUyMm5vdGlmeV9tcl9odWdnJTIyJTJDJTIwRU5EKSUwQSUwQSUyMyUyMCVFNyVCQyU5NiVFOCVBRiU5MSUyMGdyYXBoJTBBY29tcGlsZWRfZ3JhcGglMjAlM0QlMjBlbWFpbF9ncmFwaC5jb21waWxlKCk=",highlighted:`<span class="hljs-comment"># 创建 graph</span>
email_graph = StateGraph(EmailState)

<span class="hljs-comment"># 添加 nodes</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"># 添加 edges - 定义流程</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"># 从 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"># 添加最后的 edges</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"># 编译 graph</span>
compiled_graph = email_graph.<span class="hljs-built_in">compile</span>()`,wrap:!1}}),v=new w({props:{title:"步骤 5：运行应用程序",local:"步骤-5运行应用程序",headingTag:"h2"}}),H=new m({props:{code:"JTIzJTIwJUU1JTkwJTg4JUU2JUIzJTk1JUU3JTk0JUI1JUU1JUFEJTkwJUU5JTgyJUFFJUU0JUJCJUI2JUU3JUE0JUJBJUU0JUJFJThCJTBBbGVnaXRpbWF0ZV9lbWFpbCUyMCUzRCUyMCU3QiUwQSUyMCUyMCUyMCUyMCUyMnNlbmRlciUyMiUzQSUyMCUyMmpvaG4uc21pdGglNDBleGFtcGxlLmNvbSUyMiUyQyUwQSUyMCUyMCUyMCUyMCUyMnN1YmplY3QlMjIlM0ElMjAlMjJRdWVzdGlvbiUyMGFib3V0JTIweW91ciUyMHNlcnZpY2VzJTIyJTJDJTBBJTIwJTIwJTIwJTIwJTIyYm9keSUyMiUzQSUyMCUyMkRlYXIlMjBNci4lMjBIdWdnJTJDJTIwSSUyMHdhcyUyMHJlZmVycmVkJTIwdG8lMjB5b3UlMjBieSUyMGElMjBjb2xsZWFndWUlMjBhbmQlMjBJJ20lMjBpbnRlcmVzdGVkJTIwaW4lMjBsZWFybmluZyUyMG1vcmUlMjBhYm91dCUyMHlvdXIlMjBjb25zdWx0aW5nJTIwc2VydmljZXMuJTIwQ291bGQlMjB3ZSUyMHNjaGVkdWxlJTIwYSUyMGNhbGwlMjBuZXh0JTIwd2VlayUzRiUyMEJlc3QlMjByZWdhcmRzJTJDJTIwSm9obiUyMFNtaXRoJTIyJTBBJTdEJTBBJTBBJTIzJTIwJUU1JTlFJTgzJUU1JTlDJUJFJUU5JTgyJUFFJUU0JUJCJUI2JUU3JUE0JUJBJUU0JUJFJThCJTBBc3BhbV9lbWFpbCUyMCUzRCUyMCU3QiUwQSUyMCUyMCUyMCUyMCUyMnNlbmRlciUyMiUzQSUyMCUyMndpbm5lciU0MGxvdHRlcnktaW50bC5jb20lMjIlMkMlMEElMjAlMjAlMjAlMjAlMjJzdWJqZWN0JTIyJTNBJTIwJTIyWU9VJTIwSEFWRSUyMFdPTiUyMCUyNDUlMkMwMDAlMkMwMDAhISElMjIlMkMlMEElMjAlMjAlMjAlMjAlMjJib2R5JTIyJTNBJTIwJTIyQ09OR1JBVFVMQVRJT05TISUyMFlvdSUyMGhhdmUlMjBiZWVuJTIwc2VsZWN0ZWQlMjBhcyUyMHRoZSUyMHdpbm5lciUyMG9mJTIwb3VyJTIwaW50ZXJuYXRpb25hbCUyMGxvdHRlcnkhJTIwVG8lMjBjbGFpbSUyMHlvdXIlMjAlMjQ1JTJDMDAwJTJDMDAwJTIwcHJpemUlMkMlMjBwbGVhc2UlMjBzZW5kJTIwdXMlMjB5b3VyJTIwYmFuayUyMGRldGFpbHMlMjBhbmQlMjBhJTIwcHJvY2Vzc2luZyUyMGZlZSUyMG9mJTIwJTI0MTAwLiUyMiUwQSU3RCUwQSUwQSUyMyUyMCVFNSVBNCU4NCVFNyU5MCU4NiVFNSU5MCU4OCVFNiVCMyU5NSVFNyU5NCVCNSVFNSVBRCU5MCVFOSU4MiVBRSVFNCVCQiVCNiUwQXByaW50KCUyMiU1Q25Qcm9jZXNzaW5nJTIwbGVnaXRpbWF0ZSUyMGVtYWlsLi4uJTIyKSUwQWxlZ2l0aW1hdGVfcmVzdWx0JTIwJTNEJTIwY29tcGlsZWRfZ3JhcGguaW52b2tlKCU3QiUwQSUyMCUyMCUyMCUyMCUyMmVtYWlsJTIyJTNBJTIwbGVnaXRpbWF0ZV9lbWFpbCUyQyUwQSUyMCUyMCUyMCUyMCUyMmlzX3NwYW0lMjIlM0ElMjBOb25lJTJDJTBBJTIwJTIwJTIwJTIwJTIyc3BhbV9yZWFzb24lMjIlM0ElMjBOb25lJTJDJTBBJTIwJTIwJTIwJTIwJTIyZW1haWxfY2F0ZWdvcnklMjIlM0ElMjBOb25lJTJDJTBBJTIwJTIwJTIwJTIwJTIyZHJhZnRfcmVzcG9uc2UlMjIlM0ElMjBOb25lJTJDJTBBJTIwJTIwJTIwJTIwJTIybWVzc2FnZXMlMjIlM0ElMjAlNUIlNUQlMEElN0QpJTBBJTBBJTIzJTIwJUU1JUE0JTg0JUU3JTkwJTg2JUU1JTlFJTgzJUU1JTlDJUJFJUU5JTgyJUFFJUU0JUJCJUI2JTBBcHJpbnQoJTIyJTVDblByb2Nlc3NpbmclMjBzcGFtJTIwZW1haWwuLi4lMjIpJTBBc3BhbV9yZXN1bHQlMjAlM0QlMjBjb21waWxlZF9ncmFwaC5pbnZva2UoJTdCJTBBJTIwJTIwJTIwJTIwJTIyZW1haWwlMjIlM0ElMjBzcGFtX2VtYWlsJTJDJTBBJTIwJTIwJTIwJTIwJTIyaXNfc3BhbSUyMiUzQSUyME5vbmUlMkMlMEElMjAlMjAlMjAlMjAlMjJzcGFtX3JlYXNvbiUyMiUzQSUyME5vbmUlMkMlMEElMjAlMjAlMjAlMjAlMjJlbWFpbF9jYXRlZ29yeSUyMiUzQSUyME5vbmUlMkMlMEElMjAlMjAlMjAlMjAlMjJkcmFmdF9yZXNwb25zZSUyMiUzQSUyME5vbmUlMkMlMEElMjAlMjAlMjAlMjAlMjJtZXNzYWdlcyUyMiUzQSUyMCU1QiU1RCUwQSU3RCk=",highlighted:`<span class="hljs-comment"># 合法电子邮件示例</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 about your services&quot;</span>,
    <span class="hljs-string">&quot;body&quot;</span>: <span class="hljs-string">&quot;Dear Mr. Hugg, I was referred to you by a colleague and I&#x27;m interested in learning more about your consulting services. Could we schedule a call next week? Best regards, John Smith&quot;</span>
}

<span class="hljs-comment"># 垃圾邮件示例</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;YOU HAVE WON $5,000,000!!!&quot;</span>,
    <span class="hljs-string">&quot;body&quot;</span>: <span class="hljs-string">&quot;CONGRATULATIONS! You have been selected as the winner of our international lottery! To claim your $5,000,000 prize, please send us your bank details and a processing fee of $100.&quot;</span>
}

<span class="hljs-comment"># 处理合法电子邮件</span>
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;\\nProcessing legitimate email...&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;draft_response&quot;</span>: <span class="hljs-literal">None</span>,
    <span class="hljs-string">&quot;messages&quot;</span>: []
})

<span class="hljs-comment"># 处理垃圾邮件</span>
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;\\nProcessing spam email...&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;draft_response&quot;</span>: <span class="hljs-literal">None</span>,
    <span class="hljs-string">&quot;messages&quot;</span>: []
})`,wrap:!1}}),L=new w({props:{title:"第 6 步：使用 Langfuse 检查我们的邮件分类智能体 📡",local:"第-6-步使用-langfuse-检查我们的邮件分类智能体-",headingTag:"h2"}}),ll=new m({props:{code:"JTI1cGlwJTIwaW5zdGFsbCUyMC1xJTIwbGFuZ2Z1c2U=",highlighted:"%pip install -q langfuse",wrap:!1}}),tl=new m({props:{code:"aW1wb3J0JTIwb3MlMEElMjAlMEElMjMlMjBHZXQlMjBrZXlzJTIwZm9yJTIweW91ciUyMHByb2plY3QlMjBmcm9tJTIwdGhlJTIwcHJvamVjdCUyMHNldHRpbmdzJTIwcGFnZSUzQSUyMGh0dHBzJTNBJTJGJTJGY2xvdWQubGFuZ2Z1c2UuY29tJTBBb3MuZW52aXJvbiU1QiUyMkxBTkdGVVNFX1BVQkxJQ19LRVklMjIlNUQlMjAlM0QlMjAlMjJway1sZi0uLi4lMjIlMjAlMEFvcy5lbnZpcm9uJTVCJTIyTEFOR0ZVU0VfU0VDUkVUX0tFWSUyMiU1RCUyMCUzRCUyMCUyMnNrLWxmLS4uLiUyMiUwQW9zLmVudmlyb24lNUIlMjJMQU5HRlVTRV9IT1NUJTIyJTVEJTIwJTNEJTIwJTIyaHR0cHMlM0ElMkYlMkZjbG91ZC5sYW5nZnVzZS5jb20lMjIlMjAlMjMlMjAlRjAlOUYlODclQUElRjAlOUYlODclQkElMjBFVSUyMHJlZ2lvbiUwQSUyMyUyMG9zLmVudmlyb24lNUIlMjJMQU5HRlVTRV9IT1NUJTIyJTVEJTIwJTNEJTIwJTIyaHR0cHMlM0ElMkYlMkZ1cy5jbG91ZC5sYW5nZnVzZS5jb20lMjIlMjAlMjMlMjAlRjAlOUYlODclQkElRjAlOUYlODclQjglMjBVUyUyMHJlZ2lvbg==",highlighted:`<span class="hljs-keyword">import</span> os
 
<span class="hljs-comment"># Get keys for your project from the project settings page: 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"># 🇪🇺 EU region</span>
<span class="hljs-comment"># os.environ[&quot;LANGFUSE_HOST&quot;] = &quot;https://us.cloud.langfuse.com&quot; # 🇺🇸 US region</span>`,wrap:!1}}),nl=new m({props:{code:"ZnJvbSUyMGxhbmdmdXNlLmxhbmdjaGFpbiUyMGltcG9ydCUyMENhbGxiYWNrSGFuZGxlciUwQSUwQSUyMyUyMCVFNCVCOCVCQSUyMExhbmdHcmFwaCUyRkxhbmdjaGFpbiUyMCVFNSU4OCU5RCVFNSVBNyU4QiVFNSU4QyU5NiUyMExhbmdmdXNlJTIwQ2FsbGJhY2tIYW5kbGVyJUVGJUJDJTg4JUU4JUI3JTlGJUU4JUI4JUFBJUVGJUJDJTg5JTBBbGFuZ2Z1c2VfaGFuZGxlciUyMCUzRCUyMENhbGxiYWNrSGFuZGxlcigpJTBBJTBBJTIzJTIwJUU1JUE0JTg0JUU3JTkwJTg2JUU1JTkwJTg4JUU2JUIzJTk1JUU3JTk0JUI1JUU1JUFEJTkwJUU5JTgyJUFFJUU0JUJCJUI2JTBBbGVnaXRpbWF0ZV9yZXN1bHQlMjAlM0QlMjBjb21waWxlZF9ncmFwaC5pbnZva2UoJTBBJTIwJTIwJTIwJTIwaW5wdXQlM0QlN0IlMjJlbWFpbCUyMiUzQSUyMGxlZ2l0aW1hdGVfZW1haWwlMkMlMjAlMjJpc19zcGFtJTIyJTNBJTIwTm9uZSUyQyUyMCUyMnNwYW1fcmVhc29uJTIyJTNBJTIwTm9uZSUyQyUyMCUyMmVtYWlsX2NhdGVnb3J5JTIyJTNBJTIwTm9uZSUyQyUyMCUyMmRyYWZ0X3Jlc3BvbnNlJTIyJTNBJTIwTm9uZSUyQyUyMCUyMm1lc3NhZ2VzJTIyJTNBJTIwJTVCJTVEJTdEJTJDJTBBJTIwJTIwJTIwJTIwY29uZmlnJTNEJTdCJTIyY2FsbGJhY2tzJTIyJTNBJTIwJTVCbGFuZ2Z1c2VfaGFuZGxlciU1RCU3RCUwQSk=",highlighted:`<span class="hljs-keyword">from</span> langfuse.langchain <span class="hljs-keyword">import</span> CallbackHandler

<span class="hljs-comment"># 为 LangGraph/Langchain 初始化 Langfuse CallbackHandler（跟踪）</span>
langfuse_handler = CallbackHandler()

<span class="hljs-comment"># 处理合法电子邮件</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]}
)`,wrap:!1}}),Jl=new w({props:{title:"可视化我们的图表",local:"可视化我们的图表",headingTag:"h2"}}),Tl=new m({props:{code:"Y29tcGlsZWRfZ3JhcGguZ2V0X2dyYXBoKCkuZHJhd19tZXJtYWlkX3BuZygp",highlighted:"compiled_graph.get_graph().draw_mermaid_png()",wrap:!1}}),jl=new w({props:{title:"我们构建了什么",local:"我们构建了什么",headingTag:"h2"}}),ol=new w({props:{title:"关键要点",local:"关键要点",headingTag:"h2"}}),Cl=new w({props:{title:"下一步是什么？",local:"下一步是什么",headingTag:"h2"}}),rl=new rt({props:{source:"https://github.com/huggingface/agents-course/blob/main/units/zh-CN/unit2/langgraph/first_graph.mdx"}}),{c(){o=e("meta"),Bl=n(),gl=e("p"),Vl=n(),p(C.$$.fragment),dl=n(),p(u.$$.fragment),Ql=n(),r=e("p"),r.textContent=Fs,Nl=n(),h=e("ol"),h.innerHTML=Zs,fl=n(),g=e("p"),g.textContent=Es,Sl=n(),I=e("blockquote"),I.innerHTML=Gs,Al=n(),p(b.$$.fragment),Fl=n(),B=e("p"),B.textContent=Rs,Zl=n(),V=e("img"),El=n(),p(d.$$.fragment),Gl=n(),Q=e("p"),Q.textContent=qs,Rl=n(),p(N.$$.fragment),Wl=n(),f=e("p"),f.textContent=ks,ql=n(),p(S.$$.fragment),kl=n(),p(A.$$.fragment),Yl=n(),F=e("p"),F.textContent=Ys,_l=n(),p(Z.$$.fragment),$l=n(),E=e("blockquote"),E.innerHTML=_s,zl=n(),p(G.$$.fragment),Xl=n(),R=e("p"),R.textContent=$s,xl=n(),p(W.$$.fragment),vl=n(),p(q.$$.fragment),Ol=n(),k=e("p"),k.textContent=zs,Hl=n(),p(Y.$$.fragment),Ll=n(),_=e("blockquote"),_.innerHTML=Xs,Dl=n(),p($.$$.fragment),Kl=n(),z=e("p"),z.textContent=xs,Pl=n(),p(X.$$.fragment),ls=n(),x=e("p"),x.textContent=vs,ss=n(),p(v.$$.fragment),ts=n(),O=e("p"),O.textContent=Os,as=n(),p(H.$$.fragment),ns=n(),p(L.$$.fragment),Ms=n(),D=e("p"),D.textContent=Hs,es=n(),K=e("p"),K.innerHTML=Ls,Us=n(),P=e("p"),P.textContent=Ds,Js=n(),p(ll.$$.fragment),ps=n(),sl=e("p"),sl.innerHTML=Ks,Ts=n(),p(tl.$$.fragment),ys=n(),al=e("p"),al.innerHTML=Ps,is=n(),p(nl.$$.fragment),js=n(),Ml=e("p"),Ml.textContent=lt,cs=n(),el=e("p"),el.innerHTML=st,ws=n(),Ul=e("p"),Ul.innerHTML=tt,ms=n(),p(Jl.$$.fragment),os=n(),pl=e("p"),pl.textContent=at,Is=n(),p(Tl.$$.fragment),Cs=n(),yl=e("img"),us=n(),il=e("p"),il.textContent=Mt,rs=n(),p(jl.$$.fragment),hs=n(),cl=e("p"),cl.textContent=et,gs=n(),wl=e("ol"),wl.innerHTML=Ut,bs=n(),ml=e("p"),ml.textContent=Jt,Bs=n(),p(ol.$$.fragment),Vs=n(),Il=e("ul"),Il.innerHTML=pt,ds=n(),p(Cl.$$.fragment),Qs=n(),ul=e("p"),ul.textContent=Tt,Ns=n(),p(rl.$$.fragment),fs=n(),bl=e("p"),this.h()},l(l){const s=It("svelte-u9bgzb",document.head);o=U(s,"META",{name:!0,content:!0}),s.forEach(t),Bl=M(l),gl=U(l,"P",{}),it(gl).forEach(t),Vl=M(l),T(C.$$.fragment,l),dl=M(l),T(u.$$.fragment,l),Ql=M(l),r=U(l,"P",{"data-svelte-h":!0}),J(r)!=="svelte-wtpds"&&(r.textContent=Fs),Nl=M(l),h=U(l,"OL",{"data-svelte-h":!0}),J(h)!=="svelte-1w47pet"&&(h.innerHTML=Zs),fl=M(l),g=U(l,"P",{"data-svelte-h":!0}),J(g)!=="svelte-kmq3p0"&&(g.textContent=Es),Sl=M(l),I=U(l,"BLOCKQUOTE",{class:!0,"data-svelte-h":!0}),J(I)!=="svelte-gropo0"&&(I.innerHTML=Gs),Al=M(l),T(b.$$.fragment,l),Fl=M(l),B=U(l,"P",{"data-svelte-h":!0}),J(B)!=="svelte-kmmosp"&&(B.textContent=Rs),Zl=M(l),V=U(l,"IMG",{src:!0,alt:!0}),El=M(l),T(d.$$.fragment,l),Gl=M(l),Q=U(l,"P",{"data-svelte-h":!0}),J(Q)!=="svelte-i8w9z9"&&(Q.textContent=qs),Rl=M(l),T(N.$$.fragment,l),Wl=M(l),f=U(l,"P",{"data-svelte-h":!0}),J(f)!=="svelte-u3fqu"&&(f.textContent=ks),ql=M(l),T(S.$$.fragment,l),kl=M(l),T(A.$$.fragment,l),Yl=M(l),F=U(l,"P",{"data-svelte-h":!0}),J(F)!=="svelte-1oeecsl"&&(F.textContent=Ys),_l=M(l),T(Z.$$.fragment,l),$l=M(l),E=U(l,"BLOCKQUOTE",{"data-svelte-h":!0}),J(E)!=="svelte-1gaur76"&&(E.innerHTML=_s),zl=M(l),T(G.$$.fragment,l),Xl=M(l),R=U(l,"P",{"data-svelte-h":!0}),J(R)!=="svelte-r4wysq"&&(R.textContent=$s),xl=M(l),T(W.$$.fragment,l),vl=M(l),T(q.$$.fragment,l),Ol=M(l),k=U(l,"P",{"data-svelte-h":!0}),J(k)!=="svelte-se56vn"&&(k.textContent=zs),Hl=M(l),T(Y.$$.fragment,l),Ll=M(l),_=U(l,"BLOCKQUOTE",{"data-svelte-h":!0}),J(_)!=="svelte-1hjck2a"&&(_.innerHTML=Xs),Dl=M(l),T($.$$.fragment,l),Kl=M(l),z=U(l,"P",{"data-svelte-h":!0}),J(z)!=="svelte-1b8z0o4"&&(z.textContent=xs),Pl=M(l),T(X.$$.fragment,l),ls=M(l),x=U(l,"P",{"data-svelte-h":!0}),J(x)!=="svelte-cxg8gi"&&(x.textContent=vs),ss=M(l),T(v.$$.fragment,l),ts=M(l),O=U(l,"P",{"data-svelte-h":!0}),J(O)!=="svelte-9y4o4n"&&(O.textContent=Os),as=M(l),T(H.$$.fragment,l),ns=M(l),T(L.$$.fragment,l),Ms=M(l),D=U(l,"P",{"data-svelte-h":!0}),J(D)!=="svelte-1gah1tl"&&(D.textContent=Hs),es=M(l),K=U(l,"P",{"data-svelte-h":!0}),J(K)!=="svelte-p2eoxe"&&(K.innerHTML=Ls),Us=M(l),P=U(l,"P",{"data-svelte-h":!0}),J(P)!=="svelte-e1sodk"&&(P.textContent=Ds),Js=M(l),T(ll.$$.fragment,l),ps=M(l),sl=U(l,"P",{"data-svelte-h":!0}),J(sl)!=="svelte-1fd3ji6"&&(sl.innerHTML=Ks),Ts=M(l),T(tl.$$.fragment,l),ys=M(l),al=U(l,"P",{"data-svelte-h":!0}),J(al)!=="svelte-12a4tv9"&&(al.innerHTML=Ps),is=M(l),T(nl.$$.fragment,l),js=M(l),Ml=U(l,"P",{"data-svelte-h":!0}),J(Ml)!=="svelte-1vyc13"&&(Ml.textContent=lt),cs=M(l),el=U(l,"P",{"data-svelte-h":!0}),J(el)!=="svelte-ugmrhh"&&(el.innerHTML=st),ws=M(l),Ul=U(l,"P",{"data-svelte-h":!0}),J(Ul)!=="svelte-16dcubd"&&(Ul.innerHTML=tt),ms=M(l),T(Jl.$$.fragment,l),os=M(l),pl=U(l,"P",{"data-svelte-h":!0}),J(pl)!=="svelte-1ntiz7g"&&(pl.textContent=at),Is=M(l),T(Tl.$$.fragment,l),Cs=M(l),yl=U(l,"IMG",{src:!0,alt:!0}),us=M(l),il=U(l,"P",{"data-svelte-h":!0}),J(il)!=="svelte-10q7f2o"&&(il.textContent=Mt),rs=M(l),T(jl.$$.fragment,l),hs=M(l),cl=U(l,"P",{"data-svelte-h":!0}),J(cl)!=="svelte-cz9mlc"&&(cl.textContent=et),gs=M(l),wl=U(l,"OL",{"data-svelte-h":!0}),J(wl)!=="svelte-1raplg6"&&(wl.innerHTML=Ut),bs=M(l),ml=U(l,"P",{"data-svelte-h":!0}),J(ml)!=="svelte-aijfvw"&&(ml.textContent=Jt),Bs=M(l),T(ol.$$.fragment,l),Vs=M(l),Il=U(l,"UL",{"data-svelte-h":!0}),J(Il)!=="svelte-1i0l2cv"&&(Il.innerHTML=pt),ds=M(l),T(Cl.$$.fragment,l),Qs=M(l),ul=U(l,"P",{"data-svelte-h":!0}),J(ul)!=="svelte-1rewr8w"&&(ul.textContent=Tt),Ns=M(l),T(rl.$$.fragment,l),fs=M(l),bl=U(l,"P",{}),it(bl).forEach(t),this.h()},h(){hl(o,"name","hf:doc:metadata"),hl(o,"content",gt),hl(I,"class","tip"),yt(V.src,Ws="https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/LangGraph/first_graph.png")||hl(V,"src",Ws),hl(V,"alt","First LangGraph"),yt(yl.src,nt="https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/unit2/LangGraph/mail_flow.png")||hl(yl,"src",nt),hl(yl,"alt","Mail LangGraph")},m(l,s){Ct(document.head,o),a(l,Bl,s),a(l,gl,s),a(l,Vl,s),y(C,l,s),a(l,dl,s),y(u,l,s),a(l,Ql,s),a(l,r,s),a(l,Nl,s),a(l,h,s),a(l,fl,s),a(l,g,s),a(l,Sl,s),a(l,I,s),a(l,Al,s),y(b,l,s),a(l,Fl,s),a(l,B,s),a(l,Zl,s),a(l,V,s),a(l,El,s),y(d,l,s),a(l,Gl,s),a(l,Q,s),a(l,Rl,s),y(N,l,s),a(l,Wl,s),a(l,f,s),a(l,ql,s),y(S,l,s),a(l,kl,s),y(A,l,s),a(l,Yl,s),a(l,F,s),a(l,_l,s),y(Z,l,s),a(l,$l,s),a(l,E,s),a(l,zl,s),y(G,l,s),a(l,Xl,s),a(l,R,s),a(l,xl,s),y(W,l,s),a(l,vl,s),y(q,l,s),a(l,Ol,s),a(l,k,s),a(l,Hl,s),y(Y,l,s),a(l,Ll,s),a(l,_,s),a(l,Dl,s),y($,l,s),a(l,Kl,s),a(l,z,s),a(l,Pl,s),y(X,l,s),a(l,ls,s),a(l,x,s),a(l,ss,s),y(v,l,s),a(l,ts,s),a(l,O,s),a(l,as,s),y(H,l,s),a(l,ns,s),y(L,l,s),a(l,Ms,s),a(l,D,s),a(l,es,s),a(l,K,s),a(l,Us,s),a(l,P,s),a(l,Js,s),y(ll,l,s),a(l,ps,s),a(l,sl,s),a(l,Ts,s),y(tl,l,s),a(l,ys,s),a(l,al,s),a(l,is,s),y(nl,l,s),a(l,js,s),a(l,Ml,s),a(l,cs,s),a(l,el,s),a(l,ws,s),a(l,Ul,s),a(l,ms,s),y(Jl,l,s),a(l,os,s),a(l,pl,s),a(l,Is,s),y(Tl,l,s),a(l,Cs,s),a(l,yl,s),a(l,us,s),a(l,il,s),a(l,rs,s),y(jl,l,s),a(l,hs,s),a(l,cl,s),a(l,gs,s),a(l,wl,s),a(l,bs,s),a(l,ml,s),a(l,Bs,s),y(ol,l,s),a(l,Vs,s),a(l,Il,s),a(l,ds,s),y(Cl,l,s),a(l,Qs,s),a(l,ul,s),a(l,Ns,s),y(rl,l,s),a(l,fs,s),a(l,bl,s),Ss=!0},p:ct,i(l){Ss||(i(C.$$.fragment,l),i(u.$$.fragment,l),i(b.$$.fragment,l),i(d.$$.fragment,l),i(N.$$.fragment,l),i(S.$$.fragment,l),i(A.$$.fragment,l),i(Z.$$.fragment,l),i(G.$$.fragment,l),i(W.$$.fragment,l),i(q.$$.fragment,l),i(Y.$$.fragment,l),i($.$$.fragment,l),i(X.$$.fragment,l),i(v.$$.fragment,l),i(H.$$.fragment,l),i(L.$$.fragment,l),i(ll.$$.fragment,l),i(tl.$$.fragment,l),i(nl.$$.fragment,l),i(Jl.$$.fragment,l),i(Tl.$$.fragment,l),i(jl.$$.fragment,l),i(ol.$$.fragment,l),i(Cl.$$.fragment,l),i(rl.$$.fragment,l),Ss=!0)},o(l){j(C.$$.fragment,l),j(u.$$.fragment,l),j(b.$$.fragment,l),j(d.$$.fragment,l),j(N.$$.fragment,l),j(S.$$.fragment,l),j(A.$$.fragment,l),j(Z.$$.fragment,l),j(G.$$.fragment,l),j(W.$$.fragment,l),j(q.$$.fragment,l),j(Y.$$.fragment,l),j($.$$.fragment,l),j(X.$$.fragment,l),j(v.$$.fragment,l),j(H.$$.fragment,l),j(L.$$.fragment,l),j(ll.$$.fragment,l),j(tl.$$.fragment,l),j(nl.$$.fragment,l),j(Jl.$$.fragment,l),j(Tl.$$.fragment,l),j(jl.$$.fragment,l),j(ol.$$.fragment,l),j(Cl.$$.fragment,l),j(rl.$$.fragment,l),Ss=!1},d(l){l&&(t(Bl),t(gl),t(Vl),t(dl),t(Ql),t(r),t(Nl),t(h),t(fl),t(g),t(Sl),t(I),t(Al),t(Fl),t(B),t(Zl),t(V),t(El),t(Gl),t(Q),t(Rl),t(Wl),t(f),t(ql),t(kl),t(Yl),t(F),t(_l),t($l),t(E),t(zl),t(Xl),t(R),t(xl),t(vl),t(Ol),t(k),t(Hl),t(Ll),t(_),t(Dl),t(Kl),t(z),t(Pl),t(ls),t(x),t(ss),t(ts),t(O),t(as),t(ns),t(Ms),t(D),t(es),t(K),t(Us),t(P),t(Js),t(ps),t(sl),t(Ts),t(ys),t(al),t(is),t(js),t(Ml),t(cs),t(el),t(ws),t(Ul),t(ms),t(os),t(pl),t(Is),t(Cs),t(yl),t(us),t(il),t(rs),t(hs),t(cl),t(gs),t(wl),t(bs),t(ml),t(Bs),t(Vs),t(Il),t(ds),t(Qs),t(ul),t(Ns),t(fs),t(bl)),t(o),c(C,l),c(u,l),c(b,l),c(d,l),c(N,l),c(S,l),c(A,l),c(Z,l),c(G,l),c(W,l),c(q,l),c(Y,l),c($,l),c(X,l),c(v,l),c(H,l),c(L,l),c(ll,l),c(tl,l),c(nl,l),c(Jl,l),c(Tl,l),c(jl,l),c(ol,l),c(Cl,l),c(rl,l)}}}const gt='{"title":"构建你的第一个 LangGraph","local":"构建你的第一个-langgraph","sections":[{"title":"工作流程","local":"工作流程","sections":[],"depth":2},{"title":"环境设置","local":"环境设置","sections":[],"depth":2},{"title":"步骤 1：定义我们的状态","local":"步骤-1定义我们的状态","sections":[],"depth":2},{"title":"第 2 步：定义我们的节点","local":"第-2-步定义我们的节点","sections":[],"depth":2},{"title":"步骤 3：定义我们的路由逻辑","local":"步骤-3定义我们的路由逻辑","sections":[],"depth":2},{"title":"步骤 4：创建 StateGraph 并定义边","local":"步骤-4创建-stategraph-并定义边","sections":[],"depth":2},{"title":"步骤 5：运行应用程序","local":"步骤-5运行应用程序","sections":[],"depth":2},{"title":"第 6 步：使用 Langfuse 检查我们的邮件分类智能体 📡","local":"第-6-步使用-langfuse-检查我们的邮件分类智能体-","sections":[],"depth":2},{"title":"可视化我们的图表","local":"可视化我们的图表","sections":[],"depth":2},{"title":"我们构建了什么","local":"我们构建了什么","sections":[],"depth":2},{"title":"关键要点","local":"关键要点","sections":[],"depth":2},{"title":"下一步是什么？","local":"下一步是什么","sections":[],"depth":2}],"depth":1}';function bt(As){return wt(()=>{new URLSearchParams(window.location.search).get("fw")}),[]}class ft extends mt{constructor(o){super(),ot(this,o,bt,ht,jt,{})}}export{ft as component};
