OpenAI Chat

Spring AI 支持来自 OpenAI 的各种 AI 语言模型。OpenAI 是 ChatGPT 背后的公司,通过创建行业领先的文本生成模型和嵌入,在激发人们对 AI 驱动文本生成的兴趣方面发挥了重要作用。

前提条件(Prerequisites)

  • 你需要使用 OpenAI 创建一个 API 来访问 ChatGPT 模型。
  • OpenAI 注册页面创建一个账户,并在 API Keys 页面生成令牌。
  • Spring AI 项目定义了一个名为 spring.ai.openai.api-key 的配置属性,你应该将其设置为从 openai.com 获取的 API Key 的值。

可以在 application.properties 文件中设置这个配置属性:

spring.ai.openai.api-key=<your-openai-api-key>

为了提高处理 API 密钥等敏感信息时的安全性,可以使用 Spring 表达式语言 (SpEL) 来引用自定义环境变量:

# In application.yml
spring:
  ai:
    openai:
      api-key: ${OPENAI_API_KEY}
# In your environment or .env file
export OPENAI_API_KEY=<your-openai-api-key>

您还可以在 application 代码中以编程方式设置这个配置属性:

// Retrieve API key from a secure source or environment variable
String apiKey = System.getenv("OPENAI_API_KEY");

添加存储库和 BOM

Spring AI 工件发布在 Spring MilestoneSnapshot 存储库中。请参阅存储库部分将这些存储库添加到您的构建系统中。

为了帮助进行依赖管理,Spring AI 提供了 BOM(物料清单),以确保在整个项目中使用一致的 Spring AI 版本。请参阅依赖管理部分将 Spring AI BOM 添加到您的构建系统。

自动配置(Auto-configuration)

Spring AI 为 OpenAI 图像生成客户端提供了 Spring Boot 自动配置。要启用此功能,请将以下依赖项添加到项目的 Maven pom.xml文件中:

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>

或者,在你的 Gradle 构建文件 build.gradle 中添加:

dependencies {
    implementation 'org.springframework.ai:spring-ai-starter-model-openai'
}

聊天属性(Chat Properties)

Retry 属性(Retry Properties)

前缀 spring.ai.retry 用作属性前缀,允许您为 Mistral AI 模型配置 retry 机制。

属性 描述 默认值
spring.ai.retry.max-attempts 最大重试次数。 10
spring.ai.retry.backoff.initial-interval 指数退避策略的初始睡眠持续时间。 2 sec.
spring.ai.retry.backoff.multiplier 退避间隔乘数。 5
spring.ai.retry.backoff.max-interval 最大退避持续时间。 3 min.
spring.ai.retry.on-client-errors 如果为false,抛出NonTransientAiException,并且不会对4xx客户端错误码进行重试。 false
spring.ai.retry.exclude-on-http-codes 不应触发重试的HTTP状态码列表(例如抛出NonTransientAiException)。 empty
spring.ai.retry.on-http-codes 应触发重试的HTTP状态码列表(例如抛出TransientAiException)。 empty
连接属性(Connection Properties)

前缀是 spring.ai.openai 的属性,用于配置 OpenAI 的链接。

属性 描述 默认值
spring.ai.openai.base-url 连接的URL地址 https://api.openai.com
spring.ai.openai.api-key API密钥 -
spring.ai.openai.organization-id (可选)可指定用于API请求的组织ID -
spring.ai.openai.project-id (可选)可指定用于API请求的项目ID -
配置属性(Configuration Properties)

前缀是 spring.ai.openai.chat 的属性,用于配置 OpenAI 的 ChatModel 实现。

运行时选项(Runtime Options )

OpenAiChatOptions.java 提供模型配置,例如要使用的 temperature、maxToken、topP 等。

在启动时,可以使用 OpenAiChatModel (api,options) 构造函数或 spring.ai.openai.chat.options.*属性来配置默认选项。

在运行时,您可以通过在 Prompt 调用中添加新的、特定请求的选项来覆盖默认选项。例如,为特定请求覆盖默认型号和温度:

ChatResponse response = chatModel.call(
    new Prompt(
        "Generate the names of 5 famous pirates.",
        OpenAiChatOptions.builder()
            .model("mixtral-8x7b-32768")
            .temperature(0.4)
        .build()
    ));

