收藏本站,收获最前沿的人工智能与编程资讯!!

Spring AI 使用 OpenAI SDK

技术文档 27℃ 0

Spring AI 通过 OpenAI Java SDK 支持 OpenAI 的语言模型,提供与 OpenAI 服务(包括微软 Foundry 和 GitHub Models)的可靠、官方维护集成。

本实现使用 OpenAI 官方提供的 Java SDK。如需替代的 Spring AI 实现,请参考 OpenAI Chat。

OpenAI SDK 模块会根据你提供的基础 URL 自动检测服务提供商(OpenAI、微软 Foundry 或 GitHub Models)。

身份验证

身份验证通过基础 URL 和 API 密钥完成。该实现通过 Spring Boot 配置属性或环境变量提供灵活的配置选项。

使用 OpenAI

若直接使用 OpenAI,请在 OpenAI 注册页面创建账户,并在 API 密钥页面生成 API 密钥。

无需设置基础 URL,其默认值为 api.openai.com/v1:

spring.ai.openai-sdk.api-key=<your-openai-api-key>
# base-url 为可选配置,默认值为 https://api.openai.com/v1

或使用环境变量:

export OPENAI_API_KEY=<your-openai-api-key>
# OPENAI_BASE_URL 为可选配置,默认值为 https://api.openai.com/v1

使用微软 Foundry

使用微软 Foundry URL 时会自动检测该服务。可通过配置属性进行设置:

spring.ai.openai-sdk.base-url=https://<your-deployment-url>.openai.azure.com
spring.ai.openai-sdk.api-key=<your-api-key>
spring.ai.openai-sdk.microsoft-deployment-name=<your-deployment-name>

或使用环境变量:

export OPENAI_BASE_URL=https://<your-deployment-url>.openai.azure.com
export OPENAI_API_KEY=<your-api-key>

无密码身份验证(Azure 推荐使用):

微软 Foundry 支持无需提供 API 密钥的无密码身份验证,在 Azure 上运行时安全性更高。

启用无密码身份验证,请添加 com.azure:azure-identity 依赖:

<dependency>
    <groupId>com.azure</groupId>
    <artifactId>azure-identity</artifactId>
</dependency>

随后无需配置 API 密钥即可完成设置:

spring.ai.openai-sdk.base-url=https://<your-deployment-url>.openai.azure.com
spring.ai.openai-sdk.microsoft-deployment-name=<your-deployment-name>
# 无需配置 api-key - 系统将使用环境中的 Azure 凭据

使用 GitHub Models

使用 GitHub Models 基础 URL 时会自动检测该服务。你需要创建具备 models:read 权限的 GitHub 个人访问令牌(PAT)。

spring.ai.openai-sdk.base-url=https://models.inference.ai.azure.com
spring.ai.openai-sdk.api-key=github_pat_XXXXXXXXXXX

或使用环境变量:

export OPENAI_BASE_URL=https://models.inference.ai.azure.com
export OPENAI_API_KEY=github_pat_XXXXXXXXXXX

处理 API 密钥等敏感信息时,为提升安全性,可在配置属性中使用 Spring 表达式语言(SpEL):

spring.ai.openai-sdk.api-key=${OPENAI_API_KEY}

添加仓库和物料清单(BOM)

Spring AI 构件发布在 Maven 中央仓库和 Spring 快照仓库中。参考「构件仓库」章节将这些仓库添加到你的构建系统中。

为简化依赖管理,Spring AI 提供了物料清单(BOM),确保整个项目使用一致的 Spring AI 版本。参考「依赖管理」章节将 Spring AI BOM 添加到你的构建系统中。

自动配置

Spring AI 为 OpenAI SDK 聊天客户端提供 Spring Boot 自动配置。启用该功能需在项目的 Maven pom.xml 或 Gradle build.gradle 构建文件中添加以下依赖:

Maven

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

参考「依赖管理」章节将 Spring AI BOM 添加到你的构建文件中。

配置属性

连接属性

使用前缀 spring.ai.openai-sdk 配置 OpenAI SDK 客户端。

