Spring AI 工具调用踩坑实录:Think-Execute 模式下的状态一致性问题

最近在使用 Spring AI 框架做 Agent 开发时,遇到了一系列围绕工具调用(Tool Call)的坑。从 Think 阶段的记忆丢失,到消息持久化与实时推送的矛盾,再到刷新页面导致的状态错乱——每一个问题都指向同一个核心命题:如何在 LLM 应用中保证状态的干净与一致。这篇文章把我的排查和解决思路完整记录下来,希望对同样在用 Spring AI 的朋友有所帮助。

一、Think-Execute 模式下的工具调用异常

问题现象

在使用 Spring AI 框架时,我发现它的工具调用在大部分情况下是正常的,但极端场景下会暴露一个问题:

模型在 Think 阶段的默认情况下,会在 think 阶段决定工具调用,这一步会把之前的工具调用的消息存入上下文中。但如果在 Execute 阶段系统发生了崩溃或中断,就会导致记忆里多写出一条"只有调用请求、却没有返回结果"的消息。等系统恢复后,大模型再次从上下文中取回历史记录时,面对这种不完整的状态,模型在格式检查上就过不去,直接报错。

解决方案

核心思路是:取消 Think 阶段对动态管理执行权力的实现,延迟写入,保证原子性。

具体做法是,禁止在 Think 阶段就马上持有记忆,而是把记忆的持久化动作延迟到 Execute 阶段的最后一步——当工具调用执行完毕(无论成功还是失败),浏览器会在默认条件下把结果信息返回大模型,让大模型出最终结果。此时,才把模型的调用意图和工具执行结果一起成对地、原子性地更新到记忆当中。

为什么这样设计

这种设计就像数据库的事务一样:要么全部成功,包含完整的两条消息(调用请求 + 返回结果);要么遇到系统性的问题就直接回滚,什么都不写入。

这样做有两个好处:

  1. 兼容了框架层面的自纠正能力。 即使在 Execute 阶段真的出现崩溃,由于 Think 阶段的调用意图还没有被持久化,上下文不会被"脏数据"污染。
  2. 在应用层上加了一道保险。 绝对保证了 LLM 上下文状态的干净和一致性。

二、消息持久化与实时推送之间的矛盾

问题背景

紧接着上面的问题,我又遇到了另一个纠结点:用户体验与数据一致性之间的冲突。

如果为了保证数据绝对干净,非要等到工具全部 Execute 结束才把消息加载入库、再统一返回给前端,那么在这个(可能很漫长的)等待过程中,用户界面就是卡死的——没有任何反馈,体验极差。但如果我们为了体验,立刻把大模型的调用意图写入上下文,一旦后续出错,又会造成前面提到的脏数据问题。

解决方案:数据库模型重新设计

为了同时解决这两个问题,我重新设计了数据库模型和消息流转机制。

我设计了三张表:

  • Agent 表:记录 Agent 的基本信息。
  • Chat_Session 表:会话表,每个会话绑定一个 Agent。
  • Chat_Message 表:记录一段会话中所有的语义片段,绑定 session_id

关键的改动是,在 Chat_Message 表中引入了一个状态机制,包括三个状态:

状态含义
PENDING消息已创建,等待工具执行
EXECUTING工具正在执行中
COMPLETED工具执行完成,消息完整可用

整个流程

1. 即时反馈

当大模型在 Think 阶段输出工具调用后,我们立即把消息推送到前端展示给用户(比如展示"AI 正在调用 XX 工具……"的状态提示),同时消息落库,状态标记为 PENDING

2. 状态流转

进入 Execute 阶段,状态更新为 EXECUTING(执行中)。

3. 事务性闭环

当工具调用执行完毕后,需要在一个事务中完成以下操作:

  • 更新对应的执行结果消息,推送终态给前端。
  • 把状态字段修改为 COMPLETED
  • 持久化工具调用信息到数据库,并且修改状态字段为执行完毕。

这里有一个重要的设计考量:把上面的两步数据科操作抽取为一个新方法,并加上 @Transactional 事务注解,来实现原子性操作。注意,只能包含这两步数据库操作,不能有工具调用部分。 避免主事务太长,打满数据库连接池。

之后再把这步消息推送到前端。

大模型上下文的加载过滤

最后也是最核心的一步:大模型上下文向加载过滤。

当下一次大模型拼装上下文时,在 SQL 查询层面加一个过滤条件,只读取状态为 COMPLETED 的消息。通过这样设计,如果真的出现了 Execute 阶段崩溃,也不会污染上下文。


三、严重 Bug:用户刷新页面的问题

问题现象

上面的方案上线后,很快暴露了一个严重的 Bug——用户刷新页面

由于前端的逻辑,刷新后会重新加载"完成的"消息。但如果用户在某条消息"正在执行"的时候刷新了页面,那么这条消息就会从前端丢失(因为它还不是 COMPLETED)。更麻烦的是,后端工具其实已经执行完了,但前端不知道——又没有再次刷新的话,就永远看不到完整的结果。

解决方案

