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

工程 | Christian Tzolov | 2024 年 3 月 6 日 | ...

更新:截至 2024 年 3 月 13 日,Mistral AI 已在其大型模型中集成了并行函数调用支持,此功能在该博客初次发布时尚不存在。

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

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

在这里,我将讨论如何在 Java 中使用 Mistral AI 的新函数调用功能,特别是与 Spring AI 集成使用。

如果您对深入研究底层 Java 客户端的细节不感兴趣,并希望充分利用您的投入,请随意跳过下一段,直接进入使用 Spring AI 进行函数调用的部分。

1. Java 中的函数调用

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

因此,我不得不研究他们的 JavaScript/Python 客户端来弄清楚。下面是 API 各个组件及其相互连接的类图。

Mistral AI Class Diagram 1

熟悉 OpenAI API 的人会注意到,Mistral AI 的新 API 几乎相同,只有一些细微的差别。

我扩展了由 Ricken Bazolo 最初创建的 MistralAiApi Java 客户端,以包含缺失的函数调用功能。更新后的客户端运行良好,如支付状态演示所示。

由于我的重点是 Spring AI,在这里我不会深入探讨客户端的技术细节。但是,如果您感兴趣,可以查阅我下方提供的演示代码和备忘单图表。

Mistral AI Function Calling Flow 3

重要的是要注意,模型不会直接调用函数;相反,它会生成 JSON,供您在代码中调用该函数,并将结果返回给模型以继续对话。

2. 使用 Spring AI 进行函数调用

Spring AI 通过允许您定义一个返回用户定义的 java.util.Function@Bean 来简化函数调用。它会自动推断函数的输入类型并生成相应的 JSON(或 Open API)Schema。此外,Spring AI 通过使用必要的适配器代码包装您的 POJO(即函数),处理了与 AI 模型之间的复杂交互,无需您编写重复的代码。

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

2.1 工作原理?

假设我们希望 AI 模型回复它本身没有的信息。例如,如这个 Mistral AI 教程所示,获取您最近支付交易的状态。

让我们使用 Spring AI 重新实现这个教程。

使用 Initializr 引导一个新的 Boot 应用,并将 MistralAI 的 boot starter 依赖添加到 POM 中

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-mistral-ai-spring-boot-starter</artifactId>
    <version>0.8.1</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 极大地简化了您为支持函数调用而需要编写的代码。它为您协调了函数调用对话。您还可以在提示中引用多个函数 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。这种方法可以确保该函数对于所有提示问题都始终启用并可访问。但是,需要注意的是,对于不需要该函数的请求,此方法可能会传输不必要的上下文令牌。

就是这样。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 动态提示选项

使用 MistralAiChatOptions,我们可以为每个提示请求定制默认设置。例如,我们可以根据需要将模型切换到 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 的 javadoc 以了解可用选项。

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 模型之间重用相同的代码和函数。

3. 构建原生 (GraalVM) 可执行文件

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

./mvnw clean install -Pnative native:compile

这可能需要几分钟才能完成。然后您可以运行原生可执行文件

./target/mistralai-aot-demo

4. 结论

在这篇博客文章中,我们探讨了 Mistral AI 的函数调用功能与 Java 和 Spring AI 的结合使用。

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

涵盖的关键点包括

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

该博客提供了相关文档和演示的链接,读者可以进一步探索函数调用功能以及在不同语言模型提供商之间的代码可移植性。

获取 Spring 资讯

订阅 Spring 资讯,保持联系

订阅

领先一步

VMware 提供培训和认证,为您的进步加速。

了解更多

获取支持

Tanzu Spring 通过简单的订阅提供 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件。

了解更多

即将举办的活动

查看 Spring 社区即将举办的所有活动。

查看全部