Spring AI (第六期)
在第一期的时候我们给大家介绍了智能体实现的关键技术,以及所支持的系统。系统前面几期我们已经介绍完了,今天我们讲智能体的关键技术。
1.BaseAgent
BaseAgent:最基础的代理抽象类,定义了所有代理的基本状态管理和执行循环,BaseAgent类是一个智能代理的基础框架,就像是一个机器人的"大脑"模板。
这个基础类能做什么?
想象你要造一个能完成各种任务的机器人,这个类就是机器人的"基本操作系统",它提供了:
-
任务管理:能开始、执行和结束任务
-
记忆功能:能记住对话历史
-
步骤控制:把复杂任务分成小步骤完成
-
两种工作模式:普通模式和流式输出模式
举个生活例子
假设这是一个"做早餐"机器人:
-
你告诉它:“请帮我做早餐”(
userPrompt
) -
机器人开始工作:
-
第一步:从冰箱拿鸡蛋
-
第二步:煎鸡蛋
-
第三步:烤面包
-
…(最多10步)
-
-
最后告诉你:“早餐做好了!”
示例代码:
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,实现单步执行的逻辑,之后定义思考和行动两个抽象方法交给下一个类继承实现。
举个生活例子
假设这是一个"订外卖"机器人:
-
思考阶段:
-
你问:“我饿了”
-
机器人思考:“用户需要食物,应该订外卖”
-
-
行动阶段:
- 机器人执行:搜索附近餐厅 → 选择合适菜品 → 下单
-
结果:
- 返回:“已为您下单XX餐厅的XX菜品,30分钟后送达”
为什么这样设计?
这种设计有三大优点:
-
模块化:把思考和行动分开,更容易维护和扩展
-
灵活性:不同场景可以有不同的思考和行动实现
-
可控性:可以精确控制每个步骤
示例代码:
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
类是一个智能代理,它能使用各种工具来完成复杂任务。
这个代理能做什么?
想象你有一个智能助手,它不仅能和你聊天,还能使用各种工具(比如计算器、搜索引擎、数据库查询等)来帮你完成任务。这个类就是实现这种功能的核心。
这个代理的工作分为两个主要步骤:
-
思考阶段(think):
-
先检查用户的问题或指令
-
然后询问AI大模型:“为了解决这个问题,我需要使用哪些工具?”
-
AI会告诉它:“你需要使用工具A、工具B…”
-
如果没有需要使用的工具,就直接回答用户
-
-
行动阶段(act):
-
如果AI说要使用工具,就实际去调用这些工具
-
把工具返回的结果收集起来
-
如果调用了"终止工具"(比如任务完成了),就标记任务结束
-
最后返回所有工具的执行结果
-
举个生活例子
假设你让这个代理帮你"查一下北京明天的天气,然后告诉我是否需要带伞":
-
思考阶段:
- 代理会想:“要完成这个任务,我需要先用天气查询工具查天气,然后用分析工具判断是否下雨”
-
行动阶段:
-
先调用天气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元”
智能体工作流程:
-
思考:“这是复杂任务,需要分步骤”
-
行动:
-
第一步:查北京热门景点
-
第二步:查机票价格
-
第三步:查酒店价格
-
第四步:计算总花费
-
第五步:给出建议方案
-
-
结束:返回完整旅行计划
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步复杂度)
-
智能工具路由选择
-
结构化决策流程:
用户输入 → 需求分析 → 工具选择 → 执行 → 结果整合 → 终止/继续
-
-
典型工作流:
-
接收复杂需求(如旅行规划)
-
自动分解子任务
-
串联多个工具调用
-
生成整合解决方案
-
5. 系统特点
-
扩展性:通过继承实现不同能力代理
-
可靠性:完备的状态/错误处理
-
交互性:支持实时流式响应
-
可观测性:内置日志记录
这个系统就像搭建了一个"AI员工工厂":BaseAgent提供基础身体,ReActAgent植入思考模式,ToolCallAgent赋予使用工具的能力,最终Agent成为能处理复杂任务的专业助手。开发者只需关注具体业务逻辑的实现(工具定义/提示词优化),即可快速创建各种专业AI代理。