Spaces:
Sleeping
Sleeping
| # app/api/schemas/responses.py | |
| # Pydantic response models for API endpoints | |
| from pydantic import BaseModel, Field | |
| from typing import Optional, Literal, Any | |
| from datetime import datetime | |
| class DecisionDetail(BaseModel): | |
| """Details of the moderation decision.""" | |
| action: Literal["ALLOWED", "WARNING", "BLOCKED"] | |
| reason: str | |
| severity: str | |
| should_alert_parent: bool = False | |
| escalation_notes: Optional[str] = None | |
| class DeepAnalysisDetail(BaseModel): | |
| """Details from the deep analysis stage (only present for HIGH risk).""" | |
| is_confirmed: bool | |
| severity: str | |
| reasoning: str | |
| categories: list[str] = [] | |
| recommended_action: str | |
| confidence: float | |
| clip_scores: dict = {} | |
| class RiskDetail(BaseModel): | |
| """Breakdown of risk scoring.""" | |
| score: float | |
| level: Literal["LOW", "MEDIUM", "HIGH"] | |
| components: dict = {} | |
| repeat_offender: bool = False | |
| class FilterDetail(BaseModel): | |
| """Fast filter stage output.""" | |
| is_flagged: bool | |
| scores: dict[str, float] = {} | |
| max_score: float | |
| max_label: str | |
| categories: list[str] = [] | |
| class AnalysisResponse(BaseModel): | |
| """ | |
| Unified response for all /analyze/* endpoints. | |
| This is the primary contract between the AI engine | |
| and the Node.js backend (and any external consumers). | |
| """ | |
| request_id: str = Field(..., description="Unique request identifier") | |
| input_type: Literal["text", "image", "video"] | |
| status: Literal["ALLOWED", "WARNING", "BLOCKED"] | |
| risk_level: Literal["LOW", "MEDIUM", "HIGH"] | |
| risk_score: float = Field(..., ge=0, le=100, description="Composite risk score 0-100") | |
| categories: list[str] = Field(default_factory=list, description="Detected abuse categories") | |
| confidence: float = Field(..., ge=0, le=1, description="Overall confidence 0-1") | |
| # Detailed breakdowns | |
| decision: DecisionDetail | |
| risk_detail: RiskDetail | |
| filter_detail: FilterDetail | |
| deep_analysis: Optional[DeepAnalysisDetail] = None | |
| # Metadata | |
| processing_time_ms: int = Field(..., description="Total processing time in milliseconds") | |
| trace_id: Optional[str] = Field(None, description="LangSmith trace ID for observability") | |
| cached: bool = Field(False, description="Whether this result was served from cache") | |
| model_config = { | |
| "json_schema_extra": { | |
| "examples": [ | |
| { | |
| "request_id": "req_abc123", | |
| "input_type": "text", | |
| "status": "WARNING", | |
| "risk_level": "MEDIUM", | |
| "risk_score": 45.2, | |
| "categories": ["insult", "toxic"], | |
| "confidence": 0.82, | |
| "decision": { | |
| "action": "WARNING", | |
| "reason": "Content flagged as potentially harmful", | |
| "severity": "medium", | |
| "should_alert_parent": False, | |
| }, | |
| "risk_detail": { | |
| "score": 45.2, | |
| "level": "MEDIUM", | |
| "components": { | |
| "base_score": 42.0, | |
| "multi_category_penalty": 3.2, | |
| "repeat_offender_boost": 0.0, | |
| }, | |
| "repeat_offender": False, | |
| }, | |
| "filter_detail": { | |
| "is_flagged": True, | |
| "scores": {"toxic": 0.78, "insult": 0.65}, | |
| "max_score": 0.78, | |
| "max_label": "toxic", | |
| "categories": ["toxic", "insult"], | |
| }, | |
| "deep_analysis": None, | |
| "processing_time_ms": 156, | |
| "trace_id": None, | |
| "cached": False, | |
| } | |
| ] | |
| } | |
| } | |
| class HealthResponse(BaseModel): | |
| """Health check response.""" | |
| status: str | |
| version: str | |
| models: dict[str, bool] | |
| services: dict[str, bool] | |
| uptime_seconds: float | |
| class HistoryResponse(BaseModel): | |
| """Moderation history response.""" | |
| user_id: str | |
| total: int | |
| results: list[dict[str, Any]] | |
| class ErrorResponse(BaseModel): | |
| """Standard error response.""" | |
| error: str | |
| detail: str | |
| request_id: Optional[str] = None | |