属性描述默认值
spring.ai.openai-sdk.base-url连接地址。未设置时自动从 OPENAI_BASE_URL 环境变量读取api.openai.com/v1
spring.ai.openai-sdk.api-keyAPI 密钥。未设置时自动从 OPENAI_API_KEY 环境变量读取-
spring.ai.openai-sdk.organization-id可选配置,指定 API 请求使用的组织-
spring.ai.openai-sdk.timeout请求超时时间-
spring.ai.openai-sdk.max-retries请求失败的最大重试次数-
spring.ai.openai-sdk.proxyOpenAI 客户端代理设置(Java Proxy 对象)-
spring.ai.openai-sdk.custom-headers请求中包含的自定义 HTTP 头,为键值对映射-

微软 Foundry(Azure OpenAI)属性

OpenAI SDK 实现原生支持微软 Foundry(Azure OpenAI)并支持自动配置:

属性描述默认值
spring.ai.openai-sdk.microsoft-foundry启用微软 Foundry 模式。若基础 URL 包含 openai.azure.com、cognitiveservices.azure.com 或 .openai.microsoftFoundry.com,则自动启用false
spring.ai.openai-sdk.microsoft-deployment-name微软 Foundry 部署名称。未指定时使用模型名称,可通过别名 deployment-name 访问-
spring.ai.openai-sdk.microsoft-foundry-service-version微软 Foundry API 服务版本-
spring.ai.openai-sdk.credential无密码身份验证凭据对象(需要 com.azure:azure-identity 依赖)-

微软 Foundry 支持无密码身份验证。添加 com.azure:azure-identity 依赖后,未提供 API 密钥时,实现会自动尝试使用环境中的 Azure 凭据。

GitHub Models 属性

原生支持 GitHub Models:

属性描述默认值
spring.ai.openai-sdk.github-models启用 GitHub Models 模式。若基础 URL 包含 models.github.ai 或 models.inference.ai.azure.com,则自动启用false

GitHub Models 需要具备 models:read 权限的个人访问令牌。可通过 OPENAI_API_KEY 环境变量或 spring.ai.openai-sdk.api-key 属性设置。

聊天模型属性

使用前缀 spring.ai.openai-sdk.chat 配置聊天模型实现:

属性描述默认值
spring.ai.openai-sdk.chat.options.model使用的 OpenAI 聊天模型名称,可选 gpt-5-mini、gpt-4o、gpt-4o-mini、gpt-4-turbo、o1、o3-mini 等,详情参考模型页面gpt-5-mini
spring.ai.openai-sdk.chat.options.temperature采样温度,控制生成内容的创造性。数值越高输出越随机,数值越低结果越聚焦、越确定。不建议在同一请求中同时修改 temperature 和 top_p1.0
spring.ai.openai-sdk.chat.options.frequency-penalty取值范围 -2.0 至 2.0。正值会基于令牌已出现的频率降低重复生成概率0.0
spring.ai.openai-sdk.chat.options.logit-bias调整指定令牌在生成结果中出现的概率-
spring.ai.openai-sdk.chat.options.logprobs是否返回输出令牌的对数概率false
spring.ai.openai-sdk.chat.options.top-logprobs0 至 5 的整数,指定每个令牌位置返回的最可能令牌数量,需要 logprobs 设为 true-
spring.ai.openai-sdk.chat.options.max-tokens生成的最大令牌数,适用于非推理模型(如 gpt-4o、gpt-3.5-turbo),不可用于推理模型,与 maxCompletionTokens 互斥-
spring.ai.openai-sdk.chat.options.max-completion-tokens生成结果的最大令牌数上限(包含输出令牌和推理令牌),推理模型必填,不可用于非推理模型,与 maxTokens 互斥-
spring.ai.openai-sdk.chat.options.n每个输入消息生成的聊天完成结果数量1
spring.ai.openai-sdk.chat.options.output-modalities输出模式列表,可包含 text 和 audio-
spring.ai.openai-sdk.chat.options.output-audio音频输出参数,使用 AudioParameters 设置音色(ALLOY、ASH 等)和格式(MP3、FLAC 等)-
spring.ai.openai-sdk.chat.options.presence-penalty取值范围 -2.0 至 2.0。正值会基于令牌是否出现过降低生成概率0.0
spring.ai.openai-sdk.chat.options.response-format.type响应格式类型:TEXT、JSON_OBJECT、JSON_SCHEMATEXT
spring.ai.openai-sdk.chat.options.response-format.json-schema类型为 JSON_SCHEMA 时的结构化输出 JSON 模式-
spring.ai.openai-sdk.chat.options.seed指定后系统会尽力实现确定性采样,保证结果可复现-
spring.ai.openai-sdk.chat.options.stop最多 4 个终止序列,API 遇到后停止生成令牌-
spring.ai.openai-sdk.chat.options.top-p核采样,作为 temperature 的替代方案-
spring.ai.openai-sdk.chat.options.user终端用户唯一标识,用于 OpenAI 监控和检测滥用行为-
spring.ai.openai-sdk.chat.options.parallel-tool-calls工具调用时是否启用并行函数调用true
spring.ai.openai-sdk.chat.options.reasoning-effort约束推理模型的推理力度:low、medium、high-
spring.ai.openai-sdk.chat.options.verbosity控制模型响应的详细程度-
spring.ai.openai-sdk.chat.options.store是否存储本次生成结果用于 OpenAI 模型蒸馏或评估false
spring.ai.openai-sdk.chat.options.metadata开发者自定义标签,用于仪表盘筛选生成结果-
spring.ai.openai-sdk.chat.options.service-tier指定延迟等级:auto、default、flex、priority-
spring.ai.openai-sdk.chat.options.stream-options.include-usage流式响应中是否包含使用统计false
spring.ai.openai-sdk.chat.options.stream-options.include-obfuscation流式响应中是否包含混淆处理false
spring.ai.openai-sdk.chat.options.tool-choice控制模型调用的函数(可选)-
spring.ai.openai-sdk.chat.options.internal-tool-execution-enabledfalse 时 Spring AI 将工具调用代理给客户端手动处理;true(默认)时 Spring AI 内部处理函数调用true

