跳到主要内容
Java 使用 LangChain4j 构建 AI 智能体实战 | 极客日志
Java AI java
Java 使用 LangChain4j 构建 AI 智能体实战 如何使用 LangChain4j 在 Java 中构建 AI 智能体。内容包括大模型与智能体的区别,定义工具(如用户 CURD、翻译、计算等),通过 AiServices 组装智能体并绑定模型与工具,以及 Controller 调用方式。此外还涵盖了将 AiService 作为工具嵌套使用、访问工具执行结果及处理工具参数或运行时异常的方法。
协议工匠 发布于 2026/3/29 更新于 2026/7/20 46 浏览一、大模型与智能体对比
大模型:优势在知识问答和文本生成;劣势在处理实时信息、精确计算或访问个性化工具时存在局限。
智能体可以让大模型调用个性化工具 (智能体 ~= 工具 + 大模型)。例如,大模型可以英文翻译;而智能体可以英文翻译后调用个性化工具/专业工具进行润色,保存到数据库等一系列自主规划、个性化规划的应用。
二、智能体示例
官方文档:
LangChain4j 实现智能体中:一个 agent 可以包含若干@AiService;一个@AiService 可以包含若干@Tool;一个@Tool 可以包含若干工具类操作,比如 CURD、调用第三方 API、调用 http 接口,与缓存 redis/HDFS 等等交互。
注意:AiService 也可以作为其他 AiService 的@Tool
步骤:
定义工具(Tools)。工具可以是任何东西:网页搜索、外部 API 调用、或执行一段特定代码等。
使用 AiServices 来组装智能体,将工具和模型结合起来。
新建 controller 控制器进行调用返回。
1、定义工具 tools
工具 1:用户 CURD
package com.ai.LangChain4j.agent;
import dev.langchain4j.agent.tool.Tool;
import dev.langchain4j.agent.tool.P;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
@Component
public class AiUserTool {
@Autowired
private UserService userService;
@Tool("新增用户服务")
public void addUser (@P("用户名称") String name, @P("用户年龄") String age, @P("用户性别") String sex) {
( , name, age, sex);
userService.addUser(user);
}
User {
userService.findUser(name);
}
CompletableFuture<User> {
CompletableFuture.supplyAsync(() -> userService.findById(userId));
}
}
User
user
=
new
User
null
@Tool("根据用户名查询用户完整信息")
public
findUser
(@P("用户名称") String name)
return
@Async
@Tool("异步查询")
public
getUserAsync
(String userId)
return
工具 2:翻译 package com.ai.LangChain4j;
import dev.langchain4j.service.SystemMessage;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.spring.AiService;
@AiService
public interface TranslatorService {
@SystemMessage("你是一位翻译助手")
@UserMessage("请将以下句子翻译成英文:{{message}}")
String chat (String message) ;
}
工具 3:数值计算 @Component
public class MyCalculatorTool {
@Tool("用于计算两个数字的加法、减法、乘法和除法")
public double calculate (double a, double b, String operator) {
switch (operator) {
case "+" : return a + b;
case "-" : return a - b;
case "*" : return a * b;
case "/" :
if (b == 0 ) throw new IllegalArgumentException ("除数不能为零" );
return a / b;
default : throw new IllegalArgumentException ("不支持的操作符:" + operator);
}
}
}
工具 4:日期格式化 package com.ai.LangChain4j.agent;
import dev.langchain4j.agent.tool.Tool;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@Component
public class DateTimeTool {
@Tool("获取当前时间,返回格式为 yyyy-MM-dd HH:mm:ss")
public String getCurrentDateTime () {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss" );
String time = LocalDateTime.now().format(formatter);
return time;
}
}
工具 5:调用第三方 API package com.ai.LangChain4j.agent;
import org.springframework.stereotype.Component;
import dev.langchain4j.agent.tool.Tool;
import org.springframework.web.client.RestTemplate;
import java.util.Map;
@Component
public class MyWebSearchTool {
private final RestTemplate restTemplate = new RestTemplate ();
@Tool("在互联网上搜索实时信息,可以调用公开平台的 api 查询信息,例如当前新闻、天气等")
public String searchWeb (String query) {
return "根据搜索查询'" + query + "',这里是模拟的搜索结果:xxxxxxxxx" ;
}
}
2、使用 AiServices 来组装智能体,将工具和模型结合起来 package com.ai.LangChain4j.agent;
import dev.langchain4j.service.spring.AiService;
@AiService
public interface MyAssistantService {
String chat (String userMessage) ;
}
给 AI Service 绑定工具:使用 AiServices 的话,就设置 tools 就行了,之后它的实现类自动管理 tool 的调用。
package com.ai.LangChain4j.agent;
import dev.langchain4j.memory.ChatMemory;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.service.AiServices;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import dev.langchain4j.memory.chat.TokenWindowChatMemory;
import java.time.Duration;
@Configuration
public class MyAgentConfiguration {
@Bean
public MyAssistantService assistant (MyCalculatorTool calculatorTool, MyWebSearchTool webSearchTool, AiUserTool aiUserTool, BookingTools bookingTools) {
ChatMemory chatMemory = MessageWindowChatMemory.withMaxMessages(20 );
return AiServices.builder(MyAssistantService.class)
.chatModel(OpenAiChatModel.builder()
.baseUrl(baseUrl)
.apiKey(apiKey)
.modelName(modelName)
.logRequests(logRequests)
.logResponses(logResponses)
.returnThinking(false )
.timeout(Duration.ofMinutes(5 ))
.temperature(0.1 )
.build())
.tools(calculatorTool, webSearchTool, aiUserTool, bookingTools)
.chatMemory(chatMemory)
.build();
}
@Value("${langchain4j.open-ai.chat-model.api-key}")
private String apiKey;
@Value("${langchain4j.open-ai.chat-model.base-url}")
private String baseUrl;
@Value("${langchain4j.open-ai.chat-model.model-name}")
private String modelName;
@Value("${langchain4j.open-ai.chat-model.log-requests}")
private Boolean logRequests;
@Value("${langchain4j.open-ai.chat-model.log-responses}")
private Boolean logResponses;
}
3、新建 controller 控制器进行调用返回 package com.ai.LangChain4j.agent;
import com.ai.LangChain4j.CalculatorTool;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.service.AiServices;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/agent")
public class MyAgentController {
@Autowired
private MyAssistantService myAssistantService;
@Autowired
private ChatModel chatModel;
@GetMapping("/chat")
public String assistantchat (String message) {
return myAssistantService.chat(message);
}
}
三、AiService 也可以作为其他 AiService 的@Tool interface RouterAgent {
@dev .langchain4j.service.UserMessage("""
Analyze the following user request and categorize it as 'legal', 'medical' or 'technical', then forward the request as it is to the corresponding expert provided as a tool. Finally return the answer that you received from the expert without any modification. The user request is: '{{it}}'.
""" )
String askToExpert (String request) ;
}
interface MedicalExpert {
@dev .langchain4j.service.UserMessage("""
You are a medical expert. Analyze the following user request under a medical point of view and provide the best possible answer. The user request is {{it}}.
""" )
@Tool("A medical expert")
String medicalRequest (String request) ;
}
interface LegalExpert {
@dev .langchain4j.service.UserMessage("""
You are a legal expert. Analyze the following user request under a legal point of view and provide the best possible answer. The user request is {{it}}.
""" )
@Tool("A legal expert")
String legalRequest (String request) ;
}
interface TechnicalExpert {
@dev .langchain4j.service.UserMessage("""
You are a technical expert. Analyze the following user request under a technical point of view and provide the best possible answer. The user request is {{it}}.
""" )
@Tool("A technical expert")
String technicalRequest (String request) ;
}
MedicalExpert medicalExpert = AiServices.builder(MedicalExpert.class)
.chatModel(model)
.build();
LegalExpert legalExpert = AiServices.builder(LegalExpert.class)
.chatModel(model)
.build();
TechnicalExpert technicalExpert = AiServices.builder(TechnicalExpert.class)
.chatModel(model)
.build();
RouterAgent routerAgent = AiServices.builder(RouterAgent.class)
.chatModel(model)
.tools(medicalExpert, legalExpert, technicalExpert)
.build();
routerAgent.askToExpert("I broke my leg what should do" );
注意:RouterAgent 可以使用 3 个 AiService 作为 tool。
注:agent 不能使用 chat memory
四、访问执行过的 Tools interface Assistant {
Result<String> chat (String userMessage) ;
}
Result<String> result = assistant.chat("Cancel my booking 123-456" );
String answer = result.content();
List<ToolExecution> toolExecutions = result.toolExecutions();
ToolExecution toolExecution = toolExecutions.get(0 );
ToolExecutionRequest request = toolExecution.request();
String resultText = toolExecution.result();
Object resultObject = toolExecution.resultObject();
interface Assistant {
TokenStream chat (String message) ;
}
TokenStream tokenStream = assistant.chat("Cancel my booking" );
tokenStream
.onToolExecuted((ToolExecution toolExecution) -> System.out.println(toolExecution))
.onPartialResponse(...)
.onCompleteResponse(...)
.onError(...)
.start();
五、处理 Tool 异常
1、处理 tool 参数异常
方法一:抛出异常 Assistant assistant = AiServices.builder(Assistant.class)
.chatModel(chatModel)
.tools(tools)
.toolArgumentsErrorHandler((error, errorContext) -> {
throw MyCustomException(error);
})
.build();
try {
assistant.chat(...);
} catch (MyCustomException e) {
}
方法二:给 LLM 返回一个 text 消息 Assistant assistant = AiServices.builder(Assistant.class)
.chatModel(chatModel)
.tools(tools)
.toolArgumentsErrorHandler((error, errorContext) -> ToolErrorHandlerResult.text("Something is wrong with tool arguments: " + error.getMessage()))
.build();
2、处理 tool 运行时异常 注:同上,也可以抛出异常或给 LLM 返回一个 text 消息
Assistant assistant = AiServices.builder(Assistant.class)
.chatModel(chatModel)
.tools(tools)
.toolExecutionErrorHandler((error, errorContext) -> ToolErrorHandlerResult.text("Something is wrong with tool execution: " + error.getMessage()))
.build();
相关免费在线工具 Keycode 信息 查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
Escape 与 Native 编解码 JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
JavaScript / HTML 格式化 使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
JavaScript 压缩与混淆 Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
RSA密钥对生成器 生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
Mermaid 预览与可视化编辑 基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online