AI Services:工具(函数调用)

什么是工具调用?说白了,就是大模型自己发现 “我算不出来 / 查不到 / 做不了”,然后主动去调用外部工具来帮你完成。

例如:

  • 你让它查今天天气

        → 它不知道实时数据

        → 它调用天气接口

  • 你让它搜最新新闻

        → 它训练数据是旧的

        → 它调用搜索引擎

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 对结果的修复。

关于工具的更多信息将在后续教程详细介绍......

  

说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
其他应用
公众号