使用 gpt-5、gpt-5-mini、gpt-5-nano 等 GPT-5 模型时,不支持 temperature 参数。这类模型针对推理优化,不使用温度设置,指定该参数会报错。而 gpt-5-chat 等对话模型支持 temperature 参数。

所有以 spring.ai.openai-sdk.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(
        "用简单的语言解释量子计算。",
        OpenAiSdkChatOptions.builder()
            .model("gpt-4o")
            .maxTokens(150)  // 非推理模型使用 maxTokens
        .build()
    ));

推理模型(o1、o3 系列):

ChatResponse response = chatModel.call(
    new Prompt(
        "分步解这道复杂的数学题:...",
        OpenAiSdkChatOptions.builder()
            .model("o1-preview")
            .maxCompletionTokens(1000)  // 推理模型使用 maxCompletionTokens
        .build()
    ));

运行时选项

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

启动时,可通过 OpenAiSdkChatModel(options) 构造方法或 spring.ai.openai-sdk.chat.options.* 配置属性设置默认选项。

运行时,可通过为 Prompt 调用添加新的请求级别选项覆盖默认配置。例如,覆盖指定请求的默认模型和温度:

ChatResponse response = chatModel.call(
    new Prompt(
        "生成5位著名海盗的名字。",
        OpenAiSdkChatOptions.builder()
            .model("gpt-4o")
            .temperature(0.4)
        .build()
    ));

除了模型专用的 OpenAiSdkChatOptions,你还可以使用 ChatOptions#builder() 创建通用的 ChatOptions 实例。

工具调用

你可以向 OpenAiSdkChatModel 注册自定义 Java 函数或方法,让 OpenAI 模型智能选择输出包含参数的 JSON 对象,调用一个或多个注册的函数/工具。这是连接大语言模型能力与外部工具和 API 的强大技术。更多工具调用内容请参考相关文档。

使用示例:

var chatOptions = OpenAiSdkChatOptions.builder()
    .toolCallbacks(List.of(
        FunctionToolCallback.builder("getCurrentWeather", new WeatherService())
            .description("获取指定地点的天气")
            .inputType(WeatherService.Request.class)
            .build()))
    .build();

ChatResponse response = chatModel.call(
    new Prompt("旧金山的天气怎么样?", chatOptions));

多模态

多模态指模型能够同时理解和处理文本、图片、音频等多种来源信息的能力。

视觉

支持视觉多模态的 OpenAI 模型包括 gpt-4、gpt-4o、gpt-4o-mini。更多信息参考视觉指南。

