本文定位:这是一篇基于 Spring AI 官方文档的二次创作。本文将按照官方文档的结构,逐节用通俗易懂的语言重新解读,并结合真实项目代码帮助你理解每一个知识点。
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 → 运行时选项(代码中怎么动态设置参数)
官方原文:Spring AI supports DALL-E, the Image generation model from OpenAI.
翻译:Spring AI 支持 OpenAI 的 DALL-E 图像生成模型。
一句话就点明了主题——Spring AI 帮我们封装好了调用 OpenAI DALL-E 的全部细节,开发者只需要关心"传什么参数"和"怎么拿结果"。
2. 背景知识:什么是 DALL-E 和 ImageModel
在阅读官方文档之前,先搞清楚两个基础概念。
2.1 DALL-E 是什么?
DALL-E 是 OpenAI 开发的 AI 图像生成模型。你给它一段文字描述(叫做 prompt,提示词),它就能生成一张与描述匹配的图片。
目前有两个版本:
| 模型 | 特点 |
|---|
| DALL-E-2 | 较早版本,支持批量生成(最多 10 张),尺寸选择较少 |
| DALL-E-3 | 最新版本(默认),图片质量更高,支持 style 和 quality 参数,但每次只能生成 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
- 打开 OpenAI 官网 并注册账号
- 进入 API Keys 页面
- 点击 'Create new secret key' 生成一个新的密钥
- 妥善保存密钥,它只会显示一次
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.
spring:
ai:
openai:
api-key: ${OPENAI_API_KEY}
然后在系统中设置环境变量:
export OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxx
$env:OPENAI_API_KEY="sk-xxxxxxxxxxxxxxxx"
set OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxx
我们项目使用的方式:方式二。查看 application.yml:这是最佳实践——密钥不会泄露到代码仓库中。
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.
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 即可。
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 |
|---|
| 支持尺寸 | 256x256、512x512、1024x1024 | 1024x1024、1792x1024(横版)、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
quality: hd
size: 1024x1024
style: vivid
n: 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")
.N(1)
.height(1024)
.width(1024)
.build()));
通俗比喻:就像打印机的默认设置是"黑白打印",但你某次需要"彩色打印"时,可以在打印对话框里临时改成彩色——默认配置是全局的,运行时选项是临时的。
OpenAiImageOptions Builder 完整参数
官方原文给了一个完整的代码示例:
逐个参数讲解:
| 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 message = new ImageMessage("太空站内部景观,高科技感", 1.2f);
ImagePrompt prompt3 = new ImagePrompt(message, OpenAiImageOptions.builder().build());
7. 官方示例控制器解读(Sample Controller)
官方原文(来自 openai-sdk-image.html)提供了一个示例控制器:
让我们逐行解读这段官方示例:
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) throws IOException {
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.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) throws IOException {
ImageResponse imageResponse = openAiImageModel.call(new ImagePrompt("孩子在海边玩耍",
OpenAiImageOptions.builder()
.quality("standard")
.N(1)
.height(1024)
.width(1024)
.responseFormat("b64_json")
.style("natural")
.build()));
String b64Json = imageResponse.getResult().getOutput().getB64Json();
try {
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 的方式:
var imageOptions = OpenAiImageOptions.builder()
.model("dall-e-3")
.quality("hd")
.build();
var imageModel = new OpenAiSdkImageModel(imageOptions);
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() {
OpenAiAudioSpeechOptions speechOptions = OpenAiAudioSpeechOptions.builder()
.model("tts-1")
.voice(OpenAiAudioApi.SpeechRequest.Voice.NOVA)
.responseFormat(OpenAiAudioApi.SpeechRequest.AudioResponseFormat.OPUS)
.speed(1.0f)
.build();
SpeechPrompt speechPrompt = new SpeechPrompt("小池,泉眼无声惜细流,树阴照水爱晴柔。小荷才露尖尖角,早有蜻蜓立上头", speechOptions);
SpeechResponse response = openAiAudioSpeechModel.call(speechPrompt);
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-3 的 N 参数只能为 1
dall-e-2 不支持 style 和 quality 参数
- 尺寸必须是模型支持的值(参见第 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 官方文档
其他