大语言模型(LLM)正在深刻改变我们与信息交互的方式,它们不仅能回答问题、生成文本,甚至开始取代传统的搜索引擎。然而,LLM并非完美,它们有时也无法满足我们更复杂的需求,比如主动执行任务,超越纯文本的交互。本文将探讨如何利用 工具调用(Tool Calling) 这一强大的技术,并结合 Spring AI 框架,赋予 LLM 更强大的能力,使其能够主动参与到我们的日常工作中。

1. 工具调用(Tool Calling):LLM 的能力延伸

工具调用(Tool Calling) 的核心在于赋予 LLM 使用外部工具的能力,使其不再局限于自身知识库。想象一下,一位经验丰富的工匠需要组装一个柜子,他拥有各种工具:锤子、螺丝刀、电钻等等。工匠需要根据不同的部件和材料选择合适的工具。如果柜子部件是钢制的,那么锤子和钉子显然不是最佳选择。

LLM 就像这位工匠,而 工具调用(Tool Calling) 则相当于赋予了它一个工具箱。当面对问题时,LLM 可以根据问题的类型选择合适的工具来解决。这些工具可以是任何可以执行特定功能的程序,比如从数据库中检索数据、调用外部 API 获取信息、甚至控制硬件设备。这种能力使得 LLM 不仅仅是信息提供者,而是能够实际参与并执行任务的智能助手。

举个例子,如果用户询问:“明天北京的空气质量如何?” 传统的 LLM 可能会尝试根据历史数据或者常见的污染源进行推测,但结果往往不够准确。而具备 工具调用(Tool Calling) 能力的 LLM 则可以调用空气质量查询 API,获取实时的、准确的空气质量数据,并将其返回给用户。

2. Spring AI:简化 LLM 应用开发的桥梁

Spring AI 是一个旨在简化 AI 应用开发的框架,它提供了与各种 LLM 提供商(如 OpenAI, Gemini, Anthropic)以及开源模型(如本文使用的 Ollama)集成的接口。通过 Spring AI,开发者可以更加方便地将 LLM 集成到现有的 Spring 应用中,并利用 工具调用(Tool Calling) 等高级特性。

Spring AI 的优势在于其高度的抽象性和灵活性。开发者无需关心底层 LLM 平台的复杂性,只需要关注业务逻辑的实现。Spring AI 提供了统一的 API,可以轻松切换不同的 LLM 模型,从而更好地满足不同的应用场景。

3. Ollama:本地部署 LLM 的利器

Ollama 是一个开源工具,它可以让你在本地计算机上轻松下载和运行开源 LLM。这对于开发者来说非常方便,可以在本地进行模型测试和调试,而无需依赖远程 API。Ollama 支持多种模型,并且可以方便地进行模型管理和部署。

使用 Ollama 的优势在于其简洁性和易用性。只需要几行命令,就可以完成模型的下载、部署和运行。此外,Ollama 还支持 GPU 加速,可以显著提高模型的推理速度。在安全性方面,Ollama 允许开发者在本地环境中完全掌控数据,避免了将敏感数据发送到外部服务器的风险。

4. 搭建环境:Ollama + Spring AI

为了演示 工具调用(Tool Calling) 的实际应用,我们需要搭建一个开发环境。

步骤 1: 获取 Ollama 实例

可以选择以下方式:

  • 本地安装 Ollama: 下载并安装适合你操作系统的 Ollama 版本。
  • 使用 Testcontainers 运行 Ollama: 适用于 Docker 环境。
  • 通过 Kubernetes Service Bindings 绑定到 Ollama 实例: 适用于 Kubernetes 环境。

步骤 2: 拉取支持工具调用的模型

从 Ollama 模型库中拉取支持 工具调用(Tool Calling) 的模型。例如,可以使用 qwen2.5:7b 模型,因为它支持 工具调用(Tool Calling) 且发布时间较新。

ollama pull qwen2.5:7b

步骤 3: 添加 Spring AI 依赖

在你的 Spring Boot 项目中添加 spring-ai-ollama-spring-boot-starter 依赖:

<dependency>
  <groupId>org.springframework.ai</groupId>
  <artifactId>spring-ai-ollama-spring-boot-starter</artifactId>
</dependency>

步骤 4: 配置应用

application.properties 文件中配置 Ollama 连接信息和模型名称:

spring.ai.ollama.base-url=http://localhost:11434
spring.ai.ollama.chat.model=qwen2.5:7b

5. Spring AI 中工具调用(Tool Calling)的实现

Spring AI 中实现 工具调用(Tool Calling),需要定义工具,并将其注册到 ChatClient 中。

步骤 1: 定义工具

使用 @Tool 注解定义工具类。使用 @ToolParam 注解指定工具的参数。LLM 会根据用户消息的上下文,决定调用哪个工具,以及传递哪些参数。

public class WeatherTools {

    private static final List<String> CONDITIONS = Arrays.asList(
        "Sunny", "Partly Cloudy", "Cloudy", "Showers", "Rainy"
    );
    private static final Random RANDOM = new Random();

