27_Spring AI 干货笔记之 OpenAI SDK 聊天功能(官方支持)

一、OpenAI SDK

Spring AI 通过 OpenAI Java SDK 提供对 OpenAI 语言模型的支持,为 OpenAI 服务(包括 Microsoft Foundry 和 GitHub Models)提供了稳健且官方维护的集成方案。

此实现使用来自 OpenAI 的官方 Java SDK。如需了解 Spring AI 的替代实现,请参阅 OpenAI 聊天。

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

二、认证

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

2.1 使用 OpenAI

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

基础 URL 无需设置,因为它默认指向 api.openai.com/v1:

yaml 复制代码
spring.ai.openai-sdk.api-key=<your-openai-api-key>
# base-url 是可选的,默认为 https://api.openai.com/v1

或使用环境变量:

yaml 复制代码
export OPENAI_API_KEY=<your-openai-api-key>
# OPENAI_BASE_URL 是可选的,默认为 https://api.openai.com/v1

2.2 使用 Microsoft Foundry

当使用 Microsoft Foundry 的 URL 时,系统会自动检测到它。您可以使用属性进行配置:

yaml 复制代码
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>

或使用环境变量:

yaml 复制代码
export OPENAI_BASE_URL=https://<your-deployment-url>.openai.azure.com
export OPENAI_API_KEY=<your-api-key>

无密码认证(Azure 推荐):

Microsoft Foundry 支持不提供 API 密钥的无密码认证,这在 Azure 上运行时更加安全。

要启用无密码认证,请添加 com.azure:azure-identity 依赖项:

xml 复制代码
<dependency>
    <groupId>com.azure</groupId>
    <artifactId>azure-identity</artifactId>
</dependency>

然后,无需 API 密钥即可配置:

yaml 复制代码
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 凭据

2.3 使用 GitHub Models

当使用 GitHub Models 的基础 URL 时,系统会自动检测到它。您需要创建一个具有 models:read 范围的 GitHub 个人访问令牌(PAT)。

yaml 复制代码
spring.ai.openai-sdk.base-url=https://models.inference.ai.azure.com
spring.ai.openai-sdk.api-key=github_pat_XXXXXXXXXXX

或使用环境变量:

yaml 复制代码
export OPENAI_BASE_URL=https://models.inference.ai.azure.com
export OPENAI_API_KEY=github_pat_XXXXXXXXXXX

为了在处理敏感信息(如 API 密钥)时增强安全性,您可以在属性中使用 Spring 表达式语言(SpEL):

yaml 复制代码
spring.ai.openai-sdk.api-key=${OPENAI_API_KEY}

2.4 添加仓库和 BOM

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

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

三、自动配置

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

Maven

xml 复制代码
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-model-openai-sdk</artifactId>
</dependency>

Gradle

groovy 复制代码
dependencies {
    implementation 'org.springframework.ai:spring-ai-starter-model-openai-sdk'
}

请参阅 依赖管理 部分,将 Spring AI BOM 添加到您的构建文件中。

3.1 配置属性

3.1.1 连接属性

前缀 spring.ai.openai-sdk 用作属性前缀,用于配置 OpenAI SDK 客户端。

3.1.2 Microsoft Foundry (Azure OpenAI) 属性

OpenAI SDK 实现提供了对 Microsoft Foundry(Azure OpenAI)的原生支持,并支持自动配置:

Microsoft Foundry 支持无密码认证。添加 com.azure:azure-identity 依赖项,当不提供 API 密钥时,实现将自动尝试使用环境中的 Azure 凭据。

3.1.3 GitHub Models 属性

提供对 GitHub Models 的原生支持:

GitHub Models 需要一个具有 models:read 范围的个人访问令牌。通过 OPENAI_API_KEY 环境变量或 spring.ai.openai-sdk.api-key 属性进行设置。

3.1.4 聊天模型属性

前缀 spring.ai.openai-sdk.chat 是用于配置聊天模型实现的属性前缀:

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

所有以 spring.ai.openai-sdk.chat.options 为前缀的属性都可以在运行时通过向 Prompt 调用添加请求特定的 运行时选项 来覆盖。

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

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

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

3.2.1 使用示例

对于非推理模型(gpt-4o、gpt-3.5-turbo):

java 复制代码
ChatResponse response = chatModel.call(
    new Prompt(
        "用简单的术语解释量子计算。",
        OpenAiSdkChatOptions.builder()
            .model("gpt-4o")
            .maxTokens(150)  // 对于非推理模型使用 maxTokens
        .build()
    ));

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

java 复制代码
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 调用添加新的、请求特定的选项来覆盖默认选项。例如,要为特定请求覆盖默认模型和温度:

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

