本文定位:这是一篇基于 Spring AI 官方文档 - OpenAI Image Generation 的二次创作。官方文档偏向于 API 参考手册风格,对新手不够友好。本文将按照官方文档的结构,逐节用通俗易懂的语言重新解读,并结合真实项目代码帮助你理解每一个知识点。希望对大家有所帮助!

官方文档原文链接


目录


1. 官方文档说了什么?——全局概览

打开 Spring AI 官方文档的 OpenAI Image Generation 页面,你会发现它的结构大致如下:

OpenAI Image Generation
├── Prerequisites              → 前置条件(API Key 怎么获取)
├── Auto-configuration         → 自动配置(加什么依赖)
│   └── Image Generation Properties  → 配置属性(有哪些参数可以调)
│       ├── Connection Properties     → 连接相关
│       ├── Retry Properties          → 重试机制
│       └── Configuration Properties  → 图像生成参数
└── Runtime Options            → 运行时选项(代码中怎么动态设置参数)

官方原文(来自 openai-image.html):
“Spring AI supports DALL-E, the Image generation model from OpenAI.”

翻译:Spring AI 支持 OpenAI 的 DALL-E 图像生成模型。

一句话就点明了主题——Spring AI 帮我们封装好了调用 OpenAI DALL-E 的全部细节,开发者只需要关心"传什么参数"和"怎么拿结果"。

补充说明:官方文档中实际上有两个关于 OpenAI Image 的页面:

  • OpenAI Image Generationopenai-image.html):Spring AI 自己维护的 HTTP 客户端实现
  • OpenAI SDK Image Generationopenai-sdk-image.html):基于 OpenAI 官方 Java SDK 的实现

两者功能相同,API 略有差异。本文主要讲解前者(也是我们项目中使用的版本),在关键处会提及 SDK 版本的差异。


2. 背景知识:什么是 DALL-E 和 ImageModel

在阅读官方文档之前,先搞清楚两个基础概念。

2.1 DALL-E 是什么?

DALL-E 是 OpenAI 开发的 AI 图像生成模型。你给它一段文字描述(叫做 prompt,提示词),它就能生成一张与描述匹配的图片。

官方原文(来自 openai-sdk-image.html):
“DALL-E is a state-of-the-art image generation model from OpenAI that can create realistic images and art from natural language descriptions.”

翻译:DALL-E 是 OpenAI 的先进图像生成模型,可以根据自然语言描述生成逼真的图像和艺术作品。

目前有两个版本:

模型 特点
DALL-E-2 较早版本,支持批量生成(最多 10 张),尺寸选择较少
DALL-E-3 最新版本(默认),图片质量更高,支持 stylequality 参数,但每次只能生成 1 张

2.2 ImageModel 是什么?

ImageModel 是 Spring AI 框架定义的一个 Java 接口,它把"调用 AI 生成图片"这件事抽象成了一个标准方法:

public interface ImageModel {
    ImageResponse call(ImagePrompt prompt);
}

你可以把它理解为一个"图片生成器"的通用规范:

  • 输入ImagePrompt(提示词 + 生成选项)
  • 输出ImageResponse(生成结果,包含图片数据)

不同 AI 厂商各自提供实现类:

ImageModel(接口)
├── OpenAiImageModel          → OpenAI DALL-E(本文使用)
├── AzureOpenAiImageModel     → Azure OpenAI
├── StabilityAiImageModel     → Stability AI
├── ZhiPuAiImageModel         → 智谱 AI
└── QianFanImageModel         → 百度千帆

这种设计的好处是:换一个 AI 厂商,只需要换实现类和配置,业务代码完全不用动

2.3 核心类一览

类名 官方文档对应 通俗解释
ImageModel 核心接口 "图片生成器"的规范
OpenAiImageModel OpenAI 实现 具体的 OpenAI “图片生成器”
ImagePrompt 请求对象 把"我要什么图"封装成一个请求
ImageMessage 消息对象 一条图片描述文本(可设权重)
OpenAiImageOptions Runtime Options 控制生成参数的选项对象
ImageResponse 响应对象 AI 返回的生成结果
ImageGeneration 单张结果 一张图片的具体数据

