OpenAI 聊天

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

先决条件

您需要使用 OpenAI 创建一个 API 才能访问 ChatGPT 模型。

OpenAI 注册页面 创建一个帐户,并在 API 密钥页面 生成令牌。

Spring AI 项目定义了一个名为 spring.ai.openai.api-key 的配置属性,您应该将其设置为从 openai.com 获取的 API 密钥 的值。

您可以在 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>

您还可以在应用程序代码中以编程方式设置此配置

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

添加存储库和 BOM

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

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

自动配置

Spring AI 自动配置、启动模块的工件名称发生了重大变化。请参阅 升级说明 以获取更多信息。

Spring AI 为 OpenAI 聊天客户端提供了 Spring Boot 自动配置。要启用它,请将以下依赖项添加到项目的 Maven pom.xml 或 Gradle build.gradle 构建文件中

  • Maven

  • Gradle

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
dependencies {
    implementation 'org.springframework.ai:spring-ai-starter-model-openai'
}
请参阅 依赖项管理 部分,将 Spring AI BOM 添加到您的构建文件中。

聊天属性

重试属性

前缀 spring.ai.retry 用作属性前缀,可让您配置 OpenAI 聊天模型的重试机制。

财产 描述 默认值

spring.ai.retry.max-attempts

最大重试次数。

10

spring.ai.retry.backoff.initial-interval

指数退避策略的初始休眠持续时间。

2 秒。

spring.ai.retry.backoff.multiplier

退避间隔乘数。

5

spring.ai.retry.backoff.max-interval

最大退避持续时间。

3 分钟。

spring.ai.retry.on-client-errors

如果为 false,则抛出 NonTransientAiException,并且不尝试重试 4xx 客户端错误代码

spring.ai.retry.exclude-on-http-codes

不应触发重试的 HTTP 状态代码列表(例如,抛出 NonTransientAiException)。

spring.ai.retry.on-http-codes

应触发重试的 HTTP 状态代码列表(例如,抛出 TransientAiException)。

连接属性

前缀 spring.ai.openai 用作属性前缀,可让您连接到 OpenAI。

财产 描述 默认值

spring.ai.openai.base-url

要连接的 URL

api.openai.com

spring.ai.openai.api-key

API 密钥

-

spring.ai.openai.organization-id

您可以选择指定用于 API 请求的组织。

-

spring.ai.openai.project-id

您可以选择指定用于 API 请求的项目。

-

对于属于多个组织(或通过其旧版用户 API 密钥访问其项目)的用户,您可以选择指定用于 API 请求的组织和项目。这些 API 请求的用量将计入指定组织和项目的用量。

User-Agent 标头

Spring AI 自动向 OpenAI 的所有请求发送 User-Agent: spring-ai 标头。这有助于 OpenAI 识别源自 Spring AI 的请求,用于分析和支持目的。此标头会自动发送,无需 Spring AI 用户进行任何配置。

如果您是 API 提供商,正在构建 OpenAI 兼容服务,您可以通过读取服务器上传入请求的 User-Agent HTTP 标头来跟踪 Spring AI 的使用情况。

配置属性

聊天自动配置的启用和禁用现在通过以spring.ai.model.chat为前缀的顶级属性进行配置。

要启用,请将 spring.ai.model.chat=openai(默认启用)

要禁用,请将 spring.ai.model.chat=none(或任何不匹配 openai 的值)

此更改是为了允许配置多个模型。

前缀 spring.ai.openai.chat 是属性前缀,可让您配置 OpenAI 的聊天模型实现。

财产 描述 默认值

spring.ai.openai.chat.enabled (已移除且不再有效)

启用 OpenAI 聊天模型。

true

spring.ai.model.chat

启用 OpenAI 聊天模型。

openai

spring.ai.openai.chat.base-url

用于 spring.ai.openai.base-url 属性的可选覆盖,以提供特定于聊天的 URL。

-

spring.ai.openai.chat.completions-path

要附加到基本 URL 的路径。

/v1/chat/completions

spring.ai.openai.chat.api-key

用于 spring.ai.openai.api-key 的可选覆盖,以提供特定于聊天的 API 密钥。

-

spring.ai.openai.chat.organization-id

您可以选择指定用于 API 请求的组织。

-