工具 / 功能调用(Tool/Function Calling)

NVIDIA LLM API 在选择支持它的模型时支持 Tool/Function 调用。

您可以使用 ChatModel 注册自定义 Java 函数,并让提供的模型智能地选择输出一个包含参数的 JSON 对象来调用一个或多个注册的函数。这是一种将 LLM 功能与外部工具和 API 连接起来的强大技术。

多模态(Multimodal )

多模态是指模型同时理解和处理来自不同来源信息的能力,包括文本、图像、音频和其他数据格式。OpenAI 支持文本、视觉和音频输入模式。

视觉(Vision)

提供视觉多模态支持的 OpenAI 模型包括 gpt-4、gpt-4o 和 gpt-4o-mini。有关更多信息,请参阅 Vision 指南。

OpenAI 用户消息 API 可以将 base64 编码的图像或图像 URL 列表与消息结合起来。Spring AI 的消息接口通过引入媒体类型来促进多模态 AI 模型。这种类型包含消息中媒体附件的数据和详细信息,使用 Spring 的 org.springframework.util.MimeTypeorg.springframework.core.io.Resource 。原始媒体数据的资源。

下面是一个摘自 OpenAiChatModelIT.java 的代码示例,说明了如何使用 gpt-4o 模型将用户文本与图像融合。

var imageData = new ClassPathResource("/test.png");

var userMessage = UserMessage.builder()
    .text("Explain what do you see on this picture?")
    .media(List.of(new Media(MimeTypeUtils.IMAGE_PNG, imageData)))
    .build();

var response = this.chatModel
    .call(new Prompt(List.of(userMessage), OpenAiChatOptions.builder().model(modelName).build()));

或使用 GPT-4o 模型的等效图像 URL:

var userMessage = UserMessage.builder()
    .text("Explain what do you see on this picture?")
    .media(List.of(Media.builder()
        .mimeType(MimeTypeUtils.IMAGE_PNG)
        .data(URI.create("https://docs.spring.io/spring-ai/reference/_images/multimodal.test.png"))
        .build()))
    .build();

ChatResponse response = this.chatModel
    .call(new Prompt(List.of(userMessage), OpenAiChatOptions.builder().model(modelName).build()));

该示例展示了一个模型将 multimodal.test.png 图像作为输入:

与文本信息 “解释一下你在这张照片上看到了什么?” 一起,产生如下回复:

This is an image of a fruit bowl with a simple design. The bowl is made of metal with curved wire edges that
create an open structure, allowing the fruit to be visible from all angles. Inside the bowl, there are two
yellow bananas resting on top of what appears to be a red apple. The bananas are slightly overripe, as
indicated by the brown spots on their peels. The bowl has a metal ring at the top, likely to serve as a handle
for carrying. The bowl is placed on a flat surface with a neutral-colored background that provides a clear
view of the fruit inside.

音频(Audio)

提供输入音频多模态支持的 OpenAI 模型包括 GPT-4o-audio-preview。有关更多信息,请参阅音频指南。

OpenAI 用户消息 API 可以在消息中包含一个 base64 编码的音频文件列表。Spring AI 的消息接口通过引入媒体类型来促进多模态 AI 模型。这种类型利用 Spring 的 org.springframework.util.MimeTypeorg.springframework.core.io.Resource 来包含消息中媒体附件的数据和详细信息。原始媒体数据的资源。目前,OpenAI 仅支持以下媒体类型:audio/mp3audio/wav

下面是从 OpenAiChatModelIT.java 中摘录的代码示例,说明了如何使用 gpt-4o-audio-preview 模型将用户文本与音频文件融合。

var audioResource = new ClassPathResource("speech1.mp3");

var userMessage = new UserMessage("What is this recording about?",
        List.of(new Media(MimeTypeUtils.parseMimeType("audio/mp3"), audioResource)));

ChatResponse response = chatModel.call(new Prompt(List.of(userMessage),
        OpenAiChatOptions.builder().model(OpenAiApi.ChatModel.GPT_4_O_AUDIO_PREVIEW).build()));

音频输出(Output Audio)

提供输入音频多模态支持的 OpenAI 模型包括 GPT-4o-audio-preview。有关更多信息,请参阅音频指南。