2.4 调用流程图

  ┌──────────────────────────────────────────────────────┐
  │                   你的 Spring Boot 应用                │
  │                                                      │
  │  1. 构建 OpenAiImageOptions(设置质量、尺寸、风格等)   │
  │              ↓                                       │
  │  2. 构建 ImagePrompt(提示词 + Options)              │
  │              ↓                                       │
  │  3. 调用 openAiImageModel.call(prompt)               │
  │              ↓                                       │
  │  ┌──── Spring AI 框架 ────┐                          │
  │  │ 组装 HTTP 请求          │                          │
  │  │ 发送到 OpenAI API       │  ← 底层自动处理           │
  │  │ 解析响应结果            │                          │
  │  └────────────────────────┘                          │
  │              ↓                                       │
  │  4. 拿到 ImageResponse                               │
  │              ↓                                       │
  │  5. 通过 .getResult().getOutput() 获取图片 URL/Base64 │
  └──────────────────────────────────────────────────────┘

3. 前置条件(Prerequisites)

官方原文
“You will need to create an API key with OpenAI to access ChatGPT models. Create an account at OpenAI signup page and generate the token on the API Keys page.”

翻译:你需要在 OpenAI 创建一个 API Key 来访问模型。在 OpenAI 注册页面注册账户,在 API Keys 页面生成密钥。

3.1 获取 API Key

  1. 打开 OpenAI 官网 并注册账号
  2. 进入 API Keys 页面
  3. 点击 “Create new secret key” 生成一个新的密钥
  4. 妥善保存密钥,它只会显示一次

3.2 配置 API Key

官方原文
“The Spring AI project defines a configuration property named spring.ai.openai.api-key that you should set to the value of the API Key obtained from openai.com.”

翻译:Spring AI 项目定义了一个名为 spring.ai.openai.api-key 的配置属性,你需要将它设置为从 openai.com 获取的 API Key。

官方文档提供了三种配置方式,按安全性从低到高排列:

方式一:直接写在配置文件中(不推荐,仅限本地测试)

# application.properties
spring.ai.openai.api-key=sk-xxxxxxxxxxxxxxxx

方式二:通过环境变量引用(推荐)

官方原文
“For enhanced security when handling sensitive information like API keys, you can use Spring Expression Language (SpEL) to reference a custom environment variable.”

# application.yml
spring:
  ai:
    openai:
      api-key: ${OPENAI_API_KEY}

然后在系统中设置环境变量:

# Linux / macOS
export OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxx

# Windows PowerShell
$env:OPENAI_API_KEY="sk-xxxxxxxxxxxxxxxx"

# Windows CMD
set OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxx

方式三:在代码中读取(适合高级场景)

String apiKey = System.getenv("OPENAI_API_KEY");

我们项目使用的方式:方式二。查看 application.yml

spring:
  ai:
    openai:
      api-key: ${OPENAI_API_KEY}

这是最佳实践——密钥不会泄露到代码仓库中。


4. 自动配置(Auto-configuration)

官方原文
“Spring AI provides Spring Boot auto-configuration for the OpenAI Image Generation Client. To enable it add the following dependency to your project’s Maven pom.xml file.”

翻译:Spring AI 为 OpenAI 图像生成客户端提供了 Spring Boot 自动配置。只需在项目的 Maven pom.xml 中添加以下依赖即可启用。

什么是"自动配置"?

如果你有 Spring Boot 基础,应该知道 自动配置(Auto-configuration) 是 Spring Boot 的核心特性——只需要引入一个 Starter 依赖,Spring Boot 就会自动帮你创建和配置好相关的 Bean。

