[DeepAgents:LangChain的Harness-07]利用PatchToolCallsMiddleware修复错乱的消息结构

Pandas入门教程(二十二):股票数据分析实战——yfinance 获取数据、技术指标与收益率分析 把 Pandas 用在真实场景,才能体会它的价值。本文以茅台股票为例,用 yfinance 获取历史行情,完成缺失值处理与列筛选,绘制收盘价曲线,计算 SMA 移动平均线与 RSI 相对强弱指数,并通过日收益率、累计收益率和波动率完成完整的量化分析流程。 阅读详情

作为LLM提示词的一个重要组成部分,表示对话历史的消息列表在结构上有一个基本的要求:如果LLM返回的AIMessage包含ToolCall对象,那么Agent会期望每个ToolCall对象都有对应的ToolMessage。但是Agent在执行过程会因为一些异常导致LLM返回的AIMessage中的ToolCall对象没有得到正确的处理,最终导致后续的消息列表中缺失了对应的ToolMessage。PatchToolCallsMiddleware就在面临这种情况是提供了一种补救机制,自动创建并添加缺失的ToolMessage。

1. ReAct工作模式导致的对话历史的交替结构

作为Agent对话历史的消息列表之所以具有确定的结构,是源于Agent基于ReAct的工作模式。ReAct是一种让LLM将推理与行动相结合的交互模式。它解决了模型空谈不干活(只推理不调用工具)或盲目干活(只调工具不分析原因)的问题。ReAct的核心是一个循环过程,通常被称为Thought-Action-Observation循环:

  • Thought(推理):模型先写下当前的思考,分析任务目标、目前的进度以及下一步需要做什么;
  • Action(行动):模型根据推理结果,决定调用哪个工具(如搜索、计算器、API)并给出参数;
  • Observation(观察):系统执行工具后,将结果反馈给模型;
  • 循环:模型根据观察到的结果,开始新一轮的循环,直到得出最终答案。

create_agent函数创建的Agent由model和tools两个核心节点组成,model节点负责生成推理内容和生成工具调用,tools节点则负责执行工具调用并返回结果。消息列表是Agent状态的核心成员,ReAct模式清晰地体现在Agent的执行流程上:

  • 当用户指定输入调用Agent时,model节点生成提供上下文调用LLM,这里的上下文包括对话历史、工具集描述、系统指令(提示词)和响应数据格式等。经过LLM的推理,如果它觉得此时能够提供最终的答案,它会将答案封装成一个AIMessage对象返回。如果它觉得还需要调用工具来获取更多信息或进行计算,它会在生成的AIMessage对象中包含一个或多个ToolCall对象来调用工具;
  • Agent会将接收到的AIMessage对象添加到消息列表中:
    • 如果此AIMessage的ToolCall列表为空,执行流程到此结束;
    • 否则Agent会根据工具调用的信息来调用tools节点执行工具。相关的工具以并发形式的执行后,执行的结果会以ToolMessage的形式被添加到消息列表中。
  • 包含ToolMessage的消息列表会被再次提交给model节点,进入下一轮的推理循环。

这就决定了在一个推理步骤结束时,作为对话历史的消息应该具有这样的结构:

  • 如果某条AIMessage中包含了一个或多个ToolCall对象,那么在消息列表中必须有对应的一个或多个ToolMessage来描述工具调用的结果;
  • 每条ToolMessage必须包含一个tool_call_id字段来与对应的ToolCall进行匹配,以保证消息列表的结构完整性。

2. 对话历史的结构为何会被破坏?

