什么是工具调用?说白了,就是大模型自己发现 “我算不出来 / 查不到 / 做不了”,然后主动去调用外部工具来帮你完成。
例如:
你让它查今天天气
→ 它不知道实时数据
→ 它调用天气接口
你让它搜最新新闻
→ 它训练数据是旧的
→ 它调用搜索引擎
LangChain4j 中,AI 服务(AI Services)可以配置大型语言模型(LLM)能够使用的工具。例如:
/**
* 一个工具类
* 定义 AI 大模型可以调用的外部工具(这里是数学计算工具)
* 每个被 @Tool 注解标记的方法,都会被 AI 识别为可调用的工具函数
*/
class Tools {
/**
* 加法工具方法
* @Tool注解:标记该方法为 AI 可调用的工具
*/
@Tool
int add(int a, int b) {
return a + b;
}
/**
* 乘法工具方法
* @Tool注解:标记该方法为 AI 可调用的工具
*/
@Tool
int multiply(int a, int b) {
return a * b;
}
}
Assistant assistant = AiServices.builder(Assistant.class)
.chatModel(model)
// 注册工具类,AI 可自动调用其中的 @Tool 方法
.tools(new Tools())
.build();
/**
* 调用AI助手的聊天接口
* AI会解析用户提问("1+2 以及 3*4 分别是多少?"),
* 自动判断需要调用add(1,2)和multiply(3,4)工具方法,
* 执行计算后整理成自然语言返回结果
*/
String answer = assistant.chat("1+2 以及 3*4 分别是多少?");在这种情况下,大型语言模型(LLM)会先请求执行 add(1, 2) 和 multiply(3, 4) 这两个方法,然后再提供最终答案。注意,LangChain4j 会自动执行这些方法。
完整示例:
package com.hxstrive.langchain4j.aiServices;
import dev.langchain4j.agent.tool.Tool;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.service.AiServices;
import dev.langchain4j.service.SystemMessage;
public class ToolsCallDemo {
// 推荐:将OPEN_API_KEY设置成环境变量, 避免硬编码或随着代码泄露
// 注意,设置完环境变量记得重启IDEA,不然可能环境变量不会生效
private static final String API_KEY = System.getenv("OPEN_API_KEY");
// 定义业务接口
interface Assistant {
// 系统提示词:强制AI必须调用注册的工具完成计算,禁止内部直接计算
@SystemMessage("你必须调用提供的 add() 和 multiply() 工具方法来完成数学计算," +
"即使是简单的加减法也必须调用工具,采用工具计算结果,禁止修改结果,禁止在内部直接计算结果,禁止回答无关内容。")
String chat(String userMessage);
}
/**
* 一个工具类
* 定义 AI 大模型可以调用的外部工具(这里是数学计算工具)
* 每个被 @Tool 注解标记的方法,都会被 AI 识别为可调用的工具函数
*/
static class Tools {
/**
* 加法工具方法
* @Tool注解:标记该方法为 AI 可调用的工具
*/
@Tool("用于计算两个整数的加法,参数a是加数,参数b是被加数,返回两数之和")
int add(int a, int b) {
System.out.println("\nadd(" + a + ", " + b + ") 被调用了\n");
return (a + b) + 10000;
}
/**
* 乘法工具方法
* @Tool注解:标记该方法为 AI 可调用的工具
*/
@Tool("用于计算两个整数的乘法,参数a是乘数,参数b是被乘数,返回两数乘积")
int multiply(int a, int b) {
System.out.println("\nmultiply(" + a + ", " + b + ") 被调用了\n");
return (a * b) + 10000;
}
}
public static void main(String[] args) {
// 创建 ChatModel 实现类(OpenAI 为例)
ChatModel chatModel = OpenAiChatModel.builder()
.baseUrl("https://api.xty.app/v1")
.apiKey(API_KEY)
.modelName("gpt-4")
.temperature(0.7)
.logRequests(true)
.logResponses(true)
.build();
// 使用 AiServices 创建服务
Assistant assistant = AiServices.builder(Assistant.class)
.chatModel(chatModel)
// 注册工具类,AI 可自动调用其中的 @Tool 方法
.tools(new Tools())
.build();
// 发起对话
String answer = assistant.chat("1+2 以及 3*4 分别是多少?");
System.out.println("=============================================");
System.out.println(answer);
}
}运行示例,输出日志如下:
# 发起调用,包含了 tools 信息
10:54:59.422 [main] INFO dev.langchain4j.http.client.log.LoggingHttpClient -- HTTP request:
- method: POST
- url: https://api.xty.app/v1/chat/completions
- headers: [Authorization: Beare...00]...
- body: {
"model" : "gpt-4",
"messages" : [ {
"role" : "system",
"content" : "你必须调用提供的 add() 和 multiply() 工具方法来完成数学计算,即使是简单的加减法也必须调用工具,采用工具计算结果,禁止修改结果,禁止在内部直接计算结果,禁止回答无关内容。"
}, {
"role" : "user",
"content" : "1+2 以及 3*4 分别是多少?"
} ],
"temperature" : 0.7,
"stream" : false,
"tools" : [ {
"type" : "function",
"function" : {
"name" : "add",
"description" : "用于计算两个整数的加法,参数a是加数,参数b是被加数,返回两数之和",
"parameters" : {
"type" : "object",
"properties" : {
"arg0" : {
"type" : "integer"
},
"arg1" : {
"type" : "integer"
}
},
"required" : [ "arg0", "arg1" ]
}
}
}, {
"type" : "function",
"function" : {
"name" : "multiply",
"description" : "用于计算两个整数的乘法,参数a是乘数,参数b是被乘数,返回两数乘积",
"parameters" : {
"type" : "object",
"properties" : {
"arg0" : {
"type" : "integer"
},
"arg1" : {
"type" : "integer"
}
},
"required" : [ "arg0", "arg1" ]
}
}
} ]
}
# AI响应,工具调用信息,包含要调用那些工具,以及参数填充
10:55:01.728 [main] INFO dev.langchain4j.http.client.log.LoggingHttpClient -- HTTP response:
- status code: 200
- headers: [:status: 200], [alt-svc: h3=":443"; ma=86400], ...
- body: {
"id": "chatcmpl-D7ufU16WrGr30yZFzEwjYHqBNcKbt",
"object": "chat.completion",
"created": 1770778500,
"model": "gpt-4",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": null,
"refusal": null,
"tool_calls": [
{
"function": {
"arguments": "{\"arg0\": 1, \"arg1\": 2}",
"name": "add"
},
"id": "call_9l29N9Q4bBNu0u9oH7vKwBul",
"type": "function"
},
{
"function": {
"arguments": "{\"arg0\": 3, \"arg1\": 4}",
"name": "multiply"
},
"id": "call_mGAQkXI5JgV3jasyvGmsQE6R",
"type": "function"
}
],
"annotations": []
},
"logprobs": null,
"finish_reason": "tool_calls"
}
],
"usage": {
"prompt_tokens": 182,
"completion_tokens": 55,
"total_tokens": 237,
"prompt_tokens_details": {
"cached_tokens": 0,
"audio_tokens": 0
},
"completion_tokens_details": {
"reasoning_tokens": 0,
"audio_tokens": 0,
"accepted_prediction_tokens": 0,
"rejected_prediction_tokens": 0
}
},
"system_fingerprint": "fp_b54fe76834"
}
# 工具被调用了,这是 langchain4j 内部执行的调用
add(1, 2) 被调用了
multiply(3, 4) 被调用了
# 继续发起AI请求,将工具调用的结果和用户问题一起发送给大模型
10:55:01.778 [main] INFO dev.langchain4j.http.client.log.LoggingHttpClient -- HTTP request:
- method: POST
- url: https://api.xty.app/v1/chat/completions
- headers: [Authorization: Beare...00], [User-Agent: langchain4j-openai]...
- body: {
"model" : "gpt-4",
"messages" : [ {
"role" : "system",
"content" : "你必须调用提供的 add() 和 multiply() 工具方法来完成数学计算,即使是简单的加减法也必须调用工具,采用工具计算结果,禁止修改结果,禁止在内部直接计算结果,禁止回答无关内容。"
}, {
"role" : "user",
"content" : "1+2 以及 3*4 分别是多少?"
}, {
"role" : "assistant",
"tool_calls" : [ {
"id" : "call_9l29N9Q4bBNu0u9oH7vKwBul",
"type" : "function",
"function" : {
"name" : "add",
"arguments" : "{\"arg0\": 1, \"arg1\": 2}"
}
}, {
"id" : "call_mGAQkXI5JgV3jasyvGmsQE6R",
"type" : "function",
"function" : {
"name" : "multiply",
"arguments" : "{\"arg0\": 3, \"arg1\": 4}"
}
} ]
}, {
"role" : "tool",
"tool_call_id" : "call_9l29N9Q4bBNu0u9oH7vKwBul",
"content" : "10003"
}, {
"role" : "tool",
"tool_call_id" : "call_mGAQkXI5JgV3jasyvGmsQE6R",
"content" : "10012"
} ],
"temperature" : 0.7,
"stream" : false,
"tools" : [ {
"type" : "function",
"function" : {
"name" : "add",
"description" : "用于计算两个整数的加法,参数a是加数,参数b是被加数,返回两数之和",
"parameters" : {
"type" : "object",
"properties" : {
"arg0" : {
"type" : "integer"
},
"arg1" : {
"type" : "integer"
}
},
"required" : [ "arg0", "arg1" ]
}
}
}, {
"type" : "function",
"function" : {
"name" : "multiply",
"description" : "用于计算两个整数的乘法,参数a是乘数,参数b是被乘数,返回两数乘积",
"parameters" : {
"type" : "object",
"properties" : {
"arg0" : {
"type" : "integer"
},
"arg1" : {
"type" : "integer"
}
},
"required" : [ "arg0", "arg1" ]
}
}
} ]
}
# 最后,AI给出用户问题答复
10:55:03.541 [main] INFO dev.langchain4j.http.client.log.LoggingHttpClient -- HTTP response:
- status code: 200
- headers: [:status: 200], [alt-svc: h3=":443"; ma=86400],....
- body: {
"id": "chatcmpl-D7ufVHP9cch7qulzvhUfBKzLR7CmV",
"object": "chat.completion",
"created": 1770778501,
"model": "gpt-4",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "1 + 2 的结果是 10003,3 * 4 的结果是 10012。",
"refusal": null,
"annotations": []
},
"logprobs": null,
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 254,
"completion_tokens": 24,
"total_tokens": 278,
"prompt_tokens_details": {
"cached_tokens": 0,
"audio_tokens": 0
},
"completion_tokens_details": {
"reasoning_tokens": 0,
"audio_tokens": 0,
"accepted_prediction_tokens": 0,
"rejected_prediction_tokens": 0
}
},
"system_fingerprint": "fp_b54fe76834"
}
=============================================
1 + 2 的结果是 10003,3 * 4 的结果是 10012。注意,上面输出日志的结果的确是我们工具返回的结果,但是有可能返回的信息不是工具结果,而是正确的结果,1+2=2,3*4=12,这是因为 AI 内部可能会进行修正,为此,我们提供了系统提示词,禁止了 AI 对结果的修复。
关于工具的更多信息将在后续教程详细介绍......