Spring AI 的 Message 接口通过引入 Media 类型支持多模态 AI 模型。

以下代码示例展示用户文本与图片结合的用法:

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

var userMessage = new UserMessage(
    "解释你在这张图片中看到了什么?",
    List.of(new Media(MimeTypeUtils.IMAGE_PNG, imageResource)));

ChatResponse response = chatModel.call(
    new Prompt(userMessage,
        OpenAiSdkChatOptions.builder()
            .model("gpt-4o")
            .build()));

或使用图片 URL:

var userMessage = new UserMessage(
    "解释你在这张图片中看到了什么?",
    List.of(Media.builder()
        .mimeType(MimeTypeUtils.IMAGE_PNG)
        .data(URI.create("https://docs.spring.io/spring-ai/reference/_images/multimodal.test.png"))
        .build()));

ChatResponse response = chatModel.call(new Prompt(userMessage));

也可以传递多张图片。

音频

支持音频输入的 OpenAI 模型包括 gpt-4o-audio-preview。更多信息参考音频指南。

Spring AI 支持在消息中携带 Base64 编码的音频文件。目前 OpenAI 支持以下媒体类型:audio/mp3 和 audio/wav。

音频输入示例:

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

var userMessage = new UserMessage(
    "这段录音讲的是什么?",
    List.of(new Media(MimeTypeUtils.parseMimeType("audio/mp3"), audioResource)));

ChatResponse response = chatModel.call(
    new Prompt(userMessage,
        OpenAiSdkChatOptions.builder()
            .model("gpt-4o-audio-preview")
            .build()));

音频输出

gpt-4o-audio-preview 模型可以生成音频响应。

生成音频输出示例:

var userMessage = new UserMessage("给我讲一个关于 Spring 框架的笑话");

ChatResponse response = chatModel.call(
    new Prompt(userMessage,
        OpenAiSdkChatOptions.builder()
            .model("gpt-4o-audio-preview")
            .outputModalities(List.of("text", "audio"))
            .outputAudio(new AudioParameters(Voice.ALLOY, AudioResponseFormat.WAV))
            .build()));

String text = response.getResult().getOutput().getText(); // 音频文本转录
byte[] waveAudio = response.getResult().getOutput().getMedia().get(0).getDataAsByteArray(); // 音频数据

结构化输出

OpenAI 提供自定义结构化输出 API,确保模型生成的响应严格符合你提供的 JSON 模式。

配置

你可以通过 OpenAiSdkChatOptions 构造器以编程方式设置响应格式:

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(
    "如何解 8x + 7 = -23",
    OpenAiSdkChatOptions.builder()
        .model("gpt-4o-mini")
        .responseFormat(ResponseFormat.builder()
            .type(ResponseFormat.Type.JSON_SCHEMA)
            .jsonSchema(jsonSchema)
            .build())
        .build());

ChatResponse response = chatModel.call(prompt);

与 BeanOutputConverter 集成

你可以使用现有的 BeanOutputConverter 工具:

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);
String jsonSchema = outputConverter.getJsonSchema();

Prompt prompt = new Prompt(
    "如何解 8x + 7 = -23",
    OpenAiSdkChatOptions.builder()
        .model("gpt-4o-mini")
        .responseFormat(ResponseFormat.builder()
            .type(ResponseFormat.Type.JSON_SCHEMA)
            .jsonSchema(jsonSchema)
            .build())
        .build());

ChatResponse response = chatModel.call(prompt);
MathReasoning mathReasoning = outputConverter.convert(
    response.getResult().getOutput().getText());

示例控制器

创建新的 Spring Boot 项目,并在 pom(或 gradle)依赖中添加 spring-ai-openai-sdk。

在 src/main/resources 目录下添加 application.properties 文件配置 OpenAI SDK 聊天模型:

spring.ai.openai-sdk.api-key=YOUR_API_KEY
spring.ai.openai-sdk.chat.options.model=gpt-5-mini
spring.ai.openai-sdk.chat.options.temperature=0.7

将 api-key 替换为你的 OpenAI 凭据。

这会创建 OpenAiSdkChatModel 实现,你可以将其注入到类中。以下是一个简单的 @RestController 示例,使用聊天模型生成文本:

@RestController
public class ChatController {

    private final OpenAiSdkChatModel chatModel;

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