在ReAct模式中,消息列表的严格交替结构(Assistant提议 -> Tool执行 -> Assistant总结)是其逻辑闭环的基础。但是很多异常情况下会导致结构被破环,比如:

  • 并发调用与乱序返回:模型一次性发出了三个工具调用(A, B, C),但外部执行环境返回结果的顺序变成了B, A, C。如果直接按接收顺序插入消息列表,而没有与其对应的tool_call_id严格匹配,模型会把B的结果当成A的反馈;
  • 强制插入用户干预:在模型发出工具调用之后返回结果之前,用户突然又发了一条新消息(比如算了,别查了,换个任务)。这会导致包含ToolCall的AIMessage后面直接跟了一条HumanMessage,中间缺失了必要的ToolMessage提供工具执行的结果;
  • 溢出导致的截断:由于ReAct循环非常多,历史记录太长,开发者简单粗暴地删除了中间的某些消息。如果删除了某条ToolMessage,但保留了后面基于该工具结果做出的推理,思维链就会出现断层;
  • 模型解析失败:模型由于幻觉或受干扰,没有输出合法的ToolCall,系统无法提取出Action。

3. 错乱消息结构导致的问题

ReAct模式的循环特性决定了消息列表的具有上述的交替结构,而这种消息结构也反映了LLM过去的推理流程,并用以指导后续的推理。一旦这种链条断裂,模型就会陷入逻辑精神分裂,会产生以下后果:

  • 逻辑幻觉 (Hallucination) :模型会试图脑补缺失的部分。如果它提出了查询请求但没收到结果,它可能会根据训练数据编造一个虚假的结果,并以此为基础继续推理;
  • 无限递归循环 (Infinite Loop) :模型发现上一个ToolCall没有对应的结果,它会认为我刚才没做成,于是再次发起工具调用。如果系统逻辑不健壮,会陷入请求-等待-再次请求的死循环,极快地消耗Token;
  • 拒绝执行 (Model Refusal) :很多LLM对上下文一致性有要求。如果AIMessage消息包含ToolCall但紧接着不是ToolMessage,API 往往会直接报错,导致程序崩溃;
  • 因果倒置 (Causal Confusion) :如果消息顺序错位,模型会基于错误的前提得出结论。例如搜索A 的股价,结果返回了B 的股价,模型会非常自信地告诉你A涨了(实际上是B涨了)。

4. 利用PatchToolCallsMiddleware修补错乱的消息结构

我们利用下面这个实例来演示一下PatchToolCallsMiddleware针对对话历史的修补功能。我们创建了一个Agent,并注册了一个工具get_weather用于获取天气信息。我们在调用Agent的时候,构造了一个AIMessage,其中包含了一个针对get_weather工具的ToolCall对象,但是我们没有提供对应的ToolMessage。

from langchain.agents import create_agent
from deepagents.middleware.patch_tool_calls import PatchToolCallsMiddleware
from langchain.tools import tool
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage,AIMessage, ToolCall
from dotenv import load_dotenv
import asyncio

load_dotenv()

@tool
def get_weather(location: str) -> str:
    """Get the current weather for a given location."""
    return f"The current weather in {location} is sunny with a high of 25°C."

agent = create_agent(
    model=ChatOpenAI(model="gpt-5.2-chat"),
    tools=[get_weather],
    middleware=[PatchToolCallsMiddleware()])

human_message = HumanMessage(content="What's the weather like in Suzhou today?")
ai_message = AIMessage(content="")
tool_call:ToolCall = {"id": "tool_call_1", "name": "get_weather", "args": {"location": "Suzhou"}}
ai_message.tool_calls.append(tool_call)

async def main():
    result = await agent.ainvoke(input={"messages": [human_message, ai_message]})
    for message in result["messages"]:
        message.pretty_print()

asyncio.run(main())

注册的PatchToolCallsMiddleware会自动检测到这个问题,并且为这个ToolCall对象创建一个对应的ToolMessage。在如下所示的对话列表中,出现的第一个ToolMessage就是PatchToolCallsMiddleware自动创建的。正是这个ToolMessage告诉LLM针对get_weather工具调用被取消,所以它决定再次对它发起调用,使得Agent可以继续执行后续的推理和行动。

================================ Human Message =================================

What's the weather like in Suzhou today?
================================== Ai Message ==================================
Tool Calls:
  get_weather (tool_call_1)
 Call ID: tool_call_1
  Args:
    location: Suzhou
