Skip to content
🔗 分享本题
查看我的学习进度 →

25 模块 Q5 教学图:设计一个 AI 内容审核系统(实时 + 离线双链路)

🧠 图解记忆:实时链路快速拦截,离线链路深度复核,两者共享策略与反馈;点击图片可查看原图。

💡 答案要点

题目理解:

AI 内容审核:
- 实时链路:用户发内容 → 立即审核 → 通过/拦截
- 离线链路:历史内容扫描 → 违规内容下架
- 核心挑战:低延迟 + 高准确率 + 可解释

双链路架构:

用户发布内容

┌──────────────────────────────────────────────────────────┐
│                  实时审核链路(< 200ms)                  │
│   1. 同步调用 AI 审核模型                                  │
│   2. 立即返回:PASS / REJECT / NEED_REVIEW                │
│   3. 需要人工 → 进入人工审核队列                            │
└──────────────────────────────────────────────────────────┘

内容发布(通过审核后)

┌──────────────────────────────────────────────────────────┐
│                  离线审核链路(T+1 扫描)                  │
│   1. 定时扫描新发布内容                                     │
│   2. 深度审核(多模型 + 上下文)                            │
│   3. 违规 → 自动下架 + 通知用户                            │
└──────────────────────────────────────────────────────────┘

实时审核链路(< 200ms):

展开 Python 代码示例(92 行)
python
class RealTimeModeration:
    """实时内容审核"""
    
    def __init__(self, model_client, redis_cache):
        self.model = model_client
        self.cache = redis_cache
    
    async def moderate(self, content: str, user_id: str, content_id: str) -> ModerationResult:
        """
        实时审核,返回:
        - PASS: 通过
        - REJECT: 拦截
        - NEED_REVIEW: 需人工复核
        """
        
        start = time.time()
        
        # 1. 缓存检查(同内容24h内已审核)
        cache_key = f"mod:{hashlib.md5(content.encode()).hexdigest()}"
        cached = await self.cache.get(cache_key)
        if cached:
            return ModerationResult.from_json(cached)
        
        # 2. 多维度检测
        checks = await asyncio.gather(
            self.check_text_toxicity(content),      # 文本毒性
            self.check_sensitive_topics(content),   # 敏感话题
            self.check_patterns(content),           # 违规模式(正则)
            self.check_user_history(user_id),       # 用户历史
        )
        
        # 3. 决策
        decision = self.decide(checks)
        
        result = ModerationResult(
            content_id=content_id,
            decision=decision,
            confidence=max(c["confidence"] for c in checks),
            details=checks,
            latency_ms=int((time.time() - start) * 1000)
        )
        
        # 4. 写入缓存
        await self.cache.setex(cache_key, 86400, result.to_json())
        
        return result
    
    async def check_text_toxicity(self, text: str) -> dict:
        """文本毒性检测"""
        response = await self.model.moderate(text=text)
        return {
            "type": "toxicity",
            "score": response["toxicity_score"],
            "confidence": response["confidence"],
            "flagged_categories": response["flagged"]
        }
    
    async def check_sensitive_topics(self, text: str) -> dict:
        """敏感话题检测(政治、色情、暴力等)"""
        # 分层检测:先关键词过滤,再 AI 判断
        keyword_match = self.keyword_filter.match(text)
        if keyword_match:
            return {
                "type": "sensitive_topic",
                "score": 0.99,
                "confidence": 1.0,
                "flagged_categories": keyword_match.categories
            }
        
        # AI 细判
        ai_result = await self.model.analyze_topics(text)
        return {
            "type": "sensitive_topic",
            "score": ai_result["risk_score"],
            "confidence": ai_result["confidence"],
            "flagged_categories": ai_result["categories"]
        }
    
    def decide(self, checks: list[dict]) -> str:
        """综合决策"""
        
        # 硬规则:任意一项高置信度命中 → 直接拦截
        for check in checks:
            if check["score"] > 0.9 and check["confidence"] > 0.95:
                return "REJECT"
        
        # 中等风险 → 人工复核
        for check in checks:
            if check["score"] > 0.6:
                return "NEED_REVIEW"
        
        return "PASS"

离线审核链路(T+1 全量扫描):

