<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Event Streaming on Nanzet</title>
        <link>https://nanzet-blog.pages.dev/tags/event-streaming/</link>
        <description>Recent content in Event Streaming on Nanzet</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh-cn</language>
        <copyright>Nanzet</copyright>
        <lastBuildDate>Wed, 03 Jun 2026 18:48:31 +0800</lastBuildDate><atom:link href="https://nanzet-blog.pages.dev/tags/event-streaming/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>LangChain 多通道事件流生产级踩坑实录</title>
        <link>https://nanzet-blog.pages.dev/p/langchain-event-streaming-engineering-pitfalls/</link>
        <pubDate>Wed, 03 Jun 2026 18:48:31 +0800</pubDate>
        
        <guid>https://nanzet-blog.pages.dev/p/langchain-event-streaming-engineering-pitfalls/</guid>
        <description>&lt;blockquote&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://docs.langchain.com/oss/python/langchain/event-streaming&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Event streaming - Docs by LangChain&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;一句话总结&lt;/strong&gt;：&lt;strong&gt;Event Streaming（事件流）机制通过&lt;/strong&gt;&lt;strong&gt;&lt;code&gt;stream_events(version=&amp;quot;v3&amp;quot;)&lt;/code&gt;&lt;/strong&gt;&lt;strong&gt;提供强类型的数据投影（Projections），实现了对 Agent 运行时的模型回复、思考过程、工具调用生命周期及嵌套子图的细粒度、多通道实时事件流订阅，是构建现代化高响应 AI 前端的基石。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;核心概念与常用-api-解析&#34;&gt;核心概念与常用 API 解析