================================= Tool Message =================================
Name: get_weather

Tool call get_weather with id tool_call_1 was cancelled - another message came in before it could be completed.
================================== Ai Message ==================================
Tool Calls:
  get_weather (call_Exlkyg84lyVTMvOEfGuzgu6N)
 Call ID: call_Exlkyg84lyVTMvOEfGuzgu6N
  Args:
    location: Suzhou, China
================================= Tool Message =================================
Name: get_weather

The current weather in Suzhou, China is sunny with a high of 25°C.
================================== Ai Message ==================================

Today in **Suzhou, China**, the weather is **sunny** with a **high around 25 °C (77 °F)**. It should be a pleasant day overall—great for being outdoors.

PatchToolCallsMiddleware的实现非常简单,它通过重写before_agent/after_agent方法来检测AIMessage中的ToolCall对象,并且在发现缺失对应的ToolMessage时,自动创建一个新的ToolMessage来进行补充。这个新创建的ToolMessage会使用一个预定义的模板来生成内容。

class PatchToolCallsMiddleware(AgentMiddleware):
    def before_agent(self, state: AgentState, runtime: Runtime[Any]) -> dict[str, Any] | None
DeepAgents 的 graph.py 设计剖析 processed_subagents.append(spec) # 已编译的,直接用else:... 阅读详情

相关推荐

如何处理动态语言(Python / JS)的“隐形”调用链?

本文揭示动态语言(Python/JS)中静态AST解析导致调用链“断链”的核心问题,提出通过运行时追踪补全图谱的解决方案。基于Code-Graph-RAG的cgr trace机制,分别利用pytest插件与V8 Profiler捕获真实调用路径,将动态边合并至静态图谱,并在权重体系中提升动态边优先级。实践表明,该方法可显著提升图谱覆盖率,实现“结构+行为”双视角理解代码,为MCP与Rerank系统提供可靠支持。

xianyinsuifeng的博客 410

深入浅出!用 DeepAgents 搭建高效能大模型应用(收藏版)

任务规划(Planning):使用内置和read_todos工具将复杂任务分解为结构化待办事项列表,agent 按列表执行并标记完成状态。文件系统访问(Computer Access):提供lsread_filewrite_fileedit_fileglobgrep等工具,让 agent 能够读写文件、搜索文件内容。大型工具调用结果自动保存到文件,避免消耗上下文窗口。子 agent 委托(Sub-agent Delegation):通过task。

m0_48891301的博客 582

AI赋能传染病建模:从数据到动力学模型的本地实践指南

这次我们来看一个将 AI 与传染病动力学建模结合的前沿方向。想象一下,你手头有一份流感爆发的病例数据,传统的建模方法可能需要复杂的微分方程和大量的手动调参,而 AI 模型能否直接从数据中“学习”出传播规律,甚至自动跑通整个建模流程?这正是当前研究的热点。根据《Nature》的最新综述,人工智能正在重塑传染病流行病学建模,从参数推断、趋势预测到多源数据融合,AI 技术为解决传统建模中的计算瓶颈和数据难题提供了全新路径。 对于开发者、数据科学家或公共卫生领域的研究者而言,最关心的是:这套方法能不能在本地跑起来?

weixin_29051811的博客 298

中间件系统:在 Agent 执行流中插入自定义逻辑

本文介绍了中间件系统在AI Agent执行流中的应用,重点讲解了中间件的核心功能、接口设计以及典型使用场景。 主要内容包括: 中间件与Callback的区别:中间件可以修改执行流,而Callback仅用于观测 中间件接口设计:详细说明了9个关键钩子点及其作用 典型中间件实现: 工具错误处理中间件(WrapToolWithErrorHandler) 悬空工具调用修补中间件(patchtoolcalls) 中间件的执行时序和关键注意事项 中间件与回调系统的选择建议 文章通过代码示例展示了如何实现自定义中间件,并

