OpenAI 聊天

Spring AI 支持来自 OpenAI 的各种 AI 语言模型,OpenAI 是 ChatGPT 背后的公司,该公司通过创建行业领先的文本生成模型和嵌入,在激发 AI 驱动文本生成的兴趣方面发挥了关键作用。spring-doc.cadn.net.cn

前提条件

你需要用OpenAI创建一个API来访问ChatGPT模型。spring-doc.cadn.net.cn

OpenAI注册页面创建账户,并在API密钥页面生成Tokens。spring-doc.cadn.net.cn

Spring AI 项目定义了一个配置属性,名为spring.ai.openai.api-key(春.ai.openai.api-key)你应该设置为API 密钥资料来源 openai.com。spring-doc.cadn.net.cn

你可以在你的application.properties文件:spring-doc.cadn.net.cn

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

为了在处理敏感信息如 API 密钥时增强安全性,您可以使用 Spring 表达式语言(SpEL)引用自定义环境变量:spring-doc.cadn.net.cn

# 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>

你也可以在应用代码中编程设置此配置:spring-doc.cadn.net.cn

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

添加仓库和物料清单

Spring AI 产物发布于 Maven Central 和 Spring Snapshot 仓库中。 请参阅神器仓库部分,将这些仓库添加到你的构建系统中。spring-doc.cadn.net.cn

为帮助依赖管理,Spring AI 提供了物料清单(BOM),确保整个项目中使用一致版本的 Spring AI。请参考依赖管理部分,将春季AI物料清单添加到你的构建系统中。spring-doc.cadn.net.cn

自动配置

春季AI自动配置、起始模块的工件名称发生了重大变化。 更多信息请参阅升级说明spring-doc.cadn.net.cn

Spring AI 为 OpenAI 聊天客户端提供 Spring Boot 自动配置。 要启用它,请在项目的Maven中添加以下依赖pom.xml或者Gradlebuild.gradle构建文件:spring-doc.cadn.net.cn

<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的物料清单添加到你的构建文件中。

聊天属性

重试属性

前缀spring.ai.retry作为属性前缀,用于配置OpenAI聊天模型的重试机制。spring-doc.cadn.net.cn

属性 描述 默认值

spring.ai.retry.max尝试spring-doc.cadn.net.cn

重试次数上限。spring-doc.cadn.net.cn

10spring-doc.cadn.net.cn

spring.ai.retry.backoff.initial-intervalspring-doc.cadn.net.cn

指数式退避政策的初始睡眠时长。spring-doc.cadn.net.cn

两秒钟。spring-doc.cadn.net.cn

spring.ai.retry.backoff.multiplierspring-doc.cadn.net.cn

后退间隔倍数。spring-doc.cadn.net.cn

5spring-doc.cadn.net.cn

spring.ai.retry.backoff.max区间spring-doc.cadn.net.cn

最大退回时间。spring-doc.cadn.net.cn

3分钟。spring-doc.cadn.net.cn

spring.ai.retry.on-client-errorsspring-doc.cadn.net.cn

如果为假,抛出非瞬态AiException,且不要尝试重试4xx客户端错误代码spring-doc.cadn.net.cn

falsespring-doc.cadn.net.cn

spring.ai.retry.exclude-on-http-codesspring-doc.cadn.net.cn

不应该触发重试的HTTP状态码列表(例如抛出非瞬态Ai异常)。spring-doc.cadn.net.cn

emptyspring-doc.cadn.net.cn

spring.ai.retry.on-http-codesspring-doc.cadn.net.cn

应触发重试的HTTP状态码列表(例如抛出TransientAiException)。spring-doc.cadn.net.cn

emptyspring-doc.cadn.net.cn

连接性质

前缀春.ai.openai作为属性前缀,允许你连接到OpenAI。spring-doc.cadn.net.cn

属性 描述 默认值

Spring.ai.openai.base-urlspring-doc.cadn.net.cn

连接的URL(链接)spring-doc.cadn.net.cn

api.openai.comspring-doc.cadn.net.cn