除了特定于模型的 OpenAiSdkChatOptions,您还可以使用可移植的 ChatOptions 实例,通过 ChatOptions#builder() 创建。

五、工具调用

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

使用示例:

java 复制代码
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));

六、多模态

多模态性是指模型能够同时理解和处理来自各种来源的信息,包括文本、图像、音频和其他数据格式。

6.1 视觉

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

Spring AI 的 Message 接口通过引入 Media 类型来促进多模态 AI 模型的使用。

下面是一个代码示例,说明了用户文本与图像的融合:

java 复制代码
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:

java 复制代码
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));

您也可以传递多张图片。

6.2 音频

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

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

音频输入示例:

java 复制代码
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()));

6.3 输出音频

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

生成音频输出示例:

java 复制代码
var userMessage = new UserMessage("给我讲一个关于 Spring Framework 的笑话");

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().getContent(); // 音频转录文本
byte[] waveAudio = response.getResult().getOutput().getMedia().get(0).getDataAsByteArray(); // 音频数据

七、结构化输出

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

7.1 配置

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

java 复制代码
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);

7.2 与 BeanOutputConverter 集成

您可以利用现有的 BeanOutputConverter 工具:

java 复制代码
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().getContent());

八、示例控制器

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

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

yaml 复制代码
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 类示例,它使用聊天模型进行文本生成。

java 复制代码
@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 服务。

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

xml 复制代码
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-openai-sdk</artifactId>
</dependency>

或添加到您的 Gradle build.gradle 构建文件中:

groovy 复制代码
dependencies {
    implementation 'org.springframework.ai:spring-ai-openai-sdk'
}

请参阅 依赖管理 部分,将 Spring AI BOM 添加到您的构建文件中。

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

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

var chatModel = new OpenAiSdkChatModel(chatOptions);

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

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

9.1 Microsoft Foundry 配置

对于 Microsoft Foundry:

java 复制代码
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)  // 启用 Microsoft Foundry 模式
    .build();

var chatModel = new OpenAiSdkChatModel(chatOptions);

Microsoft Foundry 支持无密码认证。将 com.azure:azure-identity 依赖项添加到您的项目中。如果不提供 API 密钥,实现将自动尝试使用您环境中的 Azure 凭据。

9.2 GitHub Models 配置

对于 GitHub Models:

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

var chatModel = new OpenAiSdkChatModel(chatOptions);

十、与 Spring AI OpenAI 的主要区别

此实现与 Spring AI OpenAI 实现有几个不同之处:


何时使用 OpenAI SDK:

  • 您正在启动一个新项目

  • 您主要使用 Microsoft Foundry 或 GitHub Models

  • 您希望从 OpenAI 获得自动 API 更新

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

  • 您偏好官方 SDK 支持

何时使用 Spring AI OpenAI:

  • 您有一个使用它的现有项目

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

  • 您需要细粒度的 HTTP 控制

  • 您需要原生的 Spring 响应式支持

  • 您需要自定义的重试策略

十一、可观测性

OpenAI SDK 实现通过 Micrometer 支持 Spring AI 的可观测性功能。所有聊天模型操作都经过检测,用于监控和追踪。

十二、限制

OpenAI SDK 实现中尚未支持以下功能:

  • 音频语音生成(TTS)

  • 音频转录

  • 审核 API

  • 文件 API 操作

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

十三、其他资源

相关推荐
有来有去95271 小时前
[模型量化]-大模型量化效果评价-Qwen2.5-72B
人工智能·语言模型·gpu算力
斯外戈的小白1 小时前
【NLP】one-hot到word2vec发展路线
人工智能·自然语言处理·word2vec
zhurui_xiaozhuzaizai1 小时前
RL 训练中的“训练-推理不匹配”难题:根源分析于解决办法(重要性采样IS 、 切回 FP16精度)
人工智能
围炉聊科技1 小时前
LongCat-Image:美团的轻量化图像生成与编辑新标杆
人工智能
金叶科技智慧农业1 小时前
科技如何守护每一株幼苗?苗情生态监测系统带来田间新视角
大数据·人工智能
一招定胜负1 小时前
机器学习预备知识:numpy、pandas、matplotlib库
人工智能·机器学习·numpy
qiyue772 小时前
裁员这么猛,AI修仙抗一波
前端·人工智能·ai编程
光算科技2 小时前
谷歌是否歧视AI生成图片|用Midjourney作图要标注来源吗?
人工智能·midjourney
程思扬2 小时前
你的模型你做主:Fooocus + cpolar,安全远程生成 AI 图像
人工智能·笔记·tcp/ip·前端框架·figma·蓝湖