spring.ai.openai.chat.project-id

您可以选择指定用于 API 请求的项目。

-

spring.ai.openai.chat.options.model

要使用的 OpenAI 聊天模型的名称。您可以选择的模型包括:gpt-4ogpt-4o-minigpt-4-turbogpt-3.5-turbo 等。有关更多信息,请参阅 模型 页面。

gpt-4o-mini

spring.ai.openai.chat.options.temperature

用于控制生成完成内容明显创造性的采样温度。较高的值会使输出更随机,而较低的值会使结果更集中和确定性。不建议为同一完成请求同时修改 temperaturetop_p,因为这两个设置的交互作用难以预测。

0.8

spring.ai.openai.chat.options.frequencyPenalty

介于 -2.0 和 2.0 之间的数字。正值根据文本中现有频率对新标记进行惩罚,从而降低模型重复相同行的可能性。

0.0f

spring.ai.openai.chat.options.logitBias

修改指定标记出现在完成内容中的可能性。

-

spring.ai.openai.chat.options.maxTokens

在聊天完成中生成的最大标记数。输入标记和生成标记的总长度受模型上下文长度的限制。用于非推理模型(例如,gpt-4o,gpt-3.5-turbo)。不能用于推理模型(例如,o1,o3,o4-mini 系列)。与 maxCompletionTokens 互斥 - 同时设置两者将导致 API 错误。

-

spring.ai.openai.chat.options.maxCompletionTokens

完成生成标记数的上限,包括可见输出标记和推理标记。推理模型必需(例如,o1,o3,o4-mini 系列)。不能用于非推理模型(例如,gpt-4o,gpt-3.5-turbo)。与 maxTokens 互斥 - 同时设置两者将导致 API 错误。

-

spring.ai.openai.chat.options.n

为每个输入消息生成多少个聊天完成选项。请注意,您将根据所有选项中生成的标记数收费。将 n 保持为 1 以最大程度地降低成本。

1

spring.ai.openai.chat.options.store

是否存储此聊天完成请求的输出以供模型使用

spring.ai.openai.chat.options.metadata

开发人员定义的标签和值,用于在聊天完成仪表板中过滤完成内容

空映射

spring.ai.openai.chat.options.output-modalities

您希望模型为此请求生成的输出类型。大多数模型都能够生成文本,这是默认设置。gpt-4o-audio-preview 模型也可用于生成音频。要请求此模型同时生成文本和音频响应,您可以使用:textaudio。不支持流式传输。

-

spring.ai.openai.chat.options.output-audio

音频生成的音频参数。当 output-modalities 请求音频输出时必需:audio。需要 gpt-4o-audio-preview 模型,并且不支持流式完成。

-

spring.ai.openai.chat.options.presencePenalty

介于 -2.0 和 2.0 之间的数字。正值根据新标记是否出现在文本中对新标记进行惩罚,从而增加模型谈论新主题的可能性。

-

spring.ai.openai.chat.options.responseFormat.type

GPT-4oGPT-4o miniGPT-4 Turbo 以及所有比 gpt-3.5-turbo-1106 更新的 GPT-3.5 Turbo 模型兼容。JSON_OBJECT 类型启用 JSON 模式,它保证模型生成的消息是有效的 JSON。JSON_SCHEMA 类型启用 结构化输出,它保证模型将匹配您提供的 JSON 模式。JSON_SCHEMA 类型还需要设置 responseFormat.schema 属性。

-

spring.ai.openai.chat.options.responseFormat.name

响应格式模式名称。仅适用于 responseFormat.type=JSON_SCHEMA

custom_schema

spring.ai.openai.chat.options.responseFormat.schema

响应格式 JSON 模式。仅适用于 responseFormat.type=JSON_SCHEMA

-

spring.ai.openai.chat.options.responseFormat.strict

响应格式 JSON 模式遵循严格性。仅适用于 responseFormat.type=JSON_SCHEMA

-

spring.ai.openai.chat.options.seed

此功能处于 Beta 阶段。如果指定,我们的系统将尽力确定性地采样,以便使用相同种子和参数的重复请求应返回相同的结果。

-

spring.ai.openai.chat.options.stop

API 将停止生成更多标记的最多 4 个序列。

-

spring.ai.openai.chat.options.topP

