Source code for marivo.analysis.frames.candidate
"""CandidateSet and CandidateSetMeta."""
from __future__ import annotations
from dataclasses import dataclass
from typing import Any, Literal
from pydantic import ConfigDict, Field
from marivo.analysis.followups import (
BlockingIssue,
FollowupAction,
)
from marivo.analysis.frames.base import BaseFrame, BaseFrameMeta
CandidateShape = Literal[
"point_anomaly",
"period_shift",
"driver_axis",
"slice",
"window",
"cross_sectional_outlier",
]
CandidateObjective = Literal[
"point_anomalies",
"period_shifts",
"driver_axes",
"interesting_slices",
"interesting_windows",
"cross_sectional_outliers",
]
CandidateStrategy = Literal[
"zscore",
"delta_window_zscore",
"variance_explained",
"delta_magnitude",
"rolling_zscore",
"mad",
]
CandidateSourceKind = Literal["metric_frame", "delta_frame"]
CandidateSemanticKind = Literal["scalar", "time_series", "segmented", "panel"]
class CandidateSetMeta(BaseFrameMeta):
model_config = ConfigDict(extra="forbid")
kind: Literal["candidate_set"] = "candidate_set"
shape: CandidateShape
objective: CandidateObjective
strategy: CandidateStrategy
source_ref: str
source_kind: CandidateSourceKind
metric_ids: list[str]
semantic_kind: CandidateSemanticKind
semantic_model: str
source_refs: list[str]
recommended_followups: list[FollowupAction] = Field(default_factory=list)
blocking_issues: list[BlockingIssue] = Field(default_factory=list)
params: dict[str, Any]
[docs]
@dataclass(repr=False)
class CandidateSet(BaseFrame):
meta: CandidateSetMeta
_NEXT_INTENTS = ("select",)
def _repr_identity(self) -> str:
return (
f"CandidateSet ref={self.meta.ref} objective={self.meta.objective} "
f"strategy={self.meta.strategy} rows={self.meta.row_count}"
)
def _assert_shape(self, expected: CandidateShape) -> CandidateSet:
if self.meta.shape != expected:
from marivo.analysis.errors import SemanticKindMismatchError
raise SemanticKindMismatchError(
message=f"CandidateSet shape mismatch: expected {expected!r}",
details={
"got_shape": self.meta.shape,
"expected_shape": expected,
},
)
return self
def as_point_anomaly(self) -> CandidateSet:
return self._assert_shape("point_anomaly")
def as_period_shift(self) -> CandidateSet:
return self._assert_shape("period_shift")
def as_driver_axis(self) -> CandidateSet:
return self._assert_shape("driver_axis")
def as_slice(self) -> CandidateSet:
return self._assert_shape("slice")
def as_window(self) -> CandidateSet:
return self._assert_shape("window")
def as_cross_sectional_outlier(self) -> CandidateSet:
return self._assert_shape("cross_sectional_outlier")
[docs]
def select(self, *, rank: int = 1, attribute: str) -> Any:
"""Read one typed attribute from a single ranked candidate row."""
from marivo.analysis.intents.select import select
return select(self, rank=rank, attribute=attribute)