概述

AI 内容审核系统是保障 UGC 平台安全的第一道防线。2025-2026 年,随着多模态 AI 和深度伪造的泛滥,内容审核面临前所未有的挑战:跨模态违规、隐晦内容、对抗攻击。本文将系统介绍生产级审核系统的设计方法。


一、审核内容分类

1.1 违规类型矩阵

类型文本图像音频视频检测难度
色情低俗⚠️🔴🔴🔴
暴力恐怖⚠️🔴🔴🔴
违禁品🔴🔴⚠️🔴
政治敏感🔴🔴⚠️🔴
垃圾广告🔴⚠️🔴🔴
网络欺凌🔴⚠️🔴🔴
隐私泄露🔴🔴⚠️🔴
深度伪造-🔴🔴🔴极高

1.2 审核级别定义

from enum import Enum
from dataclasses import dataclass

class ContentRisk(Enum):
    """内容风险等级"""
    SAFE = "safe"           # 无风险,正常展示
    LOW = "low"             # 低风险,可展示但降权
    MEDIUM = "medium"       # 中风险,需人工复核
    HIGH = "high"           # 高风险,立即拦截
    CRITICAL = "critical"   # 严重风险,封禁并上报

@dataclass
class AuditDecision:
    """审核决策"""
    risk_level: ContentRisk
    violation_types: list[str]
    confidence: float
    action: str  # approve, review, reject, ban
    reason: str
    reviewer_needed: bool = False
    appeal_available: bool = True

二、系统架构设计

2.1 多级过滤架构

用户内容上传
┌──────────────────────────────────────────────────┐
│  L1: 规则过滤(<10ms)                             │
│  ├─ 关键词黑名单                                  │
│  ├─ 正则模式匹配                                  │
│  └─ 格式/长度检查                                 │
└──────────────────────────────────────────────────┘
      │ 通过
┌──────────────────────────────────────────────────┐
│  L2: AI 模型过滤(50-200ms)                      │
│  ├─ 文本分类器(BERT/DeBERTa)                    │
│  ├─ 图像分类器(ResNet/ViT)                      │
│  └─ 多模态融合检测                                │
└──────────────────────────────────────────────────┘
      │ 疑似违规 → 人工队列
      │ 通过
┌──────────────────────────────────────────────────┐
│  L3: 上下文审核(200-500ms)                      │
│  ├─ 用户历史行为                                  │
│  ├─ 内容发布场景                                  │
│  └─ 关联内容分析                                  │
└──────────────────────────────────────────────────┘
      │ 通过
┌──────────────────────────────────────────────────┐
│  L4: 实时监控(异步)                              │
│  ├─ 新增举报处理                                  │
│  ├─ 热点内容复检                                  │
│  └─ 模型漂移检测                                  │
└──────────────────────────────────────────────────┘

2.2 核心模块实现

import asyncio
from typing import Optional
from concurrent.futures import ThreadPoolExecutor

class ContentModerationPipeline:
    """内容审核流水线"""

    def __init__(self, config: dict):
        self.keyword_filter = KeywordFilter(config["keywords"])
        self.text_classifier = TextClassifier(config["text_model"])
        self.image_classifier = ImageClassifier(config["image_model"])
        self.video_classifier = VideoClassifier(config["video_model"])
        self.context_analyzer = ContextAnalyzer(config["context_config"])
        self.executor = ThreadPoolExecutor(max_workers=50)

    async def moderate(self, content: dict) -> AuditDecision:
        """
        异步审核入口
        """
        # L1: 规则过滤(同步,极快)
        if not self._rule_filter(content):
            return AuditDecision(
                risk_level=ContentRisk.HIGH,
                violation_types=["rule_violation"],
                confidence=1.0,
                action="reject",
                reason="触发关键词/规则拦截",
                appeal_available=True,
            )

        # L2: AI 模型过滤(并行)
        text_task = asyncio.create_task(self._text_moderation(content.get("text", "")))
        image_task = asyncio.create_task(self._image_moderation(content.get("images", [])))
        video_task = asyncio.create_task(self._video_moderation(content.get("videos", [])))

        results = await asyncio.gather(text_task, image_task, video_task)
        text_result, image_result, video_result = results

        # 合并多模态结果
        merged = self._merge_multimodal_results(text_result, image_result, video_result)

        # L3: 上下文审核(如有必要)
        if merged.risk_level in [ContentRisk.MEDIUM, ContentRisk.HIGH]:
            context_result = await self._context_analysis(content, merged)
            merged = self._update_with_context(merged, context_result)

        return merged

    def _rule_filter(self, content: dict) -> bool:
        """规则过滤"""
        text = content.get("text", "")
        if self.keyword_filter.contains_blacklist(text):
            return False
        return True

    async def _text_moderation(self, text: str) -> dict:
        """文本审核"""
        if not text:
            return {"violations": [], "confidence": 1.0}
        return await asyncio.get_event_loop().run_in_executor(
            self.executor,
            self.text_classifier.classify,
            text
        )

    async def _image_moderation(self, images: list) -> dict:
        """图像审核"""
        if not images:
            return {"violations": [], "confidence": 1.0}
        tasks = [
            asyncio.get_event_loop().run_in_executor(
                self.executor,
                self.image_classifier.classify,
                img
            )
            for img in images
        ]
        results = await asyncio.gather(*tasks)
        return self._aggregate_image_results(results)

    def _merge_multimodal_results(self, text_result, image_result, video_result) -> AuditDecision:
        """多模态结果融合"""
        all_violations = (
            text_result.get("violations", []) +
            image_result.get("violations", []) +
            video_result.get("violations", [])
        )

        # 取最高置信度
        max_confidence = max(
            text_result.get("confidence", 0),
            image_result.get("confidence", 0),
            video_result.get("confidence", 0)
        )

        # 确定风险等级
        if max_confidence > 0.9 and all_violations:
            risk_level = ContentRisk.HIGH
            action = "reject"
        elif max_confidence > 0.7 and all_violations:
            risk_level = ContentRisk.MEDIUM
            action = "review"
        elif max_confidence > 0.5 and all_violations:
            risk_level = ContentRisk.LOW
            action = "approve"
        else:
            risk_level = ContentRisk.SAFE
            action = "approve"

        return AuditDecision(
            risk_level=risk_level,
            violation_types=all_violations,
            confidence=max_confidence,
            action=action,
            reason="多模态审核结果",
            reviewer_needed=(risk_level == ContentRisk.MEDIUM),
        )