一种替代温度采样的核采样方法,其中模型考虑具有 top_p 概率质量的标记结果。因此,0.1 意味着只考虑组成前 10% 概率质量的标记。我们通常建议修改此项或 temperature,但不要同时修改两者。

-

spring.ai.openai.chat.options.tools

模型可以调用的工具列表。目前,仅支持函数作为工具。使用此项提供模型可以为其生成 JSON 输入的函数列表。

-

spring.ai.openai.chat.options.toolChoice

控制模型调用哪个(如果有)函数。none 表示模型不会调用函数,而是生成消息。auto 表示模型可以在生成消息或调用函数之间进行选择。通过 {"type: "function", "function": {"name": "my_function"}} 指定特定函数会强制模型调用该函数。当没有函数时,none 是默认值。如果存在函数,auto 是默认值。

-

spring.ai.openai.chat.options.user

代表您的最终用户的唯一标识符,可以帮助 OpenAI 监控和检测滥用。

-

spring.ai.openai.chat.options.stream-usage

(仅限流式传输)设置为添加一个额外的块,其中包含整个请求的令牌使用统计信息。此块的choices字段是一个空数组,所有其他块也将包含一个 usage 字段,但值为 null。

spring.ai.openai.chat.options.parallel-tool-calls

在使用工具时是否启用 并行函数调用

true

spring.ai.openai.chat.options.prompt-cache-key

OpenAI 用于优化类似请求的缓存命中率的缓存键。提高延迟并降低成本。取代用于缓存目的的已弃用的 user 字段。了解更多

-

spring.ai.openai.chat.options.safety-identifier

一个稳定的标识符,用于帮助 OpenAI 检测违反使用策略的用户。应为哈希值(例如,哈希后的用户名或电子邮件)。取代用于安全跟踪的已弃用的 user 字段。了解更多

-

spring.ai.openai.chat.options.http-headers

要添加到聊天完成请求的可选 HTTP 标头。要覆盖 api-key,您需要使用 Authorization 标头键,并且必须在键值前加上 Bearer 前缀。

-

spring.ai.openai.chat.options.tool-names

工具列表,通过其名称标识,用于在单个提示请求中启用函数调用。具有这些名称的工具必须存在于 ToolCallback 注册表中。

-

spring.ai.openai.chat.options.tool-callbacks

要注册到 ChatModel 的工具回调。

-

spring.ai.openai.chat.options.internal-tool-execution-enabled

如果为 false,Spring AI 将不会在内部处理工具调用,而是将其代理到客户端。然后,客户端负责处理工具调用,将其分派到适当的函数,并返回结果。如果为 true(默认),Spring AI 将在内部处理函数调用。仅适用于支持函数调用的聊天模型

true

spring.ai.openai.chat.options.service-tier

指定用于服务请求的 处理类型

-

spring.ai.openai.chat.options.extra-body

请求中包含的附加参数。接受任何键值对,这些键值对会被展平到 JSON 请求的顶层。旨在与支持标准 OpenAI API 之外参数的 OpenAI 兼容服务器(vLLM、Ollama 等)一起使用。官方 OpenAI API 忽略未知参数。有关详细信息,请参阅 将额外参数与 OpenAI 兼容服务器一起使用

-

使用 GPT-5 模型(如 gpt-5gpt-5-minigpt-5-nano)时,不支持 temperature 参数。这些模型针对推理进行了优化,不使用温度。指定温度值将导致错误。相比之下,像 gpt-5-chat 这样的会话模型支持 temperature 参数。

您可以为 ChatModelEmbeddingModel 实现覆盖通用的 spring.ai.openai.base-urlspring.ai.openai.api-key。如果设置了 spring.ai.openai.chat.base-urlspring.ai.openai.chat.api-key 属性,它们将优先于通用属性。这在您想为不同的模型和不同的模型端点使用不同的 OpenAI 帐户时很有用。
所有以 spring.ai.openai.chat.options 为前缀的属性都可以在运行时通过向 Prompt 调用添加请求特定的 运行时选项 来覆盖。

标记限制参数:模型特定用法

OpenAI 提供了两个互斥的参数来控制标记生成限制

参数 用例 兼容模型

maxTokens

非推理模型

gpt-4o, gpt-4o-mini, gpt-4-turbo, gpt-3.5-turbo

maxCompletionTokens

推理模型

o1, o1-mini, o1-preview, o3, o4-mini 系列

这些参数互斥。同时设置两者将导致 OpenAI API 错误。

使用示例

适用于非推理模型 (gpt-4o, gpt-3.5-turbo)

ChatResponse response = chatModel.call(
    new Prompt(
        "Explain quantum computing in simple terms.",
        OpenAiChatOptions.builder()
            .model("gpt-4o")
            .maxTokens(150)  // Use maxTokens for non-reasoning models
        .build()
    ));

适用于推理模型 (o1, o3 系列)

ChatResponse response = chatModel.call(
    new Prompt(
        "Solve this complex math problem step by step: ...",
        OpenAiChatOptions.builder()
            .model("o1-preview")
            .maxCompletionTokens(1000)  // Use maxCompletionTokens for reasoning models
        .build()
    ));

构建器模式验证: OpenAI ChatOptions 构建器通过“后设者胜”的方法自动强制执行互斥

// This will automatically clear maxTokens and use maxCompletionTokens
OpenAiChatOptions options = OpenAiChatOptions.builder()
    .maxTokens(100)           // Set first
    .maxCompletionTokens(200) // This clears maxTokens and logs a warning
    .build();

// Result: maxTokens = null, maxCompletionTokens = 200

运行时选项

OpenAiChatOptions.java 类提供了模型配置,例如要使用的模型、温度、频率惩罚等。

启动时,可以使用 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("gpt-4o")
            .temperature(0.4)
        .build()
    ));
