File size: 2,145 Bytes
0539596 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | """Pydantic schemas for structured model responses."""
from pydantic import BaseModel, ConfigDict, Field, model_validator
from gcmd_classifier.models import SupportType
class CandidateDecision(BaseModel):
"""One model-selected application-supplied candidate."""
model_config = ConfigDict(extra="forbid", frozen=True)
candidate_id: str = Field(min_length=1)
confidence: float | None = Field(default=None, ge=0.0, le=1.0)
evidence: str = Field(min_length=1)
support_type: SupportType
reason: str | None = None
class TopicResponse(BaseModel):
"""Structured multi-label Topic routing response."""
model_config = ConfigDict(extra="forbid", frozen=True)
selected: list[CandidateDecision] = Field(default_factory=list)
ambiguous_alternatives: list[str] = Field(default_factory=list)
no_selection_reason: str | None = None
class _ChildSelectionResponse(BaseModel):
"""Shared response invariants for Term and Variable-level descent decisions."""
model_config = ConfigDict(extra="forbid", frozen=True)
selected: list[CandidateDecision] = Field(default_factory=list)
stop_at_parent: bool
stop_reason: str | None = None
ambiguous_alternatives: list[str] = Field(default_factory=list)
@model_validator(mode="after")
def validate_stop_and_selection_invariants(self) -> "_ChildSelectionResponse":
"""Reject contradictory child-selection responses before orchestration can use them."""
if self.stop_at_parent and self.selected:
raise ValueError("stop_at_parent=true requires selected to be empty")
if self.selected and self.stop_at_parent:
raise ValueError("non-empty selected requires stop_at_parent=false")
if self.stop_at_parent and not self.stop_reason:
raise ValueError("stop_at_parent=true requires a non-empty stop_reason")
return self
class TermResponse(_ChildSelectionResponse):
"""Structured Term routing response beneath a selected Topic."""
class VariableResponse(_ChildSelectionResponse):
"""Structured Variable-level descent response beneath a selected parent."""
|