Function Calling 函数调用
·
一、核心概念
Function Calling(也叫 Tools 工具调用)是 LangChain4j 中让大语言模型(LLM)调用外部工具 / 函数的能力,用于弥补 LLM 本身的短板(如数学运算、数据查询、业务系统对接等)。核心逻辑:LLM 分析用户问题 → 判断是否需要调用工具 → 自动组装参数调用工具 → 获取工具返回结果 → 整理成自然语言回复用户。
二、入门案例:数学计算工具
以 “大模型不擅长数学运算,调用自定义计算器工具” 为例,完整实现步骤如下:
2.1 1. 创建工具类(标注 @Tool 注解)
工具类中的方法通过 @Tool 注解标记为可被 LLM 调用的工具,支持静态 / 非静态方法、任意访问权限,可注入 Spring 容器(@Component)。
package com.atguigu.java.ai.langchain4j.tools;
import dev.langchain4j.agent.tool.P;
import dev.langchain4j.agent.tool.Tool;
import dev.langchain4j.agent.tool.ToolMemoryId;
import org.springframework.stereotype.Component;
/**
* 计算器工具类(演示Function Calling核心用法)
*/
@Component // 注入Spring容器,方便后续配置
public class CalculatorTools {
// 基础版工具方法
@Tool // 标记为工具方法,默认使用方法名作为工具名称
double sum(double a, double b) {
System.out.println("调用加法运算");
return a + b;
}
@Tool
double squareRoot(double x) {
System.out.println("调用平方根运算");
return Math.sqrt(x);
}
// 进阶版:带注解增强的工具方法(推荐)
@Tool(
name = "加法", // 自定义工具名称(替代默认方法名)
value = "返回两个参数相加之和" // 工具描述,帮助LLM理解用途
)
double sumEnhance(
@ToolMemoryId int memoryId, // 绑定会话记忆ID,区分不同用户/会话
@P(value="加数1", required = true) double a, // 参数描述+必填校验
@P(value="加数2", required = true) double b
) {
System.out.println("调用加法运算 " + memoryId);
return a + b;
}
@Tool(
name = "平方根",
value = "返回给定参数的平方根"
)
double squareRootEnhance(
@ToolMemoryId int memoryId,
@P(value="被开方数", required = true) double x
) {
System.out.println("调用平方根运算 " + memoryId);
return Math.sqrt(x);
}
}
2.2 2. 配置 AI 服务(绑定工具类)
在 @AiService 注解中通过 tools 属性指定要绑定的工具类(Spring Bean 名称),使 LLM 能调用该工具类的方法。
java
运行
import dev.langchain4j.service.AiService;
import static dev.langchain4j.service.spring.AiServiceWiringMode.EXPLICIT;
/**
* 绑定工具的AI服务接口
*/
@AiService(
wiringMode = EXPLICIT,
chatModel = "qwenChatModel", // 指定使用的大模型(如通义千问)
chatMemoryProvider = "chatMemoryProvider", // 会话记忆提供者
tools = "calculatorTools" // 绑定计算器工具类(Spring Bean名称)
)
public interface SeparateChatAssistant {
// 核心聊天方法(带会话记忆)
String chat(@MemoryId int memoryId, @UserMessage String userMessage);
}
2.3 3. 测试工具调用
通过测试类验证 LLM 能否自动识别并调用工具完成数学运算。
package com.atguigu.java.ai.langchain4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class ToolsTest {
@Autowired
private SeparateChatAssistant separateChatAssistant;
@Test
public void testCalculatorTools() {
// 用户提问:包含加法和平方根运算
String answer = separateChatAssistant.chat(1, "1+2等于几,475695037565的平方根是多少?");
// 预期输出:3,689706.4865(LLM调用工具计算后整理的结果)
System.out.println(answer);
}
@Test
public void testCalculatorToolsEnhance() {
// 调用带@ToolMemoryId和@P的工具方法
String answer = separateChatAssistant.chat(2, "5+8等于几,100的平方根是多少?");
// 控制台会打印:调用加法运算 2 → 调用平方根运算 2
System.out.println(answer); // 预期输出:13,10
}
}
2.4 4. 工具调用流程解析