除了模型特定的 OpenAiChatOptions,您还可以使用可移植的 ChatOptions 实例,该实例使用 ChatOptions#builder() 创建。

函数调用

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

多模态

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

视觉

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

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

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

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

var userMessage = new UserMessage("Explain what do you see on this picture?",
        new Media(MimeTypeUtils.IMAGE_PNG, this.imageResource));

ChatResponse response = chatModel.call(new Prompt(this.userMessage,
        OpenAiChatOptions.builder().model(OpenAiApi.ChatModel.GPT_4_O.getValue()).build()));
从 2024 年 6 月 17 日起,GPT_4_VISION_PREVIEW 将仅适用于此模型的现有用户。如果您不是现有用户,请使用 GPT_4_O 或 GPT_4_TURBO 模型。更多详情请参阅 此处

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

var userMessage = new UserMessage("Explain what do you see on this picture?",
        new Media(MimeTypeUtils.IMAGE_PNG,
                URI.create("https://docs.springjava.cn/spring-ai/reference/_images/multimodal.test.png")));

ChatResponse response = chatModel.call(new Prompt(this.userMessage,
        OpenAiChatOptions.builder().model(OpenAiApi.ChatModel.GPT_4_O.getValue()).build()));
您也可以传递多张图片。

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

Multimodal Test Image

以及文本消息“解释你在这张图片上看到了什么?”,并生成如下响应

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.

音频

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

OpenAI 用户消息 API 可以将 base64 编码的音频文件列表与消息一起合并。Spring AI 的 消息 接口通过引入 媒体 类型来促进多模态 AI 模型。此类型包含有关消息中媒体附件的数据和详细信息,利用 Spring 的 org.springframework.util.MimeType 和用于原始媒体数据的 org.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()));
您也可以传递多个音频文件。

输出音频

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

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

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

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

您必须在 OpenAiChatOptions 中指定 audio 模态才能生成音频输出。AudioParameters 类提供了音频输出的语音和音频格式。

结构化输出

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

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

配置

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);
遵循 OpenAI JSON Schema 语言子集 格式。

与 BeanOutputConverter 工具集成

您可以利用现有的 BeanOutputConverter 工具,自动从您的领域对象生成 JSON Schema,然后将结构化响应转换为领域特定的实例

  • Java

  • Kotlin

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);
data class MathReasoning(
	val steps: Steps,
	@get:JsonProperty(value = "final_answer") val finalAnswer: String) {

	data class Steps(val items: Array<Items>) {

		data class Items(
			val explanation: String,
			val output: String)
	}
}

val outputConverter = BeanOutputConverter(MathReasoning::class.java)