在这里,只要你加了依赖,Spring Boot 就会 自动帮你创建一个 OpenAiImageModel 对象,你可以直接在代码中注入使用,无需手动 new

添加依赖

Maven

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

Gradle

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

注意:这个 Starter 是一个"全家桶",它同时激活了 OpenAI 的 ChatModel(聊天)、ImageModel(图像)、SpeechModel(语音)等多个模型的自动配置。也就是说,一个依赖搞定所有 OpenAI 模型

启用/禁用图像模型

官方原文
“Enabling and disabling of the image auto-configurations are now configured via top level properties with the prefix spring.ai.model.image.”

# 启用 OpenAI 图像模型(默认就是开启的)
spring.ai.model.image=openai

# 禁用图像模型
spring.ai.model.image=none

一般情况下不需要额外配置,默认就是启用的。


5. 配置属性详解(Configuration Properties)

这是官方文档中篇幅最大的部分,也是新手最容易迷惑的部分。官方文档用表格列出了大量配置属性,但没有详细解释每个属性的应用场景。让我们逐一拆解。

5.1 连接属性(Connection Properties)

官方原文
“The prefix spring.ai.openai is used as the property prefix that lets you connect to OpenAI.”

这些属性控制"如何连接到 OpenAI 服务器":

属性 说明 默认值 什么时候需要改?
spring.ai.openai.base-url API 服务器地址 https://api.openai.com 使用代理或第三方兼容服务时
spring.ai.openai.api-key API 密钥 必填
spring.ai.openai.organization-id 组织 ID 属于多个组织时,指定使用哪个
spring.ai.openai.project-id 项目 ID 需要区分不同项目的用量时

实用提示:如果你使用的是国内的 OpenAI 代理服务(中转 API),只需修改 base-url 即可,比如:

spring:
  ai:
    openai:
      base-url: https://your-proxy-server.com
      api-key: ${OPENAI_API_KEY}

5.2 重试属性(Retry Properties)

官方原文
“The prefix spring.ai.retry is used as the property prefix that lets you configure the retry mechanism for the OpenAI Image client.”

网络请求可能会失败(网络波动、服务器过载等),Spring AI 内置了自动重试机制:

属性 说明 默认值 通俗解释
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 4xx 错误是否重试 false 参数错误(如 400)不重试
spring.ai.retry.exclude-on-http-codes 排除特定 HTTP 状态码 指定哪些错误码不重试
spring.ai.retry.on-http-codes 指定重试的 HTTP 状态码 指定哪些错误码要重试

举个例子:假设默认配置下,第一次请求失败后等 2 秒重试,第二次失败等 10 秒(2×5),第三次等 50 秒(10×5),但不超过 3 分钟。这就是"指数退避"策略,避免频繁重试给服务器造成压力。

大多数情况下,默认值就够用了,不需要修改。

5.3 图像模型属性(Image Generation Properties)

官方原文
“The prefix spring.ai.openai.image is the property prefix that lets you configure the ImageModel implementation for OpenAI.”

翻译:以 spring.ai.openai.image 为前缀的属性用来配置 OpenAI 的图像模型实现。

这些是最核心的配置,直接决定了生成图片的效果:

属性 说明 默认值 详细解释
spring.ai.openai.image.options.model 模型 dall-e-3 选择使用哪个 DALL-E 版本
spring.ai.openai.image.options.n 生成数量 - 一次生成几张图。DALL-E-2 支持 1~10,DALL-E-3 只支持 1
spring.ai.openai.image.options.quality 图片质量 - standard(标准)或 hd(高清,更精细)。仅 DALL-E-3 支持
spring.ai.openai.image.options.response_format 响应格式 - url(返回图片链接)或 b64_json(返回 Base64 编码)
spring.ai.openai.image.options.size 图片尺寸 - 1024x1024。不同模型支持的尺寸不同(见下文)
spring.ai.openai.image.options.size_width 图片宽度 - 也可以单独设置宽度
spring.ai.openai.image.options.size_height 图片高度 - 也可以单独设置高度
spring.ai.openai.image.options.style 图片风格 - vivid(鲜艳夸张)或 natural(自然写实)。仅 DALL-E-3 支持
spring.ai.openai.image.options.user 用户标识 - 传给 OpenAI 用于监控和滥用检测

