Spaces:
Sleeping
Sleeping
| """Pydantic models for LabOps Guardian. | |
| Every stored fact carries a `source_type` + `confidence` (truth-state system) so the | |
| agent never presents a camera-guess or hypothesis as a confirmed fact. | |
| """ | |
| from __future__ import annotations | |
| from typing import Any, Literal, Optional | |
| from pydantic import BaseModel, Field | |
| SourceType = Literal[ | |
| "observed_by_sensor", | |
| "user_reported", | |
| "sop_grounded", | |
| "calculated", | |
| "camera_inferred", | |
| "pending_confirmation", | |
| "human_confirmed", | |
| "stale", | |
| ] | |
| Confidence = Literal["high", "medium", "low"] | |
| Severity = Literal["low", "medium", "high", "critical"] | |
| # ββ Core stored objects βββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| class NormalRange(BaseModel): | |
| min: float | |
| max: float | |
| unit: str = "C" | |
| class Equipment(BaseModel): | |
| id: str | |
| name: str | |
| kind: str | |
| current_temperature: Optional[str] = None | |
| status: str = "ok" # ok | alarm | error | idle | |
| normal_range: Optional[NormalRange] = None | |
| source_type: SourceType = "observed_by_sensor" | |
| confidence: Confidence = "high" | |
| updated_at: Optional[str] = None | |
| class Sample(BaseModel): | |
| sample_id: str | |
| name: str | |
| location: str | |
| storage_temperature: str | |
| max_room_temp_minutes: int = 20 | |
| room_temp_started_at: Optional[str] = None | |
| room_temp_deadline: Optional[str] = None | |
| source_type: SourceType = "user_reported" | |
| confidence: Confidence = "medium" | |
| updated_at: Optional[str] = None | |
| class Incident(BaseModel): | |
| incident_id: str | |
| type: str # temperature_excursion | centrifuge_error | ... | |
| equipment_id: str | |
| severity: Severity = "high" | |
| status: Literal["open", "investigating", "resolved"] = "open" | |
| current_value: Optional[str] = None | |
| threshold: Optional[str] = None | |
| observations: list[str] = Field(default_factory=list) | |
| tickets: list[str] = Field(default_factory=list) | |
| created_at: str | |
| updated_at: Optional[str] = None | |
| class Ticket(BaseModel): | |
| ticket_id: str | |
| incident_id: str | |
| summary: Optional[str] = None | |
| severity: str | |
| assigned_to: str | |
| status: str = "open" | |
| notes: Optional[str] = None | |
| created_at: str | |
| class PriorEvent(BaseModel): | |
| id: str | |
| equipment_id: str | |
| issue_type: str | |
| timestamp: str | |
| summary: Optional[str] = None | |
| recorded_cause: Optional[str] = None | |
| resolution: Optional[str] = None | |
| duration_hours: Optional[float] = None | |
| source_type: SourceType = "human_confirmed" | |
| confidence: Confidence = "high" | |
| class InventoryItem(BaseModel): | |
| item_name: str | |
| location: str | |
| bin: Optional[str] = None | |
| record_count: Optional[int] = None | |
| camera_inferred_count: Optional[int] = None | |
| stock_level: str = "ok" | |
| confidence: Confidence = "medium" | |
| source_type: SourceType = "camera_inferred" | |
| timestamp: Optional[str] = None | |
| class Reminder(BaseModel): | |
| id: str | |
| label: str | |
| due_at: str | |
| sample_id: Optional[str] = None | |
| kind: Literal["warning", "escalation", "manual"] = "manual" | |
| status: Literal["open", "done", "cancelled"] = "open" | |
| created_at: Optional[str] = None | |
| class Event(BaseModel): | |
| id: str | |
| type: str | |
| payload: dict[str, Any] = Field(default_factory=dict) | |
| source_type: SourceType = "user_reported" | |
| confidence: Confidence = "medium" | |
| timestamp: Optional[str] = None | |
| class Message(BaseModel): | |
| id: str | |
| recipient_role: str | |
| message: str | |
| status: Literal["draft", "sent"] = "draft" | |
| source_type: SourceType = "pending_confirmation" | |
| timestamp: Optional[str] = None | |
| class ExperimentRun(BaseModel): | |
| id: str | |
| title: str | |
| started_at: str | |
| sample_ids: list[str] = Field(default_factory=list) | |
| notes: list[str] = Field(default_factory=list) | |
| status: str = "in_progress" | |
| # ββ Request bodies ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| class EventRequest(BaseModel): | |
| type: str | |
| equipment_id: Optional[str] = None | |
| value: Optional[float] = None | |
| unit: str = "C" | |
| payload: dict[str, Any] = Field(default_factory=dict) | |
| source_type: SourceType = "observed_by_sensor" | |
| confidence: Confidence = "high" | |
| timestamp: Optional[str] = None | |
| class RetrieveSopRequest(BaseModel): | |
| issue_type: Optional[str] = None | |
| equipment_id: Optional[str] = None | |
| query: Optional[str] = None # fallback free-text search | |
| sample_id: Optional[str] = None | |
| class CreateTicketRequest(BaseModel): | |
| incident_id: str | |
| summary: Optional[str] = None | |
| severity: str = "high" | |
| assigned_to: str = "Facilities" | |
| notes: Optional[str] = None | |
| class RecallHistoryRequest(BaseModel): | |
| equipment_id: str | |
| issue_type: Optional[str] = None | |
| class CreateIncidentRequest(BaseModel): | |
| type: str | |
| equipment_id: str | |
| severity: Severity = "high" | |
| current_value: Optional[str] = None | |
| threshold: Optional[str] = None | |
| class AddObservationRequest(BaseModel): | |
| observation: str | |
| class MoveSampleRequest(BaseModel): | |
| from_location: Optional[str] = None | |
| to_location: str | |
| from_temperature: Optional[str] = None | |
| allowed_room_temp_minutes: int = 20 | |
| class ValidateCalculationRequest(BaseModel): | |
| calculation_type: str = "percent_volume_volume" | |
| target_percent: Optional[float] = None | |
| final_volume_ml: Optional[float] = None | |
| user_answer_ul: Optional[float] = None | |
| stock_percent: Optional[float] = None | |
| user_answer_g: Optional[float] = None | |
| class FindInventoryRequest(BaseModel): | |
| item_name: str | |
| class CreateReminderRequest(BaseModel): | |
| # Either the explicit label+due_at form, or the Rasa duration_minutes+message form | |
| label: Optional[str] = None | |
| due_at: Optional[str] = None | |
| sample_id: Optional[str] = None | |
| duration_minutes: Optional[int] = None | |
| message: Optional[str] = None | |
| class LogActivityEventRequest(BaseModel): | |
| person_name: str | |
| event_type: str = "lab_activity" | |
| sample_id: Optional[str] = None | |
| description: Optional[str] = None | |
| source_type: SourceType = "user_reported" | |
| confidence: Confidence = "medium" | |
| class SendEmergencyMessageRequest(BaseModel): | |
| recipient_role: str | |
| message: str | |
| confirmed: bool = False | |
| class GenerateHandoffRequest(BaseModel): | |
| incident_id: Optional[str] = None | |
| shift: Optional[str] = None | |