云计算百科
云计算领域专业知识百科平台

高级java每日一道面试题-2025年6月25日-基础篇[LangChain4j]-请描述 LangChain4j 中 Tool (工具) 的定义方式,@Tool 注解有哪些核心参数?

LangChain4j 中 Tool 的定义方式与 @Tool 注解详解

在 LangChain4j 中,Tool(工具)允许大语言模型通过函数调用方式与外部系统、API 或业务逻辑进行交互,这是实现 AI Agent 功能的关键组件。

🛠️ Tool 的定义方式

方式1:使用 @Tool 注解(最常用)

import dev.langchain4j.agent.tool.Tool;
import org.springframework.stereotype.Component;

@Component
public class CalculatorTool {

@Tool(name = "calculator", description = "执行数学计算,支持加、减、乘、除、幂运算")
public double calculate(
@Tool.Memory String expression, // 从上下文获取表达式
@Tool.P("运算类型") String operation, // 指定参数描述
@Tool.P("第一个数字") double num1,
@Tool.P("第二个数字") double num2
) {
return switch (operation.toLowerCase()) {
case "add", "+" -> num1 + num2;
case "subtract", "-" -> num1 num2;
case "multiply", "*" -> num1 * num2;
case "divide", "/" -> {
if (num2 == 0) throw new IllegalArgumentException("除数不能为零");
yield num1 / num2;
}
case "power", "^" -> Math.pow(num1, num2);
default -> throw new IllegalArgumentException("不支持的操作: " + operation);
};
}
}

方式2:实现 Tool 接口(更灵活)

import dev.langchain4j.agent.tool.Tool;
import dev.langchain4j.agent.tool.ToolExecutionRequest;
import dev.langchain4j.agent.tool.ToolSpecification;
import java.util.Optional;

public class WeatherTool implements Tool {

@Override
public String id() {
return "weather-tool";
}

@Override
public ToolSpecification specification() {
return ToolSpecification.builder()
.name("getWeather")
.description("获取指定城市的天气信息")
.addParameter("city", "string", "城市名称,如:北京、上海")
.addParameter("date", "string", "日期,格式:YYYY-MM-DD,默认为今天")
.build();
}

@Override
public Optional<String> execute(ToolExecutionRequest request, Object memoryId) {
// 解析请求参数
String city = request.arguments().get("city");
String date = request.arguments().getOrDefault("date", "today");

// 调用天气API
String weather = fetchWeatherFromAPI(city, date);

return Optional.of(weather);
}

private String fetchWeatherFromAPI(String city, String date) {
// 实际调用天气API的逻辑
return String.format("%s在%s的天气:晴,温度20-25°C", city, date);
}
}

方式3:使用 ToolBuilder(编程式构建)

import dev.langchain4j.agent.tool.ToolBuilder;
import java.util.function.Function;

public class StockTool {

public Tool createStockTool() {
return ToolBuilder.builder()
.name("getStockPrice")
.description("获取股票实时价格")
.parameter("symbol", "string", "股票代码,如:AAPL, TSLA")
.execute((request, memoryId) -> {
String symbol = request.arguments().get("symbol");
double price = fetchStockPrice(symbol);
return Optional.of(String.format("%s的当前价格是:$%.2f", symbol, price));
})
.build();
}

private double fetchStockPrice(String symbol) {
// 调用股票API
return 150.75; // 示例数据
}
}

📝 @Tool 注解的核心参数详解

1. 基本参数

参数类型必填默认值描述
name String 方法名 工具的唯一标识符,AI 根据此名称调用
value String 方法名 name 的别名,与 name 作用相同
description String 工具功能的详细描述,AI 根据描述决定是否调用

2. 方法参数注解

@Tool(name = "orderTool", description = "处理商品订单")
public String placeOrder(
// @P 注解:提供参数描述
@P("商品ID") String productId,

// @P 注解:可指定更详细的描述
@P(value = "购买数量", required = true) int quantity,

// @Tool.Memory:从上下文中获取值
@Tool.Memory String customerId,

// 默认值处理
@P(value = "配送地址", defaultValue = "默认地址") String address,

// 复杂参数类型
@P("订单备注") List<String> notes
) {
// 业务逻辑
return String.format("订单创建成功:%s x %d", productId, quantity);
}