官方文档还提到,图像模型属性可以独立覆盖连接属性:

  • spring.ai.openai.image.base-url:单独为图像模型设置不同的 API 地址
  • spring.ai.openai.image.api-key:单独为图像模型设置不同的 API Key

这在你的聊天模型和图像模型使用不同 API 提供商时非常有用。

DALL-E-2 与 DALL-E-3 支持的尺寸对比

这是新手最容易搞错的地方,官方文档虽然提到了但没有单独对比:

DALL-E-2 DALL-E-3
支持尺寸 256x256512x5121024x1024 1024x10241792x1024(横版)、1024x1792(竖版)
支持 quality ❌ 不支持 standard / hd
支持 style ❌ 不支持 vivid / natural
最大生成数 N 10 1(只能生成 1 张)
配置文件完整示例
spring:
  ai:
    openai:
      api-key: ${OPENAI_API_KEY}
      image:
        options:
          model: dall-e-3        # 使用 DALL-E-3 模型
          quality: hd            # 高清质量
          size: 1024x1024        # 图片尺寸
          style: vivid           # 鲜艳风格
          n: 1                   # 每次生成 1 张

6. 运行时选项(Runtime Options)——官方文档核心

官方原文
“The OpenAiImageOptions.java provides model configurations, such as the model to use, the quality, the size, etc.”

“On start-up, the default options can be configured with the OpenAiImageModel(OpenAiImageApi openAiImageApi) constructor and the withDefaultOptions(OpenAiImageOptions defaultOptions) method. Alternatively, use the spring.ai.openai.image.options.* properties described previously.”

“At runtime you can override the default options by adding new, request specific, options to the ImagePrompt call.”

这段话揭示了 Spring AI 配置的两层机制,这是理解官方文档的关键:

第一层:默认配置(启动时生效)

通过配置文件 application.yml 中的 spring.ai.openai.image.options.* 属性设置。这些是全局默认值,对所有图片生成请求生效。

spring:
  ai:
    openai:
      image:
        options:
          model: dall-e-3
          quality: standard

第二层:运行时覆盖(每次请求可不同)

在代码中通过 OpenAiImageOptions 对象,针对单次请求覆盖默认值。

ImageResponse response = openaiImageModel.call(
    new ImagePrompt("A light cream colored mini golden doodle",
            OpenAiImageOptions.builder()
                    .quality("hd")     // 覆盖默认的 "standard",这次用 "hd"
                    .N(1)
                    .height(1024)
                    .width(1024)
                    .build())
);

通俗比喻:就像打印机的默认设置是"黑白打印",但你某次需要"彩色打印"时,可以在打印对话框里临时改成彩色——默认配置是全局的,运行时选项是临时的

OpenAiImageOptions Builder 完整参数

官方原文给了一个完整的代码示例:

ImageResponse response = openaiImageModel.call(
    new ImagePrompt("A light cream colored mini golden doodle",
            OpenAiImageOptions.builder()
                    .quality("hd")
                    .N(4)
                    .height(1024)
                    .width(1024).build())
);

逐个参数讲解:

Builder 方法 对应配置属性 类型 可选值 说明
.model() options.model String dall-e-2, dall-e-3 选择 DALL-E 模型版本
.quality() options.quality String standard, hd 图片质量。hd = 更精细,仅 DALL-E-3
.N() options.n Integer 1~10 生成数量。DALL-E-3 只能为 1
.height() options.size_height Integer 256, 512, 1024 图片高度(像素)
.width() options.size_width Integer 256, 512, 1024 图片宽度(像素)
.style() options.style String vivid, natural 图片风格,仅 DALL-E-3
.responseFormat() options.response_format String url, b64_json 返回格式
.user() options.user String 任意 终端用户标识

