使用最新的Mistral AI API,在 Java 和 Spring AI 中进行函数调用

领先的开源大型语言模型开发商 Mistral AI 宣布,其尖端模型新增了 函数调用 支持。

函数调用 是一种便于 LLM 与外部工具和 API 集成的功能。它使语言模型能够请求执行客户端函数,从而访问必要的运行时信息或动态执行任务。

本文将带你了解如何将 Mistral AI 的新函数调用功能与 Java 特别是 Spring AI 结合使用。

如果你对底层的 Java 客户端的详细细节不感兴趣,不想浪费时间,可以直接看 使用 Spring AI 调用函数 章节。

1、使用 Java 调用函数

如果你想使用 Java 和 Spring AI 测试最新的 Mistral AI 功能,你会发现 Mistral 不支持 Java 客户端,也还没有发布函数调用 API。

因此,我不得不通过探索他们的 JavaScript/Python 客户端来解决这个问题。下面是一个类图,说明了 API 的各个组件及其相互联系。

Mistral AI 类图

熟悉 OpenAI API 的人会注意到,Mistral AI 的新 API 几乎与 OpenAI API 相同,只有一些细微差别。不过,还有一个重要的限制: 在撰写本文时,Mistral AI 不支持并行函数调用,这使它与 OpenAI、Azure OpenAI 和 Vertex AI Gemini 提供的最新 LLM 模型有所不同。

我对最初由 Ricken Bazolo 创建的 MistralAiApi Java 客户端进行了扩展,加入了缺失的函数调用功能。正如 Payment Status demo 所示,更新后的客户端运行良好。

由于本文重点是 Spring AI,所以就不在这里深入探讨客户端的复杂技术了。不过,如果你有兴趣,可以看看如下的演示代码和速查表图。

Mistral AI 功能调用流程图

值得注意的是,模型并不直接调用函数,而是生成 JSON 供你在代码中调用函数,并将结果返回给模型以继续对话。

2、使用 Spring AI 调用函数

Spring AI 允许你定义一个 @Bean 来返回用户定义的 java.util.Function,从而简化了函数调用。它会自动推断函数的输入类型,并据此生成 JSON(或 Open API)Schema。

此外,Spring AI 简化了代码移植到其他支持函数调用的 AI 模型的过程,并允许开发高效的原生(GraalVM)可执行文件。

2.1、实现

假设我们想让人工智能模型响应它所没有的信息。例如,如本 Mistral AI 教程 所示,你最近的付款交易状态。

让我们用 Spring AI 重新实现该教程。

使用 Initializr 初始化一个新的 Spring Boot 应用,并在 POM 中添加 MistralAI boot starter 依赖:

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-mistral-ai-spring-boot-starter</artifactId>
    <version>0.8.1-SNAPSHOT</version>
</dependency>

使用 application.properties 进行配置:

spring.ai.mistralai.api-key=${MISTRAL_AI_API_KEY}
spring.ai.mistralai.chat.options.model=mistral-small-latest

这会自动为你提供功能齐全的 MistralAiChatClient

@Autowired
MistralAiChatClient chatClient;

接下来,假设我们有一个由支付交易组成的数据集:

public record Transaction(String transactionId) {}

public record Status(String status) {}

public static final Map<Transaction, Status> PAYMENT_DATA = Map.of(
            new Transaction("T1001"), new Status("Paid"),
            new Transaction("T1002"), new Status("Unpaid"),
            new Transaction("T1003"), new Status("Paid"),
            new Transaction("T1004"), new Status("Paid"),
            new Transaction("T1005"), new Status("Pending"));

用户可以就该数据集提出问题,并使用函数调用来回答这些问题。例如,我们可以使用一个函数来检索交易的支付状态:

@Bean
@Description("Get payment status of a transaction")
public Function<Transaction, Status> retrievePaymentStatus() {
        return (transaction) -> new Status(PAYMENT_DATA.get(transaction).status());
}

它使用一个普通的 java.util.Function,将 Transaction 作为输入,并返回该事务的 Status。函数注册为 @Bean 并使用 @Description 注解来定义函数描述。Spring AI 极大地简化了为支持函数调用而编写的代码。它可以为你处理函数调用对话。你还可以在提示(Prompt)中引用多个函数 Bean 名称。