3. 高级配置参数

@Tool(
name = "advanced_tool",
description = "这是一个高级工具示例",

// 执行配置
executeAsync = false, // 是否异步执行,默认false
timeout = 5000, // 超时时间(毫秒)

// 元数据
tags = {"critical", "finance"}, // 标签,用于分类和过滤
version = "1.0.0", // 版本号

// 返回类型提示
returnType = ReturnType.STRING // 返回类型提示

// 权限控制
requiredPermissions = {"READ", "WRITE"}
)
public String advancedOperation(@P("输入数据") String input) {
return "处理结果: " + input;
}

🔧 Tool 的注册与配置

1. Spring Boot 自动装配

@Configuration
public class ToolConfig {

@Bean
public ToolExecutor toolExecutor(
List<Tool> tools, // 自动收集所有 @Tool 注解的 Bean
@Value("${ai.tool.timeout:30000}") long timeout
) {
ToolExecutor executor = ToolExecutor.builder()
.tools(tools)
.timeout(timeout)
.build();

// 添加自定义工具处理器
executor.addToolExecutionListener(new ToolExecutionListener() {
@Override
public void onToolExecuted(ToolExecutionEvent event) {
log.info("工具 {} 执行完成,耗时 {}ms",
event.getToolName(),
event.getExecutionTime());
}
});

return executor;
}
}

2. 手动注册工具

public class ManualToolRegistration {

public AiServices<Assistant> createAssistant() {
CalculatorTool calculator = new CalculatorTool();
WeatherTool weather = new WeatherTool();

return AiServices.builder(Assistant.class)
.chatLanguageModel(createChatModel())
.tools(calculator, weather) // 注册多个工具
.toolExecutor(createToolExecutor())
.build();
}

private ToolExecutor createToolExecutor() {
return ToolExecutor.builder()
.toolSpecificationParser(new JsonToolSpecificationParser())
.argumentExtractor(new ReflectionArgumentExtractor())
.build();
}
}

🎯 实际应用示例

示例1:电商客服 Agent

@Service
public class CustomerServiceTools {

private final OrderRepository orderRepository;
private final ProductService productService;

@Tool(name = "查找订单",
description = "根据订单号或客户信息查找订单详情",
tags = {"order", "customer-service"})
public OrderInfo findOrder(
@P(value = "订单号", required = false) String orderId,
@P(value = "客户手机号", required = false) String phone,
@P(value = "客户邮箱", required = false) String email
) {
// 验证参数
if (orderId == null && phone == null && email == null) {
throw new IllegalArgumentException("至少提供一个查询条件");
}

// 查询逻辑
Order order = orderRepository.findByCriteria(orderId, phone, email);
return convertToOrderInfo(order);
}

@Tool(name = "检查库存",
description = "检查商品库存状态,返回库存数量",
timeout = 3000)
public StockInfo checkStock(
@P("商品SKU") String sku,
@P(value = "仓库代码", defaultValue = "WH001") String warehouseCode
) {
int quantity = productService.getStockQuantity(sku, warehouseCode);
boolean inStock = quantity > 0;

return new StockInfo(sku, warehouseCode, quantity, inStock);
}

@Tool(name = "处理退货",
description = "处理客户退货申请,生成退货单")
public ReturnResult processReturn(
@P("订单号") String orderId,
@P("退货原因") ReturnReason reason,
@P("商品列表") List<ReturnItem> items,
@Tool.Memory("customerId") String customerId // 从对话记忆获取
) {
// 验证退货资格
validateReturnEligibility(orderId, customerId);

// 创建退货单
String returnId = returnService.createReturn(orderId, reason, items);

return new ReturnResult(returnId, "退货申请已受理");
}
}

示例2:数据分析工具

