Poster_Analyzer / app /src /schema.py
DatsuNTOYOTA's picture
init app
ec4da21 verified
from typing import Any, Dict, Tuple
METRIC_KEYS = [
"hierarchy_strength",
"focal_clarity",
"typography_control",
"font_conflict",
"palette_control",
"color_conflict",
"visual_clutter",
"template_genericity",
"originality",
"technical_quality",
"visual_impact",
]
REQUIRED_KEYS = {
"content_present": bool,
"hierarchy_strength": int,
"focal_clarity": int,
"typography_control": int,
"font_conflict": int,
"palette_control": int,
"color_conflict": int,
"visual_clutter": int,
"template_genericity": int,
"originality": int,
"technical_quality": int,
"visual_impact": int,
"confidence": (float, int),
"comment": str,
}
PRESENCE_SCHEMA = {
"type": "object",
"properties": {
"content_present": {"type": "boolean"},
},
"required": ["content_present"],
"additionalProperties": False,
}
def metric_schema(metric_name: str) -> Dict[str, Any]:
return {
"type": "object",
"properties": {
metric_name: {"type": "integer", "minimum": 1, "maximum": 5},
},
"required": [metric_name],
"additionalProperties": False,
}
FINAL_JUDGE_SCHEMA = {
"type": "object",
"properties": {
"label": {"type": "string", "enum": ["bad", "medium", "good"]},
"confidence": {"type": "number", "minimum": 0.0, "maximum": 1.0},
"rationale": {"type": "string"},
},
"required": ["label", "confidence", "rationale"],
"additionalProperties": False,
}
OUTPUT_SCHEMA = {
"type": "object",
"properties": {
"content_present": {"type": "boolean"},
"hierarchy_strength": {"type": "integer", "minimum": 1, "maximum": 5},
"focal_clarity": {"type": "integer", "minimum": 1, "maximum": 5},
"typography_control": {"type": "integer", "minimum": 1, "maximum": 5},
"font_conflict": {"type": "integer", "minimum": 1, "maximum": 5},
"palette_control": {"type": "integer", "minimum": 1, "maximum": 5},
"color_conflict": {"type": "integer", "minimum": 1, "maximum": 5},
"visual_clutter": {"type": "integer", "minimum": 1, "maximum": 5},
"template_genericity": {"type": "integer", "minimum": 1, "maximum": 5},
"originality": {"type": "integer", "minimum": 1, "maximum": 5},
"technical_quality": {"type": "integer", "minimum": 1, "maximum": 5},
"visual_impact": {"type": "integer", "minimum": 1, "maximum": 5},
"confidence": {"type": "number", "minimum": 0.0, "maximum": 1.0},
"comment": {"type": "string"},
},
"required": [
"content_present",
"hierarchy_strength",
"focal_clarity",
"typography_control",
"font_conflict",
"palette_control",
"color_conflict",
"visual_clutter",
"template_genericity",
"originality",
"technical_quality",
"visual_impact",
"confidence",
"comment",
],
"additionalProperties": False,
}
def validate_scores(data: Dict[str, Any]) -> Tuple[bool, str]:
for key, expected_type in REQUIRED_KEYS.items():
if key not in data:
return False, f"Missing key: {key}"
if not isinstance(data[key], expected_type):
return False, f"Invalid type for key: {key}"
for key in METRIC_KEYS:
value = data[key]
if not isinstance(value, int):
return False, f"{key} must be int"
if value < 1 or value > 5:
return False, f"{key} must be in range 1..5"
confidence = float(data["confidence"])
if confidence < 0.0 or confidence > 1.0:
return False, "confidence must be in range 0.0..1.0"
comment = data["comment"].strip()
if not comment:
return False, "comment must not be empty"
return True, "ok"