Coverage for backend/ahuora-builder-types/src/ahuora_builder_types/payloads/ml_request_schema.py: 88%
41 statements
« prev ^ index » next coverage.py v7.10.7, created at 2026-05-13 02:47 +0000
« prev ^ index » next coverage.py v7.10.7, created at 2026-05-13 02:47 +0000
1from typing import Any, Literal
3from pydantic import BaseModel, Field, model_validator
6class MLTrainRequestPayload(BaseModel):
7 """Payload describing an object-storage-backed ML training request."""
9 csv_bucket: str
10 csv_key: str
11 csv_delimiter: str | None = None
12 input_labels: list[str]
13 output_labels: list[str]
14 task_id: int
17class MLTrainingRegressionMetricPayload(BaseModel):
18 """Regression metrics produced for one trained output column."""
20 mean_squared_error: float
21 r2_score: float
24class MLTrainingChartPayload(BaseModel):
25 """Chart payload produced for one trained output column."""
27 min: float
28 max: float
29 qq_plot_data: str
30 output_label: str
33class MLTrainingResultPayload(BaseModel):
34 """Structured ML training output stored on the task and ML model records."""
36 surrogate_model: dict[str, Any]
37 charts: list[MLTrainingChartPayload]
38 metrics: list[MLTrainingRegressionMetricPayload]
39 test_results_bucket: str
40 test_results_key: str
41 timing: dict[str, Any] = Field(default_factory=dict)
44class MLTrainingCompletionPayload(BaseModel):
45 """Result returned by the ML worker after training succeeds or fails."""
47 json_response: MLTrainingResultPayload | None = None
48 error: str | None = None
49 log: str | None = None
50 traceback: str | None = None
51 task_id: int
52 status: Literal["success", "error"]
54 @model_validator(mode="after")
55 def validate_status_payload(self) -> "MLTrainingCompletionPayload":
56 """Ensure success and error payloads carry the expected companion fields."""
57 if self.status == "success":
58 if self.json_response is None: 58 ↛ 59line 58 didn't jump to line 59 because the condition on line 58 was never true
59 raise ValueError("Successful ML training payloads must include json_response.")
60 if self.error is not None: 60 ↛ 61line 60 didn't jump to line 61 because the condition on line 60 was never true
61 raise ValueError("Successful ML training payloads cannot include error text.")
62 elif self.error is None: 62 ↛ 63line 62 didn't jump to line 63 because the condition on line 62 was never true
63 raise ValueError("Failed ML training payloads must include error text.")
64 return self