@Component
public class DataAnalysisTools {

@Tool(name = "数据统计",
description = "对数据集进行统计分析,返回统计指标")
public StatisticsResult analyzeData(
@P("数据集") List<Double> dataset,
@P(value = "统计方法", defaultValue = "basic") AnalysisMethod method
) {
StatisticsResult result = new StatisticsResult();

result.setCount(dataset.size());
result.setMean(calculateMean(dataset));
result.setStdDev(calculateStdDev(dataset));

if (method == AnalysisMethod.ADVANCED) {
result.setMedian(calculateMedian(dataset));
result.setPercentiles(calculatePercentiles(dataset));
}

return result;
}

@Tool(name = "数据可视化",
description = "生成数据可视化图表",
executeAsync = true) // 异步执行,避免阻塞
public VisualizationResult visualize(
@P("数据集") Map<String, Object> data,
@P("图表类型") ChartType chartType,
@P(value = "样式配置", required = false) StyleConfig style
) {
// 异步生成图表
CompletableFuture<String> chartFuture = chartService.generateAsync(
data, chartType, style
);

// 返回任务ID,支持查询进度
String taskId = taskManager.createTask(chartFuture);

return new VisualizationResult(taskId, "图表生成任务已提交");
}
}

示例3:多步骤复杂工具

@Tool(name = "旅行规划",
description = "规划完整的旅行行程,包括交通、住宿、景点")
public TravelPlan planTravel(
@P("目的地") String destination,
@P("出发日期") LocalDate startDate,
@P("结束日期") LocalDate endDate,
@P("旅行人数") int travelers,
@P(value = "预算", defaultValue = "10000") double budget,
@P(value = "偏好", required = false) TravelPreference preference
) {
// 第一步:获取目的地信息
DestinationInfo destInfo = destinationService.getInfo(destination);

// 第二步:查找航班
List<FlightOption> flights = flightService.searchFlights(
"current_city", destination, startDate, travelers
);

// 第三步:查找酒店
List<HotelOption> hotels = hotelService.searchHotels(
destination, startDate, endDate, travelers, budget/3
);

// 第四步:生成景点推荐
List<Attraction> attractions = attractionService.recommend(
destination, preference
);

// 第五步:生成每日行程
List<DailySchedule> schedule = itineraryPlanner.createSchedule(
attractions, startDate, endDate
);

// 第六步:计算总费用
double totalCost = calculateTotalCost(flights, hotels, attractions);

return TravelPlan.builder()
.destination(destination)
.duration(Duration.between(startDate, endDate))
.flights(flights)
.hotels(hotels)
.attractions(attractions)
.dailySchedules(schedule)
.totalCost(totalCost)
.budgetStatus(totalCost <= budget ? "在预算内" : "超出预算")
.build();
}

⚙️ 配置与优化

1. 全局配置

# application.yml
langchain4j:
tools:
enabled: true
auto-registration: true
execution:
timeout: 10000 # 10秒超时
max-retries: 3
retry-delay: 1000
security:
enable-whitelist: true
allowed-tools:
calculator
weather
stock

2. 性能优化配置

@Configuration
public class ToolPerformanceConfig {

@Bean
@Primary
public ToolExecutor toolExecutor() {
return ToolExecutor.builder()
.cacheManager(createCacheManager()) // 添加缓存
.rateLimiter(createRateLimiter()) // 添加限流
.circuitBreaker(createCircuitBreaker()) // 添加熔断
.monitor(createMonitor()) // 添加监控
.build();
}

private CacheManager createCacheManager() {
return CacheManager.builder()
.maximumSize(1000)
.expireAfterWrite(10, TimeUnit.MINUTES)
.recordStats()
.build();
}

private RateLimiter createRateLimiter() {
return RateLimiter.create(100); // 每秒100个请求
}
}

3. 错误处理