spring.ai.openai.api-key(春.ai.openai.api-key)spring-doc.cadn.net.cn

API 密钥spring-doc.cadn.net.cn

-spring-doc.cadn.net.cn

spring.ai.openai.organization-idspring-doc.cadn.net.cn

可选地,你可以指定使用哪个组织来执行 API 请求。spring-doc.cadn.net.cn

-spring-doc.cadn.net.cn

spring.ai.openai.project-idspring-doc.cadn.net.cn

可选地,你可以指定用于 API 请求的项目。spring-doc.cadn.net.cn

-spring-doc.cadn.net.cn

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

用户代理头

Spring AI 会自动发送用户代理:spring-ai包含所有发送给 OpenAI 的请求的头部。这帮助 OpenAI 识别来自 Spring AI 的请求,用于分析和支持。该头部自动发送,无需 Spring AI 用户进行配置。spring-doc.cadn.net.cn

如果你是构建兼容OpenAI服务的API提供商,可以通过阅读用户代理来自服务器上收到的请求的HTTP头。spring-doc.cadn.net.cn

配置属性

现在,启用和禁用聊天自动配置通过带有前缀的顶层属性进行配置spring.ai.model.chat.spring-doc.cadn.net.cn

启用时,spring.ai.model.chat=openai(默认启用)spring-doc.cadn.net.cn

要禁用,可以选择 spring.ai.model.chat=none(或任何与 openai 不匹配的值)spring-doc.cadn.net.cn

此改动旨在允许配置多个模型。spring-doc.cadn.net.cn

前缀spring.ai.openai.chat是允许您配置OpenAI聊天模型实现的属性前缀。spring-doc.cadn.net.cn

属性 描述 默认值

spring.ai.openai.chat.enabled(已移除且不再有效)spring-doc.cadn.net.cn

启用OpenAI聊天模型。spring-doc.cadn.net.cn

truespring-doc.cadn.net.cn

spring.ai.model.chatspring-doc.cadn.net.cn

启用OpenAI聊天模型。spring-doc.cadn.net.cn

OpenAIspring-doc.cadn.net.cn

spring.ai.openai.chat.base-urlspring-doc.cadn.net.cn

可选覆盖Spring.ai.openai.base-url属性以提供聊天专用的URL。spring-doc.cadn.net.cn

-spring-doc.cadn.net.cn

spring.ai.openai.chat.completions-pathspring-doc.cadn.net.cn

附加到基础URL的路径。spring-doc.cadn.net.cn

/v1/聊天/完成spring-doc.cadn.net.cn

spring.ai.openai.chat.api-key。spring-doc.cadn.net.cn

可选覆盖spring.ai.openai.api-key(春.ai.openai.api-key)提供一个针对聊天的 API 密钥。spring-doc.cadn.net.cn

-spring-doc.cadn.net.cn

spring.ai.openai.chat.organization-idspring-doc.cadn.net.cn

可选地,你可以指定使用哪个组织来执行 API 请求。spring-doc.cadn.net.cn

-spring-doc.cadn.net.cn

spring.ai.openai.chat.project-idspring-doc.cadn.net.cn

可选地,你可以指定用于 API 请求的项目。spring-doc.cadn.net.cn

-spring-doc.cadn.net.cn

spring.ai.openai.chat.options.modelspring-doc.cadn.net.cn

OpenAI聊天模型的名称。你可以选择以下模型:GPT-4O,GPT-40-迷你,GPT-4涡轮,GPT-3.5涡轮增压,以及更多内容。更多信息请参见模型页面。spring-doc.cadn.net.cn

GPT-40-迷你spring-doc.cadn.net.cn

spring.ai.openai.chat.options.temperature.spring-doc.cadn.net.cn

采样温度控制生成完备的显微创造性。取样温度越高,输出越随机,越低,结果越聚焦且确定性强。不建议修改温度top_p对于相同的完备请求,这两个设置的相互作用很难预测。spring-doc.cadn.net.cn

0.8spring-doc.cadn.net.cn

spring.ai.openai.chat.options.frequency 惩罚spring-doc.cadn.net.cn

