你可以使用 MistralAiChatClient
注册自定义的 Java 函数,并让 Mistral AI 模型智能地选择输出一个包含调用一个或多个已注册函数参数的 JSON 对象。这使您能够将 LLM 的能力与外部工具和 API 连接起来。mistral_small_latest
和 mistral_large_latest
模型经过训练,能够检测何时应该调用函数,并以遵循函数签名的 JSON 响应。
MistralAI API不会直接调用函数;相反,模型会生成JSON,您可以使用该JSON在代码中调用函数,并将结果返回给模型以完成对话。
Note
|
截至2024年3月13日,Mistral AI已将并行函数调用的支持集成到他们的`mistral_large_latest`模型中,这是首个春季AI Mistral AI时所缺少的功能。 |
Spring AI提供了灵活且用户友好的方法来注册和调用自定义函数。通常情况下,自定义函数需要提供一个函数`名称`、描述`和函数调用`签名
(作为JSON模式),以便让模型知道该函数期待什么参数。`描述`有助于模型理解何时调用该函数。
作为开发者,你需要实现一个函数,该函数接收来自AI模型发送的函数调用参数,并将结果返回给模型。你的函数可以依次调用其他第三方服务来提供结果。
Spring AI 使得这一过程变得非常简单,只需定义一个返回 java.util.Function
的 @Bean
定义,并在调用 ChatClient
时提供 bean 名称作为选项即可。
在底层,Spring会将你的POJO(函数)用适当的适配器代码包装起来,使其能够与AI模型进行交互,这样你就无需编写繁琐的样板代码。底层基础设施的基础是[FunctionCallback.java](FunctionCallbackWrapper.java(https://github.com/spring-projects/spring-ai/blob/main/spring-ai-core/src/main/java/org/springframework/ai/model/function/FunctionCallbackWrapper.java)。
它是如何工作的
假设我们想让AI模型回应一些它所没有的信息,比如在给定位置的当前温度。
我们可以为AI模型提供关于我们自身函数的元数据,它可以在处理您的提示时用来检索那些信息。
例如,如果在处理一个提示过程中,AI模型确定它需要关于某个特定位置的温度的附加信息,它将启动一个服务器端生成的请求/响应交互。AI模型调用一个客户端函数。AI模型提供方法调用的细节作为JSON,并且执行该函数并返回响应的责任在于客户端。
Spring AI极大地简化了你需要编写的代码来支持函数调用。它为你代理了函数调用交互。你可以简单地提供你的函数定义作为一个`@Bean`,然后在你的提示选项中提供函数的bean名称。你也可以在你的提示中引用多个函数bean名称。
快速开始
让我们创建一个聊天机器人,通过调用我们自己的函数来回答问题。为了支持聊天机器人的回应,我们将注册我们自己的函数,该函数接收一个地点并返回该地点当前的天气状况。
当对模型提示进行响应需要回答如`"What’s the weather like in Boston?"`这样的问题时,AI模型将调用客户端,提供位置值作为参数传递给函数。这种类似RPC的数据以JSON形式传递。
我们的函数可以调用一些基于SaaS的天气服务API,并将天气响应返回给模型以完成对话。在这个例子中,我们将使用一个名为`MockWeatherService`的简单实现,它会硬编码各个位置的温度。
下面的 MockWeatherService.java
代表了天气服务API:
public class MockWeatherService implements Function<Request, Response> {
public enum Unit { C, F }
public record Request(String location, Unit unit) {}
public record Response(double temp, Unit unit) {}
public Response apply(Request request) {
return new Response(30.0, Unit.C);
}
}
将函数注册为Bean
通过链接:../mistralai-chat.html#_auto_configuration[MistralAiChatClient 自动配置],你可以通过多种方式在Spring上下文中注册自定义函数作为bean。
我们首先描述最适合POJO的选项。
普通Java函数
在这种方法中,你可以在应用上下文中定义`@Beans`,就像定义任何其他由Spring管理的对象一样。
在内部,Spring AI ChatClient
将创建一个 FunctionCallbackWrapper
包装器的实例,该包装器增加了通过 AI 模型调用它的逻辑。@Bean
的名称作为 ChatOption
传递。
@Configuration
static class Config {
@Bean
@Description("Get the weather in location") // function description
public Function<MockWeatherService.Request, MockWeatherService.Response> weatherFunction1() {
return new MockWeatherService();
}
...
}
@Description`注解是可选的,它提供了一个函数描述(2),帮助模型理解何时调用该函数。这是一个重要的属性,有助于AI模型确定调用哪个客户端函数。
提供函数描述的另一个选项是在`MockWeatherService.Request`上使用`@JacksonDescription`注解来提供函数描述:
@Configuration
static class Config {
@Bean
public Function<Request, Response> currentWeather3() { // (1) bean name as function name.
return new MockWeatherService();
}
...
}
@JsonClassDescription("Get the weather in location") // (2) function description
public record Request(String location, Unit unit) {}
将请求对象进行注解是一个最佳实践,其目的是使该函数产生的JSON模式尽可能描述性强,从而帮助AI模型选择正确的函数进行调用。
链接:https://github.com/spring-projects/spring-ai/blob/main/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/mistralai/tool/PaymentStatusBeanIT.java 中的 [PaymentStatusBeanIT.java] 展示了这种方法。
Tip
|
链接:https://github.com/spring-projects/spring-ai/blob/main/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/mistralai/tool/PaymentStatusBeanOpenAiIT[PaymentStatusBeanOpenAiIT]使用OpenAI API实现了相同的功能。在这方面,MistralAI与OpenAI几乎相同。 |
函数回调包装器
另一种注册函数的方法是创建`FunctionCallbackWrapper`包装器,如下所示:
@Configuration
static class Config {
@Bean
public FunctionCallback weatherFunctionInfo() {
return new FunctionCallbackWrapper<>("CurrentWeather", // (1) function name
"Get the weather in location", // (2) function description
(response) -> "" + response.temp() + response.unit(), // (3) Response Converter
new MockWeatherService()); // function code
}
...
}
它包装了第三方的`MockWeatherService`函数,并将其作为`CurrentWeather`函数注册到`MistralAiChatClient`中。它还提供了一个描述(2)和一个可选的响应转换器(3),以将响应转换成模型所期望的文本格式。
Note
|
默认情况下,响应转换器会对Response对象进行JSON序列化。 |
Note
|
FunctionCallbackWrapper`内部基于`MockWeatherService.Request`类解析函数调用签名。 |
在聊天选项中指定功能
要让模型了解并调用你的`CurrentWeather`函数,你需要在你的提示请求中启用它:
MistralAiChatClient chatClient = ...
UserMessage userMessage = new UserMessage("巴黎的天气怎么样?");
ChatResponse response = chatClient.call(new Prompt(List.of(userMessage),
MistralAiChatOptions.builder().withFunction("CurrentWeather").build())); // (1) Enable the function
logger.info("Response: {}", response);
根据用户的问题,将触发3次对`CurrentWeather`函数的调用(每个城市一次),并生成最终的响应。
注册/调用带有提示选项的函数
除了自动配置之外,您还可以动态地在您的提示请求中注册回调函数:
MistralAiChatClient chatClient = ...
UserMessage userMessage = new UserMessage("巴黎的天气怎么样?");
var promptOptions = MistralAiChatOptions.builder()
.withFunctionCallbacks(List.of(new FunctionCallbackWrapper<>(
"CurrentWeather", // name
"Get the weather in location", // function description
new MockWeatherService()))) // function code
.build();
ChatResponse response = chatClient.call(new Prompt(List.of(userMessage), promptOptions));
Note
|
在提示中注册的函数默认在此请求期间启用。 |
这种方法允许根据用户输入动态选择调用不同的函数。
'''The PaymentStatusPromptIT.java 集成测试提供了一个注册函数至 MistralAiChatClient
并在提示请求中使用它的完整示例。'''
附录
使用最新的Mistral AI API在Java和Spring AI中调用函数[(博客) 使用最新的Mistral AI API在Java和Spring AI中调用函数]
米斯特拉尔人工智能API函数调用流程
以下图表展示了Mistral AI低级API的流程,用于链接:https://docs.mistral.ai/guides/function-calling[函数调用]:
链接:https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-mistral-ai/src/test/java/org/springframework/ai/mistralai/api/tool/PaymentStatusFunctionCallingIT.java [PaymentStatusFunctionCallingIT.java] 提供了一个关于如何使用 Mistral AI API 函数调用的完整示例。它基于 https://docs.mistral.ai/guides/function-calling [Mistral AI 函数调用教程]。