flowchart TD
A[用户提问] --> B[构造UserMessage发送给LLM]
B --> C[LLM分析问题:需要调用工具]
C --> D[生成ToolExecutionRequests:组装参数调用对应工具方法]
D --> E[工具方法执行(如sum/平方根),返回结果]
E --> F[构造ToolExecutionResultMessage发送给LLM]
F --> G[LLM整理工具结果,生成自然语言回复]
G --> H[返回AiMessage给用户]
关键消息类型:
SystemMessage:系统提示词(定义 AI 角色);UserMessage:用户提问;AiMessage(工具调用请求):包含toolExecutionRequests,告知要调用的工具和参数;ToolExecutionResultMessage:工具执行结果;AiMessage(最终回复):LLM 基于工具结果整理的自然语言答案。
三、核心注解详解
3.1 1. @Tool 注解(标记工具方法)
用于标记可被 LLM 调用的方法,可选字段:
表格
| 字段 | 作用 | 默认值 |
|---|---|---|
| name | 工具名称,帮助 LLM 识别工具用途 | 方法名 |
| value | 工具描述,详细说明工具功能,推荐必写(提升 LLM 调用准确性) | 空字符串 |
3.2 2. @P 注解(标记工具方法参数)
用于描述工具方法的参数,帮助 LLM 理解参数含义并正确传参,必填字段为 value:
表格
| 字段 | 作用 | 默认值 |
|---|---|---|
| value | 参数描述(如 “加数 1”“被开方数”),必填 | - |
| required | 标记参数是否为必需项,LLM 会校验必填参数是否缺失 | true |
3.3 3. @ToolMemoryId 注解(绑定会话记忆 ID)
- 作用:将 AI 服务方法中
@MemoryId注解的参数值,自动传递给工具方法的@ToolMemoryId参数; - 适用场景:多用户 / 多会话场景,在工具方法中区分不同用户的会话,例如记录日志、隔离数据等;
- 使用条件:AI 服务方法必须有
@MemoryId参数,工具方法才能使用@ToolMemoryId。
四、硅谷小智集成工具调用(扩展)
结合之前的 “硅谷小智” 医疗客服场景,可通过 Function Calling 对接真实业务系统:
// 挂号工具类
@Component
public class RegistrationTools {
@Tool(
name = "查询号源",
value = "根据科室和日期查询协和医院的挂号号源情况"
)
String queryRegistrationSource(
@ToolMemoryId Long memoryId,
@P(value="科室名称", required = true) String department,
@P(value="预约日期", required = true) String date
) {
// 对接医院挂号系统,查询号源
return "消化内科2025-04-14上午剩余号源:5个,下午剩余号源:8个😜";
}
@Tool(
name = "预约挂号",
value = "为用户预约协和医院指定科室、日期、时间的号源"
)
String register(
@ToolMemoryId Long memoryId,
@P(value="姓名", required = true) String name,
@P(value="身份证号", required = true) String idCard,
@P(value="科室名称", required = true) String department,
@P(value="预约日期", required = true) String date,
@P(value="预约时间", required = true) String time,
@P(value="医生姓名", required = false) String doctor
) {
// 对接医院挂号系统,执行预约逻辑
return "已为" + name + "预约" + date + time + department + doctor + "的号源✅,请携带身份证就诊!";
}
}
// 小智AI服务绑定挂号工具
@AiService(
wiringMode = EXPLICIT,
chatModel = "qwenChatModel",
chatMemoryProvider = "chatMemoryProviderXiaozhi",
tools = {"registrationTools"} // 绑定挂号工具类
)
public interface XiaozhiAgent {
String chat(@MemoryId Long memoryId, @UserMessage String userMessage);
}
// 测试
@Test
public void testRegistrationTool() {
String answer = xiaozhiAgent.chat(1L, "帮我查一下消化内科2025-04-14的号源");
System.out.println(answer); // 输出工具返回的号源信息
}
五、核心总结
- Function Calling 用于弥补 LLM 短板,核心是通过
@Tool标记工具方法,在@AiService中绑定工具类; @Tool的name/value、@P注解能提升 LLM 调用工具的准确性,@ToolMemoryId支持多会话隔离;- 工具调用流程:用户提问 → LLM 判定调用工具 → 执行工具方法 → LLM 整理结果回复,关键是 LLM 自动完成 “是否调用”“如何传参” 的决策。
更多推荐



所有评论(0)