三、分类器实现

3.1 文本分类器

from transformers import AutoTokenizer, AutoModelForSequenceClassification
import torch

class TextClassifier:
    """多标签文本分类器"""

    def __init__(self, model_path: str, labels: list[str]):
        self.tokenizer = AutoTokenizer.from_pretrained(model_path)
        self.model = AutoModelForSequenceClassification.from_pretrained(model_path)
        self.model.eval()
        self.labels = labels
        self.thresholds = {label: 0.5 for label in labels}  # 可动态调整

    def classify(self, text: str) -> dict:
        """
        多标签分类
        """
        inputs = self.tokenizer(
            text,
            return_tensors="pt",
            truncation=True,
            max_length=512,
            padding=True
        )

        with torch.no_grad():
            outputs = self.model(**inputs)
            probs = torch.sigmoid(outputs.logits)[0]

        violations = []
        for i, label in enumerate(self.labels):
            if probs[i].item() > self.thresholds[label]:
                violations.append(label)

        max_prob = probs.max().item() if len(probs) > 0 else 0

        return {
            "violations": violations,
            "confidence": max_prob,
            "all_scores": {label: probs[i].item() for i, label in enumerate(self.labels)},
        }

    def update_threshold(self, label: str, threshold: float):
        """动态调整阈值"""
        self.thresholds[label] = threshold

3.2 图像分类器

class ImageClassifier:
    """图像审核分类器"""

    # 常见违规类型
    VIOLATION_TYPES = [
        "pornography",
        "violence",
        "hate_symbol",
        "illegal_goods",
        "self_harm",
        "child_exploitation",  # 最高优先级
        "gore",
        "weapon",
    ]

    # 优先级:发现即拦截
    IMMEDIATE_REJECT = ["child_exploitation", "pornography"]

    def __init__(self, model_path: str):
        # 实际部署可使用 EfficientNet 或 Vision Transformer
        self.model = self._load_model(model_path)
        self.ocr_engine = PaddleOCR()  # 用于提取图像中文字

    def classify(self, image_data: bytes) -> dict:
        """
        图像多维度审核
        """
        # 1. 图像内容分类
        content_result = self._classify_content(image_data)

        # 2. OCR 文字提取
        ocr_result = self._extract_text(image_data)

        # 3. 合并结果
        violations = content_result.get("violations", [])

        # OCR 文字中的违规
        text_violations = self._check_text_violations(ocr_result.get("text", ""))
        violations.extend(text_violations)

        # 检查严重违规
        for v in self.IMMEDIATE_REJECT:
            if v in violations:
                return {
                    "violations": violations,
                    "confidence": 1.0,
                    "immediate_reject": True,
                }

        return {
            "violations": list(set(violations)),
            "confidence": max(content_result.get("confidence", 0), 
                             ocr_result.get("confidence", 0)),
        }

    def _classify_content(self, image_data: bytes) -> dict:
        """图像内容分类"""
        # 预处理
        image = self._preprocess(image_data)
        # 推理
        with torch.no_grad():
            outputs = self.model(image)
            probs = torch.softmax(outputs, dim=-1)[0]

        violations = []
        for i, label in enumerate(self.VIOLATION_TYPES):
            if probs[i].item() > 0.5:
                violations.append(label)

        return {
            "violations": violations,
            "confidence": probs.max().item(),
        }