展开 Python 代码示例(84 行)
python
class OfflineModeration:
    """离线内容审核"""
    
    def __init__(self, db, model_client, notification_service):
        self.db = db
        self.model = model_client
        self.notify = notification_service
    
    async def daily_scan(self):
        """每日全量扫描"""
        print("Starting daily offline moderation scan...")
        
        # 1. 获取昨日新发布内容
        yesterday_content = await self.fetch_yesterday_content()
        print(f"Found {len(yesterday_content)} content to scan")
        
        # 2. 分批处理(避免内存爆炸)
        batch_size = 100
        for i in range(0, len(yesterday_content), batch_size):
            batch = yesterday_content[i:i+batch_size]
            await self.process_batch(batch)
    
    async def process_batch(self, batch: list[Content]):
        """批量深度审核"""
        
        # 1. 并发审核(离线不要求低延迟)
        results = await asyncio.gather(*[
            self.deep_moderate(content) for content in batch
        ])
        
        # 2. 汇总结果
        for content, result in zip(batch, results):
            if result.decision == "REMOVE":
                await self.remove_content(content, result)
    
    async def deep_moderate(self, content: Content) -> ModerationResult:
        """
        深度审核(离线链路):
        - 调用更强的模型
        - 检查上下文(回复关系)
        - 检查账号历史
        """
        
        # 1. 调用更准确的审核模型
        text_to_check = content.text
        
        # 2. 如果是回复,检查上下文
        if content.reply_to_id:
            parent = await self.db.get_content(content.reply_to_id)
            text_to_check = f"[原帖]{parent.text}\n[回复]{content.text}"
        
        # 3. 多标签分类
        multi_label = await self.model.multi_label_classify(text_to_check)
        
        # 4. 组合判断
        risk_score = self.calculate_risk_score(multi_label)
        
        return ModerationResult(
            content_id=content.id,
            decision="REMOVE" if risk_score > 0.7 else "PASS",
            risk_score=risk_score,
            details=multi_label
        )
    
    async def remove_content(self, content: Content, result: ModerationResult):
        """下架违规内容"""
        
        # 1. 标记为已下架
        await self.db.update_content_status(content.id, "removed")
        
        # 2. 通知用户
        await self.notify.send(
            user_id=content.user_id,
            title="内容下架通知",
            body=f"您的内容因{result.details['primary_reason']}已被下架"
        )
        
        # 3. 记录审计日志
        await self.db.insert_audit_log(
            action="content_removed",
            content_id=content.id,
            reason=result.details,
            auto=True  # 自动下架 vs 人工下架
        )

人工审核队列(人机协作):

展开 Python 代码示例(54 行)
python
class HumanReviewQueue:
    """人工审核队列"""
    
    def __init__(self, db, queue_name: str = "moderation:review"):
        self.db = db
        self.queue = queue_name
    
    async def push_for_review(self, task: dict):
        """人工审核任务入队"""
        priority = self._calculate_priority(task)
        
        await self.db.execute("""
            INSERT INTO review_queue (task_data, priority, created_at)
            VALUES ($1, $2, NOW())
        """, json.dumps(task), priority)
    
    async def pop_task(self, reviewer_id: str) -> dict:
        """审核员抢任务"""
        async with self.db.transaction():
            # 抢任务(乐观锁)
            row = await self.db.fetchrow("""
                UPDATE review_queue
                SET status = 'in_progress',
                    reviewer_id = $1,
                    started_at = NOW()
                WHERE id = (
                    SELECT id FROM review_queue
                    WHERE status = 'pending'
                    ORDER BY priority DESC, created_at ASC
                    LIMIT 1
                    FOR UPDATE SKIP LOCKED
                )
                RETURNING *
            """, reviewer_id)
        
        return json.loads(row["task_data"]) if row else None
    
    def _calculate_priority(self, task: dict) -> int:
        """计算优先级"""
        base = 100
        
        # 高风险内容优先
        if task.get("risk_score", 0) > 0.8:
            base += 50
        
        # VIP 用户的内容优先审核
        if task.get("is_vip", False):
            base += 20
        
        # 粉丝多的账号优先
        if task.get("follower_count", 0) > 100000:
            base += 10
        
        return base

面试话术:

"内容审核的双链路设计是核心:实时链路要求 < 200ms,用轻量模型 + 缓存 + 规则过滤,结果分 PASS/REJECT/NEED_REVIEW 三档;离线链路做 T+1 深度扫描,用更强模型 + 上下文分析,可以容忍更高延迟。人工复核队列用优先级队列,高风险 + 大V 内容优先处理。审核系统的可解释性很重要——不仅要判断违规,还要告诉审核员为什么违规,方便人工复核。面试能说清楚实时+离线的分层设计,说明你对'可靠系统 = 实时优先 + 离线兜底'有实战理解。"

📚 参考:OpenAI Moderation 指南(内容审核 API)


版本: v1.1 | 更新: 2026-05-09 | by 二狗子 🐕