前面我们让 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 支持 hdn: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 层直接注入具体实现类,避免歧义。
packagecom.example.springaihelloworld.service;importorg.springframework.ai.image.ImagePrompt;importorg.springframework.ai.image.ImageResponse;importorg.springframework.ai.openai.OpenAiImageModel;importorg.springframework.ai.openai.OpenAiImageOptions;importorg.springframework.ai.qianfan.QianfanImageModel;importorg.springframework.ai.qianfan.QianfanImageOptions;importorg.springframework.stereotype.Service;@ServicepublicclassImageService{privatefinalOpenAiImageModelopenAiImageModel;privatefinalQianfanImageModelqianfanImageModel;publicImageService(OpenAiImageModelopenAiImageModel,QianfanImageModelqianfanImageModel){this.openAiImageModel=openAiImageModel;this.qianfanImageModel=qianfanImageModel;}/** * 使用 OpenAI DALL-E 生成图片,返回图片 URL */publicStringgenerateImageOpenAI(Stringprompt){ImageResponseresponse=openAiImageModel.call(newImagePrompt(prompt,OpenAiImageOptions.builder().withModel("dall-e-2")// 模型名称.withHeight(1024).withWidth(1024).withN(1)// 生成一张.build()));// 从响应中提取图片 URLStringimageUrl=response.getResult().getOutput().getUrl();returnimageUrl;}/** * 使用百度千帆生成图片,返回图片 URL */publicStringgenerateImageQianfan(Stringprompt){ImageResponseresponse=qianfanImageModel.call(newImagePrompt(prompt,QianfanImageOptions.builder().withModel("Stable-Diffusion-XL")// 千帆模型.withN(1).build()));StringimageUrl=response.getResult().getOutput().getUrl();returnimageUrl;}}关键点解读:
ImagePrompt的构造函数接收提示词和ImageOptions。- 每个模型有自己的
XxxImageOptions构建器,可以设置特定参数。你也可以跳过这一步,直接使用配置文件中的默认选项。 getResult().getOutput().getUrl()返回生成图片的临时 URL。如果是 Base64 返回,可以使用getB64Json()(DALL-E 3 默认返回 Base64),但 URL 模式更方便前端直接展示。
4.2 创建 ImageController
packagecom.example.springaihelloworld.controller;importcom.example.springaihelloworld.service.ImageService;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RequestParam;importorg.springframework.web.bind.annotation.RestController;@RestControllerpublicclassImageController{privatefinalImageServiceimageService;publicImageController(ImageServiceimageService){this.imageService=imageService;}/** * OpenAI 图像生成 * GET /image/openai?prompt=一只戴着墨镜的柴犬 * 返回图片 URL */@GetMapping("/image/openai")publicStringgenerateOpenAiImage(@RequestParamStringprompt){StringimageUrl=imageService.generateImageOpenAI(prompt);return"图片已生成,URL: "+imageUrl;}/** * 千帆图像生成 * GET /image/qianfan?prompt=一只戴着墨镜的柴犬 * 返回图片 URL */@GetMapping("/image/qianfan")publicStringgenerateQianfanImage(@RequestParamStringprompt){StringimageUrl=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();Stringb64=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 的有效期和访问权限限制。