val jsonSchema = outputConverter.jsonSchema;

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

val response = openAiChatModel.call(prompt)
val content = response.getResult().getOutput().getContent()

val mathReasoning = outputConverter.convert(content)
尽管对于 JSON Schema 来说这是可选的,但 OpenAI 强制要求 结构化响应的必需字段才能正常工作。Kotlin 反射用于根据类型的可空性和参数的默认值推断哪些属性是必需的,哪些不是,因此对于大多数用例,不需要 @get:JsonProperty(required = true)@get:JsonProperty(value = "custom_name") 可以用于自定义属性名称。请确保使用此 @get: 语法在相关的 getter 上生成注释,请参阅 相关文档

通过应用程序属性配置

或者,在使用 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

示例控制器

创建 一个新的 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
用您的 OpenAI 凭据替换 api-key

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

@RestController
public class ChatController {

    private final OpenAiChatModel chatModel;

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

    @GetMapping("/ai/generate")
    public Map<String,String> generate(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
        return Map.of("generation", this.chatModel.call(message));
    }

    @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);
    }
}

手动配置

OpenAiChatModel 实现了 ChatModelStreamingChatModel,并使用 低级 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'
}
请参阅 依赖项管理 部分,将 Spring AI BOM 添加到您的构建文件中。

接下来,创建一个 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."));

OpenAiChatOptions 提供聊天请求的配置信息。OpenAiApi.BuilderOpenAiChatOptions.Builder 分别是用于 API 客户端和聊天配置的流畅选项构建器。

低级 OpenAiApi 客户端

OpenAiApi 为 OpenAI 聊天 API OpenAI 聊天 API 提供了轻量级 Java 客户端。

以下类图说明了 OpenAiApi 聊天接口和构建块

OpenAiApi Chat API Diagram

以下是一个简单的代码片段,展示了如何以编程方式使用 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));

请查阅 OpenAiApi.java 的 JavaDoc 以获取更多信息。

低级 API 示例

低级 OpenAiFileApi 客户端

OpenAiFileApi 为 OpenAI 文件 API 提供了轻量级 Java 客户端,支持文件管理操作,例如上传、列出、检索、删除文件以及访问文件内容。OpenAI 文件 API

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

OpenAiFileApi openAiFileApi = OpenAiFileApi.builder()
			.apiKey(new SimpleApiKey(System.getenv("OPENAI_API_KEY")))
			.build();

// Upload a file
byte[] fileBytes = Files.readAllBytes(Paths.get("evals.jsonl"));
OpenAiFileApi.UploadFileRequest uploadRequest = OpenAiFileApi.UploadFileRequest.builder()
			.file(fileBytes)
			.fileName("evals-data.jsonl")
			.purpose(OpenAiFileApi.Purpose.EVALS)
			.build();
ResponseEntity<OpenAiFileApi.FileObject> uploadResponse = openAiFileApi.uploadFile(uploadRequest);

// List files
OpenAiFileApi.ListFileRequest listRequest = OpenAiFileApi.ListFileRequest.builder()
			.purpose(OpenAiFileApi.Purpose.EVALS)
			.build();
ResponseEntity<OpenAiFileApi.FileObjectResponse> listResponse = openAiFileApi.listFiles(listRequest);

// Retrieve file information
ResponseEntity<OpenAiFileApi.FileObject> fileInfo = openAiFileApi.retrieveFile("file-id");

// Delete a file
ResponseEntity<OpenAiFileApi.DeleteFileResponse> deleteResponse = openAiFileApi.deleteFile("file-id");

// Retrieve file content
ResponseEntity<String> fileContent = openAiFileApi.retrieveFileContent("file-id");

低级文件 API 示例

API 密钥管理

Spring AI 通过 ApiKey 接口及其实现提供灵活的 API 密钥管理。默认实现 SimpleApiKey 适用于大多数用例,但您也可以为更复杂的场景创建自定义实现。

默认配置

默认情况下,Spring Boot 自动配置将使用 spring.ai.openai.api-key 属性创建 API 密钥 bean

spring.ai.openai.api-key=your-api-key-here

自定义 API 密钥配置

您可以使用构建器模式创建具有自己的 ApiKey 实现的 OpenAiApi 自定义实例

