图像、音频与审核模型
本教程共 45 篇 · 第 20 篇 · 更新于 2026-08-16 · 约 10 分钟阅读
本节目标:掌握 Spring AI 的三类专用模型接口:图像生成、语音转文字与语音合成、内容审核。学会接入各厂商实现,写出能跑的调用代码。
20.1 图像生成:ImageModel
图像生成统一走 ImageModel 接口。它继承自通用 Model 接口,输入输出分别是 ImagePrompt 和 ImageResponse。
@FunctionalInterface
public interface ImageModel extends Model<ImagePrompt, ImageResponse> {
ImageResponse call(ImagePrompt request);
}
ImagePrompt 装着一组 ImageMessage 和选项。ImageMessage 只有两个字段:提示词文本 text 和权重 weight。权重支持正负,负权重表示”不要出现这个东西”,部分模型支持。
ImageOptions 是通用选项:模型名、张数 n、宽 width、高 height、返回格式。每家厂商还有自己的扩展选项,比如 OpenAI 的 quality 和 style。
20.2 OpenAI 图像生成
OpenAI 的图像模型是 DALL-E 系列,2.0 起底层换成官方 SDK。依赖还是 OpenAI starter,配置:
spring.ai.openai.api-key=${OPENAI_API_KEY}
spring.ai.openai.image.model=gpt-image-1
spring.ai.openai.image.size=1024x1024
Note
spring.ai.openai.image.model的默认值是gpt-image-1-mini,示例里用的gpt-image-1是更高质量的一档,按需显式指定即可。
调用:
@RestController
public class ImageController {
private final ImageModel imageModel;
public ImageController(ImageModel imageModel) {
this.imageModel = imageModel;
}
@GetMapping("/ai/image")
public ImageResponse generate(@RequestParam(defaultValue = "一只戴帽子的柯基") String prompt) {
return imageModel.call(
new ImagePrompt(prompt,
OpenAiImageOptions.builder()
.quality("hd")
.n(1)
.height(1024)
.width(1024)
.build()));
}
}
ImageResponse 里的每个 ImageGeneration 对应一张图,getOutput() 拿到 Image 对象,里面有图片数据或 URL。
几个参数限制要记住。quality 和 style(vivid / natural)只支持 DALL-E 3。n 的范围是 1 到 10,但 DALL-E 3 只支持 1 张。尺寸按模型分档:DALL-E 3 支持 1024x1024、1792x1024、1024x1792。
20.3 Stability AI 图像生成
Stability AI 的模型是 Stable Diffusion 系列。它的 starter 是独立的:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-stability-ai</artifactId>
</dependency>
spring.ai.stabilityai.api-key=${STABILITYAI_API_KEY}
spring.ai.stabilityai.image.model=stable-diffusion-v1-6
spring.ai.stabilityai.image.width=512
spring.ai.stabilityai.image.height=512
调用方式和 OpenAI 一致,只是选项类换成 Stability 的。它的尺寸必须能被 64 整除,cfg_scale(提示词遵循度,0 到 35)是它的特色参数:
ImageResponse response = imageModel.call(
new ImagePrompt("一只穿宇航服的猫",
StabilityAiImageOptions.builder()
.width(1024)
.height(1024)
.cfgScale(7)
.build()));
cfg_scale 越高,画面越贴提示词,但可能牺牲艺术性。默认 7 是大多数场景的平衡点。返回格式可以设成 image/png 直接拿图片字节,也可以要 JSON 带 base64 数据。
Note图像模型没有统一的流式接口,全部是同步调用。图片生成通常要十几秒,接口调用方要设计好超时。
20.4 音频模型概览
把两类音频能力放在一起看:
| 能力 | 接口 | 方向 | 主流提供商 | 默认模型 |
|---|---|---|---|---|
| 语音转文字 | TranscriptionModel | 音频 → 文本 | OpenAI | whisper-1 |
| 语音合成 | TextToSpeechModel | 文本 → 音频 | OpenAI、ElevenLabs | gpt-4o-mini-tts |
两类接口都支持同步和流式两种模式。转写的流式目前不如 TTS 成熟,长音频还是分段同步处理更稳。
20.5 语音转文字:TranscriptionModel
语音转文字(STT)统一走 TranscriptionModel 接口。目前官方文档收录的提供商是 OpenAI,模型是 Whisper 系列。常见用途有会议纪要、客服质检、字幕生成、语音搜索。音频格式上,mp3、wav、m4a 都支持,传 Resource 时按文件类型自动识别。
public interface TranscriptionModel extends Model<AudioTranscriptionPrompt, AudioTranscriptionResponse> {
AudioTranscriptionResponse call(AudioTranscriptionPrompt transcriptionPrompt);
default String transcribe(Resource resource) { ... }
default String transcribe(Resource resource, AudioTranscriptionOptions options) { ... }
}
transcribe(Resource) 是最常用的快捷方法,传一个音频文件,返回文字。写业务代码时只依赖 TranscriptionModel 接口,换提供商不用改代码:
@Service
public class TranscriptionService {
private final TranscriptionModel transcriptionModel;
public TranscriptionService(TranscriptionModel transcriptionModel) {
this.transcriptionModel = transcriptionModel;
}
public String transcribeAudio(Resource audioFile) {
return transcriptionModel.transcribe(audioFile);
}
}
配置:
spring.ai.openai.api-key=${OPENAI_API_KEY}
spring.ai.openai.audio.transcription.model=whisper-1
模型有三个选择:whisper-1(默认,通用语音识别)、gpt-4o-transcribe(GPT-4o 驱动的转写)、gpt-4o-mini-transcribe(便宜版)。想要更高精度或控制输出格式,用 transcribe(resource, options) 传 OpenAiAudioTranscriptionOptions:
AudioTranscriptionOptions options = OpenAiAudioTranscriptionOptions.builder()
.language("zh")
.responseFormat(TranscriptionResponseFormat.VERBOSE_JSON)
.build();
String text = transcriptionModel.transcribe(audioFile, options);
指定 language 能提升非英语音频的准确率。VERBOSE_JSON 格式会带上每段的时间戳,做字幕和剪辑时很有用。
Azure 上的 Whisper 部署同样支持,2.0 起走 OpenAI 客户端,配置方式和第 16 章一致。
20.6 语音合成:TextToSpeechModel
语音合成(TTS)是反方向:文字进,音频出。接口有两个:TextToSpeechModel 负责普通合成,StreamingTextToSpeechModel 负责流式输出。常见用途有语音播报、有声书、视频配音、无障碍阅读。选厂商时主要看三点:音色自然度、支持的语言、延迟。OpenAI 胜在便宜和稳定,ElevenLabs 胜在音色和多语言。
public interface TextToSpeechModel extends Model<TextToSpeechPrompt, TextToSpeechResponse>,
StreamingTextToSpeechModel {
default byte[] call(String text) { ... }
TextToSpeechResponse call(TextToSpeechPrompt prompt);
}
@FunctionalInterface
public interface StreamingTextToSpeechModel extends StreamingModel<TextToSpeechPrompt, TextToSpeechResponse> {
Flux<TextToSpeechResponse> stream(TextToSpeechPrompt prompt);
default Flux<byte[]> stream(String text) { ... }
}
call(String) 返回完整音频字节,适合生成文件。stream(String) 返回 Flux<byte[]>,适合边生成边播放。两个接口都从 TextToSpeechPrompt 派生,选项和输入封装方式一致。
Note音频格式由模型决定,OpenAI 默认输出 mp3,ElevenLabs 默认是 mp3 22050Hz 32kbps。要别的格式(如 wav、pcm),在各自的选项里配
output-format。
写一个提供商无关的服务:
@Service
public class NarrationService {
private final TextToSpeechModel textToSpeechModel;
public NarrationService(TextToSpeechModel textToSpeechModel) {
this.textToSpeechModel = textToSpeechModel;
}
public byte[] narrate(String text) {
return textToSpeechModel.call(text);
}
public Flux<byte[]> streamNarration(String text) {
return textToSpeechModel.stream(text);
}
}
再配一个 REST 接口,把音频直接返回给前端:
@PostMapping(value = "/api/tts", produces = "audio/mpeg")
public ResponseEntity<byte[]> synthesize(@RequestBody String text) {
byte[] audio = textToSpeechModel.call(text);
return ResponseEntity.ok()
.contentType(MediaType.parseMediaType("audio/mpeg"))
.body(audio);
}
OpenAI TTS
spring.ai.openai.api-key=${OPENAI_API_KEY}
spring.ai.openai.audio.speech.model=gpt-4o-mini-tts
spring.ai.openai.audio.speech.voice=alloy
模型四选一:gpt-4o-mini-tts(默认,快且便宜)、gpt-4o-tts(音质更好)、tts-1 和 tts-1-hd(旧版)。音色通过 voice 参数选,alloy、echo、fable、nova 等。
ElevenLabs
ElevenLabs 以音色自然出名,支持 32 种语言,是配音类应用的热门选择。
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-elevenlabs</artifactId>
</dependency>
spring.ai.elevenlabs.api-key=${ELEVENLABS_API_KEY}
spring.ai.elevenlabs.tts.model-id=eleven_turbo_v2_5
spring.ai.elevenlabs.tts.voice-id=9BWtsMINqrJLrRacOk9x
voice-id 填的是音色 ID,不是音色名字,在 ElevenLabs 控制台里复制。它支持按请求覆盖音色和输出格式,适合做”多角色配音”。
如果应用要同时支持多家 TTS,可以把所有 TextToSpeechModel Bean 收集起来,按名字分发:
@Service
public class MultiProviderNarrationService {
private final Map<String, TextToSpeechModel> providers;
public MultiProviderNarrationService(List<TextToSpeechModel> models) {
this.providers = models.stream()
.collect(Collectors.toMap(m -> m.getClass().getSimpleName(), m -> m));
}
public byte[] narrateWith(String providerName, String text) {
return providers.get(providerName).call(text);
}
}
Spring 会把配置里启用的所有 TTS 模型注入进来。切换提供商,只改配置和名字,代码不动。
20.7 内容审核:ModerationModel
审核模型用来判断文本是否包含违规内容,比如仇恨言论、暴力、色情。它是 UGC 产品上线前的必备环节。
Spring AI 的审核接口统一为 ModerationModel,输入 ModerationPrompt,输出 ModerationResponse。响应里的 Moderation 对象带分类结果,可以按类别判断是否命中。
OpenAI 的实现:
spring.ai.openai.api-key=${OPENAI_API_KEY}
spring.ai.openai.moderation.model=omni-moderation-latest
@Service
public class ModerationService {
private final ModerationModel moderationModel;
public ModerationService(ModerationModel moderationModel) {
this.moderationModel = moderationModel;
}
public boolean isSafe(String text) {
ModerationResponse response = moderationModel.call(new ModerationPrompt(text));
return !response.getResult().getOutput().isFlagged();
}
}
Mistral 也提供审核模型,配置前缀换成 spring.ai.mistralai.moderation:
spring.ai.mistralai.api-key=${MISTRALAI_API_KEY}
spring.ai.mistralai.moderation.model=mistral-moderation-latest
依赖换成 spring-ai-starter-model-mistral-ai,业务代码不用动。这就是统一接口的价值:审核供应商随时可换。
响应里的 Moderation 对象按类别给出判定,比如仇恨言论、暴力、色情各有独立字段。按类别做精细化处理比一刀切更实用:命中色情直接拒,命中轻度辱骂可以先警告。
Tip审核调用建议放在写库之前,而不是之后。先审后存,违规内容根本不落库,少很多麻烦。
审核也可以和聊天流程串起来:用户发言先过审核,通过后再交给聊天模型。这样既挡了违规输入,也避免模型被恶意提示词带偏。审核和聊天的调用都在同一个 Spring Bean 里编排,接口统一的好处在这里体现得最明显。
20.8 小结
图像、音频、审核三大类模型,Spring AI 都提供了统一接口:ImageModel、TranscriptionModel、TextToSpeechModel、ModerationModel。每家厂商的差异收敛在依赖和配置里,业务代码只认接口。图像生成注意尺寸和数量限制,音频接口记得选对模型和格式,内容审核务必先审后存。到此为止,模型接入的知识点就齐了。下一模块进入更高级的话题:记忆、工具调用与 MCP。