LangChain Agent 流式输出:stream_mode=“values“ 数据结构解析
通过create_agent()可以创建 Agent 对象。创建后的 Agent 支持两种常见执行方式invoke()等待 Agent 执行完成一次性获得最终结果。stream()在 Agent 执行过程中逐步获得运行状态。本文主要介绍 Agent 的流式输出以及下面这行代码的作用一、完整代码下面创建两个股票查询工具然后让 Agent 查询“传智教育”的股价和公司信息。fromlangchain.agentsimportcreate_agentfromlangchain_community.chat_models.tongyiimportChatTongyifromlangchain_core.toolsimporttooltool(description获取股价传入股票名称返回字符串信息)defget_price(name:str)-str:returnf股票{name}的价格是20元tool(description获取股票信息传入股票名称返回字符串信息)defget_info(name:str)-str:returnf股票{name}是一家A股上市公司专注于IT职业教育。agentcreate_agent(modelChatTongyi(modelqwen3-max),tools[get_price,get_info],system_prompt你是一个智能助手可以回答股票相关问题)forchunkinagent.stream({messages:[{role:user,content:传智教育股价多少并介绍一下}]},stream_modevalues):latest_messagechunk[messages][-1]iflatest_message.content:print(type(latest_message).__name__,latest_message.content)try:iflatest_message.tool_calls:print(工具调用,[tc[name]fortcinlatest_message.tool_calls])exceptAttributeError:pass运行结果如下二、stream_modevalues返回什么stream_modevalues之后Agent 每完成一个执行步骤都会返回当前时刻的完整状态。每个chunk都是一个字典核心结构如下{messages:[HumanMessage(...),AIMessage(...),ToolMessage(...),AIMessage(...)]}ToolMessage工具执行后返回的结果。Agent 执行过程中messages列表会不断变长。例如第一次可能只有用户消息[HumanMessage(...)]模型决定调用工具后[HumanMessage(...),AIMessage(tool_calls[...])]工具执行完成后[HumanMessage(...),AIMessage(tool_calls[...]),ToolMessage(...),ToolMessage(...)]三、为什么使用chunk[messages][-1]latest_messagechunk[messages][-1]表示获取 Agent 当前状态中的最后一条消息也就是最近产生的消息。如果直接遍历整个列表formessageinchunk[messages]:print(message)由于每个chunk都包含完整消息历史之前的消息会被重复打印。使用[-1]则每次只查看最后一条消息输出会更加清晰。四、content和tool_calls分别是什么这两个都是 Message对象的属性提取最新消息后主要读取两个属性latest_message.content latest_message.tool_calls1.contentcontent保存消息中的文字内容。比如模型最终回答AIMessage(content传智教育当前股价为20元……)iflatest_message.content:print(latest_message.content)#输出消息中的文本。2.tool_callstool_calls保存模型产生的工具调用请求。例如AIMessage(content,tool_calls[{name:get_price,args:{name:传智教育},id:call_xxx,type:tool_call}])其中name调用的工具名称。args传递给工具的参数。id本次工具调用的唯一标识。[tc[name]fortcinlatest_message.tool_calls]#会提取所有准备调用的工具名称。五、为什么tool_calls会出现两次打印完整的AIMessage时会看到AIMessage(content,additional_kwargs{tool_calls:[{function:{arguments:{name: 传智教育},name:get_price}}]},tool_calls[{name:get_price,args:{name:传智教育}}])工具调用同时出现在additional_kwargs[tool_calls]message.tool_calls这两个位置的作用不同。additional_kwargs这里通常保存模型接口返回的附加数据其结构更接近模型原始返回结果。additional_kwargs本身是一个 Python 字典用于保存模型返回的附加数据。其中工具参数function.arguments可能仍然是 JSON 格式的字符串arguments:{name: 传智教育}tool_callsLangChain 会对工具调用数据进行解析和统一封装tool_calls[#如果调用多个工具 就会有多个字典{name:get_price,args:{name:传智教育}}]这样不管底层使用哪个模型都可以通过统一方式读取工具调用。六、总结stream_modevalues返回的是 Agent 每一步执行后的完整状态其中最重要的数据是chunk[messages]#它保存了 Agent 当前积累的全部消息。latest_messagechunk[messages][-1]#表示从完整消息列表中取出最后一条消息避免重复处理以前已经出现过的内容。消息中的两个常用属性分别是message.content#用于获取文字内容message.tool_calls#用于获取模型准备调用的工具及其参数。整个执行过程可以简单概括为用户问题 ↓ 模型决定调用工具 ↓ 工具返回查询结果 ↓ 模型整合结果 ↓ 生成最终回答