Agents

实战二:手搓 ReflectionAgent

我们在前面的提示词工程的课程中,介绍过反思机制这种智能体工程化结构。通俗来说,它不仅会按照常规流程基于模型决策执行任务,还会在每轮输出后对自己的回答进行反思,判断答案是否完整、逻辑是否清晰、结论是否可靠,如果发现不足,会自动生成反馈…

TL;DR

我们在前面的提示词工程的课程中,介绍过反思机制这种智能体工程化结构。通俗来说,它不仅会按照常规流程基于模型决策执行任务,还会在每轮输出后对自己的回答进行反思,判断答案是否完整、逻辑是否清晰、结论是否可靠,如果发现不足,会自动生成反馈…

我们在前面的提示词工程的课程中,介绍过反思机制这种智能体工程化结构。通俗来说,它不仅会按照常规流程基于模型决策执行任务,还会在每轮输出后对自己的回答进行反思,判断答案是否完整、逻辑是否清晰、结论是否可靠,如果发现不足,会自动生成反馈并进行修正,从而迭代出更高质量的结果。 到这里我们是不是可以发现,ReflectionAgent 是不是和我们之前的 ReactAgent很像,只是在其基础上增加了自我评估与修正能力。 大家应该还记得之前课程中介绍过的 Spring AI 的 Advisor 机制,也就是在模型调用前后增加一些特殊处理,形成一串责任链,按顺序执行。那么我们的反思机制其实也是可以基于 Advisor 来实现的。那到底是在模型调用前,还是模型调用后,来增加反思机制呢? 答案就是模型调用后,每次模型生成最终回答后,ReflectionAgent 会先检查结果是否达到预期标准,而不是盲目直接输出。如果回答未达标,Agent 会将反思反馈注入到下一轮推理中,引导模型重新规划任务或调用工具。 当然,增加反思机制后,智能体的响应时间会更长。因此在实际应用中,我们需要根据业务场景灵活选择:如果任务对输出质量要求高、响应可以异步处理,就可以使用 ReflectionAgent;如果更注重响应速度和用户体验,则直接使用 ReactAgent 的流式输出即可。

ReflectionAgent

ReflectionAgent 本质上是对 SimpleReactAgent 的封装,通过组合(delegate)的方式将反思能力叠加在原有 ReactAgent 上。它本身不直接处理工具调用或流式逻辑,而是把这些交给 SimpleReactAgent 去做,ReflectionAgent 负责在外层管理反思机制和轮次控制。 从 Builder 的实现可以看到,改造主要分为三个层次: - 属性配置:除了 React Agent 的基础配置外,还需增加:最大反思轮次maxReflectionRounds,防止无限调用,陷入死循环,默认设置成1,确保至少反思一次,。 - Advisor 增强:放开ChatClient的 advisors 注入配置,并再次基础上,自动注入ReflectionAdvisor,使得每次模型输出后都能进行自我评估。 - 代理 SimpleReactAgent:通过 Builder 构建一个带有反思功能的 SimpleReactAgent,并用 ReflectionAgent 封装。这样,调用 call() 时,实际上是先执行原有 React 流程,然后通过 Advisor 检查结果,如果需要反思,则注入反馈并进行下一轮推理。 通过这种方式,ReflectionAgent 实现了在不改动核心 ReactAgent 逻辑的前提下,轻松加上自我反思与迭代修正能力,结构清晰、可扩展性强。

public


            finalAdvisors


}

ReflectionAdvisor

ReflectionAdvisor是实现反思机制的核心组件,它是基于 Spring AI 的 CallAdvisor 机制,在每次模型生成输出后介入,对回答进行评估。它的主要职责是判断当前回答是否满足用户原始问题的预期标准。如果通过评估,则直接返回原始响应;如果未通过,则生成简短且可执行的反馈,并将其注入到下一轮推理中,引导模型重新规划任务或调用工具。通过 reflect() 方法,调用 ChatModel 将用户问题和当前回答组成 prompt,调用模型生成反思结果,这边需要注意的是,最好生成结构化的数据,因为这样更方便于我们后面的状态判断,也就是将输出转换为ReflectionJudgement 对象。Advisor 还会在响应上下文中设置 reflection.required 和 reflection.feedback 标记,让下一轮大模型迭代方便判断状态。

public


            你是一个严格的智能体反思评估专家。

            请判断【当前回答】是否已经充分、准确地满足【用户问题】。

            评估标准:


            【你必须且只能输出一个 JSON 对象,格式如下】


            禁止输出任何额外文本。


            log


        log


                        ## 用户问题:


                        ## 当前回答:


                        ## 输出format


}

SimpleReactAgent

