提示:如果不能访问 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 注册账号,通过代理访问。