leeyisoft的专栏 473

基于SAHI算法优化YOLOv8的小目标检测性能研究

SAHI(SliceAwareHyperInference)是一种推理优化算法,通过将大图切片为小块并分别推理的方式,实现更精细的小目标检测。提升小目标检测精度:切片后的小目标在每个小块中占比更大,模型能够更好地聚焦。兼容性强:可直接集成到现有目标检测框架中(如YOLO系列、Detectron2等)。支持大分辨率图片和视频推理:减少硬件对大图推理的限制。本文详细探讨了如何通过SAHI(切片辅助超推理算法)结合YOLOv8模型,有效提升小目标检测性能,尤其是在高分辨率图片和视频场景中表现优异。

博客 2371

[个人自用,全网最优]EDEM-FLUENT个人自学教程,拒绝手忙脚乱无用功!

[个人自用,全网最优]EDEM-FLUENT个人自学教程,拒绝手忙脚乱无用功!

zheaa的博客 4828

[DeepAgents:LangChain的Harness-12]利用create_deep_agent整合所有的Harness中间件

create_deep_agent函数是Deep Agents的核心创建方法,它在create_agent基础上预注册了多种中间件。该函数支持丰富的参数配置,包括模型选择、工具集、系统提示词、子代理、技能、记忆系统等,并默认集成多个关键中间件如TodoListMiddleware和FilesystemMiddleware。函数会强制添加迭代次数限制和默认系统提示词,强调AI助手应保持专业客观、直接高效的工作风格,要求先理解任务再执行,并持续验证直至任务完成。未指定的子代理将继承主代理的模型

JaydenAI的博客 669

Labview项目01:标准可配置序列测试框架

摘要:本文介绍了一个基于LabVIEW2020开发的通用测试框架系统。该系统采用模块化设计,包含主界面、调试界面、设置界面和登录界面。主功能包括:1)可配置测试序列,支持延时、预定值输出、随机值输出等操作;2)单步测试功能自主添加;3)界面支持测试序列编辑和权限管理。系统采用队列机制处理事件和测试流程,通过CSV文件存储测试序列,支持参数化配置。用户可自定义测试VI(A_.vi和N_.vi格式),并通过调试界面验证测试序列。最终测试结果在主界面显示,提供整体判断功能。该系统既可作为学习参考,也可用于实际测试

weixin_38637405的博客 1552

AI全栈实战 | 3.9-01 爬虫入门:requests 加 BeautifulSoup 三分钟跑通,但 90% 的人栽在这 4 个“礼貌“问题上

⚠️:本文内容仅用于。请遵守目标站点的服务条款与相关法律法规,不得对目标服务造成负担,不得采集、传播个人隐私数据。技术是中性的,边界在你手里。爬虫的入门技术(requests 发请求 + BeautifulSoup 解析)三分钟就能学会。真正区分"会用爬虫"和"会做爬虫的人"的,是这篇我们跑通"请求→解析→存储"的最小闭环,然后重点把"合规与礼貌"这根弦给你绷上。

源码获取 | 运行部署 | 定制二开修改,如果回复不及时请耐心等待,请见谅。 408

数据挖掘在人力资源分析中的实战案例

在当今竞争激烈的商业环境中,人力资源管理对于企业的成功至关重要。有效的人力资源管理能够提高员工绩效、降低员工流失率、优化人才招聘等。而数据挖掘技术为人力资源管理提供了强大的工具,通过对大量人力资源数据的分析,可以发现潜在的规律和模式,为企业的决策提供有力支持。本文的目的是通过实际案例展示数据挖掘在人力资源分析中的具体应用,涵盖员工绩效预测、人才招聘筛选、员工流失分析等多个方面。通过详细的案例分析,帮助读者理解数据挖掘技术在人力资源管理中的实际操作和应用价值。

移动开发前沿的博客 489

第十六篇:Camx IFE 、OPE 各 port口功能定义

