ump_spec.models.model
module ump-spec
provisional (not yet in the spec) G-DATA-07 is in the gate registry but not yet in the specification’s gate catalogue, so it is not normative.
Model manifest (spec §7), tiers, dependence declaration, acceptance status (§14).
Classes
Section titled “Classes”DependenceDeclaration
Section titled “DependenceDeclaration”class
class DependenceDeclaration(StrictModel)Fields
| Name | Type | Default | Description |
|---|---|---|---|
kind | DependenceKind | ||
assumption | Literal['copula', 'independence'] | None | None | Required when kind is declared_assumption. |
note | str | None | None |
Source: packages/ump-spec/src/ump_spec/models/model.py, line 93
LayerStatus
Section titled “LayerStatus”class
class LayerStatus(StrictModel)Fields
| Name | Type | Default | Description |
|---|---|---|---|
status | Literal['untested', 'passed', 'failed'] | 'untested' | |
metrics | dict[str, Any] | dict() | |
report_id | str | None | None |
Source: packages/ump-spec/src/ump_spec/models/model.py, line 101
AcceptanceStatus
Section titled “AcceptanceStatus”class
class AcceptanceStatus(StrictModel)§14: three layers. Untested is usable with reduced trust; failed is excluded (G-ACC-01).
Fields
| Name | Type | Default | Description |
|---|---|---|---|
status | AcceptanceStatusValue | 'untested' | |
computation | LayerStatus | LayerStatus() | |
identification | LayerStatus | LayerStatus() | |
decisions | LayerStatus | LayerStatus() | |
report_id | str | None | None | |
negative_control | bool | False | True for MTM: the bar must fail it. |
threshold_set_version | str | None | None | §14: the threshold-set version the status was earned against. |
regrade_by | date | None | None | §14: date by which the status must be re-run. |
Source: packages/ump-spec/src/ump_spec/models/model.py, line 107
CurveParams
Section titled “CurveParams”class
class CurveParams(StrictModel)Tier B per-channel curve.
Fields
| Name | Type | Default | Description |
|---|---|---|---|
channel | str | ||
curve_family | Literal['hill', 'logistic', 'power', 'neg_exponential'] | 'hill' | |
params | dict[str, float] | dict() | |
param_draws | dict[str, list[float]] | None | None | |
adstock | dict[str, Any] | None | None | |
input_scaling | float | None | None |
Source: packages/ump-spec/src/ump_spec/models/model.py, line 123
SpendGrid
Section titled “SpendGrid”class
class SpendGrid(StrictModel)Tier C declaration. Grid >= 21 points from 0 to 2.5x current spend is proposed (§7).
Fields
| Name | Type | Default | Description |
|---|---|---|---|
channel | str | ||
multipliers | list[float] | ||
spend | list[float] | ||
contribution | list[float] | None | None | |
contribution_lo | list[float] | None | None | |
contribution_hi | list[float] | None | None | |
current_spend | float | ||
max_seen_spend | float | None | None | |
time_aggregation | Literal['per_week', 'per_flight', 'annual'] | 'annual' | |
adstock_treatment | Literal['included', 'excluded', 'unknown'] | 'unknown' | |
uncertainty | Literal['draws', 'quantiles', 'none'] | 'none' |
Source: packages/ump-spec/src/ump_spec/models/model.py, line 134
SummaryNumber
Section titled “SummaryNumber”class
class SummaryNumber(StrictModel)Tier D: ROI or mROI at current spend only.
Fields
| Name | Type | Default | Description |
|---|---|---|---|
channel | str | ||
metric | Literal['roi', 'mroi'] | ||
value | float | ||
lo | float | None | None | |
hi | float | None | None | |
level | float | None | None | |
current_spend | float | None | None |
Source: packages/ump-spec/src/ump_spec/models/model.py, line 150
HostedEndpoint
Section titled “HostedEndpoint”class
class HostedEndpoint(StrictModel)Tier X.
Fields
| Name | Type | Default | Description |
|---|---|---|---|
endpoint_url | str | ||
revision | str | ||
validated_revision | str | None | None |
Source: packages/ump-spec/src/ump_spec/models/model.py, line 217
ModelManifest
Section titled “ModelManifest”class
class ModelManifest(ArtifactDoc)Fields
| Name | Type | Default | Description |
|---|---|---|---|
name | str | ||
client_id | str | None | None | |
tier | Tier | ||
family | ModelFamily | 'media_mix' | |
engine | str | in-house frameworks, pymc-marketing, meridian, robyn, vendor:nielsen, stub, … | |
engine_version | str | None | None | |
stub | bool | False | |
adapter_url | str | None | None | |
applies_to | AppliesTo | AppliesTo() | |
estimands | dict[str, Estimand] | dict() | |
representation | Representation | 'draws' | |
dependence | DependenceDeclaration | lambda: DependenceDeclaration(kind='none')() | |
acceptance | AcceptanceStatus | AcceptanceStatus() | |
capability_status | CapabilityStatus | 'sandbox' | |
capability_manifest_id | str | None | None | |
valid_from | ValidityInstant | None | None | Spec §7: start of the half-open validity window [valid_from, valid_to), an RFC 3339 instant (UTC, Z, milliseconds). A calendar date reads as midnight UTC. |
valid_to | ValidityInstant | None | None | Spec §7: end of the half-open validity window; the model is expired when valid_to <= now. An RFC 3339 instant; a calendar date reads as midnight UTC. |
refit_date | date | None | None | |
audit_level | Literal[1, 2, 3, 4] | 2 | |
trust_level | int | 2 | |
vendor_validated | bool | None | None | G-VEN-01 outcome for vendor tables. |
calibrated_channels | list[str] | list() | |
licence_limits | list[str] | list() | |
dataset_refs | list[str] | list() | |
payload_refs | dict[str, str] | dict() | |
curves | list[CurveParams] | list() | |
grids | list[SpendGrid] | list() | |
summaries | list[SummaryNumber] | list() | |
endpoint | HostedEndpoint | None | None | |
run_id | str | None | None | |
notes | list[dict[str, Any]] | list() | |
input_contract | InputContract | None | None | The input shape a saved workflow reruns on (optional; checked by G-DATA-07). |
role | str | None | None | Role in the acceptance bar, e.g. negative_control (core’s mirror reads it). Written by models (registry.py, intake.py), planner, experiments and Newton’s seed. |
source_type | str | None | None | Source type for vendor intake (registries/source_types.yaml). Written by models (registry.py, intake.py), planner, experiments and Newton’s seed. |
intake | dict[str, Any] | None | None | Intake record for a vendor or summary model: fallbacks applied and mapping. Written by models (registry.py, intake.py), planner, experiments and Newton’s seed. |
data_fetch | dict[str, Any] | None | None | Dataset fetch record the fit used (storage, use, fetch_record). Written by models (registry.py, intake.py), planner, experiments and Newton’s seed. |
certification | dict[str, Any] | None | None | Certification requirements and their status (§16). Written by models (registry.py, intake.py), planner, experiments and Newton’s seed. |
acceptance_notes | list[Any] | None | None | Notes from the acceptance bar (code, severity, message). Written by models (registry.py, intake.py), planner, experiments and Newton’s seed. |
calibrated_from | dict[str, Any] | None | None | The model version this one was calibrated from, with routes and adjustments. Written by models (registry.py, intake.py), planner, experiments and Newton’s seed. |
response_curves | dict[str, Any] | None | None | Response curves on a spend grid: channels, multipliers, spend grid, values. Written by models (registry.py, intake.py), planner, experiments and Newton’s seed. |
adstock_alpha_draws | dict[str, Any] | None | None | Adstock alpha draws per channel. Written by models (registry.py, intake.py), planner, experiments and Newton’s seed. |
current_spend | dict[str, Any] | None | None | Current spend per channel. Written by models (registry.py, intake.py), planner, experiments and Newton’s seed. |
segments | list[dict[str, Any]] | None | None | Audience output segments {id, size} read by G-PRIV-01. Written by models (registry.py, intake.py), planner, experiments and Newton’s seed. |
seed_tag | str | None | None | Seed label (Newton seed data). Written by models (registry.py, intake.py), planner, experiments and Newton’s seed. |
reach_curves | dict[str, Any] | None | None | Reach and frequency family profile curves (spec §16: reach curve, frequency, dedupe), carried beside the declared estimands. Written by notebook 12 through babelfin Model.from_table. |
metric_family | str | None | None | Legacy top-level metric family (sales_return, brand_awareness, …); the estimand’s own metric_family is preferred. Read by G-EXP-05 (gates._calibration_target) and experiments calibrate.py. |
Source: packages/ump-spec/src/ump_spec/models/model.py, line 225
Functions
Section titled “Functions”normalize_family
Section titled “normalize_family”function
def normalize_family(label: str | None) -> strCanonical family for a label ("brand_funnel/track" -> "media_tracking").
Raises UmpError(SCHEMA_INVALID) for an unknown label. "experiment" is refused on purpose:
experiment adapters declare adapter_kind="experiment" and the family their results calibrate.
Source: packages/ump-spec/src/ump_spec/models/model.py, line 69
validity_instant
Section titled “validity_instant”function
def validity_instant(value: Any) -> datetime | NoneA validity bound as a UTC instant (spec §4 time profile, §7 half-open window). A calendar date
(2026-01-01 or a date) reads as midnight UTC; a naive datetime reads as UTC; an offset is
converted. Anything unreadable (or empty) is None.
Source: packages/ump-spec/src/ump_spec/models/model.py, line 165
validity_expired
Section titled “validity_expired”function
def validity_expired(valid_to: Any, now: datetime | None = None) -> boolSpec §7: the window is half-open [valid_from, valid_to), so a model is expired when
valid_to <= now. No (or an unreadable) valid_to never expires.
Source: packages/ump-spec/src/ump_spec/models/model.py, line 187
Constants
Section titled “Constants”| Name | Type | Value | Description |
|---|---|---|---|
Tier | Literal['A', 'B', 'C', 'D', 'X'] | ||
TIERS | tuple[str, ...] | ('A', 'B', 'C', 'D', 'X') | |
TIER_NAMES | dict[str, str] | {'A': 'full model', 'B': 'curve parameters', 'C': 'spend table', 'D': 'summar... | |
ModelFamily | Literal['media_mix', 'audience', 'reach_frequency', 'attribution', 'brand_fun... | ||
MODEL_FAMILIES | tuple[str, ...] | ('media_mix', 'audience', 'reach_frequency', 'attribution', 'brand_funnel', '... | |
FAMILY_NOTES | dict[str, str] | {'media_mix': 'Marketing mix models (spec §16 media mix profile): response cu... | Plain words per family. Experiments are not a model family (see adapter.AdapterKind). |
FAMILY_ALIASES | dict[str, str] | {'brand_funnel/track': 'media_tracking', 'mtm': 'media_tracking', 'media_trac... | Labels seen in briefs and adapters mapped to the canonical ModelFamily value. |
Representation | Literal['draws', 'quantiles', 'interval', 'point', 'moments', 'moments_cov'] | ||
DependenceKind | Literal['joint_draws', 'joint_gaussian', 'declared_assumption', 'per_channel'... | ||
AcceptanceStatusValue | Literal['untested', 'pilot', 'passed', 'failed'] | ||
CapabilityStatus | Literal['sandbox', 'pilot', 'certified', 'restricted', 'withdrawn'] | ||
LayerName | Literal['computation', 'identification', 'decisions'] | ||
ACCEPTANCE_LAYERS | tuple[str, ...] | ('computation', 'identification', 'decisions') | |
ValidityInstant | Annotated[datetime, BeforeValidator(_coerce_validity), PlainSerializer(_insta... |