目录:
Spring AI 框架介绍
Spring AI 对话模型
Spring AI 提供了很多便利的功能,主要如下:
AI Model API
“Model API” 提供了聊天、文本转图像、音频转录、文本转语音、嵌入等功能,且不局限于某个固定的大模型提供商,如 OpenAI,Microsoft,Amazon, Google, Amazon Bedrock, Huggung Face等等。
下面是支持的 AI 模型的示意图:
ChatClient
前文介绍过,是Spring AI 中与大模型交互的主要组件,即支持同步API,也支持异步API。
向量存储API
向量存储API(Vector Store API)支持多种实现,包括新的类SQL的元数据过滤器API,多达14种向量数据库。
函数调用API
Spring AI 让大模型调用你的业务函数变得更简单。
自动配置
Springboot的自动配置和各种starter让AI模型和向量存储使用起来非常方便。
ETL数据工程
ETL框架为数据加载到向量数据库奠定了基础,有助于实现检索增强生成(RAG)模式,使您能够将数据融入AI模型,以丰富其响应内容。
下面将对这些功能进行具体介绍。
对话大模型API可以帮助开发者将AI对话集成到应用中,比如chatGPT。
ChatModel的定义如下:
public interface ChatModel extends Model<Prompt, ChatResponse> {
default String call(String message) {...}
@Override
ChatResponse call(Prompt prompt);
}
默认的call()
方法简化了初始使用,避免了更复杂的Prompt和ChatResponse类的复杂性。在实际的应用程序中,更常见的做法是使用下面的call()
方法,它接受一个Prompt实例并返回一个ChatResponse。
StreamingChatModel
的定义如下:
public interface StreamingChatModel extends StreamingModel<Prompt, ChatResponse> {
default Flux<String> stream(String message) {...}
@Override
Flux<ChatResponse> stream(Prompt prompt);
}
与ChatModel差不多,使用了响应式Flux API对响应进行流处理。
响应式Flux 是一种基于 Reactor 库实现的响应式编程模式,用于处理异步流式数据的框架。它是 Reactor 提供的两种核心 Publisher(发布者)之一,主要用于处理多元素的数据流,与 Mono(用于单一数据或无数据流)相辅相成。
Prompt是一个ModelRequest,包含消息列表和ChatOptions,如下所示:
public class Prompt implements ModelRequest<List<Message>> {
private final List<Message> messages;
private ChatOptions modelOptions;
@Override
public ChatOptions getOptions() {...}
@Override
public List<Message> getInstructions() {...}
// constructors and utility methods omitted
}
消息继承于Content接口,其中包含消息内容,类型和元数据Map:
public interface Content {
String getContent();
Map<String, Object> getMetadata();
}
public interface Message extends Content {
MessageType getMessageType();
}
消息接口根据消息类型的不同而有多种不同的实现,如下所示:
对话选项ChatOptions
指可以传递给AI模型的参数项,它是ModelOptions
的子类,定义如下:
public interface ChatOptions extends ModelOptions {
String getModel();
Float getFrequencyPenalty();
Integer getMaxTokens();
Float getPresencePenalty();
List<String> getStopSequences();
Float getTemperature();
Integer getTopK();
Float getTopP();
ChatOptions copy();
}
每个特定于模型的ChatModel/StreamingChatModel实现都可以有自己的选项。比如说,OpenAI的选项有logitBias
,seed
和user
。
这是一个很强大的功能,可以让用户在应用启动时使用模型特有的参数,然后在运行时用Prompt
请求来覆盖它们,如下图所示:
每个特定于模型的ChatModel/StreamingChatModel实现都可以有自己的选项。比如说,OpenAI的选项有logitBias
,seed
和user
。
这是一个很强大的功能,可以让用户在应用启动时使用模型特有的参数,然后在运行时用Prompt
请求来覆盖它们,如下图所示:
ChatResponse
的定义如下:
public class ChatResponse implements ModelResponse<Generation> {
private final ChatResponseMetadata chatResponseMetadata;
private final List<Generation> generations;
@Override
public ChatResponseMetadata getMetadata() {...}
@Override
public List<Generation> getResults() {...}
// other methods omitted
}
ChatResponse
对象持有AI模型的输出,其中包含元数据ChatResponseMetadata
。
Generation指模型输出结果,实现了ModelResult接口:
public class Generation implements ModelResult<AssistantMessage> {
private final AssistantMessage assistantMessage;
private ChatGenerationMetadata chatGenerationMetadata;
@Override
public AssistantMessage getOutput() {...}
@Override
public ChatGenerationMetadata getMetadata() {...}
// other methods omitted
}
ChatModel 的具体实现有很多种,在上文介绍Spring AI支持的AI模型示意图中可以看到。
在这些实现中,有些仅支持文本处理,有些不支持函数调用,有些不可调试,不支持JSON输出,各有各的特点。
Amazon Bedrock支持来自不同模型提供商的多个基础模型,如Anthropic3、Anthropic2、Llama、Cohere、Titan、Jurassic2。
使用Amazon Bedrock的好处是无需管理底层硬件或模型训练的基础设施,而是交给Amazon来托管。降低了构建生成式AI应用的技术门槛,简化了部署流程。
Amazon Bedrock与AWS的其他服务无缝集成,提供了端到端的AI开发解决方案。
Amazon Bedrock 目前尚未对中国区开放,美国和欧洲等地区是可用的。
由ChatGPT驱动的Azure OpenAI超越了传统的OpenAI功能,提供了人工智能驱动的文本生成,并增强了功能。Azure提供了额外的AI安全和负责任的AI功能。Azure OpenAI可以与其他Azure服务无缝集成,包括Azure 的向量存储服务。
在前文的例子中,我们就是以Azure OpenAI为例来演示的。Azure OpenAI的配置项均以spring.ai.azure.openai
为前缀。如下所示:
属性 | 描述 | 默认 |
---|---|---|
spring.ai.azure.openai.api-key | Azure AI OpenAI的key | - |
spring.ai.azure.openai.endpoint | Azure AI OpenAI的端点 | - |
spring.ai.azure.openai.openai-api-key | 直连OpenAI,而不是Azure OpenAI。此时系统会自动将endpoint默认设置为https://api.openai.com/v1。spring.ai.azure.openai.chat.options.deployment-name 参数必须为OpenAI的模型 |
- |
spring.ai.azure.openai.custom-headers | 一个包含请求头的map | empty map |
以下是ChatModel的配置 | ||
spring.ai.azure.openai.chat.enabled | 是否开启Azure OpenAI | true |
spring.ai.azure.openai.chat.options.deployment-name | Azure OpenAI的模型部署名。需要注意的是,部署名与模型本身的名字不是一个概念。 | gpt-4o |
spring.ai.azure.openai.chat.options.maxTokens | 生成的tokens的最大数量 | - |
spring.ai.azure.openai.chat.options.temperature | 生成内容的创造性。值越大表示随机性越大,值越小表示确定性越高 | 0.7 |
spring.ai.azure.openai.chat.options.topP | 控制生成文本时的多样性,与温度参数类型,但工作原理不同。具体来说,就是从前n个概率和大于topP 的候选词中随机采样一个词作为下一个生成词。不建议与温度同时使用,避免复杂度 |
- |
除此之外,还有spring.ai.azure.openai.chat.options.logitBias
,spring.ai.azure.openai.chat.options.user
,spring.ai.azure.openai.chat.options.n
等参数,这里就不一一列举了。ChatModel相关参数均可以在请求时动态传递运行时选项来复写。如下所示:
ChatResponse response = chatModel.call(
new Prompt(
"Generate the names of 5 famous pirates.",
AzureOpenAiChatOptions.builder()
.withDeploymentName("gpt-4o")
.withTemperature(0.4)
.build()
));
函数调用让开发者在代码中创建一个函数描述,然后将该描述通过请求传递给大模型。大模型将返回函数名和调用函数的参数。
你可以通过AzureOpenAiChatModel
来注册自定义Java函数,并让模型智能地选择输出一个包含调用这些注册函数参数的JSON对象。
Azure OpenAI API 并不直接调用函数,而是生成一个JSON对象,然后让开发者自己去调用函数,并将函数返回值给到模型来完善对话。
下面来看看具体如何做。
假设有一个Weather Service 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,如下所示:
@Configuration
static class Config {
@Bean
@Description("Get the weather in location") // function description
public Function<MockWeatherService.Request, MockWeatherService.Response> weatherFunction() {
return new MockWeatherService();
}
...
}
这里的@Description
注释用来帮助模型理解什么时候来调用这个函数。这是一个很重要的属性。当然,也可以通过在Request上添加@JsonClassDescription
注释来描述函数:
@Configuration
static class Config {
@Bean
public Function<Request, Response> currentWeather() {
return new MockWeatherService();
}
...
}
@JsonClassDescription("Get the weather in location")
public record Request(String location, Unit unit) {}
推荐在Request上添加注释来作为函数描述。
除了直接以Bean的方式定义函数外,还可以通过函数回调来定义:
@Configuration
static class Config {
@Bean
public FunctionCallback weatherFunctionInfo() {
return FunctionCallback.builder()
.function("CurrentWeather", new MockWeatherService()) // (1) function name
.description("Get the current weather in a given location") // (2) function description
.inputType(MockWeatherService.Request.class) // (3) function input type
.build();
}
...
}
通过以上两种方式的任意一种将回调函数定义成bean,然后就需要根据bean的名称来开启AI模型的函数调用:
AzureOpenAiChatModel chatModel = ...
UserMessage userMessage = new UserMessage("What's the weather like in San Francisco, Tokyo, and Paris?");
ChatResponse response = this.chatModel.call(new Prompt(List.of(this.userMessage),
AzureOpenAiChatOptions.builder().withFunction("CurrentWeather").build())); // (1) Enable the function
logger.info("Response: {}", response);
客户端注册
除了服务端注册函数回调之外,还可以在ChatClient
或者ChatModel
种注册函数回调,如下所示:
AzureOpenAiChatModel chatModel = ...
UserMessage userMessage = new UserMessage("What's the weather like in San Francisco, Tokyo, and Paris? Use Multi-turn function calling.");
var promptOptions = AzureOpenAiChatOptions.builder()
.withFunctionCallbacks(List.of(FunctionCallback.builder()
.function("CurrentWeather", new MockWeatherService()) // (1) function name and instance
.description("Get the current weather in a given location") // (2) function description
.inputType(MockWeatherService.Request.class) // (3) function input type
.build()))
.build();
ChatResponse response = this.chatModel.call(new Prompt(List.of(this.userMessage), this.promptOptions));
除了Amazon和Azure提供的对话式大模型之外,还有众多AI提供商,如Google VertexAI
,Groq
,Hugging Face
,Mistral AI
,MiniMax
,Moonshot AI
,NVIDIA
,Ollama
,Perplexity AI
,OCI Generative AI
,OpenAI
,还有百度的QianFan
,ZhiPu AI
,IBM的watsonx.AI
等。
[1]. https://docs.spring.io/spring-ai/reference/api/index.html