OpenAI 助手消息 API 可以包含一个 base64 编码的音频文件列表,其中包含消息。Spring AI 的消息接口通过引入媒体类型来促进多模态 AI 模型。这种类型利用 Spring 的 org.springframework.util.MimeTypeorg.springframework.core.io.Resource 来包含消息中媒体附件的数据和详细信息。原始媒体数据的资源。目前,OpenAI 仅支持以下音频类型:audio/mp3audio/wav

下面是一个代码示例,说明了使用 gpt-4o-audio-preview 模型对用户文本和 audio 字节数组的响应:

var userMessage = new UserMessage("Tell me joke about Spring Framework");

ChatResponse response = chatModel.call(new Prompt(List.of(userMessage),
        OpenAiChatOptions.builder()
            .model(OpenAiApi.ChatModel.GPT_4_O_AUDIO_PREVIEW)
            .outputModalities(List.of("text", "audio"))
            .outputAudio(new AudioParameters(Voice.ALLOY, AudioResponseFormat.WAV))
            .build()));

String text = response.getResult().getOutput().getContent(); // audio transcript

byte[] waveAudio = response.getResult().getOutput().getMedia().get(0).getDataAsByteArray(); // audio data

结构化输出(Structured Outputs)

OpenAI 提供自定义结构化输出 API, 确保您的模型生成的响应严格符合您提供的 JSON Schema。除了现有的 Spring AI 模型无关的结构化输出转换器外,这些 API 还提供了更高的控制力和精度。

目前,OpenAI 支持 JSON Schema 语言格式的一个子集。

配置(Configuration )

Spring AI 允许您使用 OpenAiChatOptions 构建器以编程方式配置响应格式。

使用聊天选项构建器

您可以使用 OpenAiChatOptions 构建器以编程方式设置响应格式,如下所示:

String jsonSchema = """
        {
            "type": "object",
            "properties": {
                "steps": {
                    "type": "array",
                    "items": {
                        "type": "object",
                        "properties": {
                            "explanation": { "type": "string" },
                            "output": { "type": "string" }
                        },
                        "required": ["explanation", "output"],
                        "additionalProperties": false
                    }
                },
                "final_answer": { "type": "string" }
            },
            "required": ["steps", "final_answer"],
            "additionalProperties": false
        }
        """;

Prompt prompt = new Prompt("how can I solve 8x + 7 = -23",
        OpenAiChatOptions.builder()
            .model(ChatModel.GPT_4_O_MINI)
            .responseFormat(new ResponseFormat(ResponseFormat.Type.JSON_SCHEMA, this.jsonSchema))
            .build());

ChatResponse response = this.openAiChatModel.call(this.prompt);
与 BeanOutputConverter 实用程序集成

你可以利用现有的 BeanOutputConverter 实用程序自动从域对象生成 JSON Schema, 然后将结构化响应转换为特定于域的实例:

record MathReasoning(
    @JsonProperty(required = true, value = "steps") Steps steps,
    @JsonProperty(required = true, value = "final_answer") String finalAnswer) {

    record Steps(
        @JsonProperty(required = true, value = "items") Items[] items) {

        record Items(
            @JsonProperty(required = true, value = "explanation") String explanation,
            @JsonProperty(required = true, value = "output") String output) {
        }
    }
}

var outputConverter = new BeanOutputConverter<>(MathReasoning.class);

var jsonSchema = this.outputConverter.getJsonSchema();

Prompt prompt = new Prompt("how can I solve 8x + 7 = -23",
        OpenAiChatOptions.builder()
            .model(ChatModel.GPT_4_O_MINI)
            .responseFormat(new ResponseFormat(ResponseFormat.Type.JSON_SCHEMA, this.jsonSchema))
            .build());

ChatResponse response = this.openAiChatModel.call(this.prompt);
String content = this.response.getResult().getOutput().getContent();

MathReasoning mathReasoning = this.outputConverter.convert(this.content);
通过应用程序属性进行配置

或者,使用 OpenAI 自动配置时,可以通过以下应用程序属性配置所需的响应格式:

spring.ai.openai.api-key=YOUR_API_KEY
spring.ai.openai.chat.options.model=gpt-4o-mini

