SpringAI Tool Calling 工具调用(六)

Tool Calling(工具调用),也称为函数调用,是让大语言模型(LLM)在对话中"调用"外部定义的工具或 API 的机制,通过这个机制,模型可以在生成回答前提出需要执行的操作(如获取实时天气、设置数据库记录、触发业务流程等),然后由应用端执行工具,结果再反馈回模型,最终给用户完整回复。

Tool Calling主要应用场景如下:

* 信息检索:从外部源(如数据库、Web 服务、文件系统或 Web 搜索引擎)检索信息,增强模型的知识,使其能够回答其他方式无法回答的问题。

* 执行操作:在软件系统中执行特定操作,如发送电子邮件、在数据库中创建新记录、提交表单或触发工作流。目标是自动执行原本需要人工干预或显式编程的任务。

Spring AI 提供了方便的 API 来定义工具、解析来自模型的工具调用请求以及执行工具调用。

工具定义与使用

Spring AI中工具调用流程示意图如下:

  1. 开发者定义工具,并将其注册到 Spring 容器中。

  2. 模型在生成响应时,识别到需要调用工具,会生成包含工具调用信息的响应。

  3. 应用程序接收到模型的响应后,解析其中的工具调用信息,执行相应的工具。

  4. 工具执行完成后,将结果返回给应用程序。

  5. 应用程序将工具执行结果作为上下文信息,传递给模型。

  6. 模型使用工具执行结果,生成最终的响应。

工具定义:

开发者可以通过在方法上添加@Tool注解定义工具,该注解允许提供工具的名称、描述和输入参数等信息,模型在调用工具时,会根据这些信息生成相应的调用请求。

定义工具示例如下:

Tool Calling 使用案例

  1. 配置项目pom.xml
html 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.5.3</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>SpringAIToolCalling</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>SpringAIToolCalling</name>
    <description>SpringAIToolCalling</description>

    <properties>
        <java.version>17</java.version>
    </properties>

    <!-- 导入 Spring AI BOM,用于统一管理 Spring AI 依赖的版本,
    引用每个 Spring AI 模块时不用再写 <version>,只要依赖什么模块 Mavens 自动使用 BOM 推荐的版本 -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.ai</groupId>
                <artifactId>spring-ai-bom</artifactId>
                <version>1.0.0-SNAPSHOT</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-model-deepseek</artifactId>
        </dependency>
    </dependencies>


    <!-- 声明仓库, 用于获取 Spring AI 以及相关预发布版本-->
    <repositories>
        <repository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <releases>
                <enabled>false</enabled>
            </releases>
        </repository>
        <repository>
            <name>Central Portal Snapshots</name>
            <id>central-portal-snapshots</id>
            <url>https://central.sonatype.com/repository/maven-snapshots/</url>
            <releases>
                <enabled>false</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
    </repositories>

</project>
  1. 创建tools包并创建MyTools.java类
java 复制代码
package com.example.springaitoolcalling.tools;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

@Component
public class MyTools {

    Logger log = LoggerFactory.getLogger(MyTools.class);

    @Tool(description = "返回当前系统时间")
    public String getCurrentTime() {
        log.info("调用 getCurrentTime 工具,当前时间:"+java.time.LocalDateTime.now().toString());
        return java.time.LocalDateTime.now().toString();
    }

    @Tool(description = "对两个数字执行加、减、乘、除运算")
    public double calculate(
            @ToolParam(description = "第一个数字") double a,
            @ToolParam(description = "第二个数字") double b,
            @ToolParam(description = "运算类型") String operation) {
        log.info("调用 calculate 工具,第一个数字:"+a+",第二个数字:"+b+",运算类型:"+operation);

        double result = 0;

        switch (operation) {
            case "add":
                result = a + b;
                break;
            case "subtract":
                result = a - b;
                break;
            case "multiply":
                result = a * b;
                break;
            case "divide":
                if (b != 0) {
                    result = a / b;
                }
        }

        return result;
    }

    private RestTemplate restTemplate = new RestTemplate();
    private
    String baseUrl = "http://shanhe.kim/api/youjia/youjia.php";

    @Tool(description = "查询指定省份的油价,直接返回完整 JSON 字符串")
    public String getOilPriceJson(@ToolParam(description = "省份名称") String province) {
        log.info("调用 getOilPriceJson 工具,查询省份:"+province);
        String url = String.format("%s?province=%s", baseUrl, province);
        return restTemplate.getForObject(url, String.class);
    }
}
相关推荐
leoZ2317 小时前
本地跑大模型实战(七):llama.cpp 性能调优,让推理更快更省
java·人工智能·spring·生成对抗网络·语言模型·自然语言处理·llama
To_OC8 小时前
我把《天龙八部》塞进向量数据库后,终于搞懂了 RAG 到底是个啥
人工智能·llm·agent
蜡台8 小时前
AI Agent(智能体)入门基础教程
人工智能
Akir.weiwen8 小时前
Token 层差异:从颜色值到语义状态的三层跃迁
人工智能·设计规范
迷迭香yy9 小时前
集合竞价数据挖掘实战:用Python构建开盘信号识别系统
人工智能·python·数据挖掘
大模型momo9 小时前
Spring AI 实战:多 Agent 协作实战 —— 分工拆解复杂旅游行程任务
人工智能·spring·ai·agent·旅游
小程故事多_809 小时前
从A2C、TRPO、PPO到GRPO,强化学习策略梯度算法完整演进与大模型落地实战解析
人工智能·算法
冬奇Lab9 小时前
开源项目第176期:Better Harness — 不审查 diff,审查工作流本身,给 AI 编程 Agent 的五维评估框架
人工智能·开源·agent
冬奇Lab10 小时前
代码库知识库系列(07):混合检索 BM25 + 向量——Q8 还是失败,而且总分退步了
人工智能
ajassi200010 小时前
AI语音智能体开发日记(十一)为智能设备“声”临其境——详解音频资源自动化生成流程
人工智能·ai·ai编程