数字介于-2.0到2.0之间。正值会根据新标记在文本中已有的频率进行惩罚,降低模型逐字重复同一行的可能性。spring-doc.cadn.net.cn

0.0fspring-doc.cadn.net.cn

spring.ai.openai.chat.options.logit偏见spring-doc.cadn.net.cn

修改完成中出现指定标记的可能性。spring-doc.cadn.net.cn

-spring-doc.cadn.net.cn

spring.ai.openai.chat.options.maxTokensspring-doc.cadn.net.cn

聊天补全时最多可生成的Tokens数。输入标记和生成标记的总长度受模型上下文长度限制。用于非推理模型(例如,GPT-40,GPT-3.5-turbo)。不能与推理模型(例如 o1、o3、o4-mini 系列)一起使用。与 maxCompletionTokens 互斥——同时设置两者都会导致 API 错误。spring-doc.cadn.net.cn

-spring-doc.cadn.net.cn

spring.ai.openai.chat.options.maxCompletionTokensspring-doc.cadn.net.cn

完成化可生成的Tokens数量的上限,包括可见的输出Tokens和推理Tokens。推理模型(例如 o1、o3、o4-mini 系列)必备。不能用于非推理模型(例如 gpt-4o、gpt-3.5-turbo)。与 maxTokens 互斥——同时设置两者都会导致 API 错误。spring-doc.cadn.net.cn

-spring-doc.cadn.net.cn

spring.ai.openai.chat.options.nspring-doc.cadn.net.cn

每个输入消息需要生成多少聊天补全选项。请注意,你将根据所有选项中生成的Tokens数量收费。保持n作为1,以降低成本。spring-doc.cadn.net.cn

1spring-doc.cadn.net.cn

spring.ai.openai.chat.options.storespring-doc.cadn.net.cn

是否将该聊天补全请求的输出存储在我们的模型中使用spring-doc.cadn.net.cn

falsespring-doc.cadn.net.cn

spring.ai.openai.chat.options.metadataspring-doc.cadn.net.cn

开发者自定义的标签和值,用于在聊天补全仪表盘中过滤完成内容spring-doc.cadn.net.cn

空映射spring-doc.cadn.net.cn

spring.ai.openai.chat.options.output-modalitiesspring-doc.cadn.net.cn

你希望模型为本次请求生成的输出类型。大多数模型都能生成文本,这是默认的。 这GPT-4O-音频预览模型也可以用于生成音频。为了请求该模型同时生成文本和音频响应, 你可以使用:文本,音频.不支持流媒体播放。spring-doc.cadn.net.cn

-spring-doc.cadn.net.cn

spring.ai.openai.chat.options.output-audiospring-doc.cadn.net.cn

音频生成的音频参数。当音频输出被要求时,必须通过输出模态:音频. 需要GPT-4O-音频预览模型和 is 不支持流式补全。spring-doc.cadn.net.cn

-spring-doc.cadn.net.cn

spring.ai.openai.chat.options.presence惩罚spring-doc.cadn.net.cn

数字介于-2.0到2.0之间。正值会根据新Tokens是否出现在文本中来惩罚它们,从而提高模型讨论新话题的可能性。spring-doc.cadn.net.cn

-spring-doc.cadn.net.cn

spring.ai.openai.chat.options.responseFormat.typespring-doc.cadn.net.cn

兼容于GPT-4o,GPT-4o 迷你版,GPT-4 涡轮以及所有GPT-3.5 涡轮GPT-3.5-涡轮-1106.这JSON_OBJECT类型启用 JSON 模式,保证模型生成的消息是有效的 JSON。 这JSON_SCHEMA类型支持结构化输出,保证模型与你提供的JSON模式匹配。JSON_SCHEMA类型需要设置responseFormat.schema财产也一样。spring-doc.cadn.net.cn

-spring-doc.cadn.net.cn

spring.ai.openai.chat.options.responseFormat.namespring-doc.cadn.net.cn

响应格式模式名称。仅适用于responseFormat.type=JSON_SCHEMAspring-doc.cadn.net.cn

