使用官方OpenAI Java SDK与Spring AI集成
1. 概述
Spring AI 2.0 将官方 OpenAI Java SDK 纳入其标准 OpenAI 集成。 我们可以通过 Spring 的抽象来使用它,同时让 Spring Boot 配置底层客户端。
在本教程中,我们将使用 ChatClient 汇总一个客服请求,将 Gemini 配置为可选提供商,并从原先独立的 SDK 模块迁移。
2. Spring AI 如何使用 OpenAI Java SDK
Spring AI 提供了用于处理语言模型的通用 API。在此集成中,ChatClient 会委托给 OpenAiChatModel,后者将 Spring 消息和选项转换为由官方 SDK 处理的请求。
我们的应用依赖 Spring AI 的抽象。SDK 负责处理底层 API 调用。
Spring Boot 自动配置会提供模型和 ChatClient.Builder。这与直接使用 OpenAI Java 客户端不同;在后一种方式中,我们需要自行构建 SDK 请求。
Spring AI 2.0 移除了独立的 spring-ai-openai-sdk 模块。标准 OpenAI 集成现在内部使用官方 SDK。在 Spring AI 2.0.2 中,此集成使用 Chat Completions API,不支持 OpenAI 的 Responses API。
3. 设置集成
我们的示例使用 Java 21、Spring Boot 4.1.2 和 Spring AI 2.0.2。
3.1. Maven 依赖
在我们的 Spring Boot 项目中,添加 OpenAI starter:
最新的 spring-ai-starter-model-openai 版本可在 Maven 仓库中获取。2.0.2 版本会以传递依赖的方式引入 openai-java-core 4.80.0,因此我们不需要单独的 SDK 依赖。
3.2. 凭据与模型配置
我们需要一个 OpenAI API 密钥和可用的 API 额度。我们通过 OPENAI_API_KEY 环境变量提供密钥。
在 application.yml 中,配置端点并限制示例的响应大小:
完整的 base URL 包含 /v1。SDK 在发起请求时会追加 /chat/completions。
对于 GPT-6 Luna,reasoning-effort: none 会禁用推理,而 max-completion-tokens 会限制生成的 token 数。我们还设置了请求超时并禁用自动重试,以使这个小型示例的 API 调用保持可预测。
4. 通过 ChatClient 调用 OpenAI 兼容模型
我们希望发送一个模拟的客服请求,并要求生成一句包含问题和所请求操作的摘要。
4.1. 创建摘要服务
将自动配置的 builder 注入我们的服务:
defaultSystem() 建立摘要指令。每次调用 summarize() 都会将请求添加为用户消息,同步调用模型,并返回其文本。
更完整的 ChatClient 链式 API还支持流式传输和结构化输出等功能。这里使用普通字符串,便于我们专注于 SDK 集成。
4.2. 验证 OpenAI 调用
我们的 Spring Boot 测试注入 SupportSummaryService,并用一个重复扣费请求来测试它:
设置好 API 密钥后,我们从 spring-ai-modules/spring-ai-openai 目录运行仓库中的真实调用测试:
两个真实调用测试都使用 @EnabledIfEnvironmentVariable,因此如果对应的 API 密钥环境变量缺失或为空,Maven 会报告测试被跳过。
在实际运行中,OpenAI 返回:
生成的措辞可能会有所不同,因此我们应检查输出是否非空,而不是比对精确句子。
4.3. 使用 Gemini 作为替代方案
如果需要不依赖付费 OpenAI 访问权限的替代方案,我们可以使用 Gemini 的 OpenAI 兼容端点。Gemini 3.5 Flash-Lite 提供免费套餐,但受配额和可用性限制。
在 application-gemini.yml 中,单独的 Spring Profile会覆盖提供商设置:
服务与 SDK 保持不变,但模型特定的选项仍然很重要。 Gemini 3 模型无法禁用思考,因此我们应将 none 替换为 low,并允许更多 token。
我们将每个请求的最长等待时间设为 120 秒。真实调用测试的 180 秒上限可防止 JUnit 先中断请求。
Gemini 的真实调用测试会自动激活此 profile,因此我们只需要提供其密钥和测试名称:
我们的 Gemini 3.5 Flash-Lite 运行返回:
5. 从独立的 SDK 模块迁移
此迁移适用于原先的 spring-ai-openai-sdk 集成。升级说明描述了它在 Spring AI 2.0 中的移除。
已经使用标准 OpenAI 模块的应用可以保留现有配置属性,其中 chat.options.* 会作为已弃用的别名保留。但是,手动构建 OpenAiChatModel 的代码需要更新。
在 2.0.2 中,OpenAiApi 已被移除。模型 builder 不再提供 openAiApi()、defaultOptions() 或 retryTemplate()。它通过 openAiClient() 接收 SDK 的 OpenAIClient,并通过 options() 接收模型设置。
5.1. 更新 Starter 与属性
从 Spring AI 1.1.x 迁移到 2.0.2 时,我们还需要一个兼容的 Spring Boot 4 应用。我们应将 spring-ai-starter-model-openai-sdk 替换为 3.1 节中展示的 starter。
旧 SDK starter 的配置可能包含:
对于 Spring AI 2.0.2,等效属性为:
前缀从 spring.ai.openai-sdk 变为 spring.ai.openai。我们使用扁平的 chat.model 属性。较旧的 chat.options.model 写法在 2.0.2 中仍然可用,但已弃用。
5.2. 更新模型类与选项
引用了独立模块类型的代码需要进行以下替换:
OpenAiSdkChatModel变为OpenAiChatModelOpenAiSdkChatOptions变为OpenAiChatOptions
包名从 org.springframework.ai.openaisdk 变为 org.springframework.ai.openai。这会影响显式构建模型和以编程方式设置选项的代码,即使应用的提示词保持不变。
原先的 OpenAiSdkChatModel builder 已经使用 openAiClient() 和 options(),因此当我们重命名该类时,这些方法名可以沿用。
我们的服务只使用 ChatClient.Builder 和 ChatClient,因此不引用任何 SDK 特有的类。Starter 和配置发生了变化,而其摘要代码保持不变。
6. 结论
在本文中,我们使用 Spring AI 的标准 OpenAI starter,通过官方 Java SDK 汇总了一个客服请求。 在更改端点、凭据和模型选项后,同一个服务也能与 Gemini 配合工作。
对于使用已移除 SDK 模块的应用,迁移涉及 starter、属性前缀和带 SDK 后缀的类。让应用代码以 ChatClient 为中心,可以限制服务层所需的变化。
完整示例可在 GitHub 上获取。