from __future__ import annotations from dovla_cil.tasks.predicates import SUPPORTED_PREDICATES from dovla_cil.tasks.schema import TaskSpec def validate_task(task: TaskSpec) -> None: if not task.instruction_templates: raise ValueError(f"Task {task.task_id!r} must have at least one instruction") if any(not template.strip() for template in task.instruction_templates): raise ValueError(f"Task {task.task_id!r} has an empty instruction template") object_ids = [obj.object_id for obj in task.objects] object_id_set = set(object_ids) if len(object_ids) != len(object_id_set): raise ValueError(f"Task {task.task_id!r} has duplicate object ids") _validate_object_refs(task, "target_object_ids", task.target_object_ids, object_id_set) _validate_object_refs(task, "reference_object_ids", task.reference_object_ids, object_id_set) _validate_object_refs(task, "distractor_object_ids", task.distractor_object_ids, object_id_set) for predicate in task.success_predicates: if predicate.name not in SUPPORTED_PREDICATES: raise ValueError(f"Task {task.task_id!r} uses unsupported predicate {predicate.name!r}") for arg in predicate.args: if arg not in object_id_set: raise ValueError( f"Task {task.task_id!r} predicate {predicate.as_expression()} " f"references unknown object {arg!r}" ) _validate_minimal_pairs(task, object_id_set) def _validate_object_refs( task: TaskSpec, field_name: str, values: list[str], object_id_set: set[str] ) -> None: for object_id in values: if object_id not in object_id_set: raise ValueError( f"Task {task.task_id!r} field {field_name} references unknown object {object_id!r}" ) def _validate_minimal_pairs(task: TaskSpec, object_id_set: set[str]) -> None: valid_relation_values = SUPPORTED_PREDICATES | { predicate.name for predicate in task.success_predicates } for key in ("target_object", "reference_object"): for value in task.minimal_pair_factors.get(key, []): if value not in object_id_set: raise ValueError( f"Task {task.task_id!r} minimal_pair_factors[{key!r}] " f"references unknown object {value!r}" ) for relation in task.minimal_pair_factors.get("relation", []): if relation not in valid_relation_values: raise ValueError( f"Task {task.task_id!r} minimal_pair_factors['relation'] " f"uses unsupported relation {relation!r}" )