custom_schemaspring-doc.cadn.net.cn

spring.ai.openai.chat.options.responseFormat.schemaspring-doc.cadn.net.cn

响应格式 JSON 模式。仅适用于responseFormat.type=JSON_SCHEMAspring-doc.cadn.net.cn

-spring-doc.cadn.net.cn

spring.ai.openai.chat.options.responseFormat.strictspring-doc.cadn.net.cn

响应格式 JSON schema 遵循严格性。仅适用于responseFormat.type=JSON_SCHEMAspring-doc.cadn.net.cn

-spring-doc.cadn.net.cn

spring.ai.openai.chat.options.seedspring-doc.cadn.net.cn

此功能目前处于测试阶段。如果有明确规定,我们的系统会尽最大努力以确定性方式采样,使得用相同的种子和参数重复请求应返回相同的结果。spring-doc.cadn.net.cn

-spring-doc.cadn.net.cn

spring.ai.openai.chat.options.stopspring-doc.cadn.net.cn

最多有4个序列,API会停止生成更多Tokens。spring-doc.cadn.net.cn

-spring-doc.cadn.net.cn

spring.ai.openai.chat.options.topPspring-doc.cadn.net.cn

一种与温度抽样不同的替代方案,称为核抽样,模型考虑符号的结果,满足top_p概率质量。因此,0.1 意味着只考虑构成概率质量最高 10% 的Tokens。我们通常建议更改这些或温度但不能两者兼有。spring-doc.cadn.net.cn

-spring-doc.cadn.net.cn

spring.ai.openai.chat.options.toolsspring-doc.cadn.net.cn

模型可能调用的工具列表。目前,仅支持函数作为工具。利用该列表提供模型可能生成 JSON 输入的函数列表。spring-doc.cadn.net.cn

-spring-doc.cadn.net.cn

spring.ai.openai.chat.options.toolChoicespring-doc.cadn.net.cn

控制模型调用的函数(如果有的话)。没有意味着模型不会调用函数,而是生成消息。自动意味着模型可以在生成消息或调用函数之间选择。通过指定特定函数{“类型:”函数“, ”函数“: {”name“: ”my_function“}}强制模型调用该函数。没有当没有函数存在时,是默认的。自动如果函数存在,则是默认的。spring-doc.cadn.net.cn

-spring-doc.cadn.net.cn

spring.ai.openai.chat.options.userspring-doc.cadn.net.cn

一个代表终端用户的唯一标识符,可以帮助OpenAI监控和检测滥用行为。spring-doc.cadn.net.cn

-spring-doc.cadn.net.cn

spring.ai.openai.chat.options.stream-usagespring-doc.cadn.net.cn

(仅限流媒体播放)设置为为整个请求添加一个额外的块,包含Tokens使用统计数据。这选择该块的字段是空数组,其他块也会包含使用字段,但为空值。spring-doc.cadn.net.cn

falsespring-doc.cadn.net.cn

spring.ai.openai.chat.options.parallel-tool-callsspring-doc.cadn.net.cn

是否在工具使用时启用并行函数调用spring-doc.cadn.net.cn

truespring-doc.cadn.net.cn

spring.ai.openai.chat.options.prompt-cache-keyspring-doc.cadn.net.cn

OpenAI用于优化类似请求缓存命中率的缓存密钥。提升延迟并降低成本。取代已弃用的用户用于缓存的字段。了解更多spring-doc.cadn.net.cn

-spring-doc.cadn.net.cn

spring.ai.openai.chat.options.safety-identifierspring-doc.cadn.net.cn

一个稳定的标识符,帮助OpenAI检测违反使用政策的用户。应该是哈希值(例如哈希用户名或邮箱)。取代已弃用的用户用于安全追踪的场地。了解更多spring-doc.cadn.net.cn

-spring-doc.cadn.net.cn

spring.ai.openai.chat.options.http-headersspring-doc.cadn.net.cn