ApiKey customApiKey = new ApiKey() {
    @Override
    public String getValue() {
        // Custom logic to retrieve API key
        return "your-api-key-here";
    }
};

OpenAiApi openAiApi = OpenAiApi.builder()
    .apiKey(customApiKey)
    .build();

// Create a chat model with the custom OpenAiApi instance
OpenAiChatModel chatModel = OpenAiChatModel.builder()
    .openAiApi(openAiApi)
    .build();
// Build the ChatClient using the custom chat model
ChatClient openAiChatClient = ChatClient.builder(chatModel).build();

这在您需要以下情况时很有用

  • 从安全密钥存储中检索 API 密钥

  • 动态轮换 API 密钥

  • 实现自定义 API 密钥选择逻辑

与 OpenAI 兼容服务器一起使用额外参数

vLLM、Ollama 等与 OpenAI 兼容的推理服务器通常支持 OpenAI 标准 API 中定义之外的附加参数。例如,这些服务器可能接受 top_krepetition_penalty 或其他官方 OpenAI API 不识别的采样控制参数。

extraBody 选项允许您将任意参数传递给这些服务器。extraBody 中提供的任何键值对都包含在 JSON 请求的顶层,使您能够在使用 Spring AI 的 OpenAI 客户端时利用服务器特定功能。

extraBody 参数旨在与 OpenAI 兼容服务器一起使用,而不是官方 OpenAI API。虽然官方 OpenAI API 将忽略未知参数,但它们在那里没有用处。始终查阅您的特定服务器文档以确定支持哪些参数。

使用属性进行配置

您可以使用 Spring Boot 属性配置额外参数。spring.ai.openai.chat.options.extra-body 下的每个属性都成为请求中的顶级参数

spring.ai.openai.base-url=https://:8000/v1
spring.ai.openai.chat.options.model=meta-llama/Llama-3-8B-Instruct
spring.ai.openai.chat.options.temperature=0.7
spring.ai.openai.chat.options.extra-body.top_k=50
spring.ai.openai.chat.options.extra-body.repetition_penalty=1.1

此配置将生成类似以下的 JSON 请求

{
  "model": "meta-llama/Llama-3-8B-Instruct",
  "temperature": 0.7,
  "top_k": 50,
  "repetition_penalty": 1.1,
  "messages": [...]
}

使用构建器进行运行时配置

您还可以使用选项构建器在运行时指定额外参数

ChatResponse response = chatModel.call(
    new Prompt(
        "Tell me a creative story",
        OpenAiChatOptions.builder()
            .model("meta-llama/Llama-3-8B-Instruct")
            .temperature(0.7)
            .extraBody(Map.of(
                "top_k", 50,
                "repetition_penalty", 1.1,
                "frequency_penalty", 0.5
            ))
            .build()
    ));

示例:vLLM 服务器

使用 Llama 模型运行 vLLM 时,您可能希望使用 vLLM 特定的采样参数

spring.ai.openai.base-url=https://:8000/v1
spring.ai.openai.chat.options.model=meta-llama/Llama-3-70B-Instruct
spring.ai.openai.chat.options.extra-body.top_k=40
spring.ai.openai.chat.options.extra-body.top_p=0.95
spring.ai.openai.chat.options.extra-body.repetition_penalty=1.05
spring.ai.openai.chat.options.extra-body.min_p=0.05

请参阅 vLLM 文档 以获取支持的采样参数的完整列表。

示例:Ollama 服务器

通过 OpenAI 兼容端点使用 Ollama 时,您可以传递 Ollama 特定参数

OpenAiChatOptions options = OpenAiChatOptions.builder()
    .model("llama3.2")
    .extraBody(Map.of(
        "num_predict", 100,
        "top_k", 40,
        "repeat_penalty", 1.1
    ))
    .build();

ChatResponse response = chatModel.call(new Prompt("Generate text", options));

查阅 Ollama API 文档 以获取可用参数。

extraBody 参数接受任何 Map<String, Object>,允许您传递目标服务器支持的任何参数。Spring AI 不会验证这些参数——它们会直接传递给服务器。这种设计为与各种 OpenAI 兼容实现协作提供了最大的灵活性。

推理模型中的推理内容

