Coverage for backend/ahuora-builder-types/src/ahuora_builder_types/payloads/ml_request_schema.py: 88%
42 statements
« prev ^ index » next coverage.py v7.10.7, created at 2026-07-22 05:22 +0000
« prev ^ index » next coverage.py v7.10.7, created at 2026-07-22 05:22 +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
15 model_type: str
18class MLTrainingRegressionMetricPayload(BaseModel):
19 """Regression metrics produced for one trained output column."""
21 mean_squared_error: float
22 r2_score: float
25class MLTrainingChartPayload(BaseModel):
26 """Chart payload produced for one trained output column."""
28 min: float
29 max: float
30 qq_plot_data: str
31 output_label: str
34class MLTrainingResultPayload(BaseModel):
35 """Structured ML training output stored on the task and ML model records."""
37 surrogate_model: dict[str, Any]
38 charts: list[MLTrainingChartPayload]
39 metrics: list[MLTrainingRegressionMetricPayload]
40 test_results_bucket: str
41 test_results_key: str
42 timing: dict[str, Any] = Field(default_factory=dict)
45class MLTrainingCompletionPayload(BaseModel):
46 """Result returned by the ML worker after training succeeds or fails."""
48 json_response: MLTrainingResultPayload | None = None
49 error: str | None = None
50 log: str | None = None
51 traceback: str | None = None
52 task_id: int
53 status: Literal["success", "error"]
55 @model_validator(mode="after")
56 def validate_status_payload(self) -> "MLTrainingCompletionPayload":
57 """Ensure success and error payloads carry the expected companion fields."""
58 if self.status == "success":
59 if self.json_response is None: 59 ↛ 60line 59 didn't jump to line 60 because the condition on line 59 was never true
60 raise ValueError("Successful ML training payloads must include json_response.")
61 if self.error is not None: 61 ↛ 62line 61 didn't jump to line 62 because the condition on line 61 was never true
62 raise ValueError("Successful ML training payloads cannot include error text.")
63 elif self.error is None: 63 ↛ 64line 63 didn't jump to line 64 because the condition on line 63 was never true
64 raise ValueError("Failed ML training payloads must include error text.")
65 return self