前言
在过去的十篇文章里,我们已经打造出了一个相当强大的AI应用。它有记忆,能进行多轮对话;它有知识,能通过RAG回答关于我们私有文档的问题。它就像一个博学的“学者”,你可以向它请教任何在其知识范围内的问题。
但是,这个“学者”有一个巨大的局限:它只能说,不能做。
- 如果你问它:“今天北京天气怎么样?” 它只能根据训练数据回答一个大概,无法获取实时信息。
- 如果你问它:“345乘以678等于多少?” 像
gpt-4o-mini
这样的高级模型或许能算对,但它本质上是在“预测”答案,而非进行精确计算,对于复杂运算容易出错。 - 如果你让它:“帮我预订一张明天去上海的火车票。” 它更是无能为力。
今天,我们将为我们的AI引入一个革命性的新能力:行动。我们将把它从一个“问答机器人”,升级为一个能使用工具的 “智能体(Agent)” ,让它能够响应我们的指令,去执行真正的任务。
第一部分:什么是AI Agent?从“聊天”到“行动”
AI Agent和我们之前构建的聊天机器人(Chatbot)最大的区别在于:
Chatbot 的工作是根据上下文生成文本。
Agent 的工作是根据用户目标,选择并执行动作(使用工具),最终达成目标。
这个过程模仿了人类助理的工作模式。当你对助理说:“帮我算一下5加上7等于几?” 助理不会凭空猜测,而是会执行以下步骤:
- 思考(Reasoning): “老板想让我算个数,这是一个加法运算。”
- 选择工具(Tool Selection): “我应该使用‘计算器’这个工具。”
- 准备参数(Parameter Extraction): “计算器的‘加法’功能需要两个数字,它们是5和7。”
- 执行工具(Tool Execution): 在计算器上按下
5 + 7 =
。 - 观察结果(Observation): 计算器显示结果是
12
。 - 生成最终回复(Response Generation): “老板,5加上7等于12。”
这个“思考->行动”的循环,就是Agent的核心。这之所以能实现,得益于现代大语言模型(如gpt-4o-mini
)内置的强大能力——工具调用(Tool Calling)。我们只需向模型描述我们有哪些可用的工具,模型就能在需要时,告诉我们应该调用哪个工具以及需要提供哪些参数。
第二部分:在LangChain4j中定义一个“工具”
在LangChain4j中,赋予AI一个工具非常简单:你只需要创建一个普通的Java方法,并给它加上@Tool
注解。
这个注解的作用就是向大语言模型“注册”这个方法,并告诉模型:
- 这个工具是干什么用的(通过注解的
value
属性或方法的 Javadoc)。 - 这个工具需要哪些参数(通过方法的参数列表)。
实战:创建一个计算器工具
创建
Tools
类
在service
包下创建一个新文件CalculatorTools.java
。package com.example.aidemoapp.service; import dev.langchain4j.agent.tool.Tool; import org.springframework.stereotype.Component; @Component // 将这个类注册为一个Spring Bean public class CalculatorTools { @Tool("Calculates the sum of two integers") public int add(int a, int b) { System.out.println("Tool executed: add(" + a + ", " + b + ")"); return a + b; } @Tool("Calculates the difference between two integers") public int subtract(int a, int b) { System.out.println("Tool executed: subtract(" + a + ", " + b + ")"); return a - b; } }
代码解析:
@Component
:让Spring能够发现并管理这个类的实例。@Tool("...")
:注解的描述至关重要!LLM会根据这个描述来判断用户的意图是否与该工具匹配。描述写得越清晰,Agent就越“聪明”。
第三部分:构建一个能使用工具的Agent
我们将使用AiServices
来创建一个新的Agent。这次,在构建AiService
时,我们会告诉它有哪些工具(Tools)是可用的。
在
config/LangChain4jConfig.java
中创建Agent Bean
我们将创建一个新的AI服务,专门用于演示Agent功能。// LangChain4jConfig.java // ... 其他Bean的定义 ... import com.example.aidemoapp.service.AgentAssistant; import com.example.aidemoapp.service.CalculatorTools; // ... @Configuration public class LangChain4jConfig { // ... 其他已有的Bean ... // 步骤1: 定义一个新的Agent服务接口Bean @Bean public AgentAssistant agentAssistant(ChatModel chatLanguageModel, CalculatorTools calculatorTools) { return AiServices.builder(AgentAssistant.class) .chatModel(chatLanguageModel) .tools(calculatorTools) // <-- 关键步骤:将工具注册到AI服务中 .build(); } }
定义
AgentAssistant
接口
在service
包下创建AgentAssistant.java
。package com.example.aidemoapp.service; public interface AgentAssistant { String chat(String userMessage); }
创建
AgentController
在controller
包下创建AgentController.java
。package com.example.aidemoapp.controller; import com.example.aidemoapp.service.AgentAssistant; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/api/agent") @RequiredArgsConstructor public class AgentController { private final AgentAssistant agentAssistant; @GetMapping("/chat") public String chat(@RequestParam("query") String query) { return agentAssistant.chat(query); } }
第四步:测试我们的新Agent!
启动Spring Boot应用。
进行一次普通聊天
请求URL:http://localhost:8080/api/agent/chat?query=Who are you?
你会得到一个正常的回答,比如“我是一个乐于助人的助手”。此时,查看后台日志,没有任何"Tool executed"的打印。进行一次需要使用工具的聊天
请求URL:http://localhost:8080/api/agent/chat?query=What is 5 plus 7?
稍等片刻,你会得到回答:“5 plus 7 is 12.”
现在,查看后台日志,你会看到:Tool executed: add(5, 7)
这证明了Agent成功地理解了你的意图,并调用了正确的Java方法!
再试一次
请求URL:http://localhost:8080/api/agent/chat?query=What is 100 minus 33?
你会得到回答:“100 minus 33 is 67.”
后台日志会显示:Tool executed: subtract(100, 33)
总结
今天,我们成功地为我们的AI应用解锁了一项颠覆性的能力——行动。通过LangChain4j的@Tool
注解和AiServices
,我们轻松地将一个普通的Java方法变成了AI可以调用的工具,构建了一个初级的AI智能体。
我们的AI不再只是一个“知道分子”,它变成了一个能干活的“行动派”。
目前我们的工具还很简单,只是一个本地的计算器。但在真实世界中,工具的能力是无限的:它可以是一个调用外部天气API的HTTP客户端,一个查询数据库的DAO,甚至是一个发送邮件的服务。如何构建一个能与真实世界API交互的、更强大的Agent呢?
源码获取
本文中所有实战代码均已同步更新至Gitee仓库。建议您git pull
拉取最新代码,对照本文进行学习。
下一篇预告:
《Java大模型开发入门 (12/15):Agent实战 - 打造能调用外部API的智能助手》—— 我们将把难度升级,封装一个能查询实时天气信息的API作为工具,打造一个能回答“明天上海天气怎么样?”这类问题的、更实用的智能助手。