SpringBoot 4.1講座 LLM に自作 Java メソッドを呼び出させる!Spring AI の Tool Calling(@Tool)完全ガイド

ChatGPT などの LLM(大容量言語モデル)は、非常に高い言語理解能力を持っていますが、「リアルタイムのデータ」や「自社のデータベース/業務ロジック」には直接アクセスできないという根本的な限界があります。

例えば、「現在の最新の書籍価格は?」や「現在のシステム時刻は?」と質問しても、学習データに含まれていないか、あるいは「正確な答えは分かりません」と返ってきてしまいます。Web検索機能を補助的に使用して回答はできていますが、AIの知識にはありません。

この限界を突破するのが Tool Calling(Function Calling) です!

今回は、Spring AI が提供する @Tool アノテーションを使い、LLM に自作 Java メソッドを自動認識・呼び出しさせる実装手法を解説します。

1. Tool Calling の仕組み(フロー)

Tool Calling は、AI が回答を作るプロセスの一部を アプリケーション側の Java コードに委譲(Delegation)する 仕組みです。

Plaintext

[ユーザー] ──(1) 質問送信 ──► [Spring Boot (Spring AI)]
                               │
                               ├─(2) 質問 + 利用可能なTool定義を送る ─► [LLM]
                               │                                        │
                               │                                (3) AIがToolの
                               │                                    必要性を判断
                               │                                        │
                               ├─(4) Tool呼び出し要求(関数名・引数)◄──┘
                               │
                       (5) 指定された Java メソッド(@Tool)を実行
                               │
                               ├─(6) 実行結果(データ)を送信 ─────────► [LLM]
                               │                                        │
                               │                                (7) データを組み込んで
                               │                                    最終回答を作成
                               │                                        │
[ユーザー] ◄─(8) 自然言語の回答 ─┴─(8) クライアントへ返却 ───────────────┘

重要なのは、「いつどの Tool をどの引数で呼び出すか」は LLM が自発的に判断し、実際のメソッド実行と AI へのデータ受け渡しは Spring AI が裏で全自動処理してくれる という点です。

2. @Tool アノテーションで Java メソッドを公開する

Spring AI では、コンポーネントクラスのメソッドに @Tool を付与するだけで、LLM が利用できる「道具(Tool)」として公開できます。

① 日時取得ツール(DateTimeTools.java)

LLM 単体では知り得ない「現在のシステム時刻」を返すツールです。

Java

import org.springframework.ai.tool.annotation.Tool;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

@Component
public class DateTimeTools {

    @Tool(description = "現在の日時を ISO-8601 形式で返します。")
    public String getCurrentDateTime() {
        return LocalDateTime.now().toString();
    }
}
  • description プロパティが最重要!: LLM はこの説明文を読んで「ユーザーの質問に回答するためにこのツールを使うべきか」を判定します。具体的かつ明確に目的を記述します。

② 書籍価格検索ツール(BookTools.java)

自社の在庫・価格データ(DB や InMemory マップなど)を参照するツールです。

Java

import org.springframework.ai.tool.annotation.Tool;
import org.springframework.stereotype.Component;

import java.util.Map;

@Component
public class BookTools {

    private static final Map<String, Double> PRICES = Map.of(
            "spring-boot-4", 49.99,
            "java-25-guide", 39.99,
            "docker-manual", 29.99
    );

    @Tool(description = "指定された ISBN や識別子(SKU)に基づいて書籍の最新価格を取得します。")
    public String getBookPrice(String sku) {
        Double price = PRICES.get(sku.toLowerCase());
        return price == null ? "指定された書籍は見つかりませんでした。" : "価格: $" + price;
    }
}

3. ChatClient への Tool 登録とコントローラー実装

作成した Tool を ChatClient にセットするには、リクエスト構築時に .tools(...) メソッドに Spring Bean を渡すだけです。複数指定も可能です!

BookAssistantController.java

Java

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/ai")
public class BookAssistantController {

    private final ChatClient chatClient;
    private final DateTimeTools dateTimeTools;
    private final BookTools bookTools;

    public BookAssistantController(ChatClient chatClient,
                                  DateTimeTools dateTimeTools,
                                  BookTools bookTools) {
        this.chatClient = chatClient;
        this.dateTimeTools = dateTimeTools;
        this.bookTools = bookTools;
    }

    public record AssistantAnswer(String reply) {}

    @GetMapping("/assistant")
    public AssistantAnswer assist(@RequestParam String question) {
        String reply = chatClient.prompt()
                .user(question)
                .tools(dateTimeTools, bookTools) // 複数 Tool を登録!
                .call()
                .content();

        return new AssistantAnswer(reply);
    }
}

4. 動作確認(複合クエリのテスト)

1 つの質問の中で 「書籍の価格」と「現在の時刻」の両方を尋ねる高度なリクエスト を送信してみます。

リクエスト (curl)

Bash

curl -s "http://localhost:8080/api/ai/assistant?question=spring-boot-4%20%E3%81%AE%E4%BE%A1%E6%A0%BC%E3%81%A8%E3%80%81%E4%BB%8A%E3%81%AE%E6%97%A5%E6%99%82%E3%82%92%E6%95%99%E3%81%88%E3%81%A6%E3%81%8F%E3%81%A0%E3%81%95%E3%81%84"

レスポンス

JSON

{
  "reply": "spring-boot-4 の価格は $49.99 です。また、現在のシステム日時は 2026-07-26T21:00:00 です。"
}

何が起きているのか?

LLM はユーザーの質問を解析し、1 回のやり取りの中で getBookPrice("spring-boot-4") と getCurrentDateTime() の 2 つの Tool を連続して呼び出すリクエストを自発的に発行しました。

Spring AI が両方の Java メソッドを実行して結果を統合し、自然な 1 つの文章として整形して返却してくれたのです!開発者がオーケストレーション(複雑な呼び出し制御)のコードを書く必要は全くありません。

補足:旧バージョン(Spring AI 1.x)からの変更点

以前のバージョンで提供されていた FunctionCallback や .functions(...) API は非推奨/廃止され、よりシンプルな ToolCallback / .tools(...) API および @Tool アノテーション へ一元化されました。旧コードを移行する場合は注意してください。

まとめ

  1. @Tool で Java メソッドを公開: description を明確に書くことで、LLM が呼び出すタイミングを正しく判断できる。

  2. .tools(...) で簡単にバインド: ChatClient に渡すだけで、マルチツール呼び出しやパラメータ抽出を Spring AI が全自動で処理する。

  3. 静的知識から動的システムへ: DB 検索や外部 API 連携、ドメインロジックを組み込むことで、LLM を真に実用的な業務アシスタントへと進化させられる。

次回は、「自社ドキュメントやPDFをベクトルDBに格納して検索・回答させる RAG(Retrieval-Augmented Generation)パイプライン」 の構築方法を解説します!

ここから先は

0字

¥ 100

この記事が気に入ったらチップで応援してみませんか?