from __future__ import annotations from dataclasses import dataclass from typing import Any, Callable, Dict, Awaitable from db.customer_risk_db import risk_db from utils.content_filter import should_block_customer_smart @dataclass class RiskDecision: blocked: bool category: str = "none" reason: str = "" source: str = "none" # manual/ai_filter/fallback profile: Dict[str, Any] | None = None class RiskService: def evaluate_customer(self, customer_id: str) -> Dict[str, Any]: return risk_db.evaluate_customer(customer_id) def check_manual_block(self, customer_id: str) -> RiskDecision: profile = self.evaluate_customer(customer_id) if bool(profile.get("do_not_serve")): return RiskDecision( blocked=True, category="manual_block", reason="do_not_serve", source="manual", profile=profile, ) return RiskDecision(blocked=False, source="manual", profile=profile) async def check_text_block( self, text: str, *, political_detector: Callable[[str], bool], map_detector: Callable[[str], bool], ) -> RiskDecision: try: hit, category, reason = await should_block_customer_smart(text) map_hit = map_detector(text) or category == "map" political_hit = political_detector(text) or category == "political" if hit or map_hit or political_hit: c = category if map_hit: c = "map" elif political_hit: c = "political" return RiskDecision( blocked=True, category=c or "other", reason=reason or "sensitive_text", source="ai_filter", ) return RiskDecision(blocked=False, category="none", source="ai_filter") except Exception: map_hit = map_detector(text) political_hit = political_detector(text) if map_hit: return RiskDecision(blocked=True, category="map", reason="fallback_match", source="fallback") if political_hit: return RiskDecision(blocked=True, category="political", reason="fallback_match", source="fallback") return RiskDecision(blocked=False, category="none", source="fallback") @staticmethod def build_reject_text(category: str) -> str: if category == "map": return "地图这类不做哈,这边不接地图相关需求。" if category == "sexual": return "这类不做哈,涉黄擦边内容都不接。" if category == "violent": return "这类不做哈,暴力血腥相关都不接。" if category == "political": return "这类不做哈,政治相关图片和人物都不接。" return "这类不做哈,这边不接这类需求。"