在聊天补全请求中添加可选的HTTP头。以覆盖API密钥你需要用一个授权你必须在键值前加上承载前缀。spring-doc.cadn.net.cn

-spring-doc.cadn.net.cn

spring.ai.openai.chat.options.tool-namesspring-doc.cadn.net.cn

列出了工具,按名称标识,用于在一次提示请求中实现函数调用。带有这些名称的工具必须存在于 ToolCallback 注册表中。spring-doc.cadn.net.cn

-spring-doc.cadn.net.cn

spring.ai.openai.chat.options.tool-callbacksspring-doc.cadn.net.cn

工具回调以注册到聊天模型。spring-doc.cadn.net.cn

-spring-doc.cadn.net.cn

spring.ai.openai.chat.options.internal-tool-execution-enabledspring-doc.cadn.net.cn

如果错误,Spring AI不会内部处理工具调用,而是代理给客户端。然后由客户端负责处理工具调用,将其派遣到相应函数,并返回结果。如果为真(默认),Spring AI会在内部处理函数调用。仅适用于支持函数调用的聊天模型spring-doc.cadn.net.cn

truespring-doc.cadn.net.cn

spring.ai.openai.chat.options.service-tierspring-doc.cadn.net.cn

指定用于发送请求的处理类型spring-doc.cadn.net.cn

-spring-doc.cadn.net.cn

spring.ai.openai.chat.options.extra-bodyspring-doc.cadn.net.cn

请求中需要包含的额外参数。接受任何被平放到JSON请求顶层的键值对。旨在用于支持标准 OpenAI API 参数的兼容 OpenAI 服务器(vLLM、Ollama 等)。官方 OpenAI API 忽略未知参数。详情请参见“在 OpenAI 兼容服务器中使用额外参数”。spring-doc.cadn.net.cn

-spring-doc.cadn.net.cn

当使用如GPT-5,GPT-5-迷你GPT-5-纳诺温度参数不支持。 这些模型优化为推理,不使用温度。 指定温度值会导致错误。 相比之下,像这样的对话模型GPT-5-聊天请支持该项目温度参数。spring-doc.cadn.net.cn

你可以覆盖公共信息Spring.ai.openai.base-urlspring.ai.openai.api-key(春.ai.openai.api-key)对于聊天模型嵌入模型实现。 这spring.ai.openai.chat.base-urlspring.ai.openai.chat.api-key。如果属性被设置,则优先于共同属性。 如果你想为不同模型和不同模型端点使用不同的OpenAI账户,这非常有用。
所有以spring.ai.openai.chat.options。可以通过在运行时为 Run 添加请求特定的运行时选项来覆盖提示叫。

Tokens限制参数:特定型号使用情况

OpenAI 提供了两个互斥的参数来控制Tokens生成限制:spring-doc.cadn.net.cn

参数 用例 兼容型号

maxTokensspring-doc.cadn.net.cn

非推理模型spring-doc.cadn.net.cn

GPT-4O、GPT-4O-迷你、GPT-4-涡轮、GPT-3.5-涡轮spring-doc.cadn.net.cn

maxCompletionTokensspring-doc.cadn.net.cn

推理模型spring-doc.cadn.net.cn

O1、O1-mini、O1-预览、O3、O4-Mini系列spring-doc.cadn.net.cn

这两个参数是互斥的。同时设置这两个都会触发OpenAI的API错误。

使用示例

对于非推理模型(GPT-40,GPT-3.5-turbo):spring-doc.cadn.net.cn

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系列):spring-doc.cadn.net.cn

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 聊天选项构建器自动通过“最后一盘获胜”方式强制互斥性:spring-doc.cadn.net.cn

// 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类提供模型配置,如所用模型、温度、频率惩罚等。spring-doc.cadn.net.cn

启动时,默认选项可以配置为OpenAiChatModel(api, options)构造者或spring.ai.openai.chat.options.*性能。spring-doc.cadn.net.cn

运行时,您可以通过添加新的、针对特定请求的选项来覆盖默认选项提示叫。 例如,要覆盖特定请求的默认型号和温度:spring-doc.cadn.net.cn