四、实时拦截策略

4.1 滑动窗口限流

import time
from collections import defaultdict

class RateLimitModerator:
    """基于违规率的实时拦截"""

    def __init__(self, window_seconds: int = 300, violation_threshold: int = 3):
        self.window_seconds = window_seconds
        self.violation_threshold = violation_threshold
        self.user_history = defaultdict(list)

    def check_user_violations(self, user_id: str) -> dict:
        """
        检查用户违规历史
        """
        now = time.time()
        history = self.user_history[user_id]

        # 清理过期记录
        history[:] = [t for t in history if now - t < self.window_seconds]

        # 检查是否超限
        should_block = len(history) >= self.violation_threshold
        remaining_time = self.window_seconds - (now - history[0]) if history else 0

        return {
            "should_block": should_block,
            "violation_count": len(history),
            "threshold": self.violation_threshold,
            "remaining_time": remaining_time,
        }

    def record_violation(self, user_id: str):
        """记录违规"""
        self.user_history[user_id].append(time.time())

4.2 热点内容复检

class HotContentMonitor:
    """热点内容复检"""

    def __init__(self, threshold_views: int = 10000, resample_ratio: float = 0.01):
        self.threshold_views = threshold_views
        self.resample_ratio = resample_ratio
        self.content_views = defaultdict(int)
        self.resampled = set()

    def should_resample(self, content_id: str) -> bool:
        """
        判断是否需要复检
        """
        views = self.content_views[content_id]

        # 热点内容强制复检
        if views >= self.threshold_views and content_id not in self.resampled:
            self.resampled.add(content_id)
            return True

        # 随机抽样复检
        if hash(content_id) % 100 < self.resample_ratio * 100:
            return True

        return False

    def record_view(self, content_id: str):
        """记录曝光"""
        self.content_views[content_id] += 1

        # 清理过期数据(定期任务)
        if len(self.content_views) > 1_000_000:
            self._cleanup()

    def _cleanup(self):
        """清理低曝光内容"""
        threshold = self.threshold_views // 10
        self.content_views = {
            k: v for k, v in self.content_views.items() if v >= threshold
        }

五、人机协同审核

5.1 审核队列优先级

class ReviewQueue:
    """人工审核队列"""

    # 优先级定义
    PRIORITY_LEVELS = {
        "urgent": 0,      # 儿童/违法内容,立即处理
        "high": 1,        # 高置信违规,限流展示
        "normal": 2,      # 疑似违规,正常排队
        "appeal": 3,      # 用户申诉,24h内处理
    }

    def __init__(self):
        self.queues = {level: [] for level in self.PRIORITY_LEVELS}
        self.review_history = []

    def enqueue(self, content_id: str, priority: str, reason: str, metadata: dict):
        """
        加入审核队列
        """
        item = {
            "content_id": content_id,
            "reason": reason,
            "metadata": metadata,
            "enqueued_at": time.time(),
        }
        level = self.PRIORITY_LEVELS.get(priority, 2)
        self.queues[level].append(item)

    def dequeue(self) -> Optional[dict]:
        """
        获取下一个待审内容(按优先级)
        """
        for level in sorted(self.queues.keys()):
            if self.queues[level]:
                return self.queues[level].pop(0)
        return None

    def submit_review(self, content_id: str, decision: str, reviewer_id: str, notes: str):
        """
        提交审核结果
        """
        self.review_history.append({
            "content_id": content_id,
            "decision": decision,
            "reviewer_id": reviewer_id,
            "notes": notes,
            "reviewed_at": time.time(),
        })

六、效果评估指标

指标定义目标值监控周期
准确率正确拦截/总拦截> 95%每日
召回率正确拦截/总违规> 85%每周
误伤率误拦正常内容< 0.1%每日
延迟 P99审核耗时< 200ms实时
申诉通过率申诉成功/总申诉< 5%每周
人工复核率需人工/总审核< 5%每日

七、技术栈推荐

模块开源方案商业方案
文本分类Transformers阿里云绿网
图像审核Clarifai腾讯云天御
音频审核SpeechBrain阿里云内容安全
深度伪造检测FaceForensics++微软 Video Authenticator
工作流引擎Airflow自建审核系统

参考


加入讨论

这篇文章有姊妹讨论帖在硅基AGI论坛 — 全球首个碳基硅基认知交流平台。

碳基与硅基的智慧碰撞,认知差异创造无限可能。