var options = MistralAiChatOptions.builder()
   .withFunction("retrievePaymentStatus")
   .build();

ChatResponse paymentStatusResponse = chatClient.call(
      new Prompt("What's the status of my transaction with id T1005?",  options);

我们在提示中提出问题,并在提示选项中包含相关函数名称。函数名称应与 Bean 名称一致。

提示:与其在每个请求的提示选项中重复指定函数名称,不如在 application.properties 文件中配置一次,如:spring.ai.mistralai.chat.options.functions=retrievePaymentStatus。这种方法可以确保所有提示问题都能持续启用和访问该函数。不过,需要注意的是,这种方法可能会导致为不需要该函数的请求传输不必要的 Context Token。

就这样,Spring AI 将代表你完成函数调用对话。你可以打印响应内容:

System.out.println(paymentStatusResponse.getResult().getOutput().getContent());

期望得到的结果如下:

The status of your transaction T1005 is "Pending".

提示:查看 MistralAi-AOT-Demo,这是一个简单的 Spring Boot 应用,展示了 Mistral AI 与 Spring AI 的集成。它包含各种功能,如聊天补全、流式聊天补全、嵌入和函数调用。此外,还包括原生构建说明。

有关 Spring AI 与 Mistral AI 集成的更多详情,请参阅官方文档:

2.2、动态提示(Dynamic Prompt)选项

通过 MistralAiChatOptions,可以自定义每个提示(Prompt)请求的默认设置。例如,我们可以将模型切换为 LARGE,并根据需要调整特定的请求:

ChatResponse paymentStatusResponse = chatClient
   .call(new Prompt("What's the status of my transaction with id T1005?",
            MistralAiChatOptions.builder()
               .withModel(MistralAiApi.ChatModel.LARGE.getValue())
               .withTemperature(0.6f)
               .withFunction("retrievePaymentStatus")
               .build()));

有关可用选项,请查看 MistralAiChatOptions javadocs。

2.3、代码的可移植性

将代码移植到其他支持函数调用的模型非常简单。例如,要将代码从 Mistral AI 移植到 Azure OpenAI,可以按照以下步骤操作:

  1. spring-ai-mistral-ai-spring-boot-starter 依赖替换为 spring-ai-azure-openai-spring-boot-starter

  2. 调整 application.properties 配置文件:

    spring.ai.azure.openai.api-key=${AZURE_OPENAI_API_KEY}
    spring.ai.azure.openai.endpoint=${AZURE_OPENAI_ENDPOINT}
    spring.ai.azure.openai.chat.options.model=gpt-35-turbo
    
  3. MistralAiChatOptions 重命名为 AzureOpenAiChatOptions(在未来的 Spring AI 版本中可能无需重命名)。

目前,Spring AI 可在以下平台之间移植函数调用代码:

Spring-AI-Function-Calling-Portability 示例应用演示了如何在多个 AI 模型中重复使用相同的代码和函数。

注意:目前 Mistral AI 不支持并行函数调用。

3. 构建原生(GraalVM)镜像

要构建原生镜像,你需要安装 GrallVM 21 JDK 并运行以下 maven 命令:

./mvnw clean install -Pnative native:compile

可能需要几分钟才能完成。然后就可以运行本地可执行文件了:

./target/mistralai-aot-demo

4、总结

本文结合 Java 和 Spring AI 介绍了 Mistral AI 的函数调用功能。

重点是利用 Spring AI 的函数调用,该框架通过处理与 AI 模型交互的复杂性来简化集成过程,促进代码的可移植性以及高效的本地 (GraalVM) 可执行文件的开发。

涉及的要点包括:

  • 概述 Spring AI 的函数调用,包括演示和代码示例。
  • 解释 Spring AI 支持的不同 AI 模型之间的动态提示选项和代码可移植性。
  • 构建原生 (GraalVM) 执行程序以提高性能

本文还提供了相关文档和演示的链接,你可以进一步了解函数调用功能和不同语言模型提供商之间的代码可移植性。


Ref:https://spring.io/blog/2024/03/06/function-calling-in-java-and-spring-ai-using-the-latest-mistral-ai-api