"""Bounded, model-independent API input contracts (no network or model imports).""" import json import math MAX_IMAGE_PIXELS = 16_000_000 MAX_CAPTIONS = 100 MAX_COORDINATES = 100 MAX_TOP_K = 20 def top_k_value(value): if isinstance(value, bool) or not isinstance(value, (int, float)): raise ValueError("top_k must be an integer from 1 to 20.") if not math.isfinite(value) or int(value) != value or not 1 <= value <= MAX_TOP_K: raise ValueError("top_k must be an integer from 1 to 20.") return int(value) def _records(raw): if not isinstance(raw, str) or len(raw) > 50_000: raise ValueError("Input must be a JSON string no longer than 50000 characters.") try: rows = json.loads(raw) except (json.JSONDecodeError, RecursionError) as exc: raise ValueError("Input is not valid JSON.") from exc if not isinstance(rows, list) or not 1 <= len(rows) <= 100: raise ValueError("Provide a JSON array containing 1 to 100 candidates.") return rows def _identifier(value, index): if value is None: value = str(index) if not isinstance(value, str) or not value.strip() or len(value) > 120: raise ValueError("Each id must be a nonempty string with at most 120 characters.") return value def caption_rows(raw): output = [] for index, row in enumerate(_records(raw)): if isinstance(row, str): row = {"id": str(index), "text": row} if not isinstance(row, dict) or not set(row) <= {"id", "text"}: raise ValueError('Captions must be strings or objects with "id" and "text".') caption = row.get("text") if not isinstance(caption, str) or not caption.strip() or len(caption) > 500: raise ValueError("Each caption must contain 1 to 500 characters.") output.append({"id": _identifier(row.get("id"), index), "text": caption.strip()}) if len({row["id"] for row in output}) != len(output): raise ValueError("Candidate ids must be unique.") return output def coordinate_rows(raw): output = [] for index, row in enumerate(_records(raw)): if not isinstance(row, dict) or not set(row) <= {"id", "lat", "lon"}: raise ValueError('Coordinates must be objects with "id", "lat", and "lon".') for key, bound in (("lat", 90), ("lon", 180)): number = row.get(key) if isinstance(number, bool) or not isinstance(number, (int, float)): raise ValueError(f"{key} must be a finite number.") if not math.isfinite(number) or not -bound <= number <= bound: raise ValueError(f"{key} must lie within [-{bound}, {bound}].") output.append({"id": _identifier(row.get("id"), index), "lat": float(row["lat"]), "lon": float(row["lon"])}) if len({row["id"] for row in output}) != len(output): raise ValueError("Candidate ids must be unique.") return output