图像生成初探:OpenAI 与千帆平台一键出图
前面我们让 AI 学会了对话、推理,但一直局限于文字。今天我们要解锁一个新维度——图像生成。只需要一句描述,AI 就能帮你画出对应的图片。
在 Spring AI 中,图像生成和对话聊天使用的是完全不同的模型接口。对话用的是 ChatClient,而图像生成用的是 ImageModel。好消息是,Spring AI 对图像模型也做了统一抽象,接入 OpenAI DALL-E 和百度千帆的文生图服务,代码结构几乎一样。今天我们就来同时打通这两条路,让你感受“一套 API,两套模型”的便捷。
一、痛点场景:当文字不够用的时候
你是否遇到过这样的需求:
- 做一个“AI 绘画”功能,用户输入“一只戴着墨镜的柴犬在沙滩上冲浪”,后端调用模型生成图片并返回。
- 需要动态生成营销海报背景,而不是让设计师手动出图。
- 想在应用中集成图片生成能力,但不想维护两套代码去对接不同的厂商。
如果你之前有过对接图像生成 API 的经验,可能会头疼于各家不同的请求格式、认证方式、返回结构。Spring AI 的 ImageModel 抽象正是为此而生:它定义了统一的 ImagePrompt 输入和 ImageResponse 输出,让你用同样的代码风格调用完全不同的图像模型。
二、核心概念快览
2.1 ImageModel:图像生成的“ChatClient”
和 ChatModel 负责聊天类似,ImageModel 是 Spring AI 中负责图像生成的核心接口。它定义了一个 call 方法,接收 ImagePrompt,返回 ImageResponse。
2.2 ImagePrompt 与 ImageOptions
- ImagePrompt:封装了一次图像生成请求的所有信息,包括提示词(描述文字)和生成选项(
ImageOptions)。 - ImageOptions:控制生成参数,比如图片尺寸、数量、风格等。不同模型支持的选项不同,但 Spring AI 提供了一组通用的属性,比如
height、width、n(生成数量)。
2.3 工作流程
用户输入描述文字
↓
构建 ImagePrompt(描述 + 选项)
↓
调用 imageModel.call(imagePrompt)
↓
返回 ImageResponse(包含生成的图片 URL 或 Base64 数据)
你不需要关心底层是 OpenAI 的 HTTP API 还是千帆的 RESTful 接口,因为 Spring AI 的自动配置已经帮你封装好了。
三、环境准备
3.1 获取 API Key
OpenAI
访问 platform.openai.com/api-keys 创建 API Key。图像生成需要账户有额度,DALL-E 2 和 DALL-E 3 的计费不同,建议先用 DALL-E 2 测试(成本更低)。
百度千帆
访问 console.bce.baidu.com/qianfan 开通千帆服务。在“应用接入”中创建应用,获取 API Key 和 Secret Key。千帆需要使用这两把钥匙通过 OAuth 获取 access_token,Spring AI 的 starter 会自动处理。
务必设置环境变量,避免将 Key 写入代码仓库:
- OpenAI:
export OPENAI_API_KEY=sk-xxx- 千帆:
export QIANFAN_API_KEY=your-api-key和export QIANFAN_SECRET_KEY=your-secret-key
3.2 Maven 依赖
在 pom.xml 中同时引入 OpenAI 和千帆的图像生成支持。我们继续使用 Spring AI 的 BOM 管理版本。
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring AI OpenAI Starter(包含 Chat 和 Image 模型) -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
<!-- Spring AI Qianfan Starter(包含聊天、图像、嵌入等) -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-qianfan</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>1.1.6</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
这两个 starter 可以在同一项目中共存,因为它们的自动配置会根据配置的前缀(
spring.ai.openai和spring.ai.qianfan)区分,不会互相冲突。如果你的项目之前只有 OpenAI starter,直接添加千帆依赖即可。
3.3 application.yml 配置
spring:
ai:
# OpenAI 图像生成配置
openai:
api-key: ${OPENAI_API_KEY}
image:
options:
model: dall-e-2 # 可选 dall-e-3,但更贵
size: 1024x1024 # 图片尺寸
quality: standard # dall-e-3 支持 hd
n: 1 # 生成数量
# 百度千帆图像生成配置
qianfan:
api-key: ${QIANFAN_API_KEY}
secret-key: ${QIANFAN_SECRET_KEY}
image:
options:
model: Stable-Diffusion-XL # 千帆支持的文生图模型
style: default # 风格
n: 1
四、代码实战
4.1 创建 ImageService
我们将分别使用 OpenAiImageModel 和 QianfanImageModel 来演示,因为它们各自需要不同的配置。Service 层直接注入具体实现类,避免歧义。
package com.example.springaihelloworld.service;
import org.springframework.ai.image.ImagePrompt;
import org.springframework.ai.image.ImageResponse;
import org.springframework.ai.openai.OpenAiImageModel;
import org.springframework.ai.openai.OpenAiImageOptions;
import org.springframework.ai.qianfan.QianfanImageModel;
import org.springframework.ai.qianfan.QianfanImageOptions;
import org.springframework.stereotype.Service;
@Service
public class ImageService {
private final OpenAiImageModel openAiImageModel;
private final QianfanImageModel qianfanImageModel;
public ImageService(OpenAiImageModel openAiImageModel,
QianfanImageModel qianfanImageModel) {
this.openAiImageModel = openAiImageModel;
this.qianfanImageModel = qianfanImageModel;
}
/**
* 使用 OpenAI DALL-E 生成图片,返回图片 URL
*/
public String generateImageOpenAI(String prompt) {
ImageResponse response = openAiImageModel.call(
new ImagePrompt(prompt,
OpenAiImageOptions.builder()
.withModel("dall-e-2") // 模型名称
.withHeight(1024)
.withWidth(1024)
.withN(1) // 生成一张
.build()));
// 从响应中提取图片 URL
String imageUrl = response.getResult().getOutput().getUrl();
return imageUrl;
}
/**
* 使用百度千帆生成图片,返回图片 URL
*/
public String generateImageQianfan(String prompt) {
ImageResponse response = qianfanImageModel.call(
new ImagePrompt(prompt,
QianfanImageOptions.builder()
.withModel("Stable-Diffusion-XL") // 千帆模型
.withN(1)
.build()));
String imageUrl = response.getResult().getOutput().getUrl();
return imageUrl;
}
}
关键点解读:
ImagePrompt的构造函数接收提示词和ImageOptions。- 每个模型有自己的
XxxImageOptions构建器,可以设置特定参数。你也可以跳过这一步,直接使用配置文件中的默认选项。 getResult().getOutput().getUrl()返回生成图片的临时 URL。如果是 Base64 返回,可以使用getB64Json()(DALL-E 3 默认返回 Base64),但 URL 模式更方便前端直接展示。
4.2 创建 ImageController
package com.example.springaihelloworld.controller;
import com.example.springaihelloworld.service.ImageService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ImageController {
private final ImageService imageService;
public ImageController(ImageService imageService) {
this.imageService = imageService;
}
/**
* OpenAI 图像生成
* GET /image/openai?prompt=一只戴着墨镜的柴犬
* 返回图片 URL
*/
@GetMapping("/image/openai")
public String generateOpenAiImage(@RequestParam String prompt) {
String imageUrl = imageService.generateImageOpenAI(prompt);
return "图片已生成,URL: " + imageUrl;
}
/**
* 千帆图像生成
* GET /image/qianfan?prompt=一只戴着墨镜的柴犬
* 返回图片 URL
*/
@GetMapping("/image/qianfan")
public String generateQianfanImage(@RequestParam String prompt) {
String imageUrl = imageService.generateImageQianfan(prompt);
return "图片已生成,URL: " + imageUrl;
}
}
五、运行与演示
5.1 启动应用
确保 OPENAI_API_KEY、QIANFAN_API_KEY、QIANFAN_SECRET_KEY 三个环境变量已正确设置,然后启动 Spring Boot 应用。
5.2 测试 OpenAI 图像生成
访问:
http://localhost:8080/image/openai?prompt=一只戴着墨镜的柴犬在沙滩上冲浪
返回类似:
图片已生成,URL: https://oaidalleapiprodscus.blob.core.windows.net/private/org-.../img-....png
复制该 URL 到浏览器,就能看到 AI 画的柴犬冲浪图了。
5.3 测试千帆图像生成
访问:
http://localhost:8080/image/qianfan?prompt=一只戴着墨镜的柴犬在沙滩上冲浪
稍等几秒,返回图片 URL。同样在浏览器中打开,验证效果。你可能会发现两个模型生成的风格有所不同,千帆的 Stable Diffusion 画面更偏写实或动漫风格(取决于你的模型选择),而 DALL-E 2 更倾向于艺术化渲染。
六、常见问题与避坑提示
问题一:OpenAI 返回“b64_json”而不是 URL
在 DALL-E 3 中,默认响应格式是 Base64 编码的图片数据,而不是 URL。如果你需要 URL,可以在 OpenAiImageOptions 中设置 withResponseFormat("url")(DALL-E 3 不支持 URL,只支持 Base64)。对于 DALL-E 3,你需要从 getOutput().getB64Json() 获取 Base64 字符串,然后在前端解码显示。
修改方法示例:
OpenAiImageOptions.builder()
.withModel("dall-e-3")
.withResponseFormat("b64_json") // dall-e-3 只能这样
.build();
String b64 = response.getResult().getOutput().getB64Json();
问题二:千帆 API 返回“access_token invalid”
原因通常是 api-key 或 secret-key 配置错误。千帆的认证流程需要先通过 key 和 secret 换取 token,Spring AI 的 starter 会自动处理。如果 token 获取失败,检查环境变量是否正确,且千帆控制台中该应用已启用“图像生成”服务。
问题三:同时存在两个 ImageModel Bean 导致启动报错
我们直接注入了 OpenAiImageModel 和 QianfanImageModel 的具体类型,没有使用 ImageModel 接口,因此不存在歧义。如果你通过 @Autowired ImageModel 注入,Spring 会发现两个候选 Bean 而报错。此时需要使用 @Qualifier 或 @Primary 解决。建议直接注入具体类型,这是最简单稳妥的方式。
问题四:生成的图片有内容安全限制
OpenAI 和千帆都有内容审核机制。如果提示词包含违规内容,API 会拒绝生成并返回错误。应用中应捕获相关异常并给出友好提示。
问题五:生成速度较慢
图像生成通常比文本生成耗时更长,5-20 秒都属正常。如果想提升用户体验,可以像上一篇的流式对话一样,结合异步处理:接口立刻返回“正在生成”,然后通过轮询或 WebSocket 推送完成通知和图片地址。
七、小结与下一步预告
本篇回顾
- 理解了 Spring AI 中
ImageModel的统一图像生成接口。 - 掌握了
ImagePrompt和ImageOptions的构建方式。 - 使用同一个 Service 结构,分别接入了 OpenAI DALL-E 和百度千帆两个图像生成平台。
- 学会了如何处理 Base64 和 URL 两种返回格式。
动手建议
在你的项目中挑选一个场景(比如生成用户头像、海报背景),用本文的代码骨架,分别接入 OpenAI 和千帆,对比出图质量和成本,选出最适合你业务的模型。
下一步预告
图像能生成了,那声音呢?下一篇我们将进入 语音交互实战,用 Spring AI 的语音模型封装,实现文本转语音(TTS)和语音转文字(STT)。让你的 AI 应用不仅能“看”,还能“说”和“听”。
下一篇《语音交互实战:TTS 与 STT 的 Spring AI 封装》见。
本系列博客基于 Spring AI 1.1.6 版本编写。图像生成模型的可用性和计费规则可能随时变化,请参考各平台的官方文档。实际开发中,请注意图片 URL 的有效期和访问权限限制。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)