ImagePrompt 的多种构造方式

// 方式一:只传提示词,使用全局默认配置
ImagePrompt prompt1 = new ImagePrompt("一只可爱的猫咪");

// 方式二:提示词 + 运行时选项(最常用)
ImagePrompt prompt2 = new ImagePrompt("一只可爱的猫咪",
        OpenAiImageOptions.builder()
                .quality("hd")
                .N(1)
                .height(1024)
                .width(1024).build());

// 方式三:使用 ImageMessage 对象(支持设置权重)
ImageMessage message = new ImageMessage("太空站内部景观, 高科技感", 1.2f);
ImagePrompt prompt3 = new ImagePrompt(message,
        OpenAiImageOptions.builder().build());

7. 官方示例控制器解读(Sample Controller)

官方原文(来自 openai-sdk-image.html)提供了一个示例控制器:

@RestController
public class ImageController {

    private final ImageModel imageModel;

    @Autowired
    public ImageController(ImageModel imageModel) {
        this.imageModel = imageModel;
    }

    @GetMapping("/ai/image")
    public Map<String, Object> generateImage(
            @RequestParam(value = "prompt",
                    defaultValue = "A light cream colored mini golden doodle")
            String prompt) {

        ImageResponse response = this.imageModel.call(
                new ImagePrompt(prompt,
                        OpenAiSdkImageOptions.builder()
                                .quality("hd")
                                .N(1)
                                .width(1024)
                                .height(1024)
                                .build()));

        String imageUrl = response.getResult().getOutput().getUrl();
        return Map.of("url", imageUrl);
    }
}

让我们逐行解读这段官方示例:

1. 注入方式

private final ImageModel imageModel;

@Autowired
public ImageController(ImageModel imageModel) {
    this.imageModel = imageModel;
}

注意官方用的是 ImageModel 接口类型(而不是具体的 OpenAiImageModel),并使用构造器注入。这是 Spring 推荐的最佳实践——面向接口编程,方便未来切换 AI 提供商。

2. 接收用户输入

@RequestParam(value = "prompt",
        defaultValue = "A light cream colored mini golden doodle")
String prompt

通过 URL 参数接收用户的提示词,例如:/ai/image?prompt=一只猫咪

3. 构建请求 & 调用模型

ImageResponse response = this.imageModel.call(
        new ImagePrompt(prompt, OpenAiSdkImageOptions.builder()
                .quality("hd").N(1).width(1024).height(1024)
                .build()));

这就是完整的调用过程:构建 Prompt → 调用 call() → 获取 Response

4. 提取结果

String imageUrl = response.getResult().getOutput().getUrl();
return Map.of("url", imageUrl);

调用链:response.getResult() 得到 ImageGeneration.getOutput() 得到 Image.getUrl() 得到图片 URL 字符串。

我们项目中的差异:我们的 OpenaiImageControlelr 和官方示例逻辑一致,但做了两个扩展——把图片直接渲染到浏览器(URL 方式和 Base64 方式),这在官方文档中没有涉及。接下来详细讲解。


8. 实战进阶:三种图片生成方式(结合项目代码)

项目中的 OpenaiImageControlelr.java 提供了三种使用方式,覆盖了从简到繁的三个场景。

8.1 基础调用——获取图片 URL

这是最贴近官方示例的写法:

@Autowired
private OpenAiImageModel openAiImageModel;

@RequestMapping("/image")
public void image(){
    ImageResponse response = openAiImageModel.call(
            new ImagePrompt("A light cream colored mini golden doodle",
                    OpenAiImageOptions.builder()
                            .quality("hd")
                            .N(1)
                            .height(1024)
                            .width(1024).build())
    );
    String imageUrl = response.getResult().getOutput().getUrl();
    System.out.println(imageUrl);
}

和官方示例的对比

