Spaces:
Sleeping
Sleeping
File size: 5,450 Bytes
d9af7ee | 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 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | """Constraint metadata and helper utilities for patch selection UI."""
from __future__ import annotations
from dataclasses import dataclass
from typing import Dict, Iterable, Mapping
@dataclass(frozen=True)
class MetricRange:
"""Slider bounds for a specific metric."""
default: float
minimum: float
maximum: float
step: float
label: str | None = None
description: str | None = None
@dataclass(frozen=True)
class ConstraintDefinition:
"""UI metadata + semantic description for a constraint."""
name: str
label: str
description: str
entropy: MetricRange
perplexity: MetricRange
guard: bool = False
def range_for_metric(self, metric_name: str) -> MetricRange:
"""Return the metric range for the given metric label."""
key = metric_name.lower()
if key not in ("entropy", "perplexity"):
raise ValueError(f"Unknown metric '{metric_name}'")
return getattr(self, key)
# Constraint slider definitions
CONSTRAINT_DEFINITIONS: Dict[str, ConstraintDefinition] = {
"global": ConstraintDefinition(
name="global",
label="Global Threshold",
description="H(t) > θ",
entropy=MetricRange(default=5.0, minimum=0.0, maximum=20.0, step=0.5),
perplexity=MetricRange(default=300.0, minimum=0.0, maximum=2000.0, step=5.0),
),
"additive": ConstraintDefinition(
name="additive",
label="Additive Monotonic",
description="H(t) - H(t-1) > θ",
entropy=MetricRange(default=0.5, minimum=0.0, maximum=10.0, step=0.1),
perplexity=MetricRange(default=5.0, minimum=0.0, maximum=100.0, step=1.0),
),
"multiplicative": ConstraintDefinition(
name="multiplicative",
label="Multiplicative Monotonic",
description="H(t) / H(t-1) > θ",
entropy=MetricRange(default=1.5, minimum=1.0, maximum=5.0, step=0.1),
perplexity=MetricRange(default=1.5, minimum=1.0, maximum=5.0, step=0.1),
),
"additive_min": ConstraintDefinition(
name="additive_min",
label="Additive from Min",
description="H(t) - min(H) > θ",
entropy=MetricRange(default=2.0, minimum=0.0, maximum=10.0, step=0.1),
perplexity=MetricRange(default=20.0, minimum=0.0, maximum=100.0, step=1.0),
),
"multiplicative_min": ConstraintDefinition(
name="multiplicative_min",
label="Multiplicative from Min",
description="H(t) / min(H) > θ",
entropy=MetricRange(default=2.0, minimum=1.0, maximum=10.0, step=0.1),
perplexity=MetricRange(default=3.0, minimum=1.0, maximum=10.0, step=0.1),
),
"cumulative": ConstraintDefinition(
name="cumulative",
label="Cumulative Sum (Min)",
description="Σ H(t) > θ (boundary after exceeding)",
entropy=MetricRange(default=10.0, minimum=0.0, maximum=100.0, step=1.0),
perplexity=MetricRange(default=100.0, minimum=0.0, maximum=1000.0, step=10.0),
),
"cumulative_max": ConstraintDefinition(
name="cumulative_max",
label="Cumulative Sum (Max)",
description="Σ H(t) ≤ θ (boundary before exceeding)",
entropy=MetricRange(default=50.0, minimum=0.0, maximum=500.0, step=5.0),
perplexity=MetricRange(default=500.0, minimum=0.0, maximum=10000.0, step=50.0),
),
}
MIN_GUARD_DEFINITION = ConstraintDefinition(
name="min_metric",
label="Minimum Metric for Boundary",
description="AND guard: boundaries only trigger once metric exceeds this value",
entropy=MetricRange(
default=0.0,
minimum=0.0,
maximum=20.0,
step=0.1,
label="Minimum Entropy for Boundary",
description="Guard: boundaries only trigger once entropy exceeds this value",
),
perplexity=MetricRange(
default=0.0,
minimum=0.0,
maximum=2000.0,
step=5.0,
label="Minimum Perplexity for Boundary",
description="Guard: boundaries only trigger once perplexity exceeds this value",
),
guard=True,
)
def iter_constraint_definitions() -> Iterable[ConstraintDefinition]:
"""Iterate definitions in sorted order by display label."""
return sorted(CONSTRAINT_DEFINITIONS.values(), key=lambda c: c.label)
def get_constraint_definition(name: str) -> ConstraintDefinition:
"""Return definition by name."""
if name == MIN_GUARD_DEFINITION.name:
return MIN_GUARD_DEFINITION
try:
return CONSTRAINT_DEFINITIONS[name]
except KeyError as exc:
raise KeyError(f"Unknown constraint '{name}'") from exc
def default_thresholds_for_metric(metric_name: str) -> Mapping[str, float]:
"""Return default slider values for each constraint given the metric."""
return {
definition.name: definition.range_for_metric(metric_name).default
for definition in iter_constraint_definitions()
}
def guard_range_for_metric(metric_name: str) -> MetricRange:
"""Return metric range for the guard slider."""
metric_range = MIN_GUARD_DEFINITION.range_for_metric(metric_name)
if metric_range.label and metric_range.description:
return metric_range
return MetricRange(
default=metric_range.default,
minimum=metric_range.minimum,
maximum=metric_range.maximum,
step=metric_range.step,
label=MIN_GUARD_DEFINITION.label,
description=MIN_GUARD_DEFINITION.description,
)
|