Spring AI (第六期)

Spring AI (第六期)

在第一期的时候我们给大家介绍了智能体实现的关键技术,以及所支持的系统。系统前面几期我们已经介绍完了,今天我们讲智能体的关键技术。

1.BaseAgent

BaseAgent:最基础的代理抽象类,定义了所有代理的基本状态管理和执行循环,BaseAgent类是一个智能代理的基础框架,就像是一个机器人的"大脑"模板。
这个基础类能做什么?


想象你要造一个能完成各种任务的机器人,这个类就是机器人的"基本操作系统",它提供了:

  1. 任务管理:能开始、执行和结束任务

  2. 记忆功能:能记住对话历史

  3. 步骤控制:把复杂任务分成小步骤完成

  4. 两种工作模式:普通模式和流式输出模式

举个生活例子

假设这是一个"做早餐"机器人:

  1. 你告诉它:“请帮我做早餐”(userPrompt

  2. 机器人开始工作:

    • 第一步:从冰箱拿鸡蛋

    • 第二步:煎鸡蛋

    • 第三步:烤面包

    • …(最多10步)

  3. 最后告诉你:“早餐做好了!”

示例代码:

public String run(String userPrompt) {
        //1.基础校验
        if (this.state != AgentState.IDLE) {
            throw new RuntimeException("Cannot run agent from state:" + this.state);
        }
        //2.校验用户提示词
        if (StringUtil.isBlank(userPrompt)) {
            throw new RuntimeException("Cannot run agent with empty user prompt:");
        }
        //执行更改状态
        this.state = AgentState.RUNNING;
        //记录消息上下文
        messageList.add(new UserMessage(userPrompt));
        //保存结果列表
        List<String> results = new ArrayList<>();
        try {
            //执行循环
            for (int i = 0; i < maxSteps&&state!=AgentState.FINISHED; i++) {
                int StepNumber = i + 1;
                currentStep  = StepNumber;
                log.info("Execution  step {}/{} ", StepNumber,maxSteps);
                //单步执行
                String stepResult = step();
                String  result = "Step"+StepNumber+":"+stepResult;
                results.add(result);
            }
            //是否超出步骤限制
            if (currentStep >= maxSteps) {
                state  = AgentState.FINISHED;
                results.add("Execution  step "+maxSteps+" is finished");
            }
            return String.join("\n", results);
        }catch (Exception e){
            state  = AgentState.ERROR;
            log.error("An error occurred when saving the result list:{}", e.getMessage());
            return "An error occurred when saving the result list:"+e.getMessage();
        }finally {
            //清理资源
            this.cleanup();
        }
    }
2.RecActAgent

它实现了我们第一期所讲的RecAct,将执行过程分为思考和行动两个关键步骤,我们用它继承前面的BaseAgent,实现单步执行的逻辑,之后定义思考和行动两个抽象方法交给下一个类继承实现。
举个生活例子


假设这是一个"订外卖"机器人:

  1. 思考阶段

    • 你问:“我饿了”

    • 机器人思考:“用户需要食物,应该订外卖”

  2. 行动阶段

    • 机器人执行:搜索附近餐厅 → 选择合适菜品 → 下单
  3. 结果

    • 返回:“已为您下单XX餐厅的XX菜品,30分钟后送达”

为什么这样设计?

这种设计有三大优点:

  1. 模块化:把思考和行动分开,更容易维护和扩展

  2. 灵活性:不同场景可以有不同的思考和行动实现

  3. 可控性:可以精确控制每个步骤

示例代码:

public abstract boolean think();
public abstract String act();
@Override
    public String step() {
        try {
            boolean shouldAct = think();
            if (!shouldAct) {
                return "经过思考不需要行动就能完成";
            }
            //再行动
            return act();
        } catch (Exception e) {
            e.printStackTrace();
            return "执行操作时发生错误:" + e.getMessage();
        }

    }
3.ToolCallAgent

这个是四个类中最复杂的类,这个 ToolCallAgent 类是一个智能代理,它能使用各种工具来完成复杂任务。
这个代理能做什么?


想象你有一个智能助手,它不仅能和你聊天,还能使用各种工具(比如计算器、搜索引擎、数据库查询等)来帮你完成任务。这个类就是实现这种功能的核心。

这个代理的工作分为两个主要步骤:

  1. 思考阶段(think)

    • 先检查用户的问题或指令

    • 然后询问AI大模型:“为了解决这个问题,我需要使用哪些工具?”

    • AI会告诉它:“你需要使用工具A、工具B…”

    • 如果没有需要使用的工具,就直接回答用户

  2. 行动阶段(act)

    • 如果AI说要使用工具,就实际去调用这些工具

    • 把工具返回的结果收集起来

    • 如果调用了"终止工具"(比如任务完成了),就标记任务结束

    • 最后返回所有工具的执行结果

举个生活例子

假设你让这个代理帮你"查一下北京明天的天气,然后告诉我是否需要带伞":

  1. 思考阶段

    • 代理会想:“要完成这个任务,我需要先用天气查询工具查天气,然后用分析工具判断是否下雨”
  2. 行动阶段

    • 先调用天气API查北京天气

    • 然后分析返回的数据,判断是否有雨

    • 最后告诉你:“明天北京有小雨,建议带伞”

示例代码:

@Override
    public boolean think() {
        //1.校验拼接用户提示词
        if (StrUtil.isBlank(getNextStepPrompt())){
            UserMessage userMessage  = new UserMessage(getNextStepPrompt());
            getMessageList().add(userMessage);
        }

        //2.调用 AI 大模型,获取要调用的工具名称
        List<Message> messageList = getMessageList();
        Prompt prompt = new Prompt(messageList,this.chatOptions);
        try {
            ChatResponse chatResponse = getChatClient()
                    .prompt(prompt)
                    .system(getSystemPrompt())
                    .tools(availableTools)
                    .call()
                    .chatResponse();
            //记录响应,用于等下Act
            this.toolCallChatResponse  = chatResponse;

            //3.解析工具调用结果,获取要调用的工具
            //助手消息
            AssistantMessage assistantMessage = chatResponse.getResult().getOutput();
            //获取要调用的工具列表
            List<AssistantMessage.ToolCall> toolCallList = assistantMessage.getToolCalls();
            //输出提示信息
            String result = assistantMessage.getText();
            log.info(getName()+"的思考"+result);
            log.info("助手调用了{}个工具", toolCallList.size());
            String toolCallInfo = toolCallList.stream()
                    .map(toolCall -> String.format("工具调用:%s,参数:%s", toolCall.name(), toolCall.arguments()))
                    .collect(Collectors.joining("\n"));
            log.info(toolCallInfo);
            //  没有工具调用返回false
            if (toolCallList.isEmpty()){
                //  只有不调用工具时才添加助手消息
                getMessageList().add(assistantMessage);
                return false;
            }else {
                //  调用工具时不用添加助手消息,调用工具时会自动添加助手消息
                return true;
            }
        } catch (Exception e) {
            //异常处理
            log.error("添加助手消息异常: {}", e.getMessage());
            getMessageList().add(new AssistantMessage("处理时遇到了错误:"+e.getMessage())


);
            return false;
        }
    }




 @Override
    public String act() {
        if (!toolCallChatResponse.hasToolCalls()){
            return "没有工具调用";
        }
        Prompt prompt = new Prompt(getMessageList(),this.chatOptions);
        //获取工具调用
        ToolExecutionResult toolExecutionResult = toolCallingManager.executeToolCalls(prompt, toolCallChatResponse);
        //记录消息上下文,conversationHistory 已经包含了助手消息和工具调用返回的结果
        setMessageList(toolExecutionResult.conversationHistory());
        ToolResponseMessage toolResponseMessage = (ToolResponseMessage)CollUtil.getLast(toolExecutionResult.conversationHistory());
        //判断是否调用了终止工具
        boolean terminateToolCalled = toolResponseMessage.getResponses().stream()
                .anyMatch(response -> response.name().equals("doTerminate"));
        if (terminateToolCalled){
            //任务完成
            setState(AgentState.FINISHED);
        }

        String results = toolResponseMessage.getResponses().stream()
                .map(response -> "工具" + response.name() + "返回结果" + response.responseData())
                .collect(Collectors.joining("\n"));

        log.info("工具调用结果:{}", results);
        return results;
    }
4.Agent

这个 Agent 类就是最终一个拥有自主规划能力的"超级智能体"
这个超级智能体是什么?

想象你有一个全能私人助理:

  • 它能听懂你的各种需求

  • 知道什么时候该用工具(比如计算器、搜索引擎)

  • 能自己规划任务步骤

  • 知道什么时候任务算完成了

举个实际例子

用户说:“我想去北京旅游,预算5000元”

智能体工作流程

  1. 思考:“这是复杂任务,需要分步骤”

  2. 行动:

    • 第一步:查北京热门景点

    • 第二步:查机票价格

    • 第三步:查酒店价格

    • 第四步:计算总花费

    • 第五步:给出建议方案

  3. 结束:返回完整旅行计划

public Agent(ToolCallback[] allTools, ChatModel dashscopeChatModel) {
        super(allTools);
        this.setName("Super agent");
        String SYSTEM_PROMPT = "提示词";
        this.setSystemPrompt(SYSTEM_PROMPT);
        String NEXT_STEP_PROMPT = "提示词";
        this.setNextStepPrompt(NEXT_STEP_PROMPT);
        this.setMaxSteps(20);
        // 初始化客户端
        ChatClient chatClient = ChatClient.builder(dashscopeChatModel)
                .defaultAdvisors(new MyLoggerAdvisor())
                .build();
        this.setChatClient(chatClient);
    }
5.总结
1. 基础架构
  • BaseAgent:所有代理的"母版",提供:

    • 状态管理(空闲/运行中/完成/错误)

    • 执行流程控制(最大步骤数)

    • 双模式支持(普通/流式响应)

    • 记忆功能(维护对话上下文)

2. 核心机制
  • ReAct模式(ReActAgent):

在这里插入图片描述

  • 先思考后行动的逻辑闭环

  • 支持多步骤任务分解

3. 工具调用
  • ToolCallAgent

    • 工具动态调用能力

    • 自动维护工具调用上下文

    • 终止条件检测(通过terminate工具)

4. 超级代理(Agent)
  • 核心优势

    • 自主任务规划(20步复杂度)

    • 智能工具路由选择

    • 结构化决策流程:

    用户输入 → 需求分析 → 工具选择 → 执行 → 结果整合 → 终止/继续

  • 典型工作流

    1. 接收复杂需求(如旅行规划)

    2. 自动分解子任务

    3. 串联多个工具调用

    4. 生成整合解决方案

5. 系统特点
  • 扩展性:通过继承实现不同能力代理

  • 可靠性:完备的状态/错误处理

  • 交互性:支持实时流式响应

  • 可观测性:内置日志记录

这个系统就像搭建了一个"AI员工工厂":BaseAgent提供基础身体,ReActAgent植入思考模式,ToolCallAgent赋予使用工具的能力,最终Agent成为能处理复杂任务的专业助手。开发者只需关注具体业务逻辑的实现(工具定义/提示词优化),即可快速创建各种专业AI代理。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一入JAVA毁终身

感谢,破费了,破费了

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值