一些支持推理模型(如 DeepSeek R1、带推理解析器的 vLLM)的 OpenAI 兼容服务器通过其 API 响应中的 reasoning_content 字段暴露模型的内部思维链。此字段包含模型得出最终答案所使用的逐步推理过程。

Spring AI 将 JSON 响应中的此字段映射到 AssistantMessage 元数据中的 reasoningContent 键。

关于 reasoning_content 可用性的重要区别

  • OpenAI 兼容服务器 (DeepSeek, vLLM):在聊天完成 API 响应中暴露 reasoning_content

  • 官方 OpenAI 模型 (GPT-5, o1, o3):在聊天完成 API 响应中暴露推理文本 ❌

官方 OpenAI 推理模型在使用聊天完成 API 时会隐藏思维链内容。它们仅在用量统计中暴露 reasoning_tokens 计数。要从官方 OpenAI 模型访问实际推理文本,您必须使用 OpenAI 的响应 API(此客户端目前不支持的单独端点)。

回退行为: 当服务器未提供 reasoning_content 时(例如,官方 OpenAI 聊天完成),reasoningContent 元数据字段将为空字符串。

访问推理内容

使用兼容服务器时,您可以从响应元数据中访问推理内容。

直接使用 ChatModel

// Configure to use DeepSeek R1 or vLLM with a reasoning model
ChatResponse response = chatModel.call(
    new Prompt("Which number is larger: 9.11 or 9.8?")
);

// Get the assistant message
AssistantMessage message = response.getResult().getOutput();

// Access the reasoning content from metadata
String reasoning = message.getMetadata().get("reasoningContent");
if (reasoning != null && !reasoning.isEmpty()) {
    System.out.println("Model's reasoning process:");
    System.out.println(reasoning);
}

// The final answer is in the regular content
System.out.println("\nFinal answer:");
System.out.println(message.getContent());

使用 ChatClient

ChatClient chatClient = ChatClient.create(chatModel);

String result = chatClient.prompt()
    .user("Which number is larger: 9.11 or 9.8?")
    .call()
    .chatResponse()
    .getResult()
    .getOutput()
    .getContent();

// To access reasoning content with ChatClient, retrieve the full response
ChatResponse response = chatClient.prompt()
    .user("Which number is larger: 9.11 or 9.8?")
    .call()
    .chatResponse();

AssistantMessage message = response.getResult().getOutput();
String reasoning = message.getMetadata().get("reasoningContent");

流式传输推理内容

使用流式响应时,推理内容会像常规消息内容一样跨块累积

Flux<ChatResponse> responseFlux = chatModel.stream(
    new Prompt("Solve this logic puzzle...")
);

StringBuilder reasoning = new StringBuilder();
StringBuilder answer = new StringBuilder();

responseFlux.subscribe(chunk -> {
    AssistantMessage message = chunk.getResult().getOutput();

    // Accumulate reasoning if present
    String reasoningChunk = message.getMetadata().get("reasoningContent");
    if (reasoningChunk != null) {
        reasoning.append(reasoningChunk);
    }

    // Accumulate the final answer
    if (message.getContent() != null) {
        answer.append(message.getContent());
    }
});

示例:DeepSeek R1

DeepSeek R1 是一种推理模型,它暴露其内部推理过程

spring.ai.openai.api-key=${DEEPSEEK_API_KEY}
spring.ai.openai.base-url=https://api.deepseek.com
spring.ai.openai.chat.options.model=deepseek-reasoner

当您向 DeepSeek R1 发出请求时,响应将包括推理内容(模型的思维过程)和最终答案。

有关推理模型的更多详细信息,请参阅 DeepSeek API 文档

示例:带有推理解析器的 vLLM

vLLM 在配置推理解析器时支持推理模型

vllm serve deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B \
    --enable-reasoning \
    --reasoning-parser deepseek_r1
spring.ai.openai.base-url=https://:8000/v1
spring.ai.openai.chat.options.model=deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B

请参阅 vLLM 推理输出文档 以获取支持的推理模型和解析器。

reasoning_content 的可用性完全取决于您使用的推理服务器。并非所有与 OpenAI 兼容的服务器都暴露推理内容,即使在使用支持推理的模型时也是如此。请始终参阅您的服务器的 API 文档,以了解响应中可用的字段。

© . This site is unofficial and not affiliated with VMware.