spring.ai.openai.chat.options.response-format.type=JSON_SCHEMA
spring.ai.openai.chat.options.response-format.name=MySchemaName
spring.ai.openai.chat.options.response-format.schema={"type":"object","properties":{"steps":{"type":"array","items":{"type":"object","properties":{"explanation":{"type":"string"},"output":{"type":"string"}},"required":["explanation","output"],"additionalProperties":false}},"final_answer":{"type":"string"}},"required":["steps","final_answer"],"additionalProperties":false}
spring.ai.openai.chat.options.response-format.strict=true

示例控制器(Sample Controller)

创建一个新的 Spring Boot 项目,并将 spring-ai-starter-model-openai 添加到 pom (或 gradle) 依赖项中。

在 src/main/resources 目录下添加 application.properties 文件,以启用和配置 OpenAi 聊天模型:

spring.ai.openai.api-key=YOUR_API_KEY
spring.ai.openai.chat.options.model=gpt-4o
spring.ai.openai.chat.options.temperature=0.7

这将创建一个 OpenAiChatModel 的实现,你可以将其注入到你的类中。下面是一个简单的 @Controller 类的示例,它使用聊天模型进行文本生成。

@RestController
public class ChatController {

    private final OpenAiChatModel chatModel;

    @Autowired
    public ChatController(OpenAiChatModel chatModel) {
        this.chatModel = chatModel;
    }

    /**
     * 文本生成
     * @param message 提示词
     * @return 响应结果
     */
    @GetMapping("/ai/generate")
    @Operation(summary = "文本生成")
    public Map<String, Object> generate(@RequestParam(value = "message", defaultValue = "你好!") String message) {
        try {
            String response = chatModel.call(message);
            return Map.of(
                    "success", true,
                    "generation", response,
                    "message", "Generated successfully"
            );
        } catch (Exception e) {
            return Map.of(
                    "success", false,
                    "error", e.getMessage(),
                    "message", "Generation failed"
            );
        }
    }

    @GetMapping("/ai/generateStream")
    public Flux<ChatResponse> generateStream(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
        Prompt prompt = new Prompt(new UserMessage(message));
        return this.chatModel.stream(prompt);
    }

}

手动配置(Manual Configuration)

OpenAiChatModel 实现了 ChatModel 和 StreamingChatModel, 并使用低级 OpenAiApi 客户端连接 OpenAI 服务。

要启用它,添加 spring-ai-openai 依赖到你的项目 Maven pom.xml 文件:

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-openai</artifactId>
</dependency>

或者,在你的 Gradle 构建文件 build.gradle 中添加:

dependencies {
    implementation 'org.springframework.ai:spring-ai-openai'
}

接下来,创建一个 OpenAiChatModel 实例,并使用它生成文本响应:

 var openAiApi = OpenAiApi.builder()
            .apiKey(System.getenv("OPENAI_API_KEY"))
            .build();
var openAiChatOptions = OpenAiChatOptions.builder()
            .model("gpt-3.5-turbo")
            .temperature(0.4)
            .maxTokens(200)
            .build();
var chatModel = new OpenAiChatModel(this.openAiApi, this.openAiChatOptions);

ChatResponse response = this.chatModel.call(
    new Prompt("Generate the names of 5 famous pirates."));

// Or with streaming responses
Flux<ChatResponse> response = this.chatModel.stream(
    new Prompt("Generate the names of 5 famous pirates."));

轻量级 OpenAiApi 客户端

OpenAiApi 为 OpenAI Chat API 提供了轻量级 Java 客户端

以下类图展示了 OpenAiApi 聊天界面和构建块:

以下是一个简单的代码片段,展示了如何以编程方式使用 API:

OpenAiApi openAiApi = OpenAiApi.builder()
            .apiKey(System.getenv("OPENAI_API_KEY"))
            .build();

ChatCompletionMessage chatCompletionMessage =
    new ChatCompletionMessage("Hello world", Role.USER);

// Sync request
ResponseEntity<ChatCompletion> response = this.openAiApi.chatCompletionEntity(
    new ChatCompletionRequest(List.of(this.chatCompletionMessage), "gpt-3.5-turbo", 0.8, false));

// Streaming request
Flux<ChatCompletionChunk> streamResponse = this.openAiApi.chatCompletionStream(
        new ChatCompletionRequest(List.of(this.chatCompletionMessage), "gpt-3.5-turbo", 0.8, true));
作者:Jeebiz  创建时间:2025-08-03 11:43
最后编辑:Jeebiz  更新时间:2025-08-31 23:07