文章目录
- [Spring AI Alibaba 图像模型实战(文生图)](#Spring AI Alibaba 图像模型实战(文生图))
-
- 版本
- 一、依赖引入
- [二、yml 配置](#二、yml 配置)
- 三、代码案例
-
- [1. 控制器:注入 ImageModel,三种接口](#1. 控制器:注入 ImageModel,三种接口)
- 2.(可选)图片未完成时的重试
Spring AI Alibaba 图像模型实战(文生图)
用 Spring AI Alibaba 接入阿里云百炼 DashScope,完成「文字 → 图片」。
版本
- Spring Boot:
3.4.5 - spring-ai-alibaba-starter-dashscope:
1.0.0.4 - Java:
17
Spring-ai更新速度快,请以官方为准
可参考网址:
一、依赖引入
xml
<!-- Spring Web,提供 REST 接口 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring AI Alibaba:自动装配 DashScopeImageModel -->
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
<version>1.0.0.4</version>
</dependency>
<!-- 官方 DashScope SDK(部分场景会用到) -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dashscope-sdk-java</artifactId>
<version>2.22.18</version>
</dependency>
二、yml 配置
yaml
# 复制为 application.yaml;密钥用环境变量,不要写死在仓库里
spring:
application:
name: spring-image-demo
ai:
dashscope:
# IDEA Run Configuration → Environment:DASHSCOPE_API_KEY=sk-xxx
api-key: ${DASHSCOPE_API_KEY}
image:
options:
# DashScopeImageModel 兼容的万相文生图模型
# 不要用 qwen-image-* 等多模态同步模型,会报 url error / 400
model: wanx2.1-t2i-turbo
启动前设置环境变量:
powershell
$env:DASHSCOPE_API_KEY="你的百炼API Key"
三、代码案例
1. 控制器:注入 ImageModel,三种接口
java
@RestController
@RequestMapping("/example")
public class DashScopeImageController {
/** 由 starter 自动配置注入(底层是 DashScopeImageModel) */
private final ImageModel imageModel;
private static final String DEFAULT_PROMPT = "为人工智能生成一张富有科技感的图片!";
public DashScopeImageController(ImageModel imageModel) {
this.imageModel = imageModel;
}
/**
* 最简文生图:用默认 prompt 生成一张图,把远端 URL 的字节写回浏览器。
* GET /example/image
*/
@GetMapping("/image")
public void image(HttpServletResponse response) {
// 1)构造 ImagePrompt(只有提示词,模型走 yml 默认配置)
ImageResponse imageResponse = imageModel.call(new ImagePrompt(DEFAULT_PROMPT));
// 2)异步任务完成后,结果里一般是临时图片 URL
String imageUrl = imageResponse.getResult().getOutput().getUrl();
try {
// 3)服务端打开 URL,把 PNG 字节写给前端(浏览器直接显示图片)
URL url = URI.create(imageUrl).toURL();
InputStream in = url.openStream();
response.setHeader("Content-Type", MediaType.IMAGE_PNG_VALUE);
response.getOutputStream().write(in.readAllBytes());
response.getOutputStream().flush();
} catch (IOException e) {
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}
/**
* 同一 prompt 生成多张图,返回 URL 集合。
* GET /example/image/multiPrompt?prompt=一只会编程的猫&count=2
*/
@GetMapping("/image/multiPrompt")
public ResponseEntity<Collection<String>> generateImageWithMultiPrompt(
@RequestParam(value = "prompt", defaultValue = "一只会编程的猫") String prompt,
@RequestParam(defaultValue = "2") int count) {
// N:一次要几张图
ImageOptions options = ImageOptionsBuilder.builder()
.N(count)
.build();
ImageResponse response = imageModel.call(new ImagePrompt(prompt, options));
// 每张结果取 URL,收集成 Set
Set<String> imageSet = response.getResults().stream()
.map(result -> result.getOutput().getUrl())
.collect(Collectors.toSet());
return ResponseEntity.ok(imageSet);
}
/**
* 多条件拼 prompt + 宽高。
* GET /example/image/multipleConditions?subject=猫&environment=办公室&style=生动
*/
@GetMapping("/image/multipleConditions")
public ResponseEntity<?> multipleConditions(
@RequestParam(value = "subject", defaultValue = "一只会编程的猫") String subject,
@RequestParam(value = "environment", defaultValue = "办公室") String environment,
@RequestParam(value = "height", defaultValue = "1024") Integer height,
@RequestParam(value = "width", defaultValue = "1024") Integer width,
@RequestParam(value = "style", defaultValue = "生动") String style) {
// 把多个参数拼成一句完整提示词
String prompt = String.format(
"一个%s,置身于%s的环境中,使用%s的艺术风格,高清4K画质,细节精致",
subject, environment, style
);
ImageOptions options = ImageOptionsBuilder.builder()
.height(height)
.width(width)
.build();
try {
ImageResponse response = imageModel.call(new ImagePrompt(prompt, options));
// 成功时直接返回图片 URL 字符串
return ResponseEntity.ok(response.getResult().getOutput().getUrl());
} catch (Exception e) {
// 失败时返回 JSON 错误信息,避免空白 500
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(Map.of(
"error", "图像生成失败",
"message", e.getMessage(),
"timestamp", LocalDateTime.now()
));
}
}
}
2.(可选)图片未完成时的重试
万相文生图是异步任务。旧版在 pending 时可能抛 RuntimeException,默认 Retry 可能不够。可提供自定义 RetryTemplate:
java
@Configuration
public class ImageRetryConfig {
@Bean
@Primary
RetryTemplate imageRetryTemplate() {
return RetryTemplate.builder()
.maxAttempts(30) // 最多重试次数
// 初始间隔 2s,倍率 1.5,上限 15s
.exponentialBackoff(Duration.ofSeconds(2), 1.5, Duration.ofSeconds(15))
.retryOn(RuntimeException.class)
.build();
}
}
注意:HTTP 401(Key 无效)、400(参数错误)属于不可恢复错误,靠加长重试解决不了。