soupstick's picture
rebuild: 5-agent fraud intelligence suite with trained models + FastAPI
cc1ad5a
from __future__ import annotations
import json
from datetime import datetime, timezone
from pathlib import Path
from typing import Any, get_args, get_origin
from pydantic import BaseModel
APP_VERSION = "1.0.0"
SEED = 42
ROOT_DIR = Path(__file__).resolve().parents[1]
DATA_DIR = ROOT_DIR / "data"
ARTIFACT_DIR = ROOT_DIR / "model_artifacts"
METADATA_PATH = ARTIFACT_DIR / "metadata.json"
def utc_now_iso() -> str:
return datetime.now(timezone.utc).isoformat().replace("+00:00", "Z")
def ensure_runtime_dirs() -> None:
DATA_DIR.mkdir(parents=True, exist_ok=True)
ARTIFACT_DIR.mkdir(parents=True, exist_ok=True)
def load_metadata() -> dict[str, Any]:
if not METADATA_PATH.exists():
return {}
return json.loads(METADATA_PATH.read_text(encoding="utf-8"))
def save_metadata(payload: dict[str, Any]) -> None:
ensure_runtime_dirs()
METADATA_PATH.write_text(json.dumps(payload, indent=2), encoding="utf-8")
def _annotation_to_name(annotation: Any) -> str:
origin = get_origin(annotation)
if origin is None:
if annotation in {str, int, float, bool}:
return annotation.__name__
return str(annotation).replace("typing.", "")
if origin is list:
args = get_args(annotation)
inner = _annotation_to_name(args[0]) if args else "object"
return f"list[{inner}]"
if origin is dict:
args = get_args(annotation)
key_name = _annotation_to_name(args[0]) if args else "object"
value_name = _annotation_to_name(args[1]) if len(args) > 1 else "object"
return f"dict[{key_name}, {value_name}]"
if origin is tuple:
return "tuple"
if str(origin).endswith("Literal"):
values = ", ".join(repr(value) for value in get_args(annotation))
return f"Literal[{values}]"
if str(origin).endswith("Union"):
args = ", ".join(_annotation_to_name(arg) for arg in get_args(annotation))
return f"Union[{args}]"
return str(annotation).replace("typing.", "")
def schema_fields(model_cls: type[BaseModel]) -> list[dict[str, Any]]:
fields = []
for name, field in model_cls.model_fields.items():
fields.append(
{
"name": name,
"type": _annotation_to_name(field.annotation),
"required": field.is_required(),
}
)
return fields