我们还需要对 SimpleReactAgent 的核心 call 流程进行一定的增强,改造从第58行开始,主要体现在三方面: - 增加迭代轮次控制:引入 reflectionRound 来记录当前反思轮次,每次模型生成最终答案后,如果反思机制要求重新规划任务,就会进入下一轮迭代,直到达到 maxReflectionRounds 限制,防止无限循环。 - 判断是否进入反思模式:通过 Advisor 注入的上下文信息 reflection.required 和 reflection.feedback 来判断本轮回答是否需要反思。 - 补充上下文信息:如果当前回答未通过评估,会获取反馈并注入到下一轮上下文中,引导模型重新规划和决策。将这些反馈信息都封装成 AssistantMessage,并追加到 messages 中。这样不仅保证下一轮推理有完整的历史信息,也让反思的结果能被模型观察到,形成完整的反思机制闭环。

public


            messages


        messages
        messages


    messages


        chatMemory


        round

            log

            messages
                    你已达到最大推理轮次限制。
                    请基于当前已有的上下文信息,
                    直接给出最终答案。
                    禁止再调用任何工具。
                    如果信息不完整,请合理总结和说明。


                reflectionRound
                log


                    log

                        chatMemory


                messages
                        【


                        请你根据以上反思意见重新规划任务,
                        必要时可以重新调用工具,
                        然后再给出最终答案。


                chatMemory


        messages

        chatResponse


                            log

                                    messages
                                    toolCall


                        log

                        result

                        safeJson


                        messages


}

系统提示词

我们基于之前的提示词,增加一部分“反思机制”的提示词,用于扩展模型回复的能力,防止模型认为反思不通过或达到最大迭代轮次,则选择不回复不总结的情况。

public
            ## 角色
            你是一个严格遵循

            ## 工具调用规则(极其重要)


            ## 工具执行结果
            系统会自动将工具执行结果作为

            ## 最终答案规则


            ## 强制要求(必须遵守)


            ## 反思机制
            如果在反思过程中,助手判断当前回答未能完全满足用户问题,或者达到最大反思轮次,你必须遵循以下规则:

Builder

我们对 SimpleReactAgent 的Builder 也需要做一定的处理增强,增加 maxReflectionRounds 和 Advisor:

public

}

public


//            if (tools == null || tools.isEmpty()) {
//                throw new IllegalArgumentException("tools 不能为空!");
//            }


}

到这里我们的改造基本就完成了,可以看到我们的 SimpleReactAgent 增加了 Advisor 机制,这为后续能力增强提供了非常便利的入口,比如可以轻松实现日志打印、上下文记忆压缩、请求拦截等功能。而 ReflectionAgent 则完全是建立在 SimpleReactAgent 之上的封装,它通过增加反思评估与迭代能力,让模型在每轮回答后能够自我检查、生成反馈并进行修正,从而输出更高质量、更可靠的结果。 这样一来,我们既保持了 SimpleReactAgent 的核心 ReAct 架构和工具调用能力,又在此基础上实现了可控的自我优化,形成了一个清晰、可扩展、同时支持高级功能的智能体结构。

效果演示

与SimpleReactAgent的调用方式类似,我们只需要构建 ChatModel 和 tools 就可以直接轻松使用ReflectionAgent的能力。

public


    opts
    opts
    opts


            请你根据北京今天的天气、未来七天的天气趋势、以及上海今天的天气,并搜索北京天气的预警情况,生成一份不少于


}

因为我们的工具都是模拟数据,非常适合验证反思机制的场景,因为模型的反思肯定会觉得工具的返回结果不够完整(因为我是写死的)。 从图中的结果,我们可以明显看到,再第一轮使用 WeatherQueryTool 和 SearchTool 工具的时候,反思机制判断未通过,第二轮,又发起调用了 SearchTool,说明我们的 SearchTool 这个模拟写死的数据查询是有问题的,达到最大迭代次数后,智能体进行了强制输出。这也反映出,我们的反思机制是有效的,如果是使用真实的工具,如调用 tavily search 等,反思机制会持续的增强我们的上下文,提升我们的回答质量。

总结

ReflectionAgent 是基于 SimpleReactAgent 的增强版本,它在每轮输出后会对模型的回答进行自我评估,如果发现答案不够完整或存在问题,会生成反馈并引导模型重新规划任务或调用工具,从而迭代出更高质量的结果。这一机制通过 Advisor 实现,插入在模型调用之后,保证了反思判断与上下文注入的灵活性。 基于 ReactAgent 的架构,我们可以在其上扩展出各种场景的智能体,比如 Plan & Execute、DeepResearch 等。所有增强功能本质上都是围绕 ReactAgent 和 Advisor 机制进行组合,实现上下文管理、工具调用和策略控制,从而快速构建出适应不同业务需求的智能体。

版本提示

模型、框架与接口会持续变化。涉及版本号、参数与生产配置时,请在实践前对照对应官方文档。

LLMentor系统化学习大模型应用工程

内容来自个人课程知识库备份,并经过结构化整理。技术版本持续演进,生产使用前请结合官方文档验证。