Spring AI 内容审核模型

提示:如果不能访问 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 模型

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

使用 OpenAiModerationModel 审核

在 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 审核

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 注册账号,通过代理访问。  

说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
其他应用
公众号