本文定位 :这是一篇基于 Spring AI 官方文档 - OpenAI Image Generation 的二次创作。官方文档偏向于 API 参考手册风格,对新手不够友好。本文将按照官方文档的结构,逐节用通俗易懂的语言重新解读,并结合真实项目代码帮助你理解每一个知识点。希望对大家有所帮助!
官方文档原文链接:
目录
- [1. 官方文档说了什么?------全局概览](#1. 官方文档说了什么?——全局概览)
- [2. 背景知识:什么是 DALL-E 和 ImageModel](#2. 背景知识:什么是 DALL-E 和 ImageModel)
- [3. 前置条件(Prerequisites)](#3. 前置条件(Prerequisites))
- [4. 自动配置(Auto-configuration)](#4. 自动配置(Auto-configuration))
- [5. 配置属性详解(Configuration Properties)](#5. 配置属性详解(Configuration Properties))
- [5.1 连接属性(Connection Properties)](#5.1 连接属性(Connection Properties))
- [5.2 重试属性(Retry Properties)](#5.2 重试属性(Retry Properties))
- [5.3 图像模型属性(Image Generation Properties)](#5.3 图像模型属性(Image Generation Properties))
- [6. 运行时选项(Runtime Options)------官方文档核心](#6. 运行时选项(Runtime Options)——官方文档核心)
- [7. 官方示例控制器解读(Sample Controller)](#7. 官方示例控制器解读(Sample Controller))
- [8. 实战进阶:三种图片生成方式(结合项目代码)](#8. 实战进阶:三种图片生成方式(结合项目代码))
- [8.1 基础调用------获取图片 URL](#8.1 基础调用——获取图片 URL)
- [8.2 URL 方式------下载图片返回给浏览器](#8.2 URL 方式——下载图片返回给浏览器)
- [8.3 Base64 方式------直接返回图片数据](#8.3 Base64 方式——直接返回图片数据)
- [9. 两种响应格式深度对比:URL vs Base64](#9. 两种响应格式深度对比:URL vs Base64)
- [10. 手动配置(Manual Configuration)](#10. 手动配置(Manual Configuration))
- [11. 可观测性(Observability)](#11. 可观测性(Observability))
- [12. 扩展阅读:SpeechModel 语音生成(类比理解 Spring AI 统一设计)](#12. 扩展阅读:SpeechModel 语音生成(类比理解 Spring AI 统一设计))
- [13. 常见问题与排错指南](#13. 常见问题与排错指南)
- [14. 总结](#14. 总结)
- [15. 参考资料](#15. 参考资料)
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 Generation (
openai-image.html):Spring AI 自己维护的 HTTP 客户端实现- OpenAI SDK Image Generation (
openai-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 | 最新版本(默认),图片质量更高,支持 style 和 quality 参数,但每次只能生成 1 张 |
2.2 ImageModel 是什么?
ImageModel 是 Spring AI 框架定义的一个 Java 接口,它把"调用 AI 生成图片"这件事抽象成了一个标准方法:
java
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 namedspring.ai.openai.api-keythat 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。
官方文档提供了三种配置方式,按安全性从低到高排列:
方式一:直接写在配置文件中(不推荐,仅限本地测试)
properties
# 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."
yaml
# application.yml
spring:
ai:
openai:
api-key: ${OPENAI_API_KEY}
然后在系统中设置环境变量:
bash
# Linux / macOS
export OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxx
# Windows PowerShell
$env:OPENAI_API_KEY="sk-xxxxxxxxxxxxxxxx"
# Windows CMD
set OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxx
方式三:在代码中读取(适合高级场景)
java
String apiKey = System.getenv("OPENAI_API_KEY");
我们项目使用的方式 :方式二。查看
application.yml:
yamlspring: 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:
xml
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
Gradle:
groovy
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 prefixspring.ai.model.image."
yaml
# 启用 OpenAI 图像模型(默认就是开启的)
spring.ai.model.image=openai
# 禁用图像模型
spring.ai.model.image=none
一般情况下不需要额外配置,默认就是启用的。
5. 配置属性详解(Configuration Properties)
这是官方文档中篇幅最大的部分,也是新手最容易迷惑的部分。官方文档用表格列出了大量配置属性,但没有详细解释每个属性的应用场景。让我们逐一拆解。
5.1 连接属性(Connection Properties)
官方原文 :
"The prefixspring.ai.openaiis 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即可,比如:
yamlspring: ai: openai: base-url: https://your-proxy-server.com api-key: ${OPENAI_API_KEY}
5.2 重试属性(Retry Properties)
官方原文 :
"The prefixspring.ai.retryis 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 prefixspring.ai.openai.imageis 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 张) |
配置文件完整示例
yaml
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 thewithDefaultOptions(OpenAiImageOptions defaultOptions)method. Alternatively, use thespring.ai.openai.image.options.*properties described previously.""At runtime you can override the default options by adding new, request specific, options to the
ImagePromptcall."
这段话揭示了 Spring AI 配置的两层机制,这是理解官方文档的关键:
第一层:默认配置(启动时生效)
通过配置文件 application.yml 中的 spring.ai.openai.image.options.* 属性设置。这些是全局默认值,对所有图片生成请求生效。
yaml
spring:
ai:
openai:
image:
options:
model: dall-e-3
quality: standard
第二层:运行时覆盖(每次请求可不同)
在代码中通过 OpenAiImageOptions 对象,针对单次请求覆盖默认值。
java
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 完整参数
官方原文给了一个完整的代码示例:
javaImageResponse 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 的多种构造方式
java
// 方式一:只传提示词,使用全局默认配置
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)提供了一个示例控制器:
java@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. 注入方式
java
private final ImageModel imageModel;
@Autowired
public ImageController(ImageModel imageModel) {
this.imageModel = imageModel;
}
注意官方用的是 ImageModel 接口类型 (而不是具体的 OpenAiImageModel),并使用构造器注入。这是 Spring 推荐的最佳实践------面向接口编程,方便未来切换 AI 提供商。
2. 接收用户输入
java
@RequestParam(value = "prompt",
defaultValue = "A light cream colored mini golden doodle")
String prompt
通过 URL 参数接收用户的提示词,例如:/ai/image?prompt=一只猫咪。
3. 构建请求 & 调用模型
java
ImageResponse response = this.imageModel.call(
new ImagePrompt(prompt, OpenAiSdkImageOptions.builder()
.quality("hd").N(1).width(1024).height(1024)
.build()));
这就是完整的调用过程:构建 Prompt → 调用 call() → 获取 Response。
4. 提取结果
java
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
这是最贴近官方示例的写法:
java
@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 字符串,而在实际业务中,我们通常需要把图片直接展示给用户。下面这段代码展示了如何做到:
java
@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 ofvividornatural. 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 ofurlorb64_json."
使用 b64_json 格式,OpenAI 会直接在响应中返回图片的 Base64 编码,省去了二次下载:
java
@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 ofurlorb64_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 的方式:
java
// 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 的语音生成代码:
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-3的N参数只能为 1dall-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~10dall-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 Image Generation --- 本文主要参考
- OpenAI SDK Image Generation (Official) --- 基于 OpenAI 官方 Java SDK 的版本
- Spring AI Getting Started --- 入门指南与依赖管理
- ImageOptions 源码
- OpenAiImageOptions 源码
OpenAI 官方文档
- OpenAI Images API Reference --- API 参数详细定义
- OpenAI Image Generation Guide --- DALL-E 使用指南
- OpenAI Models --- 模型列表与能力说明