需要注意的是,类似 CSLTFEPortIdRawDump 是没有downscale功能的,所以如果遇到fov不正确的问题,可以排除下TFE这边的 output port是否被接到了 CSLTFEPortIdRawDump 上面来。我们知道Camx 的IFE 、OPE有不少的output port,各个port是有哪些功能的呢?老一点的框架平台,采用的TEF、OPE。

233

从一段视频到可漫游的 4D 有声场景:思路拆解与最小复现手记

只需一段手机视频,你就能生成可"走进去"的 4D 有声场景:转头时狗叫声方向随之变化,走近时声音更清晰。本文拆解 Video-to-4DAVScene 的核心思路,手把手带你用几十行 Python 搭出最小管线,把视频中的运动物体变成带空间位置的声源,并附上三个真实踩坑的排障经验,代码可直接跑。🎧

helloagent的博客 235

python实现边缘检测Canny算子 (附完整源码)

python实现边缘检测Canny算子 (附完整源码)

希望我的博客,能帮上你解决学习中工作中所遇到的问题 457

【每天一个 Python 小案例30】Python 基础知识综合小项目:我的工具盒

作为系列收官,本篇把前 29 篇的知识点合成一个能直接用的命令行工具"我的工具盒":计算器(用 ast 解析表达式,不碰 eval)、单位换算与温度转换(一张换算表 + 特例分支)、记账与分类统计(Decimal + JSON 持久化)、以及用"字典当命令表"把菜单和业务逻辑解耦的主循环。文中对比了 eval 的安全隐患与 ast 白名单的做法,解释了 lambda 闭包在字典里的写法与晚绑定陷阱,并在最后给出整个系列的知识地图,把变量、数据结构、控制流、函数、类、异常、文件、标准库八块内容对应到具体篇目。

xinjiyaya的博客 427

LangGraph-StateGraph 和 Graph API 源码分析

摘要: StateGraph是LangGraph的核心API,用于构建有状态工作流图。本文分析了其实现原理,包括: 核心类关系:StateGraph(构建器)和CompiledStateGraph(继承自Pregel的可执行图) 关键流程:状态模式到通道的映射、节点到PregelNode的转换 实现特点: 支持TypedDict和Pydantic两种状态模式 自动选择通道类型(LastValue或BinaryOperatorAggregate) 通过映射函数处理节点输入输出 边实现基于通道写入机制 编译过程

838

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

详解Python条件语句

在 Python 中,if...else 是一种条件语句,可以根据给定的条件执行不同的操作。这个语句通常用于控制程序的流程。

2601_96798737的博客 208

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

Python3 协程:异步编程的核心机制与实战

协程是解决I/O密集型任务等待瓶颈的高效机制,相比线程更轻量、无锁开销。从yield到async/await的演进,使异步编程语义清晰、易于理解。通过async/await可实现并发执行多个任务(如gather、create_task),显著提升网络请求、爬虫等场景性能。关键在于使用异步库(如aiohttp)替代同步库,避免阻塞事件循环。合理控制超时与并发数,才能发挥协程最大优势。

Lxn2zh的博客 159

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

torch.compile 差异仅 1e-6,边界样本预测为何翻转

torch.compile 加速后输出与 eager 不一致,部分预测翻转。逐层对比与 graph break 分析定位到动态分支翻转根因。容差回归仅适用于无分支翻转场景,零容忍场景应禁用编译。

昨日种种,皆成今我。今日种种,皆成新我。 159

二进制木马免杀-Python 分离免杀与 Web 挂马

二进制木马免杀-Python 分离免杀与 Web 挂马

2503_94637398的博客 268

蓝桥杯·全国青少年信息素养大赛·电子学会Python/C++考级 备考:莫队算法离线区间查询详解