    @Tool(description = "获取指定城市今天的天气")
    public String getTodaysWeather(@ToolParam(description = "城市名称") String city) {
        if (city == null || city.trim().isEmpty()) {
            return "请输入有效的城市名称。";
        }
        String condition = CONDITIONS.get(RANDOM.nextInt(CONDITIONS.size()));
        int temp = RANDOM.nextInt(30);
        return String.format(
            "今天 %s 的天气是 %s,温度 %d°C",
            city, condition, temp
        );
    }
}

步骤 2: 创建 ChatService

创建一个 @Service 类,使用 ChatClient.Builder 构建 ChatClient,并将工具注册到 ChatClient 中。

@Service
public class ChatbotService {

    private final ChatClient chatClient;

    public ChatbotService(ChatClient.Builder modelBuilder) {
        this.chatClient = modelBuilder
            .defaultTools(new DateTimeTools(), new WeatherTools())
            .build();
    }

    public String handleMessage(String message) {
        return this.chatClient.prompt()
            .user(message)
            .call()
            .content();
    }
}

步骤 3: 创建 Controller

创建一个简单的 Controller 类,通过 HTTP 接口与系统进行交互。

@RestController
@RequestMapping("/api/chatbot")
public class ChatbotController {

    private final ChatbotService chatbotService;

    public ChatbotController(ChatbotService chatbotService) {
        this.chatbotService = chatbotService;
    }

    @GetMapping(value = "")
    public String handleMessage(@RequestParam(value = "message") String message) {
        return chatbotService.handleMessage(message);
    }
}

6. 实战演示:查询天气

现在,我们可以通过 HTTP 请求与系统进行交互,测试 工具调用(Tool Calling) 的效果。

发送以下请求:

curl --location 'http://localhost:8080/api/chatbot?message=今天伊斯坦布尔的温度是多少?'

LLM 会分析用户的问题,判断需要调用 getTodaysWeather 工具,并将 “伊斯坦布尔” 作为城市参数传递给该工具。

getTodaysWeather("伊斯坦布尔") 方法执行后,返回结果(例如:”今天伊斯坦布尔的天气是晴朗,温度 24°C”)将被传递回 LLM。

LLM 会将该信息格式化为用户友好的最终答案:

今天伊斯坦布尔的天气是晴朗,温度 24°C。

这个流程展示了 工具调用(Tool Calling) 的强大之处:LLM 可以根据用户的需求,自动选择合适的工具,并利用工具获取的信息来生成更准确、更有用的答案。

7. 高级应用:构建智能助手

工具调用(Tool Calling) 不仅可以用于查询天气,还可以用于构建更复杂的智能助手。例如,可以开发一个可以预定机票、发送邮件、甚至控制智能家居设备的助手。

以下是一些可能的应用场景:

  • 预定机票: LLM 可以调用机票预订 API,根据用户的出行时间和目的地,自动搜索合适的航班,并完成预订。
  • 发送邮件: LLM 可以调用邮件发送 API,根据用户提供的收件人、主题和内容,自动发送邮件。
  • 控制智能家居设备: LLM 可以调用智能家居 API,根据用户的指令,控制灯光、温度、以及其他智能设备。

为了实现这些高级应用,需要定义更多的工具,并将其与 LLM 集成。同时,还需要设计更加智能的对话流程,以便 LLM 可以更好地理解用户的意图,并选择合适的工具来完成任务。

例如,一个用于预定机票的工具可以包含以下参数:

  • 出发城市
  • 到达城市
  • 出发日期
  • 返回日期
  • 乘客人数

LLM 可以根据用户的提问,自动提取这些参数,并将其传递给机票预订 API。

8. 挑战与未来

虽然 工具调用(Tool Calling) 带来了巨大的潜力,但也存在一些挑战。

  • 工具的发现与管理: 如何让 LLM 发现和使用新的工具?如何管理大量的工具?
  • 工具的安全问题: 如何保证工具的安全性,防止恶意使用?
  • 多步推理与复杂任务: 如何让 LLM 完成需要多步推理的复杂任务?

为了解决这些挑战,研究人员正在探索各种新的技术,例如:

  • 模型上下文协议 (MCP): 一种用于管理和协调多个工具的协议。
  • 知识图谱: 用于存储和检索工具的信息。
  • 强化学习: 用于训练 LLM 如何有效地使用工具。

工具调用(Tool Calling) 的未来充满了机遇。随着技术的不断发展,我们可以期待更加智能、更加强大的 LLM 应用,它们将能够更好地满足我们的需求,并改变我们与世界交互的方式。

9. 总结与展望

工具调用(Tool Calling) 是赋予大语言模型(LLM)实际行动能力的强大技术。结合 Spring AI 的便捷性和 Ollama 的本地部署能力,开发者可以轻松构建出更加智能、更加实用的 LLM 应用。虽然目前还存在一些挑战,但随着技术的不断进步,工具调用(Tool Calling) 将在未来发挥越来越重要的作用,为我们带来更美好的智能生活。强烈建议大家深入研究模型上下文协议(MCP),并思考仅仅依赖 工具调用(Tool Calling) 是否足以应对更复杂的 Agent 工作流。

想要更深入地了解 工具调用(Tool Calling) 的实践,可以参考 GitHub 链接:https://github.com/batuhannoz/tool-call-demo。相信通过实践,你会对 工具调用(Tool Calling) 有更深刻的理解,并能将其应用到你的项目中,创造出更多令人惊艳的应用。