对比项 官方示例 我们的代码
注入类型 ImageModel(接口) OpenAiImageModel(实现类)
注入方式 构造器注入 @Autowired 字段注入
返回方式 返回 JSON {"url": "..."} 打印到控制台

两种写法功能完全一样,官方的写法更规范(面向接口 + 构造器注入),但我们的写法更简洁直观,适合学习。

访问方式http://localhost:8080/openai/image,然后在控制台查看输出的 URL。


8.2 URL 方式——下载图片返回给浏览器

官方文档中只返回了图片的 URL 字符串,而在实际业务中,我们通常需要把图片直接展示给用户。下面这段代码展示了如何做到:

@RequestMapping("/image2")
public void image2(HttpServletResponse response){
    ImageResponse imageResponse = openAiImageModel.call(
            new ImagePrompt("孩子在海边玩耍", OpenAiImageOptions.builder()
                    .quality("standard")
                    .N(1)
                    .height(1024)
                    .width(1024)
                    .style("natural")
                    .build())
    );

    String imageUrl = imageResponse.getResult().getOutput().getUrl();
    try {
        URL url = URI.create(imageUrl).toURL();
        InputStream in = url.openStream();

        // 输出到浏览器
        response.setHeader("Content-Type", MediaType.IMAGE_JPEG_VALUE);
        response.getOutputStream().write(in.readAllBytes());
        response.getOutputStream().flush();

    } catch (IOException e) {
        response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    }
}

关键点解析

1. 中文提示词:DALL-E 支持中文描述,"孩子在海边玩耍" 可以正常工作。

2. style("natural"):使用官方文档中提到的 natural 风格。

官方原文
“The style of the generated images. Must be one of vivid or natural. Vivid causes the model to lean towards generating hyper-real and dramatic images. Natural causes the model to produce more natural, less hyper-real looking images.”

  • vivid:超现实、戏剧化——适合创意设计、概念艺术
  • natural:自然写实——适合生活场景、产品图

3. 图片下载并返回浏览器的流程

OpenAI 返回图片临时 URL
    ↓
URI.create(imageUrl).toURL()    // 将字符串转为 URL 对象
    ↓
url.openStream()                 // 打开网络输入流,下载图片
    ↓
response.setHeader("Content-Type", "image/jpeg")  // 告诉浏览器这是图片
    ↓
response.getOutputStream().write(in.readAllBytes()) // 写入响应
    ↓
浏览器直接展示图片

访问方式http://localhost:8080/openai/image2,等待片刻后浏览器直接显示图片。


8.3 Base64 方式——直接返回图片数据

官方原文
response_format: The format in which the generated images are returned. Must be one of url or b64_json.”

使用 b64_json 格式,OpenAI 会直接在响应中返回图片的 Base64 编码,省去了二次下载:

@RequestMapping("/image3")
public void image3(HttpServletResponse response){
    ImageResponse imageResponse = openAiImageModel.call(
            new ImagePrompt("孩子在海边玩耍", OpenAiImageOptions.builder()
                    .quality("standard")
                    .N(1)
                    .height(1024)
                    .width(1024)
                    .responseFormat("b64_json")   // 关键:指定返回 Base64
                    .style("natural")
                    .build())
    );

    // 注意:这里用的是 getB64Json() 而不是 getUrl()
    String b64Json = imageResponse.getResult().getOutput().getB64Json();

    try {
        // 把 Base64 字符串解码为字节数组
        byte[] decode = Base64.getDecoder().decode(b64Json);
        // 输出到浏览器
        response.setHeader("Content-Type", MediaType.IMAGE_JPEG_VALUE);
        response.getOutputStream().write(decode);
        response.getOutputStream().flush();

    } catch (IOException e) {
        response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    }
}

关键差异

