LangGraph实现自治循环代理ReAct及事件流的应用
之前介绍的
Router Agent和Tool Calling Agent,我们通过两个实际的案例证明了随着任务需求的复杂性增加,代理架构中对中间流程的控制自由度也必须相应提高。之所以要从Router Agent调整到Tool Calling Agent架构的原因在于,当路由分支中的节点涉及多个工具时,需要Agent可以根据用户的实际输入灵活选择工具,这一需求是Router Agent无法满足的。然而,Tool Calling Agent的局限性又在于:虽然它可以自主选择工具,但在其架构中,每次仅能执行一次函数调用(无论是单个外部函数还是多个外部函数)。因此,当任务需要依次执行 A 工具、B 工具和 C 工具时,它无法支持这种自主控制的过程。因此,面对这种更复杂的需求,就需要引入了Full Autonomous(自治循环代理)架构,即如下图所示:![image-20260207144808128]()
Full Autonmonous 以两种主要的方式去扩展了Agent对工作流的控制,分别是:
- 多步骤决策:
Agent可以控制一系列决策,而不仅仅是一个决策。 - 工具访问:
Agent可以选择并使用多种工具来完成任务。
满足上述两个条件,典型且通用的代理架构,就是基于ReAct思想而形成的代理模式。在《Ch.3 ReAct Agent 基本理论与项目实战》课程中,我们重点讲解了ReAct的核心理念,并手动实现了基于该思想构建的自治循环代理流程。整体来看,其核心还是在于为大模型配备足够丰富的外部工具,使用合适的提示词,引导大模型在接收到用户输入后,进入自主思考和循环执行的状态,以实现最终目标。 当然,这是我们从非技术角度通俗的解释和理解自治循环代理的这个过程。
1、LangGraph中ReAct的构建原理
在 LangGraph 开发框架中有一些预构建的组件。上节课介绍的 ToolNode 是其中一个,它用于处理外部函数调用,其内部结合了 LangGraph 底层的图结构,能够接收 JSON Schema 形式的数据,执行工具函数并返回结果。除此之外,LangGraph的预构建组件中还包含了 ReAct 代理架构,在 LangGraph 框架中,ReAct 组件被改造成适配图结构的循环代理,其具体过程是:大模型可以在一个 while 循环中被重复调用。每一步,代理来自主决定调用哪些工具及其输入,然后执行这些工具,并将输出作为观察结果反馈给大模型。当代理判断不再需要调用更多工具时,while 循环便会终止,输出最终的结果。
因此,我们需要理解的关键概念是:LangGraph预构建的ReAct组件,其实就是通过接入大模型,搭配着Tool Calling Agent,再结合Router Agent 共同构建起来的图,这个图以自治循环代理的架构形式提供服务。其图结构如下图所示:
如上图所示的代理架构在 LangGraph 中的实现机制类似于 LangChain 中的 ReAct Agent,毕竟 LangGraph 的底层语言是 LangChain 的 LCEL 表达式语言。因此,该 ReAct Agent 架构是从 LangChain 已实现的 ReAct Agent 迁移而来,不同的是在LangGraph框架中适配的是图结构,而非AgentExecuter。其本质依然基于一种规划(Planning)的思想:
LangChain Agents: https://reference.langchain.com/python/langchain/agents/
Agent Planning:https://smith.langchain.com/hub/hwchase17/react?organizationId=33612d73-91c5-5140-b8a0-f3155ff5dc45
1 | Answer the following questions as best you can. You have access to the following tools: |
这种代理实现的机制表明了,在LangGraph中实现的预构建ReAct代理结构,它支持:
- Tool calling :允许大模型根据需要选择和使用各种工具。
- Memory:使代理能够保留和使用先前步骤中的信息。
- Planning :授权大模型制定并遵循多步骤计划以实现目标。
而其在图结构中的具体构建的工作流如下图所示:
如图所示,Agent节点使用消息列表的形式来调用大语言模型,Messages Modifier指的是在传递到大模型之前,修饰用户的原始输入内容,可以是SystemMessage(作为背景信息添加的消息列表的开头)、Runnable(可运行)等不同状态,如果生成的 AIMessage 包含tool_calls,则该图将调用 tools 。 tools 节点执行工具(每个 tool_call 1 个工具)并且将响应作为ToolMessage对象添加到消息列表。然后Agent节点再次调用大语言模型。重复该过程,直到响应中不再存在tool_calls ,最终由Agent节点将完整的消息列表作为包含键 messages的字典返回。
那么如何实现上述这个非常复杂的过程呢?非常简单,既然我们一直提到的是预构建组件,则说明整个过程已经由LangGraph内部封装好了,其提供给开发者使用的接口就是:create_react_agent方法。
LangGraph create_react_agent:点击查看源码参数介绍
2. 案例实操:构建复杂工具应用的ReAct自治代理
在这个案例中,我们将通过一个多工具场景需求来测试 LangGraph 中 ReAct 代理的构建方法和效果。我们设计了几个工具,以实现实时数据的查询和管理。首先,用户可以通过一个工具根据城市名称实时获取当前天气信息。接着,如果用户希望将查询到的天气数据保存到本地数据库中,可以使用另一个工具完成数据的插入操作。此外,我们还提供了一个工具,允许用户基于本地数据库中的天气数据进行提问数据进行提问。通过这些工具的组合,我们能够快速验证如何在复杂的应用场景中有效地整合不同功能,并实际的感知LangGraph框架下ReAct代理模式带来的开发便捷性和可扩展性。
首先,我们设置一下LangSmith的配置,用于追踪和可视化ReAct的中间过程。这里新建了一个项目,命名为langGraph_ReAct,导入基础配置的代码如下图所示:
LangSmith:https://www.langchain.com/langsmith
1 | import os |
true
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
langGraph_ReAct
首先,我们接入实时天气数据查询的在线API,代码定义如下:
1 | import requests |
测试一下get_weather函数的有效性,正常情况下可以得到输入城市名的实时天气信息。测试代码如下所示:
1 | get_weather('beijing') |
'{"coord": {"lon": 116.3972, "lat": 39.9075}, "weather": [{"id": 800, "main": "Clear", "description": "\\u6674", "icon": "01d"}], "base": "stations", "main": {"temp": 20.5, "feels_like": 19.28, "temp_min": 19.94, "temp_max": 20.5, "pressure": 1016, "humidity": 26, "sea_level": 1016, "grnd_level": 1010}, "visibility": 10000, "wind": {"speed": 1.95, "deg": 270, "gust": 5.15}, "clouds": {"all": 0}, "dt": 1730190567, "sys": {"type": 2, "id": 2000403, "country": "CN", "sunrise": 1730155186, "sunset": 1730193377}, "timezone": 28800, "id": 1816670, "name": "Beijing", "cod": 200}'
从返回的结果是Json数据类型,包含了非常丰富的实时天气数据,如天气条件、温度、湿度、风速、天气描述等信息,这里我们选择一些重要的数据参数进行存储操作(存储至Mysql数据库中)。提取的参数如下:
| 字段名称 | 描述 |
|---|---|
| city_id | 城市的唯一标识符 |
| city_name | 城市名称 |
| main_weather | 主要天气状况 |
| description | 天气的详细描述 |
| temperature | 当前温度 |
| feels_like | 体感温度 |
| temp_min | 最低温度 |
| temp_max | 最高温度 |
接下来,设计一个用于存储实时天气信息的表。这里我们定义一个新的模型 Weather,并包括上述所提取出来的的字段。连接 Mysql数据库及创建表的代码如下所示:
1 | from sqlalchemy import create_engine, Column, Integer, String, Float |
接下来,使用LangChain的tool 装饰器将普通的函数注册为LangGraph中支持的工具服务,根据需求的设计,我们要依次创建三个外部函数,分别是:
get_weather工具:用于根据城市名称实时查询该城市的当前天气数据。insert_weather_to_db工具:如果用户想要把查询到的天气数据插入到数据库的表中,则使用此函数完成数据库的插入操作。query_weather_from_db工具:如果用户想基于本地数据库的天气数据直接进行提问,则使用此函数完成数据库的查询操作。
如上节课实践的流程一样,我们依然使用pydantic来做工具的参数校验和结构化输出。三个工具函数的定义代码依次如下所示:
1 | from langchain_core.tools import tool |
然后,定义实时联网检索外部工具,通过该函数获取最新的网络数据信息。
1 | class SearchQuery(BaseModel): |
然后把所有定义的工具存储在一个列表中,如下代码所示:
1 | tools = [fetch_real_time_info, get_weather, insert_weather_to_db, query_weather_from_db] |
1 | tools |
[StructuredTool(name='fetch_real_time_info', description='Get real-time Internet information', args_schema=<class '__main__.SearchQuery'>, func=<function fetch_real_time_info at 0x00000222A40605E0>),
<function __main__.get_weather(loc)>,
StructuredTool(name='insert_weather_to_db', description='Insert weather information into the database.', args_schema=<class '__main__.WeatherInfo'>, func=<function insert_weather_to_db at 0x00000222A4060C20>),
StructuredTool(name='query_weather_from_db', description='Query weather information from the database by city name.', args_schema=<class '__main__.QueryWeatherSchema'>, func=<function query_weather_from_db at 0x00000222A4060CC0>)]
准备好工具后,接下来定义用于构建AI Agent的大模型实例,这里我们使用OpenAI的在线GPT-4模型。代码如下:
1 | import getpass |
当有了工具列表和模型后,就可以通过create_react_agent这个LangGraph框架中预构建的方法来创建自治循环代理(ReAct)的工作流,其必要的参数如下:
- model: 支持工具调用的LangChain聊天模型。
- tools: 工具列表、ToolExecutor 或 ToolNode 实例。
- state_schema:图的状态模式。必须有
messages和is_last_step键。默认为定义这两个键的Agent State。
上述三点我们均在前面的课程中详细且作为重点介绍过,大家应该是比较容易理解的。所以,创建ReAct代理的代码就如下所示:
1 | from langgraph.prebuilt import create_react_agent |
1 | graph |
<langgraph.graph.state.CompiledStateGraph at 0x222a674c610>
我们可以逐步的分析和解释一下这一行代码中涉及的图构建过程:
- Step 1. 定义图状态模式
LangGraph中的主要图类型是StateGraph。每个节点通过State中的参数获取有效信息,执行完节点的内部逻辑后,更新该State状态中的值。不同的状态模式,可以通过注释设置状态的特定属性(例如覆盖现有值)或添加到现有属性。伪代码如下:
1 | from typing import Annotated |
- Step 2. 定义
Router Function
设置边缘条件,有条件的原因是,根据节点的输出,可以采用多个路径之一。在该节点运行之前,所采用的路径是未知的(由大模型决定)。
- 条件边缘:调用代理后,如果代理说要采取行动,那么应该调用调用工具的函数。如果代理说已经完成,那么就应该完成。
- 正常边:调用工具后,它应该始终返回给代理来决定下一步做什么。
伪代码如下:
1 | # 定义决定是否继续执行任务的路由函数 |
- Step 3. 定义大模型的交互函数
接下来需要通过一个节点函数加载我想要使用的大模型。它需要满足两个标准:
- 应该与消息一起使用,因为图的状态主要是消息列表(聊天历史记录)。
- 需要与工具调用一起使用,其内部使用的是预构建的ToolNode。
伪代码如下:
1 | from typing import Literal |
- Step 4. 构建图结构
最后,把上述所有的组件放在一起构建图结构,这与我们手动构建图的方式基本一致,伪代码如下:
1 | from langgraph.graph import END, START, StateGraph |
理解了上面的create_react_agent方法内部的构建原理后,其实就能明白:当通过create_react_agent(llm, tools=tools)一行代码的执行,现在得到的已经是一个编译后、可执行的图了。我们可以通过mermaid方法来可视化经过create_react_agent方法构造出来的图结构,代码如下所示:
1 | from IPython.display import Image, display |
返回的是编译好的LangGraph可运行程序,可直接用于聊天交互。调用方式则和之前使用的方法一样,我们可以依次针对不同复杂程度的需求依次进行提问。首先是测试是否可以不使用工具,直接调用大模型生成响应。
1 | # query="你好,请你介绍一下你自己" |
{'messages': [HumanMessage(content='你好,请你介绍一下你自己', additional_kwargs={}, response_metadata={}, id='268158b3-ec6d-44a7-bbd5-bb43d449ff7e'),
AIMessage(content='你好!我是一个由人工智能驱动的助手,旨在帮助解答问题、提供信息并协助完成各种任务。我可以处理广泛的主题,包括但不限于科技、教育、娱乐、天气、新闻等。如果你有任何特定的问题或需要帮助的地方,请随时告诉我!', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 67, 'prompt_tokens': 343, 'total_tokens': 410, 'prompt_tokens_details': {'cached_tokens': 0}, 'completion_tokens_details': {'reasoning_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_72bbfa6014', 'finish_reason': 'stop', 'logprobs': None}, id='run-968ec2f8-eb4b-45cf-ac55-398deba6e6fe-0', usage_metadata={'input_tokens': 343, 'output_tokens': 67, 'total_tokens': 410, 'input_token_details': {'cache_read': 0}, 'output_token_details': {'reasoning': 0}})]}
1 | finan_response["messages"][-1].content |
'你好!我是一个由人工智能驱动的助手,旨在帮助解答问题、提供信息并协助完成各种任务。我可以处理广泛的主题,包括但不限于科技、教育、娱乐、天气、新闻等。如果你有任何特定的问题或需要帮助的地方,请随时告诉我!'
加大输入问题的复杂度,接下来我们提问的问题希望它能够自动找到正确的工具函数,基于工具的执行结果作为既定的事实,引导生成最终的回复。
1 | finan_response = graph.invoke({"messages":["北京今天的天气怎么样?"]}) |
<__main__.Weather object at 0x00000222A5896390>
{'messages': [HumanMessage(content='北京今天的天气怎么样?', additional_kwargs={}, response_metadata={}, id='3ea29a69-311d-4003-935f-18ca24bc9e6f'),
AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_BMA4Jp782AMVBw4VS1x3nv8h', 'function': {'arguments': '{"city_name":"Beijing"}', 'name': 'query_weather_from_db'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 18, 'prompt_tokens': 342, 'total_tokens': 360, 'prompt_tokens_details': {'cached_tokens': 0}, 'completion_tokens_details': {'reasoning_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_72bbfa6014', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-eb43ab41-161c-4acb-b8d7-b5890745ce55-0', tool_calls=[{'name': 'query_weather_from_db', 'args': {'city_name': 'Beijing'}, 'id': 'call_BMA4Jp782AMVBw4VS1x3nv8h', 'type': 'tool_call'}], usage_metadata={'input_tokens': 342, 'output_tokens': 18, 'total_tokens': 360, 'input_token_details': {'cache_read': 0}, 'output_token_details': {'reasoning': 0}}),
ToolMessage(content='{"city_id": 1816670, "city_name": "Beijing", "main_weather": "Clouds", "description": "晴,少云", "temperature": 14.94, "feels_like": 13.59, "temp_min": 14.94, "temp_max": 14.94}', name='query_weather_from_db', id='8b21e310-8581-4a4f-b3a0-c3c2b4b22195', tool_call_id='call_BMA4Jp782AMVBw4VS1x3nv8h'),
AIMessage(content='北京今天的天气是多云的。具体情况如下:\n\n- 天气描述:晴,少云\n- 当前温度:14.94°C\n- 体感温度:13.59°C\n- 最低温度:14.94°C\n- 最高温度:14.94°C', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 67, 'prompt_tokens': 440, 'total_tokens': 507, 'prompt_tokens_details': {'cached_tokens': 0}, 'completion_tokens_details': {'reasoning_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_72bbfa6014', 'finish_reason': 'stop', 'logprobs': None}, id='run-25dabd3b-195e-49ce-a431-b9f535fdd01c-0', usage_metadata={'input_tokens': 440, 'output_tokens': 67, 'total_tokens': 507, 'input_token_details': {'cache_read': 0}, 'output_token_details': {'reasoning': 0}})]}
1 | finan_response["messages"][-1].content |
'北京今天的天气是多云的。具体情况如下:\n\n- 天气描述:晴,少云\n- 当前温度:14.94°C\n- 体感温度:13.59°C\n- 最低温度:14.94°C\n- 最高温度:14.94°C'
1 | finan_response = graph.invoke({"messages":["北京今天的天气怎么样?"]}) |
<__main__.Weather object at 0x00000222A5896390>
{'messages': [HumanMessage(content='北京今天的天气怎么样?', additional_kwargs={}, response_metadata={}, id='3ea29a69-311d-4003-935f-18ca24bc9e6f'),
AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_BMA4Jp782AMVBw4VS1x3nv8h', 'function': {'arguments': '{"city_name":"Beijing"}', 'name': 'query_weather_from_db'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 18, 'prompt_tokens': 342, 'total_tokens': 360, 'prompt_tokens_details': {'cached_tokens': 0}, 'completion_tokens_details': {'reasoning_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_72bbfa6014', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-eb43ab41-161c-4acb-b8d7-b5890745ce55-0', tool_calls=[{'name': 'query_weather_from_db', 'args': {'city_name': 'Beijing'}, 'id': 'call_BMA4Jp782AMVBw4VS1x3nv8h', 'type': 'tool_call'}], usage_metadata={'input_tokens': 342, 'output_tokens': 18, 'total_tokens': 360, 'input_token_details': {'cache_read': 0}, 'output_token_details': {'reasoning': 0}}),
ToolMessage(content='{"city_id": 1816670, "city_name": "Beijing", "main_weather": "Clouds", "description": "晴,少云", "temperature": 14.94, "feels_like": 13.59, "temp_min": 14.94, "temp_max": 14.94}', name='query_weather_from_db', id='8b21e310-8581-4a4f-b3a0-c3c2b4b22195', tool_call_id='call_BMA4Jp782AMVBw4VS1x3nv8h'),
AIMessage(content='北京今天的天气是多云的。具体情况如下:\n\n- 天气描述:晴,少云\n- 当前温度:14.94°C\n- 体感温度:13.59°C\n- 最低温度:14.94°C\n- 最高温度:14.94°C', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 67, 'prompt_tokens': 440, 'total_tokens': 507, 'prompt_tokens_details': {'cached_tokens': 0}, 'completion_tokens_details': {'reasoning_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_72bbfa6014', 'finish_reason': 'stop', 'logprobs': None}, id='run-25dabd3b-195e-49ce-a431-b9f535fdd01c-0', usage_metadata={'input_tokens': 440, 'output_tokens': 67, 'total_tokens': 507, 'input_token_details': {'cache_read': 0}, 'output_token_details': {'reasoning': 0}})]}
1 | finan_response = graph.invoke({"messages":["你知道 cloud 3.5 发布的 computer use 吗?请用中文回复我"]}) |
{'messages': [HumanMessage(content='你知道 cloud 3.5 发布的 computer use 吗?请用中文回复我', additional_kwargs={}, response_metadata={}, id='c1ba742a-2c74-4aed-b774-b176ab60e8e1'),
AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_xt4I3LDtRRzOYKyb01fA4Rv5', 'function': {'arguments': '{"query":"cloud 3.5 发布的 computer use"}', 'name': 'fetch_real_time_info'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 24, 'prompt_tokens': 355, 'total_tokens': 379, 'prompt_tokens_details': {'cached_tokens': 0}, 'completion_tokens_details': {'reasoning_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_72bbfa6014', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-cb591e6e-f410-4ab0-a77a-ece56767b728-0', tool_calls=[{'name': 'fetch_real_time_info', 'args': {'query': 'cloud 3.5 发布的 computer use'}, 'id': 'call_xt4I3LDtRRzOYKyb01fA4Rv5', 'type': 'tool_call'}], usage_metadata={'input_tokens': 355, 'output_tokens': 24, 'total_tokens': 379, 'input_token_details': {'cache_read': 0}, 'output_token_details': {'reasoning': 0}}),
ToolMessage(content='[{"title": "升级了来自Anthropic 的Claude 3.5 Sonnet(现已推出) - AWS", "link": "https://aws.amazon.com/cn/blogs/china/upgraded-claude-3-5-sonnet-from-anthropic-available-now-computer-use-public-beta-and-claude-3-5-haiku-coming-soon-in-amazon-bedrock/", "snippet": "计算机使用– Claude 3.5 Sonnet 目前在Amazon Bedrock 中提供计算机使用功能(公测版),这使得Claude 能够感知并与计算机界面进行交互。开发人员可以 ...", "date": "5 days ago", "position": 1}]', name='fetch_real_time_info', id='dba1ac63-46d2-4b19-926f-3c28da7b29f6', tool_call_id='call_xt4I3LDtRRzOYKyb01fA4Rv5'),
AIMessage(content='关于 Cloud 3.5 发布的 computer use 功能,目前的信息显示,Claude 3.5 Sonnet 现在在 Amazon Bedrock 中提供计算机使用功能(公测版)。这使得 Claude 能够感知并与计算机界面进行交互。更多详情可以查看 [AWS 官方博客](https://aws.amazon.com/cn/blogs/china/upgraded-claude-3-5-sonnet-from-anthropic-available-now-computer-use-public-beta-and-claude-3-5-haiku-coming-soon-in-amazon-bedrock/)。', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 122, 'prompt_tokens': 541, 'total_tokens': 663, 'prompt_tokens_details': {'cached_tokens': 0}, 'completion_tokens_details': {'reasoning_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_45c6de4934', 'finish_reason': 'stop', 'logprobs': None}, id='run-e45a1550-0c7d-4096-b1a0-238ca7cc8248-0', usage_metadata={'input_tokens': 541, 'output_tokens': 122, 'total_tokens': 663, 'input_token_details': {'cache_read': 0}, 'output_token_details': {'reasoning': 0}})]}
1 | finan_response["messages"][-1].content |
'关于 Cloud 3.5 发布的 computer use 功能,目前的信息显示,Claude 3.5 Sonnet 现在在 Amazon Bedrock 中提供计算机使用功能(公测版)。这使得 Claude 能够感知并与计算机界面进行交互。更多详情可以查看 [AWS 官方博客](https://aws.amazon.com/cn/blogs/china/upgraded-claude-3-5-sonnet-from-anthropic-available-now-computer-use-public-beta-and-claude-3-5-haiku-coming-soon-in-amazon-bedrock/)。'
继续加大问题的难度,我们要在一个问题中涉及多个工具的使用,比如:
1 | finan_response = graph.invoke({"messages":["帮我查一下北京、上海,哈尔滨三个城市的天气,告诉我哪个城市最适合出游。同时,把查询到的数据存储到数据库中"]}) |
{'messages': [HumanMessage(content='帮我查一下北京、上海,哈尔滨三个城市的天气,告诉我哪个城市最适合出游。同时,把查询到的数据存储到数据库中', additional_kwargs={}, response_metadata={}, id='7da34790-3f00-46d0-859e-b6f7cef4ee5d'),
AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_ro4igb9igPivvs0HZXKHAhwG', 'function': {'arguments': '{"loc": "Beijing"}', 'name': 'get_weather'}, 'type': 'function'}, {'id': 'call_IRBeslzB7okZa28rAnrNdNbB', 'function': {'arguments': '{"loc": "Shanghai"}', 'name': 'get_weather'}, 'type': 'function'}, {'id': 'call_J3yXYOErmnZmooW7A0Wrsh5I', 'function': {'arguments': '{"loc": "Harbin"}', 'name': 'get_weather'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 60, 'prompt_tokens': 370, 'total_tokens': 430, 'prompt_tokens_details': {'cached_tokens': 0}, 'completion_tokens_details': {'reasoning_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_72bbfa6014', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-e630e698-033f-463c-8b48-2107eaa616c2-0', tool_calls=[{'name': 'get_weather', 'args': {'loc': 'Beijing'}, 'id': 'call_ro4igb9igPivvs0HZXKHAhwG', 'type': 'tool_call'}, {'name': 'get_weather', 'args': {'loc': 'Shanghai'}, 'id': 'call_IRBeslzB7okZa28rAnrNdNbB', 'type': 'tool_call'}, {'name': 'get_weather', 'args': {'loc': 'Harbin'}, 'id': 'call_J3yXYOErmnZmooW7A0Wrsh5I', 'type': 'tool_call'}], usage_metadata={'input_tokens': 370, 'output_tokens': 60, 'total_tokens': 430, 'input_token_details': {'cache_read': 0}, 'output_token_details': {'reasoning': 0}}),
ToolMessage(content='{"coord": {"lon": 116.3972, "lat": 39.9075}, "weather": [{"id": 800, "main": "Clear", "description": "\\u6674", "icon": "01n"}], "base": "stations", "main": {"temp": 17.72, "feels_like": 16.36, "temp_min": 14.94, "temp_max": 17.72, "pressure": 1017, "humidity": 31, "sea_level": 1017, "grnd_level": 1012}, "visibility": 10000, "wind": {"speed": 1.3, "deg": 282, "gust": 4.19}, "clouds": {"all": 0}, "dt": 1730195826, "sys": {"type": 2, "id": 2000403, "country": "CN", "sunrise": 1730155186, "sunset": 1730193377}, "timezone": 28800, "id": 1816670, "name": "Beijing", "cod": 200}', name='get_weather', id='969b2663-e3db-4b18-b5ce-433b65adf673', tool_call_id='call_ro4igb9igPivvs0HZXKHAhwG'),
ToolMessage(content='{"coord": {"lon": 121.4581, "lat": 31.2222}, "weather": [{"id": 800, "main": "Clear", "description": "\\u6674", "icon": "01n"}], "base": "stations", "main": {"temp": 17.92, "feels_like": 17.31, "temp_min": 17.92, "temp_max": 17.93, "pressure": 1019, "humidity": 59, "sea_level": 1019, "grnd_level": 1017}, "visibility": 10000, "wind": {"speed": 5, "deg": 20}, "clouds": {"all": 0}, "dt": 1730196000, "sys": {"type": 1, "id": 9659, "country": "CN", "sunrise": 1730153230, "sunset": 1730192904}, "timezone": 28800, "id": 1796236, "name": "Shanghai", "cod": 200}', name='get_weather', id='75725f62-f9d2-4fe2-8865-fea606416b6a', tool_call_id='call_IRBeslzB7okZa28rAnrNdNbB'),
ToolMessage(content='{"coord": {"lon": 126.65, "lat": 45.75}, "weather": [{"id": 500, "main": "Rain", "description": "\\u5c0f\\u96e8", "icon": "10n"}], "base": "stations", "main": {"temp": 8.62, "feels_like": 8.62, "temp_min": 8.62, "temp_max": 8.62, "pressure": 1016, "humidity": 70, "sea_level": 1016, "grnd_level": 999}, "visibility": 10000, "wind": {"speed": 0.91, "deg": 129, "gust": 1.16}, "rain": {"1h": 0.36}, "clouds": {"all": 97}, "dt": 1730196009, "sys": {"country": "CN", "sunrise": 1730153336, "sunset": 1730190306}, "timezone": 28800, "id": 2037013, "name": "Harbin", "cod": 200}', name='get_weather', id='6b49bbfe-e45d-449b-84b2-314f760467ca', tool_call_id='call_J3yXYOErmnZmooW7A0Wrsh5I'),
AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_izOMSYgvfloxuJkXgDB1Voz6', 'function': {'arguments': '{"city_id": 1816670, "city_name": "Beijing", "main_weather": "Clear", "description": "晴", "temperature": 17.72, "feels_like": 16.36, "temp_min": 14.94, "temp_max": 17.72}', 'name': 'insert_weather_to_db'}, 'type': 'function'}, {'id': 'call_Bc8WJdfNZMzo3hXCyunaCznj', 'function': {'arguments': '{"city_id": 1796236, "city_name": "Shanghai", "main_weather": "Clear", "description": "晴", "temperature": 17.92, "feels_like": 17.31, "temp_min": 17.92, "temp_max": 17.93}', 'name': 'insert_weather_to_db'}, 'type': 'function'}, {'id': 'call_NanSRD2EDHeOlUktShccuSaW', 'function': {'arguments': '{"city_id": 2037013, "city_name": "Harbin", "main_weather": "Rain", "description": "小雨", "temperature": 8.62, "feels_like": 8.62, "temp_min": 8.62, "temp_max": 8.62}', 'name': 'insert_weather_to_db'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 202, 'prompt_tokens': 1177, 'total_tokens': 1379, 'prompt_tokens_details': {'cached_tokens': 0}, 'completion_tokens_details': {'reasoning_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_72bbfa6014', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-8a14762c-6309-4f27-8eae-a422867a293d-0', tool_calls=[{'name': 'insert_weather_to_db', 'args': {'city_id': 1816670, 'city_name': 'Beijing', 'main_weather': 'Clear', 'description': '晴', 'temperature': 17.72, 'feels_like': 16.36, 'temp_min': 14.94, 'temp_max': 17.72}, 'id': 'call_izOMSYgvfloxuJkXgDB1Voz6', 'type': 'tool_call'}, {'name': 'insert_weather_to_db', 'args': {'city_id': 1796236, 'city_name': 'Shanghai', 'main_weather': 'Clear', 'description': '晴', 'temperature': 17.92, 'feels_like': 17.31, 'temp_min': 17.92, 'temp_max': 17.93}, 'id': 'call_Bc8WJdfNZMzo3hXCyunaCznj', 'type': 'tool_call'}, {'name': 'insert_weather_to_db', 'args': {'city_id': 2037013, 'city_name': 'Harbin', 'main_weather': 'Rain', 'description': '小雨', 'temperature': 8.62, 'feels_like': 8.62, 'temp_min': 8.62, 'temp_max': 8.62}, 'id': 'call_NanSRD2EDHeOlUktShccuSaW', 'type': 'tool_call'}], usage_metadata={'input_tokens': 1177, 'output_tokens': 202, 'total_tokens': 1379, 'input_token_details': {'cache_read': 0}, 'output_token_details': {'reasoning': 0}}),
ToolMessage(content='{"messages": ["天气数据已成功存储至Mysql数据库。"]}', name='insert_weather_to_db', id='3faca92c-6a82-40ba-9f59-a5f62326400f', tool_call_id='call_izOMSYgvfloxuJkXgDB1Voz6'),
ToolMessage(content='{"messages": ["天气数据已成功存储至Mysql数据库。"]}', name='insert_weather_to_db', id='fafbdce3-6ea1-4d93-8ec3-8a32606e6ca7', tool_call_id='call_Bc8WJdfNZMzo3hXCyunaCznj'),
ToolMessage(content='{"messages": ["天气数据已成功存储至Mysql数据库。"]}', name='insert_weather_to_db', id='0c98e550-8562-4125-9e08-2391c7c1b703', tool_call_id='call_NanSRD2EDHeOlUktShccuSaW'),
AIMessage(content='以下是北京、上海和哈尔滨的天气情况:\n\n1. **北京**:\n - 天气:晴\n - 温度:17.72°C\n - 体感温度:16.36°C\n - 最低温度:14.94°C\n - 最高温度:17.72°C\n\n2. **上海**:\n - 天气:晴\n - 温度:17.92°C\n - 体感温度:17.31°C\n - 最低温度:17.92°C\n - 最高温度:17.93°C\n\n3. **哈尔滨**:\n - 天气:小雨\n - 温度:8.62°C\n - 体感温度:8.62°C\n - 最低温度:8.62°C\n - 最高温度:8.62°C\n\n根据天气情况,北京和上海的天气都是晴朗的,比较适合出游。哈尔滨有小雨,不太适合出游。如果一定要选择一个最适合出游的城市,我会推荐上海,因为气温稍微高一点,更加舒适。\n\n所有查询到的天气数据已经成功存储到数据库中。', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 267, 'prompt_tokens': 1558, 'total_tokens': 1825, 'prompt_tokens_details': {'cached_tokens': 1280}, 'completion_tokens_details': {'reasoning_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_72bbfa6014', 'finish_reason': 'stop', 'logprobs': None}, id='run-51e04ca7-3475-49fb-a5c0-8493faf347a1-0', usage_metadata={'input_tokens': 1558, 'output_tokens': 267, 'total_tokens': 1825, 'input_token_details': {'cache_read': 1280}, 'output_token_details': {'reasoning': 0}})]}
1 | finan_response["messages"][-1].content |
'以下是北京、上海和哈尔滨的天气情况:\n\n1. **北京**:\n - 天气:晴\n - 温度:17.72°C\n - 体感温度:16.36°C\n - 最低温度:14.94°C\n - 最高温度:17.72°C\n\n2. **上海**:\n - 天气:晴\n - 温度:17.92°C\n - 体感温度:17.31°C\n - 最低温度:17.92°C\n - 最高温度:17.93°C\n\n3. **哈尔滨**:\n - 天气:小雨\n - 温度:8.62°C\n - 体感温度:8.62°C\n - 最低温度:8.62°C\n - 最高温度:8.62°C\n\n根据天气情况,北京和上海的天气都是晴朗的,比较适合出游。哈尔滨有小雨,不太适合出游。如果一定要选择一个最适合出游的城市,我会推荐上海,因为气温稍微高一点,更加舒适。\n\n所有查询到的天气数据已经成功存储到数据库中。'
同时,可以在数据库中查看数据的插入情况:
1 | finan_response = graph.invoke({"messages":["帮我分析一下数据库中北京和哈尔滨城市天气的信息,做一个详细的对比,并生成出行建议"]}) |
<__main__.Weather object at 0x00000222A72E6350>
<__main__.Weather object at 0x00000222A6F4AC50>
{'messages': [HumanMessage(content='帮我分析一下数据库中北京和哈尔滨城市天气的信息,做一个详细的对比,并生成出行建议', additional_kwargs={}, response_metadata={}, id='de625a6f-c247-41dd-9bf0-e5e2af41459f'),
AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_f2h95mzFmIAZ7LwcBaL1QUHP', 'function': {'arguments': '{"city_name": "Beijing"}', 'name': 'query_weather_from_db'}, 'type': 'function'}, {'id': 'call_8P3qlq6yM9kelaHqRZ9zZ4O0', 'function': {'arguments': '{"city_name": "Harbin"}', 'name': 'query_weather_from_db'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 52, 'prompt_tokens': 361, 'total_tokens': 413, 'prompt_tokens_details': {'cached_tokens': 0}, 'completion_tokens_details': {'reasoning_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_72bbfa6014', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-33535fcc-cb90-4bc5-b8e2-421d7b20e68b-0', tool_calls=[{'name': 'query_weather_from_db', 'args': {'city_name': 'Beijing'}, 'id': 'call_f2h95mzFmIAZ7LwcBaL1QUHP', 'type': 'tool_call'}, {'name': 'query_weather_from_db', 'args': {'city_name': 'Harbin'}, 'id': 'call_8P3qlq6yM9kelaHqRZ9zZ4O0', 'type': 'tool_call'}], usage_metadata={'input_tokens': 361, 'output_tokens': 52, 'total_tokens': 413, 'input_token_details': {'cache_read': 0}, 'output_token_details': {'reasoning': 0}}),
ToolMessage(content='{"city_id": 1816670, "city_name": "Beijing", "main_weather": "Clear", "description": "晴", "temperature": 17.72, "feels_like": 16.36, "temp_min": 14.94, "temp_max": 17.72}', name='query_weather_from_db', id='d1b400d9-02f4-4ffd-9f00-0cfc2298bf92', tool_call_id='call_f2h95mzFmIAZ7LwcBaL1QUHP'),
ToolMessage(content='{"city_id": 2037013, "city_name": "Harbin", "main_weather": "Rain", "description": "小雨", "temperature": 8.62, "feels_like": 8.62, "temp_min": 8.62, "temp_max": 8.62}', name='query_weather_from_db', id='d84861cd-fc8f-44f8-8faa-5b5b8218bace', tool_call_id='call_8P3qlq6yM9kelaHqRZ9zZ4O0'),
AIMessage(content='### 天气对比分析\n\n#### 北京\n- **天气状况**: 晴\n- **详细描述**: 晴\n- **当前温度**: 17.72°C\n- **体感温度**: 16.36°C\n- **最低温度**: 14.94°C\n- **最高温度**: 17.72°C\n\n#### 哈尔滨\n- **天气状况**: 雨\n- **详细描述**: 小雨\n- **当前温度**: 8.62°C\n- **体感温度**: 8.62°C\n- **最低温度**: 8.62°C\n- **最高温度**: 8.62°C\n\n### 出行建议\n\n#### 北京\n1. **穿着建议**: 北京天气晴朗,温度适中,建议穿轻便的春秋装。\n2. **活动建议**: 适合户外活动,如散步、慢跑或骑行。\n3. **防晒措施**: 即使是晴天,依然建议使用防晒霜和佩戴太阳镜。\n\n#### 哈尔滨\n1. **穿着建议**: 哈尔滨气温较低且有小雨,建议穿保暖的衣物,并携带雨具。\n2. **活动建议**: 降雨可能影响户外活动,建议选择室内活动。\n3. **行车安全**: 雨天路滑,驾车请注意安全,保持车距。\n\n这两座城市当前的天气差异较大,出行前请根据实际天气情况做好相应准备。', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 355, 'prompt_tokens': 566, 'total_tokens': 921, 'prompt_tokens_details': {'cached_tokens': 0}, 'completion_tokens_details': {'reasoning_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_45c6de4934', 'finish_reason': 'stop', 'logprobs': None}, id='run-af1a77c2-2fd4-4549-8683-d8df867221d1-0', usage_metadata={'input_tokens': 566, 'output_tokens': 355, 'total_tokens': 921, 'input_token_details': {'cache_read': 0}, 'output_token_details': {'reasoning': 0}})]}
1 | print(finan_response["messages"][-1].content) |
### 天气对比分析
#### 北京
- **天气状况**: 晴
- **详细描述**: 晴
- **当前温度**: 17.72°C
- **体感温度**: 16.36°C
- **最低温度**: 14.94°C
- **最高温度**: 17.72°C
#### 哈尔滨
- **天气状况**: 雨
- **详细描述**: 小雨
- **当前温度**: 8.62°C
- **体感温度**: 8.62°C
- **最低温度**: 8.62°C
- **最高温度**: 8.62°C
### 出行建议
#### 北京
1. **穿着建议**: 北京天气晴朗,温度适中,建议穿轻便的春秋装。
2. **活动建议**: 适合户外活动,如散步、慢跑或骑行。
3. **防晒措施**: 即使是晴天,依然建议使用防晒霜和佩戴太阳镜。
#### 哈尔滨
1. **穿着建议**: 哈尔滨气温较低且有小雨,建议穿保暖的衣物,并携带雨具。
2. **活动建议**: 降雨可能影响户外活动,建议选择室内活动。
3. **行车安全**: 雨天路滑,驾车请注意安全,保持车距。
这两座城市当前的天气差异较大,出行前请根据实际天气情况做好相应准备。
通过对不同复杂程度输入问题的测试,我们发现当前架构能够非常准确且快速地完成任务目标。在涉及多个任务的顺序执行时,ReAct 代理能够自主决策并执行,真正实现了完全的自治循环代理。此外,其可扩展性也十分出色。对于不同的业务需求,我们只需调整接入的大模型实例(可使用其他开源或在线模型)作为 ReAct 的基础模型。对于工具的配置,也无需特别进行复杂的编排,只需明确定义每个工具的输入和输出,然后通过工具列表的形式直接注册到大模型实例及 ToolNode 实例中。这种方法在快速构建智能代理方面,非常值得大家尝试。
3. LangGraph中的事件流
流式输出的作用在于,它能实时捕捉并输出任务处理过程中的状态变化。这意味着,任何中间过程中的新状态和值都可以被即时获取到。所以,流式输出功能本质上不直接参与Agent的执行过程,仅仅是用来追踪、记录Agent在处理不同任务时产生的各个事件、状态和值。
在实际应用中,流式输出尤其适用于需要快速反馈的业务场景,如聊天机器人,因为大语言模型可能需要几秒钟才能生成对查询的完整响应,这远远慢于应用程序对最终用户的响应速度约为 200-300 毫秒的阈值,如果是涉及多个大模型调用的复杂应用程序,这种延时会变得更加明显。让应用程序感觉响应更快的关键策略是显示中间进度;即,通过 token 流式传输大模型Token的输出,以此来显著提升用户体验。而在开发阶段,利用流式输出功能可以准确追踪到事件的具体执行阶段,并捕获相关数据,从而接入不同逻辑的数据处理和决策流程。是我们在应用开发中必须理解和掌握的技术点。
流式输出功能在LangGraph 框架中的实现方式,相较于Assistant API是简单很多的,但基本思路一样。因为LangGraph底层是基于 LangChain 构建的,所有就直接把LangChain中的回调系统拿过来使用了。在LangChain中的流式输出是:以块的形式传输最终输出,即一旦监测到有可用的块,就直接生成它。最常见和最关键的流数据是大模型本身生成的输出。 大模型通常需要时间才能生成完整的响应,通过实时流式传输输出,用户可以在生成时看到部分结果,这可以提供即时反馈并有助于减少用户的等待时间。如下所示:
1 | import getpass |
1 | chunks = [] |
|你好|!|我是|一个|由|人工|智能|驱|动|的|虚|拟|助手|,|旨|在|帮助|回答|问题|和|提供|信息|。我|能够|处理|各种|主题|,包括|常|识|问题|、|技术|支持|、|语言|翻|译|、|写|作|建议|等等|。|我的|设计|目标|是|尽|量|理解|你的|问题|并|提供|有|用|的|答案|。
|由于|我是|基|于|大|规模|的|语言|模型|构|建|的|,因此|我的|知识|和|能力|是|基|于|对|大量|文本|数据|的|分析|。我|没有|个人|经验|或|感|情|,但|我|会|尽|力|为|你|提供|准确|和|及时|的信息|。
|如果|你|有|任何|问题|或|需要|帮助|,请|随|时|告诉|我|!||
1 | chunks[0] |
AIMessageChunk(content='', additional_kwargs={}, response_metadata={}, id='run-034a91b3-9509-4442-8c0d-3d17774451bf')
每一个块,都是一个AIMessageChunk对象,用来代表AIMessage对象的一部分。消息块在设计上是可加的,比如:
1 | chunks[0] + chunks[1] + chunks[2] + chunks[3] + chunks[4] |
AIMessageChunk(content='你好!我是一个', additional_kwargs={}, response_metadata={}, id='run-034a91b3-9509-4442-8c0d-3d17774451bf')
而进一步的,除了流式传输大模型的输出之外,通过更复杂的工作流程或管道流式传输进度也很有用,比如 AI Agent 中的中间处理过程,这就涉及到工作流概念。
3.1 LangGraph使用流输出
LangGraph框架中的工作流中由各个步骤的节点和边组成。这里的流式传输涉及在各个节点请求更新时跟踪图状态的变化。这样可以更精细地监控工作流中当前处于活动状态的节点,并在工作流经过不同阶段时提供有关工作流状态的实时更新。其实现方式也是和LangChain一样通过.stream和.astream方法执行流式输出,只不过适配到了图结构中。调用.stream和.astream方法时可以指定几种不同的模式,即:
- “values” :在图中的每个步骤之后流式传输状态的完整值。
- “updates” :在图中的每个步骤之后将更新流式传输到状态。如果在同一步骤中进行多个更新(例如运行多个节点),则这些更新将单独流式传输。
- “debug” :在整个图的执行过程中流式传输尽可能多的信息,主要用于调试程序。
- “messages”:记录每个
messages中的增量token。 - “custom”:自定义流,通过
LangGraph 的 StreamWriter方法
首先来看Stream方法,该方法返回一个迭代器,在生成输出块时同步生成它们。我们可以使用for循环来实时处理每个块。生成的块的类型取决于正在流式传输的组件。例如,当从大模型流式传输时,每个组件将是一个AIMessageChunk,但是,对于其他组件,块可能会有所不同。其LangGraph框架中实现的源码如下:
LangGraph Graph stream:https://reference.langchain.com/python/langgraph/graphs/#langgraph.graph.state.CompiledStateGraph.stream
1 | def stream( |
- values :在图表的每个步骤之后流式传输状态的完整值。
1 | def print_stream(stream): |
================================[1m Human Message [0m=================================
你好,南京现在的天气怎么样?
==================================[1m Ai Message [0m==================================
Tool Calls:
query_weather_from_db (call_xfRWSscdr2S6Fgo1GnxAQUFk)
Call ID: call_xfRWSscdr2S6Fgo1GnxAQUFk
Args:
city_name: Nanjing
None
=================================[1m Tool Message [0m=================================
Name: query_weather_from_db
{"messages": ["未找到城市 'Nanjing' 的天气信息。"]}
==================================[1m Ai Message [0m==================================
Tool Calls:
get_weather (call_Wd4DNds56FewTYwx7Z6SEBnw)
Call ID: call_Wd4DNds56FewTYwx7Z6SEBnw
Args:
loc: Nanjing
=================================[1m Tool Message [0m=================================
Name: get_weather
{"coord": {"lon": 118.7778, "lat": 32.0617}, "weather": [{"id": 800, "main": "Clear", "description": "\u6674", "icon": "01d"}], "base": "stations", "main": {"temp": 18.75, "feels_like": 18.12, "temp_min": 18.75, "temp_max": 18.75, "pressure": 1023, "humidity": 55, "sea_level": 1023, "grnd_level": 1020}, "visibility": 10000, "wind": {"speed": 4.89, "deg": 77, "gust": 6.84}, "clouds": {"all": 0}, "dt": 1730257590, "sys": {"country": "CN", "sunrise": 1730240389, "sunset": 1730279826}, "timezone": 28800, "id": 1799962, "name": "Nanjing", "cod": 200}
==================================[1m Ai Message [0m==================================
Tool Calls:
insert_weather_to_db (call_rcwMjfSIFM5S1WihC2RD8xIC)
Call ID: call_rcwMjfSIFM5S1WihC2RD8xIC
Args:
city_id: 1799962
city_name: Nanjing
main_weather: Clear
description: 晴
temperature: 18.75
feels_like: 18.12
temp_min: 18.75
temp_max: 18.75
=================================[1m Tool Message [0m=================================
Name: insert_weather_to_db
{"messages": ["天气数据已成功存储至Mysql数据库。"]}
==================================[1m Ai Message [0m==================================
南京现在的天气是晴天,气温为18.75°C,体感温度约为18.12°C。空气清新,能见度良好。
- updates :在图中的每个步骤之后将更新流式传输到状态。
1 | def print_stream(stream): |
{'agent': {'messages': [AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_Ma7bxsvHjIXCXozwmJieVtJJ', 'function': {'arguments': '{"loc": "Tianjin"}', 'name': 'get_weather'}, 'type': 'function'}, {'id': 'call_uM3KOsUgIogoBdJbcXwPYEqp', 'function': {'arguments': '{"loc": "Inner Mongolia"}', 'name': 'get_weather'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 47, 'prompt_tokens': 347, 'total_tokens': 394, 'prompt_tokens_details': {'cached_tokens': 0}, 'completion_tokens_details': {'reasoning_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_72bbfa6014', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-5cd03389-b67e-416d-a92f-9c02e4ca75b0-0', tool_calls=[{'name': 'get_weather', 'args': {'loc': 'Tianjin'}, 'id': 'call_Ma7bxsvHjIXCXozwmJieVtJJ', 'type': 'tool_call'}, {'name': 'get_weather', 'args': {'loc': 'Inner Mongolia'}, 'id': 'call_uM3KOsUgIogoBdJbcXwPYEqp', 'type': 'tool_call'}], usage_metadata={'input_tokens': 347, 'output_tokens': 47, 'total_tokens': 394, 'input_token_details': {'cache_read': 0}, 'output_token_details': {'reasoning': 0}})]}}
{'tools': {'messages': [ToolMessage(content='{"coord": {"lon": 117.1767, "lat": 39.1422}, "weather": [{"id": 800, "main": "Clear", "description": "\\u6674", "icon": "01d"}], "base": "stations", "main": {"temp": 18.97, "feels_like": 18.46, "temp_min": 18.97, "temp_max": 18.97, "pressure": 1025, "humidity": 59, "sea_level": 1025, "grnd_level": 1024}, "visibility": 10000, "wind": {"speed": 7, "deg": 140}, "clouds": {"all": 0}, "dt": 1730258008, "sys": {"type": 1, "id": 9619, "country": "CN", "sunrise": 1730241393, "sunset": 1730279591}, "timezone": 28800, "id": 1792947, "name": "Tianjin", "cod": 200}', name='get_weather', id='d667c453-d237-438f-9735-1b6d7854717d', tool_call_id='call_Ma7bxsvHjIXCXozwmJieVtJJ'), ToolMessage(content='{"cod": "404", "message": "city not found"}', name='get_weather', id='c81bf119-461b-4956-aab7-4bcfd67dc461', tool_call_id='call_uM3KOsUgIogoBdJbcXwPYEqp')]}}
{'agent': {'messages': [AIMessage(content='天津的天气情况如下:\n- 天气:晴\n- 温度:18.97°C\n- 体感温度:18.46°C\n- 风速:7 m/s\n- 湿度:59%\n\n内蒙古的天气信息暂时无法获取,可能是因为城市名不够具体或者数据暂时不可用。如果你有具体的内蒙古城市名称,可以提供给我以便查询。', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 90, 'prompt_tokens': 659, 'total_tokens': 749, 'prompt_tokens_details': {'cached_tokens': 0}, 'completion_tokens_details': {'reasoning_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_72bbfa6014', 'finish_reason': 'stop', 'logprobs': None}, id='run-e89e91d2-14a3-420c-b19d-08e59a57883f-0', usage_metadata={'input_tokens': 659, 'output_tokens': 90, 'total_tokens': 749, 'input_token_details': {'cache_read': 0}, 'output_token_details': {'reasoning': 0}})]}}
- debug :在整个图中的执行过程中流式传输尽可能多的信息
1 | def print_stream(stream): |
{'type': 'task', 'timestamp': '2024-10-30T03:14:44.538467+00:00', 'step': 1, 'payload': {'id': 'ec74ada5-a269-f1ab-3344-64ef7aa0cb0d', 'name': 'agent', 'input': {'messages': [HumanMessage(content='你好,天津、内蒙现在的天气怎么样?', additional_kwargs={}, response_metadata={}, id='2b048b3c-6ff7-4576-9e97-f5e1986ae085')], 'is_last_step': False}, 'triggers': ['start:agent']}}
{'type': 'task_result', 'timestamp': '2024-10-30T03:14:47.434922+00:00', 'step': 1, 'payload': {'id': 'ec74ada5-a269-f1ab-3344-64ef7aa0cb0d', 'name': 'agent', 'error': None, 'result': [('messages', [AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_NaK0YDbmUSm1pSPgmcuaglHl', 'function': {'arguments': '{"loc": "Tianjin"}', 'name': 'get_weather'}, 'type': 'function'}, {'id': 'call_870GtpjxM8Rgw36N7wIqfRDq', 'function': {'arguments': '{"loc": "Inner Mongolia"}', 'name': 'get_weather'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 47, 'prompt_tokens': 347, 'total_tokens': 394, 'prompt_tokens_details': {'cached_tokens': 0}, 'completion_tokens_details': {'reasoning_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_72bbfa6014', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-6c23f36c-e854-4e3f-beef-04be5ae46041-0', tool_calls=[{'name': 'get_weather', 'args': {'loc': 'Tianjin'}, 'id': 'call_NaK0YDbmUSm1pSPgmcuaglHl', 'type': 'tool_call'}, {'name': 'get_weather', 'args': {'loc': 'Inner Mongolia'}, 'id': 'call_870GtpjxM8Rgw36N7wIqfRDq', 'type': 'tool_call'}], usage_metadata={'input_tokens': 347, 'output_tokens': 47, 'total_tokens': 394, 'input_token_details': {'cache_read': 0}, 'output_token_details': {'reasoning': 0}})])], 'interrupts': []}}
{'type': 'task', 'timestamp': '2024-10-30T03:14:47.434922+00:00', 'step': 2, 'payload': {'id': '29849df1-72f9-e753-4982-c0ca4403a93d', 'name': 'tools', 'input': {'messages': [HumanMessage(content='你好,天津、内蒙现在的天气怎么样?', additional_kwargs={}, response_metadata={}, id='2b048b3c-6ff7-4576-9e97-f5e1986ae085'), AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_NaK0YDbmUSm1pSPgmcuaglHl', 'function': {'arguments': '{"loc": "Tianjin"}', 'name': 'get_weather'}, 'type': 'function'}, {'id': 'call_870GtpjxM8Rgw36N7wIqfRDq', 'function': {'arguments': '{"loc": "Inner Mongolia"}', 'name': 'get_weather'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 47, 'prompt_tokens': 347, 'total_tokens': 394, 'prompt_tokens_details': {'cached_tokens': 0}, 'completion_tokens_details': {'reasoning_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_72bbfa6014', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-6c23f36c-e854-4e3f-beef-04be5ae46041-0', tool_calls=[{'name': 'get_weather', 'args': {'loc': 'Tianjin'}, 'id': 'call_NaK0YDbmUSm1pSPgmcuaglHl', 'type': 'tool_call'}, {'name': 'get_weather', 'args': {'loc': 'Inner Mongolia'}, 'id': 'call_870GtpjxM8Rgw36N7wIqfRDq', 'type': 'tool_call'}], usage_metadata={'input_tokens': 347, 'output_tokens': 47, 'total_tokens': 394, 'input_token_details': {'cache_read': 0}, 'output_token_details': {'reasoning': 0}})], 'is_last_step': False}, 'triggers': ['branch:agent:should_continue:tools']}}
{'type': 'task_result', 'timestamp': '2024-10-30T03:14:48.719462+00:00', 'step': 2, 'payload': {'id': '29849df1-72f9-e753-4982-c0ca4403a93d', 'name': 'tools', 'error': None, 'result': [('messages', [ToolMessage(content='{"coord": {"lon": 117.1767, "lat": 39.1422}, "weather": [{"id": 800, "main": "Clear", "description": "\\u6674", "icon": "01d"}], "base": "stations", "main": {"temp": 18.97, "feels_like": 18.46, "temp_min": 18.97, "temp_max": 18.97, "pressure": 1025, "humidity": 59, "sea_level": 1025, "grnd_level": 1024}, "visibility": 10000, "wind": {"speed": 7, "deg": 140}, "clouds": {"all": 0}, "dt": 1730258008, "sys": {"type": 1, "id": 9619, "country": "CN", "sunrise": 1730241393, "sunset": 1730279591}, "timezone": 28800, "id": 1792947, "name": "Tianjin", "cod": 200}', name='get_weather', id='ed06d7f2-4d33-4511-be9c-3325dccdc5de', tool_call_id='call_NaK0YDbmUSm1pSPgmcuaglHl'), ToolMessage(content='{"cod": "404", "message": "city not found"}', name='get_weather', id='d4f47099-64d4-4071-8956-515ae231cf79', tool_call_id='call_870GtpjxM8Rgw36N7wIqfRDq')])], 'interrupts': []}}
{'type': 'task', 'timestamp': '2024-10-30T03:14:48.719462+00:00', 'step': 3, 'payload': {'id': 'c0a70cf0-9581-d545-c4db-564234efbf12', 'name': 'agent', 'input': {'messages': [HumanMessage(content='你好,天津、内蒙现在的天气怎么样?', additional_kwargs={}, response_metadata={}, id='2b048b3c-6ff7-4576-9e97-f5e1986ae085'), AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_NaK0YDbmUSm1pSPgmcuaglHl', 'function': {'arguments': '{"loc": "Tianjin"}', 'name': 'get_weather'}, 'type': 'function'}, {'id': 'call_870GtpjxM8Rgw36N7wIqfRDq', 'function': {'arguments': '{"loc": "Inner Mongolia"}', 'name': 'get_weather'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 47, 'prompt_tokens': 347, 'total_tokens': 394, 'prompt_tokens_details': {'cached_tokens': 0}, 'completion_tokens_details': {'reasoning_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_72bbfa6014', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-6c23f36c-e854-4e3f-beef-04be5ae46041-0', tool_calls=[{'name': 'get_weather', 'args': {'loc': 'Tianjin'}, 'id': 'call_NaK0YDbmUSm1pSPgmcuaglHl', 'type': 'tool_call'}, {'name': 'get_weather', 'args': {'loc': 'Inner Mongolia'}, 'id': 'call_870GtpjxM8Rgw36N7wIqfRDq', 'type': 'tool_call'}], usage_metadata={'input_tokens': 347, 'output_tokens': 47, 'total_tokens': 394, 'input_token_details': {'cache_read': 0}, 'output_token_details': {'reasoning': 0}}), ToolMessage(content='{"coord": {"lon": 117.1767, "lat": 39.1422}, "weather": [{"id": 800, "main": "Clear", "description": "\\u6674", "icon": "01d"}], "base": "stations", "main": {"temp": 18.97, "feels_like": 18.46, "temp_min": 18.97, "temp_max": 18.97, "pressure": 1025, "humidity": 59, "sea_level": 1025, "grnd_level": 1024}, "visibility": 10000, "wind": {"speed": 7, "deg": 140}, "clouds": {"all": 0}, "dt": 1730258008, "sys": {"type": 1, "id": 9619, "country": "CN", "sunrise": 1730241393, "sunset": 1730279591}, "timezone": 28800, "id": 1792947, "name": "Tianjin", "cod": 200}', name='get_weather', id='ed06d7f2-4d33-4511-be9c-3325dccdc5de', tool_call_id='call_NaK0YDbmUSm1pSPgmcuaglHl'), ToolMessage(content='{"cod": "404", "message": "city not found"}', name='get_weather', id='d4f47099-64d4-4071-8956-515ae231cf79', tool_call_id='call_870GtpjxM8Rgw36N7wIqfRDq')], 'is_last_step': False}, 'triggers': ['tools']}}
{'type': 'task_result', 'timestamp': '2024-10-30T03:14:50.707154+00:00', 'step': 3, 'payload': {'id': 'c0a70cf0-9581-d545-c4db-564234efbf12', 'name': 'agent', 'error': None, 'result': [('messages', [AIMessage(content='天津的天气情况如下:\n\n- 天气:晴\n- 温度:18.97°C\n- 体感温度:18.46°C\n- 风速:7 m/s\n- 湿度:59%\n\n很遗憾,无法获取内蒙古的具体天气信息。如果你能提供一个具体的城市名称,我可以为你查询更详细的天气信息。', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 82, 'prompt_tokens': 659, 'total_tokens': 741, 'prompt_tokens_details': {'cached_tokens': 0}, 'completion_tokens_details': {'reasoning_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_72bbfa6014', 'finish_reason': 'stop', 'logprobs': None}, id='run-461964bb-3be1-41b2-9766-305990a9ffec-0', usage_metadata={'input_tokens': 659, 'output_tokens': 82, 'total_tokens': 741, 'input_token_details': {'cache_read': 0}, 'output_token_details': {'reasoning': 0}})])], 'interrupts': []}}
如果在异步开发环境中,则可以使用astream方法来实现流式传输,是专为非阻塞工作流程而设计。可使用的模式和stream是一致的,只不过需要调整为异步函数的定义方法,代码如下所示:
1 | async for chunk in graph.astream(input={"messages": ["你好,四川的天气怎么样?"]}, stream_mode="values"): |
================================[1m Human Message [0m=================================
你好,四川的天气怎么样?
==================================[1m Ai Message [0m==================================
Tool Calls:
query_weather_from_db (call_jElzMBgWJamba4swVQlUZ5IW)
Call ID: call_jElzMBgWJamba4swVQlUZ5IW
Args:
city_name: Sichuan
<__main__.Weather object at 0x00000222AAA89490>
=================================[1m Tool Message [0m=================================
Name: query_weather_from_db
{"city_id": 1794299, "city_name": "Sichuan", "main_weather": "Clouds", "description": "多云", "temperature": 1.67, "feels_like": -0.58, "temp_min": 1.67, "temp_max": 1.67}
==================================[1m Ai Message [0m==================================
四川目前的天气是多云,气温为1.67°C,体感温度接近-0.58°C。
如果只想得到最终结果,可以使用相同的方法并只跟踪收到的最后一个值,代码如下:
1 | async for chunk in graph.astream(input={"messages": ["你好,四川的天气怎么样?"]}, stream_mode="values"): |
1 | final_result["messages"][-1].pretty_print() |
==================================[1m Ai Message [0m==================================
四川目前的天气是多云。当前气温为1.67°C,体感温度是-0.58°C。
1 | inputs = {"messages": [("human", "你好,乌鲁木齐的天气怎么样?")]} |
接收到的更新节点: 'agent'
{'messages': [AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_ieilOQoqoNZDnjLzDwtSiSGa', 'function': {'arguments': '{"city_name":"Urumqi"}', 'name': 'query_weather_from_db'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 19, 'prompt_tokens': 346, 'total_tokens': 365, 'prompt_tokens_details': {'cached_tokens': 0}, 'completion_tokens_details': {'reasoning_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_72bbfa6014', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-98d46758-afbd-4c95-965b-8f44d83fe959-0', tool_calls=[{'name': 'query_weather_from_db', 'args': {'city_name': 'Urumqi'}, 'id': 'call_ieilOQoqoNZDnjLzDwtSiSGa', 'type': 'tool_call'}], usage_metadata={'input_tokens': 346, 'output_tokens': 19, 'total_tokens': 365, 'input_token_details': {'cache_read': 0}, 'output_token_details': {'reasoning': 0}})]}
接收到的更新节点: ‘tools’
{‘messages’: [ToolMessage(content=’{“messages”: [“未找到城市 'Urumqi' 的天气信息。”]}’, name=’query_weather_from_db’, id=’0852ae9f-b8a8-4a21-926e-765c7f084400’, tool_call_id=’call_ieilOQoqoNZDnjLzDwtSiSGa’)]}
接收到的更新节点: ‘agent’
{‘messages’: [AIMessage(content=’’, additional_kwargs={‘tool_calls’: [{‘id’: ‘call_FA2ZvwygZsZLNgQfWE6zBH8X’, ‘function’: {‘arguments’: ‘{“loc”:”Urumqi”}’, ‘name’: ‘get_weather’}, ‘type’: ‘function’}], ‘refusal’: None}, response_metadata={‘token_usage’: {‘completion_tokens’: 16, ‘prompt_tokens’: 393, ‘total_tokens’: 409, ‘prompt_tokens_details’: {‘cached_tokens’: 0}, ‘completion_tokens_details’: {‘reasoning_tokens’: 0}}, ‘model_name’: ‘gpt-4o-2024-08-06’, ‘system_fingerprint’: ‘fp_72bbfa6014’, ‘finish_reason’: ‘tool_calls’, ‘logprobs’: None}, id=’run-5cd79453-e69d-47b0-a8d8-198be000ad1e-0’, tool_calls=[{‘name’: ‘get_weather’, ‘args’: {‘loc’: ‘Urumqi’}, ‘id’: ‘call_FA2ZvwygZsZLNgQfWE6zBH8X’, ‘type’: ‘tool_call’}], usage_metadata={‘input_tokens’: 393, ‘output_tokens’: 16, ‘total_tokens’: 409, ‘input_token_details’: {‘cache_read’: 0}, ‘output_token_details’: {‘reasoning’: 0}})]}
接收到的更新节点: ‘tools’
{‘messages’: [ToolMessage(content=’{“coord”: {“lon”: 87.6005, “lat”: 43.801}, “weather”: [{“id”: 801, “main”: “Clouds”, “description”: “\u6674\uff0c\u5c11\u4e91”, “icon”: “02d”}], “base”: “stations”, “main”: {“temp”: 5.53, “feels_like”: 3.99, “temp_min”: 5.53, “temp_max”: 5.53, “pressure”: 1029, “humidity”: 81, “sea_level”: 1029, “grnd_level”: 926}, “visibility”: 10000, “wind”: {“speed”: 2, “deg”: 110}, “clouds”: {“all”: 20}, “dt”: 1730260508, “sys”: {“type”: 1, “id”: 9677, “country”: “CN”, “sunrise”: 1730248978, “sunset”: 1730286202}, “timezone”: 28800, “id”: 1529102, “name”: “\u00dcr\u00fcmqi”, “cod”: 200}’, name=’get_weather’, id=’57b6b3b8-cfc4-435b-ba94-65380b28cf11’, tool_call_id=’call_FA2ZvwygZsZLNgQfWE6zBH8X’)]}
接收到的更新节点: ‘agent’
{‘messages’: [AIMessage(content=’’, additional_kwargs={‘tool_calls’: [{‘id’: ‘call_RiMagTnBGHBCVFdy2ApzG2qt’, ‘function’: {‘arguments’: ‘{“city_id”:1529102,”city_name”:”Ürümqi”,”main_weather”:”Clouds”,”description”:”晴,少云”,”temperature”:5.53,”feels_like”:3.99,”temp_min”:5.53,”temp_max”:5.53}’, ‘name’: ‘insert_weather_to_db’}, ‘type’: ‘function’}], ‘refusal’: None}, response_metadata={‘token_usage’: {‘completion_tokens’: 68, ‘prompt_tokens’: 672, ‘total_tokens’: 740, ‘prompt_tokens_details’: {‘cached_tokens’: 0}, ‘completion_tokens_details’: {‘reasoning_tokens’: 0}}, ‘model_name’: ‘gpt-4o-2024-08-06’, ‘system_fingerprint’: ‘fp_72bbfa6014’, ‘finish_reason’: ‘tool_calls’, ‘logprobs’: None}, id=’run-d3fb79a3-b429-4c47-8d72-19d2901f21dc-0’, tool_calls=[{‘name’: ‘insert_weather_to_db’, ‘args’: {‘city_id’: 1529102, ‘city_name’: ‘Ürümqi’, ‘main_weather’: ‘Clouds’, ‘description’: ‘晴,少云’, ‘temperature’: 5.53, ‘feels_like’: 3.99, ‘temp_min’: 5.53, ‘temp_max’: 5.53}, ‘id’: ‘call_RiMagTnBGHBCVFdy2ApzG2qt’, ‘type’: ‘tool_call’}], usage_metadata={‘input_tokens’: 672, ‘output_tokens’: 68, ‘total_tokens’: 740, ‘input_token_details’: {‘cache_read’: 0}, ‘output_token_details’: {‘reasoning’: 0}})]}
接收到的更新节点: ‘tools’
{‘messages’: [ToolMessage(content=’{“messages”: [“天气数据已成功存储至Mysql数据库。”]}’, name=’insert_weather_to_db’, id=’124ec142-2441-4865-b75b-b597e2023ce1’, tool_call_id=’call_RiMagTnBGHBCVFdy2ApzG2qt’)]}
接收到的更新节点: ‘agent’
{‘messages’: [AIMessage(content=’乌鲁木齐当前的天气情况是:晴,少云。气温为5.53°C,体感温度为3.99°C。天气数据已成功存储到数据库中。’, additional_kwargs={‘refusal’: None}, response_metadata={‘token_usage’: {‘completion_tokens’: 44, ‘prompt_tokens’: 766, ‘total_tokens’: 810, ‘prompt_tokens_details’: {‘cached_tokens’: 0}, ‘completion_tokens_details’: {‘reasoning_tokens’: 0}}, ‘model_name’: ‘gpt-4o-2024-08-06’, ‘system_fingerprint’: ‘fp_72bbfa6014’, ‘finish_reason’: ‘stop’, ‘logprobs’: None}, id=’run-c551db7f-4bd0-4c06-bbe0-59b98bd89fb9-0’, usage_metadata={‘input_tokens’: 766, ‘output_tokens’: 44, ‘total_tokens’: 810, ‘input_token_details’: {‘cache_read’: 0}, ‘output_token_details’: {‘reasoning’: 0}})]}
而如果我们想流式传输每个过程中的 Tokens, 代码如下:
1 | from langchain_core.messages import AIMessageChunk, HumanMessage |
[{'name': 'fetch_real_time_info', 'args': {}, 'id': 'call_fgn93Rd0qvQrb2g8CSBASi5h', 'type': 'tool_call'}]
[{'name': 'fetch_real_time_info', 'args': {}, 'id': 'call_fgn93Rd0qvQrb2g8CSBASi5h', 'type': 'tool_call'}]
[{'name': 'fetch_real_time_info', 'args': {}, 'id': 'call_fgn93Rd0qvQrb2g8CSBASi5h', 'type': 'tool_call'}]
[{'name': 'fetch_real_time_info', 'args': {'query': ''}, 'id': 'call_fgn93Rd0qvQrb2g8CSBASi5h', 'type': 'tool_call'}]
[{'name': 'fetch_real_time_info', 'args': {'query': '查询'}, 'id': 'call_fgn93Rd0qvQrb2g8CSBASi5h', 'type': 'tool_call'}]
[{'name': 'fetch_real_time_info', 'args': {'query': '查询数据库'}, 'id': 'call_fgn93Rd0qvQrb2g8CSBASi5h', 'type': 'tool_call'}]
[{'name': 'fetch_real_time_info', 'args': {'query': '查询数据库中'}, 'id': 'call_fgn93Rd0qvQrb2g8CSBASi5h', 'type': 'tool_call'}]
[{'name': 'fetch_real_time_info', 'args': {'query': '查询数据库中所有'}, 'id': 'call_fgn93Rd0qvQrb2g8CSBASi5h', 'type': 'tool_call'}]
[{'name': 'fetch_real_time_info', 'args': {'query': '查询数据库中所有城市'}, 'id': 'call_fgn93Rd0qvQrb2g8CSBASi5h', 'type': 'tool_call'}]
[{'name': 'fetch_real_time_info', 'args': {'query': '查询数据库中所有城市的'}, 'id': 'call_fgn93Rd0qvQrb2g8CSBASi5h', 'type': 'tool_call'}]
[{'name': 'fetch_real_time_info', 'args': {'query': '查询数据库中所有城市的天气'}, 'id': 'call_fgn93Rd0qvQrb2g8CSBASi5h', 'type': 'tool_call'}]
[{'name': 'fetch_real_time_info', 'args': {'query': '查询数据库中所有城市的天气数据'}, 'id': 'call_fgn93Rd0qvQrb2g8CSBASi5h', 'type': 'tool_call'}]
[{'name': 'fetch_real_time_info', 'args': {'query': '查询数据库中所有城市的天气数据'}, 'id': 'call_fgn93Rd0qvQrb2g8CSBASi5h', 'type': 'tool_call'}]
[{"title": "天气和气象数据网站集合原创 - CSDN博客", "link": "https://blog.csdn.net/qq_912917507/article/details/104323432", "snippet": "我们可以使用天气网,全球天气网(www.tianqi.com)提供全国各大城市的历史天气预报查询,历史气温查询,历史天气数据来源于城市当天的天气预报信息。 ... 在IT ...", "date": "Feb 15, 2020", "position": 1}]|目前|我|无法|直接|从|数据库|中|查询|所有|城市|的|天气|数据|。如果|您|需要|查询|某|个|特|定|城市|的|天气|数据|,请|提供|城市|名称|,我|将|为|您|查询|。|
astream中其他的模式大家可以自行尝试,这里不重复进行说明,总体而言,我们要理解的是,同步stream和异步astream都是流式传输的默认实现,用于流式传输链中的最终输出。
3.2 LangGraph中的事件流
对于上述使用的.stream()或.astream()仅流式传输链中最后一步的输出,这对于一些对话聊天类的应用程序来说基本就足够了,但是当我们的AI Agent是一个使用了多个大模型调用的更复杂的链时,我们有时希望在最终输出中也使用到一些中间值。例如,在构建RAG对话应用程序时,很多场景都是最终生成的响应 + 检索到的源文档一起返回给用户,例如:
如果想获取到这样的中间事件和步骤,可以使用LangGraph框架中的 astream_events 方法,注意:此方法仅支持异步。用来访问自定义事件和中间输出。使用该方法运行图时,可以得到如下相关事件:
LangChain CallBack:https://docs.langchain.com/oss/python/langchain/models#streaming-events
如下代码可以打印包含流式聊天模型输出的事件,其中 version=”v2” 参数是指定使用 测试版 API 的版本,现在必须指定。
1 | async for event in graph.astream_events({"messages": ["你好,请你介绍一下你自己"]}, version="v2"): |
on_chain_start: LangGraph
on_chain_start: __start__
on_chain_end: __start__
on_chain_start: agent
on_chain_start: call_model
on_chain_start: RunnableSequence
on_chain_start: StateModifier
on_chain_end: StateModifier
on_chat_model_start: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_stream: ChatOpenAI
on_chat_model_end: ChatOpenAI
on_chain_end: RunnableSequence
on_chain_end: call_model
on_chain_start: _write
on_chain_end: _write
on_chain_start: should_continue
on_chain_end: should_continue
on_chain_stream: agent
on_chain_end: agent
on_chain_stream: LangGraph
on_chain_end: LangGraph
这个过程明确标识了Agent执行的每个阶段。从on_chain_start: LangGraph 开始,写入__start__节点,启动call_model节点( on_chain_start: call_model )。然后开始聊天模型调用( on_chat_model_start: ChatOpenAI ), 按token的增量流式返回 ( on_chat_model_stream: ChatOpenAI ),直到聊天模型( on_chat_model_end: ChatOpenAI )输出完全部内容后停止。继而将结果写回通道( ChannelWrite<call_model,messages> ),再次回到call_model节点做决策,最终完成整个图的运行流程。
我们可以从中提取具体的某个 event(事件),比如:
1 | events = [] |
1 | events[0] |
{'event': 'on_chain_start',
'data': {'input': {'messages': ['你好,请你介绍一下你自己']}},
'name': 'LangGraph',
'tags': [],
'run_id': '82a8cc1d-4607-47bc-88e5-cf4027857fd0',
'metadata': {},
'parent_ids': []}
1 | events[10] |
{'event': 'on_chat_model_stream',
'data': {'chunk': AIMessageChunk(content='您好', additional_kwargs={}, response_metadata={}, id='run-fd2157b0-6ff4-40df-8749-84deab32adbd')},
'run_id': 'fd2157b0-6ff4-40df-8749-84deab32adbd',
'name': 'ChatOpenAI',
'tags': ['seq:step:2'],
'metadata': {'langgraph_step': 1,
'langgraph_node': 'agent',
'langgraph_triggers': ['start:agent'],
'langgraph_path': ('__pregel_pull', 'agent'),
'langgraph_checkpoint_ns': 'agent:b43bb514-1964-53fd-a747-94d646ccd17c',
'checkpoint_ns': 'agent:b43bb514-1964-53fd-a747-94d646ccd17c',
'ls_provider': 'openai',
'ls_model_name': 'gpt-4o',
'ls_model_type': 'chat',
'ls_temperature': 0.7},
'parent_ids': ['82a8cc1d-4607-47bc-88e5-cf4027857fd0',
'4d367cb2-9d0a-4d5b-9f31-b0295ea3fce1',
'aa31ad82-b577-4b8c-bbb9-cb8879b42dda',
'aa2387eb-9371-4e02-a238-bb7fd8185cba']}
所有事件都会包含event 、 name和data字段,其中:
- event :正在发出的事件类型。
- name :这是事件的名称
- data :这是与事件关联的数据。
基于此就可以按照name、tags或type等不同的字段来进行事件过滤,比如我们现在选择仅包含聊天模型的输出:
1 | async for event in graph.astream_events({"messages": ["你好,请你介绍一下你自己"]}, version="v2"): |
{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='你好', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='!', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='我是', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='一个', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='由', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='人工', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='智能', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='驱', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='动', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='的', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='助手', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content=',可以', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='帮助', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='回答', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='问题', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='、', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='提供', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='信息', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='、', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='进行', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='任务', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='自动', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='化', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='等', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='。我', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='可以', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='处理', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='多', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='种', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='语言', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='的', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='文本', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content=',并', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='能', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='与', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='各种', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='应用', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='程序', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='和', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='工具', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='进行', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='集', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='成', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content=',以', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='满足', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='不同', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='的', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='需求', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='。如果', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='你', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='有', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='任何', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='问题', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='或者', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='需要', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='帮助', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content=',', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='随', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='时', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='告诉', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='我', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='!', additional_kwargs={}, response_metadata={}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='', additional_kwargs={}, response_metadata={'finish_reason': 'stop', 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_72bbfa6014'}, id='run-599ff39e-910f-48a7-a87b-eaabd1154d29')}, 'run_id': '599ff39e-910f-48a7-a87b-eaabd1154d29', 'name': 'ChatOpenAI', 'tags': ['seq:step:2'], 'metadata': {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'checkpoint_ns': 'agent:79d639f6-6c89-f63f-9d09-4c0be3bd44d7', 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.7}, 'parent_ids': ['c1ebffad-910f-4fe7-914f-832bf6967cad', '85a346c6-9632-4039-902b-abad71845000', 'e7c1e9cf-b472-4e13-bdac-197b1981df38', 'b7763813-9d0b-488c-b6bf-cc035dacad80']}|
每种类型的事件都包含不同格式的数据。而其中data是一个非常重要的,包含此事件的实际数据。在on_chat_model_stream事件中,就是需要响应的流式Token,如上图所示是一个 AIMessageChunk,其中包含消息的content以及id ,提取的代码就非常简单了,和我们上面实现的方式一致,即直接采用如下代码:
1 | first = True |
你好|!|我是|一个|由|人工|智能|驱|动|的|助手|,|旨|在|帮助|回答|各种|问题|和|执行|特|定|任务|。我|能够|进行|自然|语言|处理|,|提供|信息|查询|、|天气|预|报|、|简单|计算|等|服务|。如果|你|有|任何|问题|或|需要|帮助|,|随|时|可以|告诉|我|!|
stream_mode=”messages”模式是直接做的格式化提取的实现过程,当然,理解了上述事件流,我们也可以直接在当前的流程下自定义数据流,比如:
1 | async for event in graph.astream_events({"messages": ["你好,请你介绍一下你自己"]}, version="v2"): |
|你好|!|我是|一个|由|人工|智能|驱|动|的|助手|,|旨|在|帮助|回答|问题|、|提供|信息|和|执行|任务|。|我的|能力|包括|自然|语言|理解|、|信息|检|索|、|数据|处理|等等|。如果|你|有|任何|问题|或者|需要|帮助|,|随|时|可以|问|我|!||
由此可见,在处理事件流中的信息时,我们可以根据实际需求灵活地选择输出和展示的内容格式。这种灵活性正是在复杂业务流程中引入事件流的核心原因。
至此,我们就完整实现了在LangGraph中ReAct自治代理的完整构建,对于这个预构建的ReAct组件,它是集成了外部工具、记忆和规划三个核心概念,所以除了我们可以自定义外部工具以外,还可以给它制定不同的步骤规划方式,即Planning,以及通过Memory去赋予Agent多轮对话的能力,而这两部分的内容,我们将在下一节课程中展开详细的探讨和实践。