@Slf4j
@Component
public class GlobalToolErrorHandler implements ToolExecutionErrorHandler {

@Override
public Optional<String> handleError(ToolExecutionRequest request, Throwable error) {
log.error("工具执行失败: {}", request.name(), error);

// 根据错误类型返回不同的提示
if (error instanceof IllegalArgumentException) {
return Optional.of("参数错误: " + error.getMessage());
} else if (error instanceof TimeoutException) {
return Optional.of("工具执行超时,请稍后重试");
} else if (error instanceof RateLimitExceededException) {
return Optional.of("请求过于频繁,请稍后再试");
}

// 生产环境隐藏具体错误
return Optional.of("系统繁忙,请稍后重试");
}
}

🔍 最佳实践

1. 工具设计原则

public class ToolDesignPrinciples {

// 原则1:单一职责
@Tool(name = "单一功能工具", description = "每个工具只做一件事")
public String doOneThingWell(@P("输入") String input) {
// …
}

// 原则2:参数验证
@Tool(name = "带验证的工具")
public Result validatedTool(@P("用户ID") String userId) {
if (StringUtils.isBlank(userId)) {
throw new ValidationException("用户ID不能为空");
}
// …
}

// 原则3:文档完整
@Tool(
name = "well_documented",
description = """
这是一个文档完整的工具。
功能:计算两个数的和。
注意:仅支持整数运算。
示例:输入(5, 3)返回8。
"""
,
tags = {"math", "basic"}
)
public int add(@P("第一个加数") int a, @P("第二个加数") int b) {
return a + b;
}
}

2. 安全性考虑

@Component
public class SecureTools {

@PreAuthorize("hasRole('USER')") // Spring Security 集成
@Tool(name = "敏感操作", description = "需要权限验证的操作")
public String sensitiveOperation(@P("数据") String data) {
// 需要用户认证
return "操作成功";
}

@Tool(name = "输入净化工具")
public String sanitizedOperation(
@P("用户输入")
@Sanitize(type = SanitizeType.HTML) // 防止XSS
String userInput
) {
// 输入已自动净化
return process(userInput);
}
}

📊 调试与监控

1. 工具调用日志

@Aspect
@Component
@Slf4j
public class ToolLoggingAspect {

@Around("@annotation(dev.langchain4j.agent.tool.Tool)")
public Object logToolExecution(ProceedingJoinPoint joinPoint) throws Throwable {
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
Tool toolAnnotation = method.getAnnotation(Tool.class);

long startTime = System.currentTimeMillis();

try {
Object result = joinPoint.proceed();
long duration = System.currentTimeMillis() startTime;

log.info("工具执行成功 – 工具: {}, 耗时: {}ms",
toolAnnotation.name(), duration);

return result;
} catch (Exception e) {
log.error("工具执行失败 – 工具: {}", toolAnnotation.name(), e);
throw e;
}
}
}

2. 监控指标

@Component
public class ToolMetrics {

private final MeterRegistry meterRegistry;

@EventListener
public void handleToolExecution(ToolExecutionEvent event) {
// 记录执行时间
meterRegistry.timer("tool.execution.time",
"tool", event.getToolName(),
"status", event.isSuccess() ? "success" : "error"
).record(event.getExecutionTime(), TimeUnit.MILLISECONDS);

// 记录调用次数
meterRegistry.counter("tool.execution.count",
"tool", event.getToolName()
).increment();
}
}

🎯 总结

@Tool 注解核心参数回顾

  • name/value – 工具标识符
  • description – 功能描述(最重要的参数)
  • tags – 分类标签
  • executeAsync – 异步执行开关
  • timeout – 超时设置
  • returnType – 返回类型提示
  • 工具设计要点

  • 清晰的描述:AI 依赖描述理解工具功能
  • 合理的参数设计:使用 @P 注解提供参数说明
  • 错误处理:优雅处理异常并提供有用反馈
  • 性能考虑:设置适当的超时和异步执行
  • 安全性:验证输入,控制访问权限
  • 通过合理使用 Tool 和 @Tool 注解,你可以让 AI 模型具备调用外部服务、执行业务逻辑的能力,从而构建出功能强大的 AI Agent 应用。

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 高级java每日一道面试题-2025年6月25日-基础篇[LangChain4j]-请描述 LangChain4j 中 Tool (工具) 的定义方式,@Tool 注解有哪些核心参数?
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!