对比项 image2(URL 方式) image3(Base64 方式)
responseFormat 不设置(默认 url "b64_json"
获取数据 .getOutput().getUrl() .getOutput().getB64Json()
后续处理 需要通过 URL 下载图片字节 直接用 Base64.getDecoder().decode() 解码
是否有网络延迟 有(需要二次下载) 无(数据已在响应中)

访问方式http://localhost:8080/openai/image3


9. 两种响应格式深度对比:URL vs Base64

官方原文
response_format: The format in which the generated images are returned. Must be one of url or b64_json.”

这是使用 ImageModel 时最重要的决策之一,值得单独展开:

对比维度 url 格式(默认) b64_json 格式
响应内容 图片的临时访问 URL 图片的 Base64 编码字符串
获取图片的 Java 方法 getOutput().getUrl() getOutput().getB64Json()
响应体积 很小(只有 URL 字符串) 很大(整张图片编码后的文本)
链接有效期 约 1 小时后失效 不存在链接问题,数据在手
获取图片数据 需通过 URL 二次下载 直接 Base64 解码即可
适用场景 前端直接用 <img src="url"> 展示 需要保存到数据库/文件/OSS
网络稳定性要求 需要两次网络请求 一次请求搞定

选择建议

  • 只需要前端临时展示:用 url(默认),更轻量
  • 需要持久保存图片:用 b64_json,避免 URL 过期问题
  • 网络环境不稳定:用 b64_json,减少网络请求次数

10. 手动配置(Manual Configuration)

官方原文(来自 openai-sdk-image.html):
“If you are not using Spring Boot auto-configuration, you can manually configure the OpenAI SDK Image Model.”

如果你的项目没有使用 Spring Boot 自动配置(比如非 Spring Boot 项目或有特殊需求),官方文档提供了手动创建 ImageModel 的方式:

// 1. 构建默认选项
var imageOptions = OpenAiImageOptions.builder()
        .model("dall-e-3")
        .quality("hd")
        .build();

// 2. 手动创建 ImageModel(SDK 版本示例)
var imageModel = new OpenAiSdkImageModel(imageOptions);

// 3. 调用生成
ImageResponse response = imageModel.call(
        new ImagePrompt("A light cream colored mini golden doodle",
                OpenAiSdkImageOptions.builder()
                        .N(1)
                        .width(1024)
                        .height(1024)
                        .build()));

什么时候用手动配置?

  • 非 Spring Boot 项目(纯 Spring 或其他框架)
  • 需要同时创建多个不同配置的 ImageModel 实例
  • 需要完全控制对象创建过程

对于大多数 Spring Boot 项目,自动配置就够了,不需要手动创建。


11. 可观测性(Observability)

官方原文(来自 openai-sdk-image.html):
“The OpenAI SDK implementation supports Spring AI’s observability features through Micrometer. All image model operations are instrumented for monitoring and tracing.”

翻译:OpenAI SDK 实现通过 Micrometer 支持 Spring AI 的可观测性特性。所有图像模型操作都已配置了监控和追踪。

这意味着你可以通过 Spring Boot Actuator + Micrometer 监控图像生成的:

  • 调用次数
  • 响应时间
  • 错误率

这对生产环境非常有用,但对入门学习不是必须的。如果需要接入,只需添加 Actuator 和 Micrometer 相关依赖即可。


12. 扩展阅读:SpeechModel 语音生成(类比理解 Spring AI 统一设计)

Spring AI 的一大设计亮点是所有模型遵循相同的使用范式。为了加深理解,我们对比看一下项目中 OpenaiSpeechControlelr.java 的语音生成代码:

@Autowired
private OpenAiAudioSpeechModel openAiAudioSpeechModel;

@RequestMapping("/tts")
public void tts(){
    // 1. 构建语音选项(类比 OpenAiImageOptions)
    OpenAiAudioSpeechOptions speechOptions = OpenAiAudioSpeechOptions.builder()
            .model("tts-1")
            .voice(OpenAiAudioApi.SpeechRequest.Voice.NOVA)
            .responseFormat(OpenAiAudioApi.SpeechRequest.AudioResponseFormat.OPUS)
            .speed(1.0f)
            .build();

    // 2. 构建语音请求(类比 ImagePrompt)
    SpeechPrompt speechPrompt = new SpeechPrompt(
            "小池, 泉眼无声惜细流, 树阴照水爱晴柔. 小荷才露尖尖角, 早有蜻蜓立上头",
            speechOptions);

    // 3. 调用模型生成语音(类比 imageModel.call())
    SpeechResponse response = openAiAudioSpeechModel.call(speechPrompt);

    // 4. 将语音数据写入文件
    File file = new File(System.getProperty("user.dir") + "/output.opus");
    try (FileOutputStream fos = new FileOutputStream(file)) {
        fos.write(response.getResult().getOutput());
    } catch (IOException e) {
        log.error("文件写入失败, e:", e);
    }
}

类比对照表

步骤 图像生成(ImageModel) 语音生成(SpeechModel)
模型类 OpenAiImageModel OpenAiAudioSpeechModel
选项类 OpenAiImageOptions OpenAiAudioSpeechOptions
请求类 ImagePrompt SpeechPrompt
响应类 ImageResponse SpeechResponse
输出类型 图片 URL / Base64 音频字节数组
调用方式 imageModel.call(prompt) speechModel.call(prompt)

统一模式构建 Options → 构建 Prompt → 调用 Model.call() → 处理 Response

这就是 Spring AI 的优雅之处——所有模型遵循相同的调用范式,学会一个就能触类旁通。


13. 常见问题与排错指南

Q1:调用报 401 Unauthorized?

原因:API Key 配置错误或未设置环境变量。
解决:检查 OPENAI_API_KEY 环境变量是否正确设置,确认 Key 是否有效。

Q2:调用报 400 Bad Request?

原因:参数组合不合法,需参照官方文档中的参数约束。
解决

  • dall-e-3N 参数只能为 1
  • dall-e-2 不支持 stylequality 参数
  • 尺寸必须是模型支持的值(参见第 5.3 节的对比表)

Q3:图片 URL 过期了怎么办?

OpenAI 返回的图片 URL 是临时链接(通常 1 小时内有效)。如果需要长期保存,参照官方文档建议:

  • 使用 b64_json 格式直接获取图片数据
  • 或拿到 URL 后立即下载并存储到自己的服务器/OSS

Q4:生成速度很慢?

  • DALL-E-3 + hd 质量会比较慢,可以尝试 standard 质量
  • Spring AI 内置的重试机制也可能导致感知变慢(参见第 5.2 节的重试属性)
  • 网络因素也可能影响速度,建议配置代理

Q5:可以生成多张图片吗?

  • dall-e-2:支持,N 可设置 1~10
  • dall-e-3不支持,每次只能生成 1 张(官方文档明确说明)

14. 总结

本文沿着官方文档的脉络,用通俗的语言重新梳理了 Spring AI ImageModel 的完整知识体系:

官方文档章节 本文对应 核心要点
Prerequisites 第 3 章 获取并安全配置 API Key
Auto-configuration 第 4 章 加一个 Starter 依赖即可自动注入 ImageModel
Configuration Properties 第 5 章 连接、重试、图像生成三类属性,DALL-E-2 与 DALL-E-3 参数差异
Runtime Options 第 6 章 两层配置机制——全局默认 + 运行时覆盖
Sample Controller 第 7 章 官方示例逐行解读
Manual Configuration 第 10 章 非 Spring Boot 项目的手动配置方式
Observability 第 11 章 通过 Micrometer 监控模型调用

额外收获

  • 三种图片输出方式(控制台 URL、浏览器 URL 下载、浏览器 Base64 直出)
  • URL vs Base64 响应格式的深度对比与选型建议
  • 通过 SpeechModel 类比,理解 Spring AI 的统一设计模式

15. 参考资料

Spring AI 官方文档

OpenAI 官方文档

其他

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