ChatResponse response = chatModel.call(
    new Prompt(
        "Generate the names of 5 famous pirates.",
        OpenAiChatOptions.builder()
            .model("gpt-4o")
            .temperature(0.4)
        .build()
    ));
除了模型特定的OpenAiChatOptions,你还可以使用用ChatOptions#builder()创建的可移动ChatOptions实例。

函数调用

你可以用OpenAiChatModel并让OpenAI模型智能地选择输出包含参数的JSON对象,以调用一个或多个注册函数。 这是一种强大的技术,将LLM功能与外部工具和API连接起来。 阅读更多关于工具调用的信息。spring-doc.cadn.net.cn

模 态

多模态指的是模型能够同时理解和处理来自多种来源的信息,包括文本、图像、音频及其他数据格式。 OpenAI 支持文本、视觉和音频输入模式。spring-doc.cadn.net.cn

视觉

提供视觉多模态支持的OpenAI模型包括GPT-4,GPT-4OGPT-40-迷你. 更多信息请参阅《愿景指南》。spring-doc.cadn.net.cn

OpenAI 用户消息 API 可以与消息一起包含 base64 编码的图片或图片 URL 列表。 Spring AI 的 Message 界面通过引入媒体类型,促进了多模态 AI 模型的发展。 这种类型包含了关于消息中媒体附件的数据和详细信息,利用Spring的org.springframework.util.MimeType以及一个org.springframework.core.io.Resource对于原始媒体数据。spring-doc.cadn.net.cn

以下是摘自OpenAiChatModelIT.java的代码示例,展示了用户文本与图像的融合过程,使用GPT-4O型。spring-doc.cadn.net.cn

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()));
GPT_4_VISION_PREVIEW自2024年6月17日起将继续仅对现有该型号用户开放。如果您不是现有用户,请使用GPT_4_O或GPT_4_TURBO型号。更多细节请见此处

或使用图片URL的对应GPT-4O型:spring-doc.cadn.net.cn