&lt;/h2&gt;&lt;p&gt;在构建&lt;u&gt;交互式 AI Agent &lt;/u&gt;时，&lt;strong&gt;全链路的流式输出能力&lt;/strong&gt;是基础。LangChain 构建于 LangGraph 之上，引入了类型安全的投影（Projections）机制，替代了以往直接解析原始底层事件字典的复杂操作。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;stream_events(..., version=&amp;quot;v3&amp;quot;)&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
启动&lt;strong&gt;流式追踪&lt;/strong&gt;的核心方法，必须显式声明 &lt;code&gt;version=&amp;quot;v3&amp;quot;&lt;/code&gt; 以启用最新的强类型事件栈。它返回一个包含多种流式生成器属性的综合对象，允许你针对不同的数据通道进行独立订阅。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;消息投影：Message Projection (&lt;/strong&gt;&lt;strong&gt;&lt;code&gt;stream.messages&lt;/code&gt;&lt;/strong&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;br&gt;
针对模型输出通道。它会生成 &lt;code&gt;ChatModelStream&lt;/code&gt; 对象序列（每次大模型调用产生一个）。每个 Message 流对象暴露了细粒度的增量属性：
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.text&lt;/code&gt;：模型生成的标准文本块增量（Deltas）。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.reasoning&lt;/code&gt;：模型生成的推理/思考过程增量（针对支持&lt;font style=&#34;color:rgb(43, 45, 49);&#34;&gt;大模型思维链&lt;/font&gt;&lt;font style=&#34;color:rgb(43, 45, 49);&#34;&gt; &lt;/font&gt;CoT 的深度思考模型）。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.tool_calls&lt;/code&gt;：模型发起工具调用时的参数分块。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.output&lt;/code&gt;：大模型调用完成后的最终静态消息对象，可从中读取如 Token 消耗等数据（&lt;code&gt;message.output.usage_metadata&lt;/code&gt;）。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;工具执行投影：&lt;/strong&gt;&lt;strong&gt;Tool Execution Projection (&lt;/strong&gt;&lt;strong&gt;&lt;code&gt;stream.tool_calls&lt;/code&gt;&lt;/strong&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;br&gt;
专门&lt;strong&gt;追踪工具的执行生命周期&lt;/strong&gt;（注意区分于上文的 .tool_calls，前者是模型生成参数，后者是本地引擎执行工具）。它暴露了工具调用的输入、输出增量（output_deltas）、最终输出（output）和执行报错（error）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;State &amp;amp; Output (&lt;/strong&gt;&lt;strong&gt;&lt;code&gt;stream.values&lt;/code&gt;&lt;/strong&gt;&lt;strong&gt;&amp;amp; &lt;strong&gt;&lt;strong&gt;&lt;code&gt;stream.output&lt;/code&gt;&lt;/strong&gt;&lt;/strong&gt;)&lt;/strong&gt;&lt;br&gt;
用于&lt;strong&gt;监控 Agent 状态流转&lt;/strong&gt;。&lt;code&gt;values&lt;/code&gt; 会生成&lt;strong&gt;每次图状态更新的完整快照&lt;/strong&gt;，而 &lt;code&gt;output&lt;/code&gt; 则&lt;strong&gt;在执行完毕后提供最终收敛的图状态&lt;/strong&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;周边与扩展-api-梳理&#34;&gt;周边与扩展 API 梳理
&lt;/h2&gt;&lt;p&gt;结合文档内容及其中涉及的高级扩展特性，以下机制在企业级复杂工作流中不可或缺：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;嵌套子图：Nested Subgraphs (&lt;/strong&gt;&lt;strong&gt;&lt;code&gt;stream.subgraphs&lt;/code&gt;&lt;/strong&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;br&gt;
在多智能体（Multi-Agent）架构中，一个主 Agent 可能会作为工具调用子 Agent。子 Agent 的事件流会进入嵌套命名空间。通过访问 stream.subgraphs，可以获取子图独立的 .messages 和 .tool_calls 投影。利用实例化时传入的 name 属性（反映在 subagent.graph_name），可以精准过滤和路由特定子 Agent 的流式事件。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;并发消费：Concurrent Consumption (&lt;/strong&gt;&lt;strong&gt;&lt;code&gt;astream_events&lt;/code&gt;&lt;/strong&gt;&lt;strong&gt;与 &lt;strong&gt;&lt;strong&gt;&lt;code&gt;interleave&lt;/code&gt;&lt;/strong&gt;&lt;/strong&gt;)&lt;/strong&gt;&lt;br&gt;
由于 stream_events 提供了多个维度的流（文本流、工具流等），LangChain 提供了&lt;strong&gt;两种并发消费模式&lt;/strong&gt;：
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;异步模式&lt;/strong&gt;：使用 &lt;code&gt;astream_events&lt;/code&gt; 配合原生的 &lt;code&gt;asyncio.gather()&lt;/code&gt;，开启多个协程并发拉取 &lt;code&gt;.messages&lt;/code&gt; 和 &lt;code&gt;.tool_calls&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;同步模式&lt;/strong&gt;：使用 &lt;code&gt;stream.interleave(&amp;quot;messages&amp;quot;, &amp;quot;tool_calls&amp;quot;)&lt;/code&gt; 方法，它会将选定的多个流通道交织提取，产生 &lt;code&gt;(name, item)&lt;/code&gt;元组，&lt;u&gt;适合阻塞式脚本&lt;/u&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;中间件转换器：Middleware Transformers 与 PII 脱敏扩展&lt;/strong&gt;&lt;br&gt;
中间件支持声明&lt;strong&gt;流式转换器&lt;/strong&gt;（StreamTransformer）。通过在 &lt;code&gt;AgentMiddleware&lt;/code&gt; 子类中配置 &lt;code&gt;transformers&lt;/code&gt; 属性，可以&lt;u&gt;实现对流式数据的动态拦截与修改&lt;/u&gt;。文档中提及的 PIIMiddleware 正是利用了此扩展槽，当配置 &lt;code&gt;apply_to_output=True&lt;/code&gt; 时，能够在文本块或工具输出流向客户端之前，实施实时的 &lt;strong&gt;PII（个人身份信息）&lt;/strong&gt;脱敏清洗，彻底封闭了流式传输导致的数据泄露窗口。产生的新通道可通过 &lt;code&gt;stream.extensions&lt;/code&gt; 获取。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;工程化代码落地示例&#34;&gt;工程化代码落地示例
&lt;/h2&gt;&lt;p&gt;以下代码展示了如何使用 &lt;code&gt;stream.interleave&lt;/code&gt; 同步交织提取模型推理过程（含文本与思考块）以及本地工具执行生命周期，这是一个标准的终端/前端流式对接工程范例。&lt;/p&gt;
&lt;div class=&#34;highlight&#34; title=&#34;event_streaming_agent.py&#34;&gt;&lt;div style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;13
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;14
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;15
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;16
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;17
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;18
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;19
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;20
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;21
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;22
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;23
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;24
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;25
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;26
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;27
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;28
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;29
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;30
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;31
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;32
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;33
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;34
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;35
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;36
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;37
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;38
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;39
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;40
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;41
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;42
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;43
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;44
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;45
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;46
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;47
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;48
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;49
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;50
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;51
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;52
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;53
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;54
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;55
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;56
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;57
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;58
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;59
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;60
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;61
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;62
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;63
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;64
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;65
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;66
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;67
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;68
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;69
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;70
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;71
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;72
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;73
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;74
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;75
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;76
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;77
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;78
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;79
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;80
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;81
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;82
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;83
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;84
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;85
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;86
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;87
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;88
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;89
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;90
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;91
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;92
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;93
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;94
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;95
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#!/usr/bin/env python3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# -*- coding: utf-8 -*-&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Author         : nanzet&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Description    : 演示 LangChain V3 Event Streaming 机制，优化多通道流的终端排版与阅读体验&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# requirements   : pip install -U langchain langchain-deepseek langgraph requests&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; warnings
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; requests
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; langchain.agents &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; create_agent
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; langchain.chat_models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; init_chat_model
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; langchain_core.tools &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; tool
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# 忽略 LangChain V3 流式协议的实验性警告 (通过正则匹配 message)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;warnings&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filterwarnings(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;ignore&amp;#34;&lt;/span&gt;, message&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;.*The v3 streaming protocol on Pregel is experimental.*&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# 声明工具&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@tool&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;get_weather&lt;/span&gt;(city: &lt;span style=&#34;color:#ff5c57&#34;&gt;str&lt;/span&gt;) &lt;span style=&#34;color:#ff6ac1&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;str&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&amp;#34;&amp;#34;获取指定城市实时的天气状况。&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;try&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        response &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; requests&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get(&lt;span style=&#34;color:#5af78e&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;https://wttr.in/&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;{&lt;/span&gt;city&lt;span style=&#34;color:#5af78e&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;?format=3&amp;#34;&lt;/span&gt;, timeout&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;5.0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; response&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;status_code &lt;span style=&#34;color:#ff6ac1&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;200&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; response&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;text
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;无法获取天气数据。&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;except&lt;/span&gt; Exception &lt;span style=&#34;color:#ff6ac1&#34;&gt;as&lt;/span&gt; e:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;查询出错: &lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;str&lt;/span&gt;(e)&lt;span style=&#34;color:#5af78e&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;main&lt;/span&gt;() &lt;span style=&#34;color:#ff6ac1&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    model &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; init_chat_model(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;deepseek-reasoner&amp;#34;&lt;/span&gt;, model_provider&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;deepseek&amp;#34;&lt;/span&gt;, temperature&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    agent &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; create_agent(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        model&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;model,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        tools&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;[get_weather],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;开始发起请求并订阅多通道流：&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    stream &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; agent&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;stream_events(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;messages&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                {&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;role&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;user&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;content&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;请问南京市江宁区今天的天气怎么样？&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        version&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;v3&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# 5. 使用 interleave 并发交织提取消息流和工具流&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; stream_name, item &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; stream&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;interleave(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;messages&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;tool_calls&amp;#34;&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; stream_name &lt;span style=&#34;color:#ff6ac1&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;messages&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#78787e&#34;&gt;# --- 优化点 1：优雅处理推理流 (Reasoning) ---&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            has_reasoning &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; delta &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; item&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;reasoning:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;not&lt;/span&gt; has_reasoning:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#78787e&#34;&gt;# 首次进入推理流，打印表头并开启灰色字体 (\033[90m)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;\n\033&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;[90m[AI 思考过程]:&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&lt;/span&gt;, end&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;, flush&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    has_reasoning &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#78787e&#34;&gt;# 循环内只打印干净的内容&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(delta, end&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;, flush&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; has_reasoning:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#78787e&#34;&gt;# 推理结束，关闭颜色控制 (\033[0m) 并换行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;\033&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;[0m&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&lt;/span&gt;, end&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;, flush&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#78787e&#34;&gt;# --- 优化点 2：优雅处理正文流 (Text) ---&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            has_text &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; delta &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; item&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;text:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;not&lt;/span&gt; has_text:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;[最终回复]:&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&lt;/span&gt;, end&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;, flush&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    has_text &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(delta, end&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;, flush&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; has_text:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;elif&lt;/span&gt; stream_name &lt;span style=&#34;color:#ff6ac1&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;tool_calls&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#78787e&#34;&gt;# --- 优化点 3：优雅处理工具流 ---&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;[系统执行] 准备调用工具: &lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;{&lt;/span&gt;item&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;tool_name&lt;span style=&#34;color:#5af78e&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;，入参: &lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;{&lt;/span&gt;item&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;input&lt;span style=&#34;color:#5af78e&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; delta &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; item&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;output_deltas:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#78787e&#34;&gt;# 如果不需要看中间过程，可以注释掉这行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ff6ac1&#34;&gt;pass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; item&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;output:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;[系统执行] 工具调用完成！(耗时短，已隐藏中间流)&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;__name__&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    main()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;输出结果：&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;13
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;14
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;15
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;16
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;17
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;18
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;19
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;20
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;21
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;22
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;23
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;24
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;25
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;26
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;开始发起请求并订阅多通道流&lt;span style=&#34;color:#ff5c57&#34;&gt;：&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[&lt;span style=&#34;color:#ff9f43&#34;&gt;AI 思考过程&lt;/span&gt;]&lt;span style=&#34;color:#ff5c57&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;用户想知道南京市江宁区今天的天气情况&lt;span style=&#34;color:#ff5c57&#34;&gt;。&lt;/span&gt;我可以使用 get_weather 工具来查询&lt;span style=&#34;color:#ff5c57&#34;&gt;。&lt;/span&gt;江宁区是南京市的一个区&lt;span style=&#34;color:#ff5c57&#34;&gt;，&lt;/span&gt;所以我应该用&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;南京&amp;#34;&lt;/span&gt;作为城市参数来查询天气&lt;span style=&#34;color:#ff5c57&#34;&gt;。&lt;/span&gt;让我获取一下&lt;span style=&#34;color:#ff5c57&#34;&gt;。&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[最终回复]&lt;span style=&#34;color:#ff5c57&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;好的&lt;span style=&#34;color:#ff5c57&#34;&gt;，&lt;/span&gt;我来查一下南京市江宁区今天的天气情况&lt;span style=&#34;color:#ff5c57&#34;&gt;。&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[系统执行] 准备调用工具&lt;span style=&#34;color:#ff5c57&#34;&gt;:&lt;/span&gt; get_weather&lt;span style=&#34;color:#ff5c57&#34;&gt;，&lt;/span&gt;入参&lt;span style=&#34;color:#ff5c57&#34;&gt;:&lt;/span&gt; {&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;city&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;南京&amp;#39;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[系统执行] 工具调用完成&lt;span style=&#34;color:#ff5c57&#34;&gt;！&lt;/span&gt;(耗时短&lt;span style=&#34;color:#ff5c57&#34;&gt;，&lt;/span&gt;已隐藏中间流)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[&lt;span style=&#34;color:#ff9f43&#34;&gt;AI 思考过程&lt;/span&gt;]&lt;span style=&#34;color:#ff5c57&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;The weather info shows &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;南京: 🌦️ +84°F&amp;#34;&lt;/span&gt;. This is the weather &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; Nanjing city. The user asked about 南京市江宁区 (Jiangning District, Nanjing). Since the weather API returns data &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; the city level, I&lt;span style=&#34;color:#ff5c57&#34;&gt;&amp;#39;&lt;/span&gt;ll share this information with the user.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;84&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;°&lt;/span&gt;F is about &lt;span style=&#34;color:#ff9f43&#34;&gt;29&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;°&lt;/span&gt;C. Let me convert&lt;span style=&#34;color:#ff5c57&#34;&gt;:&lt;/span&gt; (&lt;span style=&#34;color:#ff9f43&#34;&gt;84&lt;/span&gt; - &lt;span style=&#34;color:#ff9f43&#34;&gt;32&lt;/span&gt;) &lt;span style=&#34;color:#ff5c57&#34;&gt;×&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;5&lt;/span&gt;/&lt;span style=&#34;color:#ff9f43&#34;&gt;9&lt;/span&gt; = &lt;span style=&#34;color:#ff9f43&#34;&gt;52&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;×&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;5&lt;/span&gt;/&lt;span style=&#34;color:#ff9f43&#34;&gt;9&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;≈&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;28.9&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;°&lt;/span&gt;C.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[最终回复]&lt;span style=&#34;color:#ff5c57&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;根据查询到的天气信息&lt;span style=&#34;color:#ff5c57&#34;&gt;，&lt;/span&gt;南京市&lt;span style=&#34;color:#ff5c57&#34;&gt;（&lt;/span&gt;包含江宁区&lt;span style=&#34;color:#ff5c57&#34;&gt;）&lt;/span&gt;今天的情况如下&lt;span style=&#34;color:#ff5c57&#34;&gt;：&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;🌦&lt;/span&gt;️ **天气&lt;span style=&#34;color:#ff5c57&#34;&gt;：&lt;/span&gt;多云/阴有雨&lt;span style=&#34;color:#ff5c57&#34;&gt;（🌦&lt;/span&gt;️&lt;span style=&#34;color:#ff5c57&#34;&gt;）&lt;/span&gt;**
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;🌡&lt;/span&gt;️ **气温&lt;span style=&#34;color:#ff5c57&#34;&gt;：&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;84&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;°&lt;/span&gt;F&lt;span style=&#34;color:#ff5c57&#34;&gt;（&lt;/span&gt;约 &lt;span style=&#34;color:#ff9f43&#34;&gt;29&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;°&lt;/span&gt;C&lt;span style=&#34;color:#ff5c57&#34;&gt;）&lt;/span&gt;**
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;江宁区作为南京市的一个区&lt;span style=&#34;color:#ff5c57&#34;&gt;，&lt;/span&gt;天气状况与南京市整体基本一致&lt;span style=&#34;color:#ff5c57&#34;&gt;。&lt;/span&gt;今天可能有阵雨或阴雨天气&lt;span style=&#34;color:#ff5c57&#34;&gt;，&lt;/span&gt;气温在29&lt;span style=&#34;color:#ff5c57&#34;&gt;°&lt;/span&gt;C左右&lt;span style=&#34;color:#ff5c57&#34;&gt;，&lt;/span&gt;体感较热&lt;span style=&#34;color:#ff5c57&#34;&gt;，&lt;/span&gt;建议出门带伞&lt;span style=&#34;color:#ff5c57&#34;&gt;，&lt;/span&gt;注意防暑防雨&lt;span style=&#34;color:#ff5c57&#34;&gt;。&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;说明：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;font style=&#34;color:rgb(43, 45, 49);&#34;&gt;在构建复杂的智能体应用时，传统的 Token 流式输出是不够的。我们必须采用 &lt;/font&gt;&lt;strong&gt;&lt;font style=&#34;color:rgb(43, 45, 49);&#34;&gt;Event Streaming（事件流）&lt;/font&gt;&lt;/strong&gt;&lt;font style=&#34;color:rgb(43, 45, 49);&#34;&gt; 机制。通过订阅框架发出的结构化事件流，前端不仅能实现文本的打字机渲染，还能实时感知 Agent 的底层生命周期，比如精准地渲染出‘正在思考中’或‘正在调用 XX 数据库工具’的过渡态 UI，从而极大提升用户的交互体验。&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font style=&#34;color:rgb(43, 45, 49);&#34;&gt;&lt;/font&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;font style=&#34;color:rgb(43, 45, 49);&#34;&gt;Token Streaming（Token 流式输出 / 纯文本打字机效果）&lt;/font&gt;&lt;/strong&gt;&lt;font style=&#34;color:rgb(43, 45, 49);&#34;&gt;：&lt;/font&gt;&lt;font style=&#34;color:rgb(43, 45, 49);&#34;&gt;&lt;br&gt;
&lt;/font&gt;&lt;font style=&#34;color:rgb(43, 45, 49);&#34;&gt;这是最基础的大模型特性。模型生成一个字，就向外吐一个字。它只有单一的数据通道（纯字符串）。&lt;/font&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;font style=&#34;color:rgb(43, 45, 49);&#34;&gt;Event Streaming（事件流）&lt;/font&gt;&lt;/strong&gt;&lt;font style=&#34;color:rgb(43, 45, 49);&#34;&gt;：&lt;br&gt;
&lt;/font&gt;&lt;font style=&#34;color:rgb(43, 45, 49);&#34;&gt;这是 Agent 时代的高级特性。因为 Agent 的运行不仅包含“说话”，还包含“思考”、“调用工具”、“状态流转”、“子图切换”。因此，框架必须将数据抽象为结构化的 &lt;/font&gt;&lt;strong&gt;&lt;font style=&#34;color:rgb(43, 45, 49);&#34;&gt;“事件（Event）”&lt;/font&gt;&lt;/strong&gt;&lt;font style=&#34;color:rgb(43, 45, 49);&#34;&gt;。前端或消费端收到的不再是纯文本，而是一个个带有类型标识的 JSON 对象（如 {&amp;ldquo;event&amp;rdquo;: &amp;ldquo;on_tool_start&amp;rdquo;, &amp;ldquo;data&amp;rdquo;: {&amp;hellip;}}）。&lt;/font&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;常见踩坑与高频面试点&#34;&gt;常见踩坑与高频面试点
&lt;/h2&gt;&lt;p&gt;在复杂 Agent 系统的监控与流式前端对接中，Event Streaming 是考察候选人全栈工程能力的绝佳切入点。&lt;/p&gt;
&lt;h4 id=&#34;常见踩坑-1混淆大模型生成工具参数的流与本地执行工具的流&#34;&gt;常见踩坑 1：混淆大模型生成工具参数的流与本地执行工具的流
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;现象与痛点&lt;/strong&gt;：在对接流式 UI 时，开发者错误地监听了 message.tool_calls 来判断工具是否执行完毕并回显结果，导致前端一直拿不到后端函数的真实返回值。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;工程对策&lt;/strong&gt;：必须严格区分模型输出通道与执行生命周期通道。&lt;code&gt;message.tool_calls&lt;/code&gt; 是模型在推断该调用哪个函数及逐步生成 JSON 入参的过程（属于模型幻觉高发区）；而 &lt;font style=&#34;color:#DF2A3F;&#34;&gt;&lt;code&gt;stream.tool_calls&lt;/code&gt;&lt;/font&gt;&lt;font style=&#34;color:#DF2A3F;&#34;&gt; 才是底层状态机（ToolNode）实际在本地执行 Python 函数的过程和最终返回值&lt;/font&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;常见踩坑-2流式脱敏窗口遗漏&#34;&gt;常见踩坑 2：流式脱敏窗口遗漏
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;现象与痛点&lt;/strong&gt;：在涉及&lt;u&gt;医疗、金融数据&lt;/u&gt;的 Agent 中，虽然在系统末尾编写了&lt;u&gt;状态拦截器&lt;/u&gt;用于&lt;strong&gt;数据脱敏&lt;/strong&gt;，但在流式输出期间（&lt;u&gt;SSE 向前端不断发送 Token 时&lt;/u&gt;），敏感的 PII （个人身份信息）数据已经被实时暴露出去了。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;工程对策&lt;/strong&gt;：使用针对流底层的 Middleware Transformers 技术。如配置内置的 &lt;code&gt;PIIMiddleware(..., apply_to_output=True)&lt;/code&gt;，它能&lt;font style=&#34;color:#DF2A3F;&#34;&gt;在流式字节块被 yield 出去之前进行物理拦截和擦除，封死动态传输过程中的泄露窗口&lt;/font&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;高频面试点-1多智能体multi-agent架构下的前端状态机追踪&#34;&gt;高频面试点 1：多智能体（Multi-Agent）架构下的前端状态机追踪
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;面试官提问&lt;/strong&gt;：“在 Supervisor 调配多个 Worker Agent 的复杂架构中，我们希望前端不仅展示文本，还要展示‘当前是哪个子智能体正在处理任务’，流式接口该如何设计与消费？”&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;满分回答&lt;/strong&gt;：在底层，我们会在实例化子 Agent 时赋予独立的命名空间（如 &lt;code&gt;create_agent(name=&amp;quot;finance_agent&amp;quot;)）&lt;/code&gt;。在客户端消费端，我不再订阅全量的裸协议事件，而是&lt;u&gt;通过 V3 版本的事件流 API，订阅 stream.subgraphs 投影&lt;/u&gt;。在处理循环中，通过校验 &lt;code&gt;subagent.graph_name&lt;/code&gt; 来过滤事件，从而准确向前端下发当前正在活跃的节点拓扑信息及专属于该域的工作流进度。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;高频面试点-2包含深度思考cot模型的异构流解析&#34;&gt;高频面试点 2：包含深度思考（CoT）模型的异构流解析
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;面试官提问&lt;/strong&gt;：“当我们引入具有 Deep Thinking 能力的模型（如 DeepSeek-R1）时，如何在不破坏原有文本流的情况下，实时独立解析并展示其思维链内容？”&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;满分回答&lt;/strong&gt;：利用 &lt;code&gt;stream.messages&lt;/code&gt; 产生的强类型生成器属性。模型返回的信息已被框架从物理层面拆分为并行的独立迭代器，我只需独立&lt;font style=&#34;color:#DF2A3F;&#34;&gt;遍历 &lt;/font&gt;&lt;font style=&#34;color:#DF2A3F;&#34;&gt;&lt;code&gt;item.reasoning&lt;/code&gt;&lt;/font&gt;&lt;font style=&#34;color:#DF2A3F;&#34;&gt; 获取思维链增量块&lt;/font&gt;，和&lt;font style=&#34;color:#DF2A3F;&#34;&gt;遍历 &lt;/font&gt;&lt;font style=&#34;color:#DF2A3F;&#34;&gt;&lt;code&gt;item.text&lt;/code&gt;&lt;/font&gt;&lt;font style=&#34;color:#DF2A3F;&#34;&gt; 获取正文增量块&lt;/font&gt;。由于投影视角解耦了这两者，前端渲染层可以针对不同的数据通道分配独立的组件视图，而不需要在后端手动执行复杂的长字符串切分或正则匹配。&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        
    </channel>
</rss>
