提示:如果不能访问 OpenAI,请点击 AiCode API 注册账号,通过代理访问。
Spring AI 1.0.0 对内容审核功能提供了全面支持,集成了多种主流的内容审核模型,以满足不同场景下的内容安全需求。其中最具代表性的包括 OpenAI 审核模型和 Mistral AI 审核模型,此外通常还支持其他主流提供商的审核能力(如 Azure AI Content Safety 等)。下面将以 OpenAI 的 Omni Moderation 模型为例。
注意:OpenAI 已在 2023 年下半年逐步下线了 text-moderation-latest 和 text-moderation-stable 等传统文本审核模型并推出了更强大的替代方案,目前主要的内容审核替代方案是 Omni Moderation 模型
Omni Moderation 模型是 OpenAI 于 2024 年 9 月 26 日在审核 API 中引入的新一代多模态审核模型,模型名为 “omni-moderation-latest”。
Omni Moderation 模型基于 GPT-4o 技术,能够利用其强大的语言理解和多模态处理能力,实现对有害内容的精准识别。
Omni Moderation 模型支持文本和图像输入。对于图像输入,目前支持暴力(暴力和暴力 / 血腥)、自我伤害(自我伤害、自我伤害 / 意图和自我伤害 / 指示)以及性相关(性相关,但不包括涉及未成年人的性内容)这六类,其他类别目前仅支持文本分类,未来计划为更多类别扩展多模态支持。
相比之前的模型,该模型新增了两类文本有害内容检测,分别是 “非法行为”,包括如何实施不当行为的指导或建议,如 “如何盗窃”;以及 “非法 / 暴力”,涵盖涉及暴力的违法行为。
新模型的评分现在更准确地反映了内容违反相关政策的可能性,并将在未来的审核模型中保持更高的一致性,能为审核决策提供更精细的控制。
该模型可应用于多个领域,如社交媒体平台、生产力工具、生成式 AI 平台等,帮助这些平台审核用户生成的内容,确保内容的安全性和合规性。例如,Grammarly 将审核 API 用作其 AI 通信辅助工具中的安全防护措施,ElevenLabs 结合内部解决方案与审核 API 一起使用,以扫描其音频 AI 产品生成的内容。
开发者可以通过 OpenAI 的审核 API 使用该模型,在请求中指定“model”:“omni-moderation-latest”,并按照要求提供文本或图像输入。图像输入可以是 URL 或 base64 编码的图像。该模型对开发者免费开放,速率限制根据使用等级而定。
在项目的构建文件中添加 spring-ai-openai 依赖。如果是 Maven 项目,在 pom.xml 中添加如下依赖:
<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-openai-spring-boot-starter</artifactId> </dependency>
如果是 Gradle 项目,在build.gradle中添加:
implementation 'org.springframework.ai:spring-ai-openai-spring-boot-starter'
使用spring.ai.openai.moderation作为属性前缀来配置 OpenAI 审核模型。例如,可以配置spring.ai.openai.moderation.options.model来指定审核模型的 ID,例如:
spring: application: name: springai_demo1 # AI配置 ai: # openai相关配置 openai: # 基础地址 # 访问 https://api.xty.app/register?aff=pO2q 地址注册账号即可访问 OpenAI 了 base-url: https://api.xty.app # AI KEY api-key: sk-vHTHX8D3wNZBfR**************42BeB8A23e48AbB600 # 聊天模型配置 chat: options: model: gpt-4-turbo # gpt-3.5-turbo # 图片模型配置 image: options: # 需要高级接口 model: dall-e-3 # 内容审核 moderation: options: # 默认 text-moderation-latest 模型,但 2023 年已经下架 model: text-moderation-latest chat: memory: # 会话历史持久化 repository: jdbc: # 启动时不自动执行初始化SQL脚本,手动创建数据表 initialize-schema: never client: # true 开启,自动注入 ChatClient,false 关闭,需要手动创建 ChatClient enabled: true # 日志配置 logging: charset: console: UTF-8 level: root: info org.springframework.ai: debug org.springframework.web.client: debug
在 Spring AI 1.0.0 中,OpenAiModerationModel 类是用于实现 OpenAI 内容审核功能的关键类。
OpenAiModerationModel 类实现了 Spring AI 中抽象的 ModerationModel 接口,该接口定义了一个通用的用于内容审核的 AI 模型,目前主要适用于文本类型内容审核。
它通过与 OpenAI 的审核 API 进行交互,利用 OpenAI 的审核模型来提供内容审核能力。
例如:使用 omni-moderation-latest 模型快速审核文本
package com.hxstrive.springai.springai_openai.example.moderation_model;
import org.springframework.ai.moderation.*;
import org.springframework.ai.openai.OpenAiModerationModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.util.List;
@SpringBootApplication
public class OpenAiModerationExample implements CommandLineRunner {
// 自动注入高层模型(Spring AI 自动配置)
@Autowired
private OpenAiModerationModel moderationModel;
public static void main(String[] args) {
SpringApplication.run(OpenAiModerationExample.class, args);
}
@Override
public void run(String... args) throws Exception {
String textToModerate = "This is a violent message: kill all people.";
moderateWithModel(textToModerate);
}
private void moderateWithModel(String text) {
System.out.println("开始审核文本:" + text);
// OpenAI 已在 2023 年下半年逐步下线了 text-moderation-latest 和 text-moderation-stable 等传统文本审核模型
// 并推出了更强大的替代方案,目前主要的内容审核替代方案是 Omni Moderation 模型
ModerationOptions options = ModerationOptionsBuilder.builder()
.model("omni-moderation-latest").build();
ModerationPrompt prompt = new ModerationPrompt(text, options);
ModerationResponse response = moderationModel.call(prompt);
if (response.getResults().isEmpty()) {
System.out.println("审核无结果");
return;
}
Moderation moderation = response.getResult().getOutput();
List<ModerationResult> resultList = moderation.getResults();
for(ModerationResult result : resultList) {
System.out.println("审核结果:是否违规=" + result.isFlagged());
System.out.println("违规类别及概率:");
// 输出具体违规类别的概率(如暴力、仇恨、色情等)
Categories categories = result.getCategories();
System.out.println(categories);
}
}
}运行结果:
开始审核文本:This is a violent message: kill all people.
2025-10-12 07:59:31.911 [restartedMain] DEBUG org.springframework.web.client.DefaultRestClient - Writing [OpenAiModerationRequest[prompt=This is a violent message: kill all people., model=omni-moderation-latest]] as "application/json" with org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
2025-10-12 07:59:35.040 [restartedMain] DEBUG org.springframework.web.client.DefaultRestClient - Reading to [org.springframework.ai.openai.api.OpenAiModerationApi$OpenAiModerationResponse]
审核结果:是否违规=true
违规类别及概率:
Categories{sexual=false, hate=false, harassment=false, selfHarm=false, sexualMinors=false, hateThreatening=false, violenceGraphic=false, selfHarmIntent=false, selfHarmInstructions=false, harassmentThreatening=false, violence=true, dangerousAndCriminalContent=false, health=false, financial=false, law=false, pii=false}上述结果中,Categories 类定义了内容审核类别标记类,用于记录内容是否属于各类有害或需要审核的类别,字段值为 true 表示内容被标记为对应类别,false 则表示未被标记。每个字段的含义如下:
public final class Categories {
/**
* 标记内容是否包含性相关内容(不涉及未成年人)
*/
private final boolean sexual;
/**
* 标记内容是否包含仇恨性内容(基于种族、性别、宗教等的仇恨言论)
*/
private final boolean hate;
/**
* 标记内容是否包含骚扰性内容
*/
private final boolean harassment;
/**
* 标记内容是否包含自我伤害相关内容
*/
private final boolean selfHarm;
/**
* 标记内容是否包含涉及未成年人的性相关内容
*/
private final boolean sexualMinors;
/**
* 标记内容是否包含带有威胁性质的仇恨言论
*/
private final boolean hateThreatening;
/**
* 标记内容是否包含血腥暴力的图像或描述
*/
private final boolean violenceGraphic;
/**
* 标记内容是否包含自我伤害的意图表达
*/
private final boolean selfHarmIntent;
/**
* 标记内容是否包含自我伤害的具体指导或方法
*/
private final boolean selfHarmInstructions;
/**
* 标记内容是否包含带有威胁性质的骚扰内容
*/
private final boolean harassmentThreatening;
/**
* 标记内容是否包含暴力相关内容(不包括血腥细节)
*/
private final boolean violence;
/**
* 标记内容是否包含危险及 criminal 相关内容
*/
private final boolean dangerousAndCriminalContent;
/**
* 标记内容是否包含健康相关的误导性或有害信息
*/
private final boolean health;
/**
* 标记内容是否包含金融相关的欺诈或有害信息
*/
private final boolean financial;
/**
* 标记内容是否包含与法律相关的违规信息
*/
private final boolean law;
/**
* 标记内容是否包含个人身份信息(Personally Identifiable Information)
*/
private final boolean pii;
}OpenAiModerationApi 类是与 OpenAI 内容审核 API 直接交互的核心组件,负责处理底层 HTTP 通信、请求构建和响应解析,为上层 OpenAiModerationModel 类提供基础支持。
以下是其主要特性和使用说明:
封装 OpenAI 审核 API 的调用逻辑,支持文本内容的安全审核
处理 API 请求的参数构建、身份验证(API Key)和响应转换
支持配置审核模型版本、请求超时等参数
例如:
AiConfig.java 创建配置类,配置 OpenAiModerationApi 的实例,如下:
package com.hxstrive.springai.springai_openai.example.moderation_model2;
import org.springframework.ai.model.SimpleApiKey;
import org.springframework.ai.model.openai.autoconfigure.OpenAIAutoConfigurationUtil;
import org.springframework.ai.model.openai.autoconfigure.OpenAiConnectionProperties;
import org.springframework.ai.model.openai.autoconfigure.OpenAiModerationProperties;
import org.springframework.ai.openai.api.OpenAiModerationApi;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestClient;
@Configuration
public class AiConfig {
@Bean
public OpenAiModerationApi openAiModerationApi(OpenAiConnectionProperties commonProperties,
OpenAiModerationProperties moderationProperties,
ObjectProvider<RestClient.Builder> restClientBuilderProvider,
ResponseErrorHandler responseErrorHandler) {
// 合并通用配置(commonProperties)和图像专用配置(imageProperties),解决配置冲突(如专用配置优先级高于通用配置)
OpenAIAutoConfigurationUtil.ResolvedConnectionProperties resolved =
OpenAIAutoConfigurationUtil.resolveConnectionProperties(commonProperties, moderationProperties, "moderation");
return OpenAiModerationApi.builder()
.baseUrl(resolved.baseUrl())
.apiKey(new SimpleApiKey(resolved.apiKey()))
.headers(resolved.headers())
.restClientBuilder(restClientBuilderProvider.getIfAvailable(RestClient::builder))
.responseErrorHandler(responseErrorHandler)
.build();
}
}OpenAiModerationExample.java 注入 OpenAiModerationApi 类,实现内容审核,如下:
package com.hxstrive.springai.springai_openai.example.moderation_model2;
import org.springframework.ai.openai.api.OpenAiModerationApi;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.ResponseEntity;
@SpringBootApplication
public class OpenAiModerationExample implements CommandLineRunner {
// 自动注入高层模型(Spring AI 自动配置)
@Autowired
private OpenAiModerationApi moderationApi;
public static void main(String[] args) {
SpringApplication.run(OpenAiModerationExample.class, args);
}
@Override
public void run(String... args) throws Exception {
String textToModerate = "This is a violent message: kill all people.";
moderateWithModel(textToModerate);
}
private void moderateWithModel(String text) {
System.out.println("开始审核文本:" + text);
// OpenAI 已在 2023 年下半年逐步下线了 text-moderation-latest 和 text-moderation-stable 等传统文本审核模型
// 并推出了更强大的替代方案,目前主要的内容审核替代方案是 Omni Moderation 模型
OpenAiModerationApi.OpenAiModerationRequest openAiModerationRequest =
new OpenAiModerationApi.OpenAiModerationRequest(text, "omni-moderation-latest");
ResponseEntity<OpenAiModerationApi.OpenAiModerationResponse> response =
moderationApi.createModeration(openAiModerationRequest);
if(response.getStatusCode().is2xxSuccessful()) {
OpenAiModerationApi.OpenAiModerationResponse body = response.getBody();
OpenAiModerationApi.OpenAiModerationResult[] results = body.results();
for(OpenAiModerationApi.OpenAiModerationResult result : results) {
System.out.println("审核结果:是否违规=" + result.flagged());
System.out.println("违规类别及概率:");
// 输出具体违规类别的概率(如暴力、仇恨、色情等)
OpenAiModerationApi.Categories categories = result.categories();
System.out.println(categories);
OpenAiModerationApi.CategoryScores categoryScores = result.categoryScores();
System.out.println(categoryScores);
}
}
}
}运行结果:
开始审核文本:This is a violent message: kill all people. 2025-10-12 08:13:55.546 [restartedMain] DEBUG org.springframework.web.client.DefaultRestClient - Writing [OpenAiModerationRequest[prompt=This is a violent message: kill all people., model=omni-moderation-latest]] as "application/json" with org.springframework.http.converter.json.MappingJackson2HttpMessageConverter 2025-10-12 08:13:57.889 [restartedMain] DEBUG org.springframework.web.client.DefaultRestClient - Reading to [org.springframework.ai.openai.api.OpenAiModerationApi$OpenAiModerationResponse] 审核结果:是否违规=true 违规类别及概率: Categories[sexual=false, hate=false, harassment=false, selfHarm=false, sexualMinors=false, hateThreatening=false, violenceGraphic=false, selfHarmIntent=false, selfHarmInstructions=false, harassmentThreatening=false, violence=true] CategoryScores[sexual=3.740956047302422E-5, hate=0.02014029890433389, harassment=0.1420878728418502, selfHarm=5.809901648210263E-4, sexualMinors=5.307507822667365E-6, hateThreatening=0.004939012081301744, violenceGraphic=0.005449343371132853, selfHarmIntent=2.9935662423285716E-4, selfHarmInstructions=2.509859855363941E-4, harassmentThreatening=0.11940118719446828, violence=0.9424031506545018]
在 Spring AI 中使用 OpenAI 对图片进行审核,主要依赖 OpenAI 的 Omni Moderation 模型(omni-moderation-latest),该模型支持多模态审核(包括文本和图像)。
如果模型不支持多模态,又该如何对图片进行审核呢?我们可以通过 chat 多模态模型提取图片的详细描述信息,然后再使用内容审核模型对图片描述进行审核,也可以实现图片审核功能。
示例代码如下:
package com.hxstrive.springai.springai_openai.example.moderation_model3;
import org.springframework.ai.content.Media;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.moderation.*;
import org.springframework.ai.openai.OpenAiModerationModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.MediaType;
import java.net.URI;
import java.util.List;
@SpringBootApplication
public class OpenAiModerationExample implements CommandLineRunner {
// 自动注入高层模型(Spring AI 自动配置)
@Autowired
private OpenAiModerationModel moderationModel;
@Autowired
private ChatModel chatModel;
public static void main(String[] args) {
SpringApplication.run(OpenAiModerationExample.class, args);
}
@Override
public void run(String... args) throws Exception {
try {
String textToModerate = describeImageFromUrl("http://resource.hxstrive.com/ai-images/ai-fengjing-2.png");
moderateWithModel(textToModerate);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 从图片URL提取描述信息(适用于网络图片)
* @param imageUrl 图片的网络URL
* @return 图片的文本描述
*/
private String describeImageFromUrl(String imageUrl) throws Exception {
UserMessage userMessage = UserMessage.builder()
.text("请分析这张图片并生成详细描述,包括场景、物体、色彩和可能的用途。")
.media(List.of(new Media(MediaType.IMAGE_PNG, new URI(imageUrl))))
.build();
Prompt prompt = new Prompt(userMessage);
ChatResponse response = chatModel.call(prompt);
return response.getResult().getOutput().getText();
}
private void moderateWithModel(String text) {
System.out.println("开始审核文本:" + text);
// OpenAI 已在 2023 年下半年逐步下线了 text-moderation-latest 和 text-moderation-stable 等传统文本审核模型
// 并推出了更强大的替代方案,目前主要的内容审核替代方案是 Omni Moderation 模型
ModerationOptions options = ModerationOptionsBuilder.builder()
.model("omni-moderation-latest").build();
ModerationPrompt prompt = new ModerationPrompt(text, options);
ModerationResponse response = moderationModel.call(prompt);
if (response.getResults().isEmpty()) {
System.out.println("审核无结果");
return;
}
Moderation moderation = response.getResult().getOutput();
List<ModerationResult> resultList = moderation.getResults();
for(ModerationResult result : resultList) {
System.out.println("审核结果:是否违规=" + result.isFlagged());
System.out.println("违规类别及概率:");
// 输出具体违规类别的概率(如暴力、仇恨、色情等)
Categories categories = result.getCategories();
System.out.println(categories);
}
}
}运行结果:
2025-10-12 08:14:59.683 [restartedMain] DEBUG org.springframework.web.client.DefaultRestClient - Writing [ChatCompletionRequest[messages=[ChatCompletionMessage[rawContent=[{type=text, text=请分析这张图片并生成详细描述,包括场景、物体、色彩和可能的用途。}, {type=image_url, image_url={url=http://resource.hxstrive.com/ai-images/ai-fengjing-2.png}}], role=USER, name=null, toolCallId=null, toolCalls=null, refusal=null, audioOutput=null, annotations=null]], model=gpt-4-turbo, store=null, metadata=null, frequencyPenalty=null, logitBias=null, logprobs=null, topLogprobs=null, maxTokens=null, maxCompletionTokens=null, n=null, outputModalities=null, audioParameters=null, presencePenalty=null, responseFormat=null, seed=null, serviceTier=null, stop=null, stream=false, streamOptions=null, temperature=0.7, topP=null, tools=null, toolChoice=null, parallelToolCalls=null, user=null, reasoningEffort=null, webSearchOptions=null]] as "application/json" with org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
2025-10-12 08:15:12.486 [restartedMain] DEBUG org.springframework.web.client.DefaultRestClient - Reading to [org.springframework.ai.openai.api.OpenAiApi$ChatCompletion]
开始审核文本:这张图片展示了一幅壮丽的自然景观,场景位于群山环绕的山谷中,中央有一条蜿蜒的河流或湖泊。远处的群山被白雪覆盖,呈现出冬季的寒冷与宁静。山脉的形态各异,左侧的山峰陡峭而雄伟,右侧的山脉较为平缓,给人一种稳重的感觉。
在前景中,河流或湖泊的两岸是秋季的金黄色草地和森林,树叶呈现出金黄和橙色的色彩,与远处的白雪形成鲜明对比。这样的色彩搭配使整幅画面既有冷色调的清新,又不失暖色调的温柔。蓝色的天空上点缀着白色的云朵,云层厚重而有层次,为整个景观增添了一份动感。
这幅图像的色彩丰富且具有层次感,蓝色、白色、黄色和橙色的组合让人感到宁静而又充满活力。可能的用途包括用作自然风光摄影、旅游宣传材料、壁纸或艺术作品展示。这种场景适合用于强调环境保护和自然美景的重要性,同时也能激发观众对于户外活动和探索自然的兴趣。
2025-10-12 08:15:12.542 [restartedMain] DEBUG org.springframework.web.client.DefaultRestClient - Writing [OpenAiModerationRequest[prompt=这张图片展示了一幅壮丽的自然景观,场景位于群山环绕的山谷中,中央有一条蜿蜒的河流或湖泊。远处的群山被白雪覆盖,呈现出冬季的寒冷与宁静。山脉的形态各异,左侧的山峰陡峭而雄伟,右侧的山脉较为平缓,给人一种稳重的感觉。
在前景中,河流或湖泊的两岸是秋季的金黄色草地和森林,树叶呈现出金黄和橙色的色彩,与远处的白雪形成鲜明对比。这样的色彩搭配使整幅画面既有冷色调的清新,又不失暖色调的温柔。蓝色的天空上点缀着白色的云朵,云层厚重而有层次,为整个景观增添了一份动感。
这幅图像的色彩丰富且具有层次感,蓝色、白色、黄色和橙色的组合让人感到宁静而又充满活力。可能的用途包括用作自然风光摄影、旅游宣传材料、壁纸或艺术作品展示。这种场景适合用于强调环境保护和自然美景的重要性,同时也能激发观众对于户外活动和探索自然的兴趣。, model=omni-moderation-latest]] as "application/json" with org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
2025-10-12 08:15:13.801 [restartedMain] DEBUG org.springframework.web.client.DefaultRestClient - Reading to [org.springframework.ai.openai.api.OpenAiModerationApi$OpenAiModerationResponse]
审核结果:是否违规=false
违规类别及概率:
Categories{sexual=false, hate=false, harassment=false, selfHarm=false, sexualMinors=false, hateThreatening=false, violenceGraphic=false, selfHarmIntent=false, selfHarmInstructions=false, harassmentThreatening=false, violence=false, dangerousAndCriminalContent=false, health=false, financial=false, law=false, pii=false}更多信息请参考官方文档:
https://docs.spring.io/spring-ai/reference/api/moderation/openai-moderation.html
提示:如果不能访问 OpenAI,请点击 AiCode API 注册账号,通过代理访问。