feat: implement t-604 keyword prompt moderation
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from enum import Enum
|
||||
from typing import Any, Protocol
|
||||
|
||||
|
||||
class ModerationError(RuntimeError):
|
||||
"""Base error for content-moderation failures."""
|
||||
|
||||
|
||||
class ModerationUnavailableError(ModerationError):
|
||||
"""Provider could not return a verdict (down / timeout / not implemented).
|
||||
|
||||
The orchestration layer converts this into a fail-closed BLOCK or a
|
||||
fail-open PASS depending on ``MODERATION_FAIL_CLOSED`` policy.
|
||||
"""
|
||||
|
||||
|
||||
class ModerationConfigError(ModerationError):
|
||||
"""Provider is misconfigured (missing credentials / biz type / endpoint)."""
|
||||
|
||||
|
||||
class Verdict(str, Enum):
|
||||
PASS = "pass" # 放行
|
||||
REVIEW = "review" # 建议人工复审(是否等同拦截由 policy 决定)
|
||||
BLOCK = "block" # 拦截
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ModerationResult:
|
||||
"""Normalized moderation verdict, decoupled from any vendor's response shape.
|
||||
|
||||
NOTE: ``raw`` is only for debugging in-process; never persist it verbatim
|
||||
(may contain the moderated content / vendor internals). Compliance logging
|
||||
stores a summary (verdict + labels + request_id), not ``raw``.
|
||||
"""
|
||||
|
||||
verdict: Verdict
|
||||
labels: tuple[str, ...] = ()
|
||||
score: int | None = None
|
||||
keywords: tuple[str, ...] = ()
|
||||
request_id: str = ""
|
||||
raw: Any = field(default=None, repr=False, compare=False)
|
||||
|
||||
|
||||
class ModerationProvider(Protocol):
|
||||
def moderate_text(self, text: str, *, biz_type: str = "") -> ModerationResult:
|
||||
...
|
||||
Reference in New Issue
Block a user