var userMessage = new UserMessage("Explain what do you see on this picture?",
        new Media(MimeTypeUtils.IMAGE_PNG,
                URI.create("https://docs.spring.io/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图像:spring-doc.cadn.net.cn

多模态测试图像

并附上短信“请解释你在这张图片上看到了什么?”,并生成如下回复:spring-doc.cadn.net.cn

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-音频预览. 更多信息请参阅音频指南。spring-doc.cadn.net.cn

OpenAI 用户消息 API 可以将 base64 编码的音频文件列表与消息一起整合。 Spring AI 的 Message 界面通过引入媒体类型,促进了多模态 AI 模型的发展。 这种类型包含了关于消息中媒体附件的数据和详细信息,利用Spring的org.springframework.util.MimeType以及一个org.springframework.core.io.Resource对于原始媒体数据。 目前,OpenAI 仅支持以下媒体类型:音频/mp3音频/WAV.spring-doc.cadn.net.cn

以下是OpenAiChatModelIT.java中摘录的代码示例,展示了用户文本与音频文件的融合过程GPT-4O-音频预览型。spring-doc.cadn.net.cn

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-音频预览. 更多信息请参阅音频指南。spring-doc.cadn.net.cn

OpenAI 助手消息 API 可以包含包含 base64 编码的音频文件列表,并附有该消息。 Spring AI 的 Message 界面通过引入媒体类型,促进了多模态 AI 模型的发展。 这种类型包含了关于消息中媒体附件的数据和详细信息,利用Spring的org.springframework.util.MimeType以及一个org.springframework.core.io.Resource对于原始媒体数据。 目前,OpenAI 仅支持以下音频类型:音频/mp3音频/WAV.spring-doc.cadn.net.cn

下面是一个代码示例,展示了用户文本的响应以及一个音频字节数组,使用GPT-4O-音频预览型:spring-doc.cadn.net.cn

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以产生音频输出。 这音频参数class 提供音频输出的语音和音频格式。spring-doc.cadn.net.cn

结构化输出

OpenAI 提供自定义的结构化输出 API,确保你的模型生成的响应严格符合你提供的条件JSON 模式. 除了现有的Spring AI模型无关的结构化输出转换器外,这些API还提供了更强的控制和精度。spring-doc.cadn.net.cn

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

配置

Spring AI 允许你通过编程方式配置响应格式OpenAiChatOptions建造者或通过应用属性。spring-doc.cadn.net.cn

使用聊天选项生成器

你可以用OpenAiChatOptions架构师如下所示:spring-doc.cadn.net.cn

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 模式,然后将结构化响应转换为域特定的实例:spring-doc.cadn.net.cn

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:语法,请参见相关文档

通过应用属性配置

或者,在使用 OpenAI 自动配置时,你可以通过以下应用属性配置所需的响应格式:spring-doc.cadn.net.cn

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)依赖。spring-doc.cadn.net.cn

添加一个application.properties归档于以下src/主/资源用于启用和配置OpenAi聊天模型的目录:spring-doc.cadn.net.cn

spring.ai.openai.api-key=YOUR_API_KEY
spring.ai.openai.chat.options.model=gpt-4o
spring.ai.openai.chat.options.temperature=0.7
替换API密钥用你的OpenAI资质。

这将产生OpenAiChatModel你可以把这些实现注入到你的类中。 这里有一个简单的例子@RestController使用聊天模式生成文本的课程。spring-doc.cadn.net.cn

@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 实现了聊天模型StreamingChatModel并使用低级 OpenAiApi 客户端连接 OpenAI 服务。spring-doc.cadn.net.cn

添加春艾开胃对你项目Maven的依赖pom.xml文件:spring-doc.cadn.net.cn

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

或者去你的Gradlebuild.gradle构建文件。spring-doc.cadn.net.cn

dependencies {
    implementation 'org.springframework.ai:spring-ai-openai'
}
请参考依赖管理部分,将Spring AI的物料清单添加到你的构建文件中。

接下来,创建一个OpenAiChatModel并用于文本生成:spring-doc.cadn.net.cn

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.构建器OpenAiChatOptions.Builder分别是 API 客户端和聊天配置的流利选项构建器。spring-doc.cadn.net.cn

低级OpenAiApi客户端

OpenAiApi 提供了一个轻量级的 OpenAI 聊天 API 的 Java 客户端。spring-doc.cadn.net.cn

以下类图展示了OpenAiAPI聊天界面与构建模块:spring-doc.cadn.net.cn

OpenAiApi 聊天 API 图

这里有一个简单的片段,展示了如何以程序方式使用该 API:spring-doc.cadn.net.cn

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。spring-doc.cadn.net.cn

底层API示例

低级 OpenAiFileApi 客户端

OpenAiFileApi为OpenAI文件API提供了一个轻量级的Java客户端,支持上传、列出、检索、删除文件和访问文件内容等文件管理作。OpenAI 文件 APIspring-doc.cadn.net.cn

这里有一个简单的片段,展示了如何以程序方式使用该 API:spring-doc.cadn.net.cn

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接口及其实现。默认实现,SimpleApiKey适用于大多数用例,但你也可以为更复杂的场景创建自定义实现。spring-doc.cadn.net.cn

默认配置

默认情况下,Spring Boot 自动配置会使用spring.ai.openai.api-key(春.ai.openai.api-key)财产:spring-doc.cadn.net.cn

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

自定义API密钥配置

你可以创建一个自定义实例OpenAiAPI用你自己的ApiKey使用构建模式实现:spring-doc.cadn.net.cn

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();

这在你需要时非常有用:spring-doc.cadn.net.cn

在兼容 OpenAI 的服务器中使用额外参数

像 vLLM、Ollama 等兼容 OpenAI 的推理服务器通常支持超出 OpenAI 标准 API 定义的参数。 例如,这些服务器可能接受以下参数top_k,repetition_penalty,或其他官方 OpenAI API 不认可的抽样控制。spring-doc.cadn.net.cn

额外内容选项允许你向这些服务器传递任意参数。 任何提供于额外内容包含在 JSON 请求的顶层,使你在使用 Spring AI 的 OpenAI 客户端时能够利用服务器特有的功能。spring-doc.cadn.net.cn

额外内容参数是用于兼容 OpenAI 的服务器的,而不是官方的 OpenAI API。 虽然官方 OpenAI API 会忽略未知参数,但它们在那里没有任何作用。 请务必查阅你所在服务器的文档,确定支持哪些参数。spring-doc.cadn.net.cn

带有属性的配置

你可以用 Spring Boot 属性配置额外参数。 每个财产spring.ai.openai.chat.options.extra-body成为请求中的顶层参数:spring-doc.cadn.net.cn

spring.ai.openai.base-url=http://localhost: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 请求:spring-doc.cadn.net.cn

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

运行时配置与构建器

你也可以在运行时使用选项构建器指定额外参数:spring-doc.cadn.net.cn

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-doc.cadn.net.cn

spring.ai.openai.base-url=http://localhost: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文档以获取支持的完整采样参数列表。spring-doc.cadn.net.cn

示例:Ollama 服务器

通过兼容 OpenAI 的端点使用 Ollama 时,你可以传递 Ollama 特定的参数:spring-doc.cadn.net.cn

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 文档以获取可用参数。spring-doc.cadn.net.cn

额外内容参数接受任意Map<String,对象>允许你传递目标服务器支持的任何参数。 Spring AI 不验证这些参数——它们直接传递给服务器。 这种设计为处理多样化兼容 OpenAI 的实现提供了最大灵活性。spring-doc.cadn.net.cn

推理模型中的推理内容

一些支持推理模型的兼容 OpenAI 服务器(如 DeepSeek R1、带推理解析器的 vLLM)通过reasoning_content在他们的API响应中填写字段。 该字段包含模型为得出最终答案所采用的逐步推理过程。spring-doc.cadn.net.cn

Spring AI 将该字段从 JSON 响应映射到理由内容在 AssistantMessage 元数据中的关键。spring-doc.cadn.net.cn

关于 的重要区别reasoning_content可用性:spring-doc.cadn.net.cn

  • 兼容OpenAI的服务器(DeepSeek,vLLM):Exposereasoning_content在聊天补全API中 ✅spring-doc.cadn.net.cn

  • 官方OpenAI模型(GPT-5、o1、o3):请勿在聊天补全API回复❌中暴露推理文本spring-doc.cadn.net.cn

官方 OpenAI 推理模型在使用 Chat Completions API 时会隐藏思考链内容。 他们只会暴露reasoning_tokens在使用统计中计入。 要访问官方OpenAI模型中的实际推理文本,必须使用OpenAI的Responses API(该客户端目前不支持的独立端点)。spring-doc.cadn.net.cn

备用行为:什么时候reasoning_content服务器不提供(例如官方OpenAI聊天补全),理由内容元数据字段将是一个空字符串。spring-doc.cadn.net.cn

访问推理内容

使用兼容服务器时,你可以访问响应元数据中的推理内容。spring-doc.cadn.net.cn

直接使用 ChatModel:spring-doc.cadn.net.cn

// 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:spring-doc.cadn.net.cn

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");

流媒体推理内容

使用流式回复时,推理内容会像普通消息内容一样被分段叠加:spring-doc.cadn.net.cn

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-doc.cadn.net.cn

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提出请求时,回复会包括推理内容(模型的思考过程)和最终答案。spring-doc.cadn.net.cn

有关推理模型的更多细节,请参阅 DeepSeek API 文档spring-doc.cadn.net.cn

示例:带推理解析器的vLLM

vLLM在配置推理解析器时支持推理模型:spring-doc.cadn.net.cn

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

请参阅vLLM推理输出文档中支持的推理模型和解析器。spring-doc.cadn.net.cn

的可用性reasoning_content这完全取决于你使用的推理服务器。 并非所有兼容 OpenAI 的服务器都会暴露推理内容,即使使用具备推理能力的模型。 务必查看服务器的API文档,了解响应中可用的字段。spring-doc.cadn.net.cn