工具与函数调用
大约 3 分钟
第九章:工具调用(Tools/Function Calling):白名单、校验、最小权限
9.1 先讲清楚一句话:模型不会“执行”,只会“提议”
工具调用的正确心智模型是:
- 模型输出一个“想调用工具的意图 + 参数”
- 你的系统根据白名单与权限决定“允不允许”
- 你的系统执行工具并返回结果
- 模型基于工具结果生成最终回答
所以你要重点防的是:
- 工具越权(调用不该调用的动作)
- 参数注入(参数里带恶意 payload)
- 数据泄露(工具把敏感数据带回模型/日志)
9.2 高层写法:@Tool + AI Services(推荐)
9.2.1 定义工具
package com.example.langchain4j.tools;
import dev.langchain4j.agent.tool.P;
import dev.langchain4j.agent.tool.Tool;
import java.util.Map;
import org.springframework.stereotype.Component;
@Component
public class SupportTools {
@Tool("在 FAQ 中搜索答案。参数 keyword 为关键字。")
public Map<String, Object> searchFaq(@P("关键字,例如 发票") String keyword) {
if (keyword == null || keyword.isBlank()) {
throw new IllegalArgumentException("keyword 不能为空");
}
return Map.of(
"keyword", keyword,
"hits", 2,
"items", new String[]{
"如何重置密码:进入个人中心-安全设置。",
"如何开票:进入订单详情页-申请发票。"
}
);
}
@Tool("创建工单。只有用户明确要求人工处理时才能调用。")
public Map<String, Object> createTicket(@P("标题") String title, @P("详细描述") String detail) {
if (title == null || title.isBlank()) {
throw new IllegalArgumentException("title 不能为空");
}
if (detail == null || detail.isBlank()) {
throw new IllegalArgumentException("detail 不能为空");
}
return Map.of(
"ticketId", "T-" + System.currentTimeMillis(),
"status", "CREATED",
"title", title
);
}
}9.2.2 在 AI Service 中启用工具
package com.example.langchain4j.services;
import dev.langchain4j.service.SystemMessage;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.spring.AiService;
@AiService
public interface KnowledgeAssistant {
@SystemMessage("""
你是企业知识库助手。
规则:
1) 优先解释清楚解决步骤。
2) 如果需要查 FAQ,才调用 searchFaq。
3) 只有用户明确要求人工处理时,才调用 createTicket。
""")
String chat(@UserMessage String message);
}通常情况下,Spring Boot 集成会把 @Component 里的 @Tool 方法自动发现并注册为可用工具(具体以你使用的 starter 版本为准)。如果你的 starter 没有自动发现能力,也可以手动把工具提供者注册到 AI Service 构建器里(下一节会给“低层写法”)。
9.3 低层写法:ToolSpecification(更可控)
当你需要做更严格的白名单与参数 Schema 时,低层 API 更适合。典型场景:
- 某些工具只能对某些用户开放(RBAC)
- 工具参数需要更复杂校验(范围、枚举、正则)
- 工具需要审计与 requestId
这类实现建议统一放在“工具执行服务”里,再由 Facade 统一接入(第 13 章会组合)。
9.4 最小安全基线(请当作必须项)
- 白名单:只注册允许的工具;不要做“按名字反射调用”
- 参数校验:空值、范围、格式、长度必须校验
- 最小权限:工具执行前做权限判断(租户隔离、RBAC)
- 脱敏:日志、工具结果、错误信息都要脱敏
- 审计:记录 requestId、工具名、参数摘要、结果摘要
9.5 本章小结
你已经把“工具调用”放到了正确的安全模型里:模型只提议,你的系统才是执行者与守门人。下一章我们解决另一个上线必踩坑:结构化输出(JSON)如何做到“可解析、可兜底、可重试”。