    @GetMapping("/ai/generate")
    public Map<String,String> generate(
            @RequestParam(value = "message", defaultValue = "给我讲个笑话") String message) {
        return Map.of("generation", chatModel.call(message));
    }

    @GetMapping("/ai/generateStream")
    public Flux<ChatResponse> generateStream(
            @RequestParam(value = "message", defaultValue = "给我讲个笑话") String message) {
        Prompt prompt = new Prompt(new UserMessage(message));
        return chatModel.stream(prompt);
    }
}

手动配置

OpenAiSdkChatModel 实现了 ChatModel 接口,并使用官方 OpenAI Java SDK 连接 OpenAI 服务。

在项目的 Maven pom.xml 文件中添加 spring-ai-openai-sdk 依赖:

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

或在 Gradle build.gradle 构建文件中添加:

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

参考「依赖管理」章节将 Spring AI BOM 添加到你的构建文件中。

接下来,创建 OpenAiSdkChatModel 并用于文本生成:

var chatOptions = OpenAiSdkChatOptions.builder()
    .model("gpt-4o")
    .temperature(0.7)
    .apiKey(System.getenv("OPENAI_API_KEY"))
    .build();

var chatModel = OpenAiSdkChatModel.builder()
    .options(chatOptions)
    .build();

ChatResponse response = chatModel.call(
    new Prompt("生成5位著名海盗的名字。"));

// 或使用流式响应
Flux<ChatResponse> response = chatModel.stream(
    new Prompt("生成5位著名海盗的名字。"));

微软 Foundry 配置

微软 Foundry 配置:

var chatOptions = OpenAiSdkChatOptions.builder()
    .baseUrl("https://your-resource.openai.azure.com")
    .apiKey(System.getenv("OPENAI_API_KEY"))
    .deploymentName("gpt-4")
    .azureOpenAIServiceVersion(AzureOpenAIServiceVersion.V2024_10_01_PREVIEW)
    .azure(true)  // 启用微软 Foundry 模式
    .build();

var chatModel = OpenAiSdkChatModel.builder()
    .options(chatOptions)
    .build();

微软 Foundry 支持无密码身份验证。在项目中添加 com.azure:azure-identity 依赖,若未提供 API 密钥,实现会自动尝试使用环境中的 Azure 凭据。

GitHub Models 配置

GitHub Models 配置:

var chatOptions = OpenAiSdkChatOptions.builder()
    .baseUrl("https://models.inference.ai.azure.com")
    .apiKey(System.getenv("GITHUB_TOKEN"))
    .model("gpt-4o")
    .githubModels(true)
    .build();

var chatModel = OpenAiSdkChatModel.builder()
    .options(chatOptions)
    .build();

与 Spring AI OpenAI 的核心区别

本实现与 Spring AI OpenAI 实现在多个方面存在差异:

维度官方 OpenAI SDK现有 OpenAI 实现
HTTP 客户端OkHttp(通过官方 SDK)Spring RestClient/WebClient
API 更新通过 SDK 更新自动同步手动维护
Azure 支持原生支持,含无密码认证手动构建 URL
GitHub Models原生支持不支持
音频/内容审核暂不支持完全支持
重试逻辑SDK 管理(指数退避)Spring Retry(可自定义)
依赖官方 OpenAI SDKSpring WebFlux

使用 OpenAI SDK 的场景:

  • 启动新项目

  • 主要使用微软 Foundry 或 GitHub Models

  • 希望自动同步 OpenAI 的 API 更新

  • 不需要音频转录或内容审核功能

  • 偏好官方 SDK 支持

使用 Spring AI OpenAI 的场景:

  • 现有项目已在使用

  • 需要音频转录或内容审核功能

  • 需要精细化的 HTTP 控制

  • 需要原生 Spring 响应式支持

  • 需要自定义重试策略

可观测性

OpenAI SDK 实现通过 Micrometer 支持 Spring AI 的可观测性特性。所有聊天模型操作都已埋点,可用于监控和链路追踪。

局限性

OpenAI SDK 实现暂不支持以下功能:

  • 音频语音生成(TTS)

  • 音频转录

  • 内容审核 API

  • 文件 API 操作

这些功能在 Spring AI OpenAI 实现中可用。

相关推荐