后端侧:

  1. 引入 FAILED 状态。 前端或后端在每次拉取消息向接口时,增加一层逻辑判断:遍历所有处于 EXECUTING 状态的数据,如果发现其创建时间距离现在已经超过了 5 分钟(可配置的超时阈值),直接将其修改为 FAILED
  2. 加上 Session 级别的乐观锁。 防止多个请求因并发而重复执行同一条消息的工具调用。

前端侧:

前端也需要特殊处理。当前端发现一个 F5 刷新后底层 TCP 连接已经断开了,后端的工具调用执行完毕后,向已关闭的连接推送消息时会出现 IO 异常。此时需要用 try-catch 包裹推送逻辑,捕获异常后将消息透过备选写入数据库落库,保证后端一致性。这样用户再次刷新时,就能从数据库中拿到完整的数据。


总结

这一系列问题的本质,都是在 LLM 应用中如何处理异步工具调用的状态一致性。几个核心原则:

  1. 写入要原子。 调用意图和执行结果必须成对写入,不能只写一半。
  2. 推送要即时。 用户体验不能为了数据一致性而牺牲,通过状态机来兼顾两者。
  3. 过滤要严格。 大模型的上下文加载必须只读取已完成的消息,避免脏数据污染。
  4. 异常要兜底。 超时检测、乐观锁、IO 异常捕获——每一层都要有自己的防御机制。

在 AI Agent 的工程化落地中,LLM 本身的能力只是一部分,围绕它的状态管理、消息流转、异常处理才是真正决定系统是否可靠的关键。

内容概要:本文研究了计及碳排放的多微网电能交互分布式运行策略,提出了一种基于交替方向乘子法(ADMM)的优化方法,旨在实现多微电网系统在满足能源供需平衡的同时降低碳排放。文中构建了包含分布式电源、储能系统、可控负荷及碳排放约束的多微网协同优化模型,通过ADMM算法将全局优化问题分解为各微网子系统独立求解的子问题,实现分布式协同调度,在保障各微网自治性的同时兼顾系统整体的经济性与低碳性。研究通过Matlab代码完成了算法仿真,验证了所提策略在提升能源利用效率、减少碳排放、增强系统鲁棒性与可扩展性方面的有效性,为低碳化、去中心化的能源互联网运行提供了理论支持与实践参考。; 适合人群:具备电力系统分析、优化理论及Matlab编程基础的科研人员、电气工程及相关专业的研究生,以及从事智慧能源、分布式能源系统规划与运行的工程技术人员。; 使用场景及目标:①应用于多微电网系统的分布式能量管理与协同优化调度;②支持“双碳”目标下的低碳电网运行策略设计与政策评估;③为ADMM等分布式优化算法在能源系统中的工程化应用提供完整的模型构建、算法实现与仿真验证案例。; 阅读建议:读者应结合Matlab代码深入理解ADMM算法的迭代流程、拉格朗日函数构造与收敛条件设定,重点关注模型中碳排放因子的引入方式、变量分解机制与子问题求解过程,建议通过调整微网数量、碳价参数及通信拓扑结构进行多场景仿真,以深化对分布式协同机制与环保经济权衡关系的理解。
下载代码方式:https://pan.quark.cn/s/cc130f55eddd BUCK变换器,亦称为降压型转换器,在开关电源技术中属于一种基础电路拓扑,其核心功能在于实现从高电压到低电压的转换,并且在转换过程中确保输出端电压的稳定性。本文的核心内容集中在对BUCK变换器的运行机制进行剖析、阐释电流连续模式(CCM)与断续模式(DCM)之间的差异,并深入探讨这两种模式在稳态下的相互关系,同时研究BUCK变换器的交流等效电路模型以及电压与电流补偿回路的构建方法。BUCK变换器的原理示意图如图1所示,其显著特征在于输出电压值低于输入电压值,输出电流保持连续状态,而输入电流则呈现出脉动特性。变换器的工作过程可以划分为两个主要阶段:在第一个阶段,即开关管导通期间,电感元件负责储存能量,电流呈现出线性增长的趋势,并且同时向负载提供能量;在第二个阶段,即开关管截止期间,电感通过二极管实现能量的续流,电流则表现出线性递减的态势。依据电感元件的伏秒平衡原理,可以推导出涉及开关管占空比、电感元件电感量、输入电压以及输出电压之间关系的数学公式,这些公式对于深入理解和设计BUCK变换器具有关键性的指导意义。 接下来,文章对CCM和DCM两种模式进行了详细的比较分析。在CCM模式下,电感电流在整个开关周期内均保持连续的状态,而在DCM模式下,电感电流则会出现中断现象。确定BUCK变换器工作模式的关键依据是其电感电流纹波值与输出电流值相等这一边界条件。当电流纹波值等于零,即在整个开关周期内电感电流保持完全连续时,BUCK变换器被归类为CCM模式;相对地,若电流纹波值大于零,则表明变换器处于DCM模式;介于两者之间的情况则界定为CCM与DCM的过渡状态。 在DCM模式下,对BUCK...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值