备赛进行时:第十八届蓝桥杯软件赛报名已于 2026-10-08 10:00 开启、12-18 14:00 截止,省赛定在 2027-04-10(C/C++·Python 程序设计 9:00–13:00);中国电子学会 2026 年 12 月软件编程(C/C++ 一级至十级、Python 一级至六级)考级报名 9/23–12/2 16:00、统考 12-12;全国青少年信息素养大赛 2026—2027 赛季算法应用主题赛也已进入复盘练兵窗口。

IT_Scratch的博客 139

【Python】国家中小学智慧教育平台电子教材批量下载与 PDF 合成实战

成果:两本语文电子课本(一年级上册 118 页 / 23MB、三年级上册 130 页 / 30.3MB),合计 248 页、约 54MB,单本下载加合成 40~60 秒,PDF 页数校验全部通过。经验教训SPA 站点的数据接口优先从 bundle 里挖,比抓页面稳得多;资源链接要按 private/public 分组看待,只取平台公开部分;页数、目录名这类“可推断”的信息,永远用实际响应验证一次;受限环境里“能不能跑浏览器”要在方案定稿前确认。后续计划:这版 PDF 是图片版,没有文字层;

木头大左的博客 138

魔塔社区微调训练Qwen2-1.5B-Instruct模型并烧录到‌RK3568开发板教程

本文基于Ubuntu 22.04 + CUDA 13.0.3环境,使用LLaMA-Factory框架对Qwen2-1.5B-Instruct模型进行LoRA微调,训练儿童故事生成专用模型。通过配置qwen模板、制作alpaca格式数据集、执行sft训练并合并LoRA权重,最终将模型转换为GGUF格式,并量化为Q4_K_M以适配RK3568嵌入式平台。全程支持国产镜像加速下载与显存优化,实现高效轻量化部署。

浅清秋慕夏的博客 186

【回眸】DeepSeek V4.1 Flash 快速上手与实战

本文介绍如何高效本地部署开源大模型,通过现代化工具链实现分钟级环境搭建。聚焦显存优化、一键安装、代码调用与多轮对话实现,解决“显存不足”“连接超时”等痛点,提供参数调优与结构化输出技巧,助力开发者在离线场景下快速构建稳定、高效的本地推理系统。

啤酒鸭的物联网开发记录博客 223

智叟云集-手机证据抓取系统的工程结构与应用入口

本文系统阐述手机证据抓取系统的工程结构与应用入口,涵盖四大层面:工程目录划分(Android、Python服务、Web页面、测试与构建工具);Android组件通过Manifest声明可启动页面,主界面由MainActivity管理;Python服务通过run.py解析参数并启动FastAPI应用,支持远程访问;浏览器页面采用HTML/CSS/JS分离架构,静态资源通过路径关联,实现动态交互。各模块分工明确,协同构建可运行的采集系统。

2301_77178996的博客 232

Java Arrays.asList 常见坑详解|UnsupportedOperationException、数组联动、基本类型 bug

解析 Arrays.asList 常见开发陷阱,演示 UnsupportedOperationException、底层数组引用共享、基本类型数组问题,区分 Arrays 内部 ArrayList 与 java.util.ArrayList,给出数组转 List 的各种场景正确代码。

weixin_42617033的博客 473

利用python中matplotlib.pyplot库绘制图

plt.plot(x,y) # x,y是每个点的坐标,plot()把每个点按顺序画折线。plt.subplots(2,2)表示绘制2*2的子图布局,axs[0,0]表示在第0行第0列绘制子图...coordinates_i[:,0]表示获取每一行(每一个spot)的第0列(x坐标)coordinates_i[:,1]表示获取每一行(每一个spot)的第0列(y坐标)plot.subplot(2,2,1) 表示子图布局是2*2的,开始绘制第一个。也可以导入数据绘制。可以设置color属性,设置颜色。

qq_46147236的博客 102
上一篇: [DeepAgents:LangChain的Harness-06]通过HumanInTheLoopMiddleware引入人机交互
下一篇: [DeepAgents:LangChain的Harness-08]利用SummarizationMiddleware对长程对话瘦身
JaydenAI
博客等级 码龄1年 243粉丝 324原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值