agentic-rl-main / opsd_utils /dynamic_trigger_monitor.py
Jack04810's picture
Add files using upload-large-folder tool
2f943cb verified
Raw History Blame Contribute Delete
3.26 kB
from __future__ import annotations
from dataclasses import dataclass
@dataclass(frozen=True)
class DynamicTriggerConfig:
ema_alpha: float = 0.10
min_progress: float = 0.20
patience_steps: int = 20
sampling_mixed_max: float = 0.20
sampling_zero_loss_min: float = 0.70
rl_mixed_min: float = 0.30
rl_zero_loss_max: float = 0.30
class DynamicTriggerMonitor:
"""Observe candidate signal-driven phase triggers without controlling training."""
def __init__(self, config: DynamicTriggerConfig):
self.config = config
self._mixed_ema: float | None = None
self._zero_loss_ema: float | None = None
self._sampling_streak = 0
self._rl_streak = 0
self._sampling_trigger_progress: float | None = None
self._rl_trigger_progress: float | None = None
def _update_ema(self, previous: float | None, value: float) -> float:
if previous is None:
return float(value)
alpha = max(0.0, min(float(self.config.ema_alpha), 1.0))
return alpha * float(value) + (1.0 - alpha) * previous
def update(self, *, mixed_rate: float, zero_loss_rate: float, progress: float) -> dict[str, float]:
self._mixed_ema = self._update_ema(self._mixed_ema, mixed_rate)
self._zero_loss_ema = self._update_ema(self._zero_loss_ema, zero_loss_rate)
eligible = float(progress) >= float(self.config.min_progress)
sampling_now = eligible and (
self._mixed_ema <= float(self.config.sampling_mixed_max)
and self._zero_loss_ema >= float(self.config.sampling_zero_loss_min)
)
rl_now = eligible and (
self._mixed_ema >= float(self.config.rl_mixed_min)
and self._zero_loss_ema <= float(self.config.rl_zero_loss_max)
)
self._sampling_streak = self._sampling_streak + 1 if sampling_now else 0
self._rl_streak = self._rl_streak + 1 if rl_now else 0
patience = max(1, int(self.config.patience_steps))
if self._sampling_trigger_progress is None and self._sampling_streak >= patience:
self._sampling_trigger_progress = float(progress)
if self._rl_trigger_progress is None and self._rl_streak >= patience:
self._rl_trigger_progress = float(progress)
return {
"dynamic_mixed_rate_ema": float(self._mixed_ema),
"dynamic_zero_loss_rate_ema": float(self._zero_loss_ema),
"dynamic_sampling_needed_now": float(sampling_now),
"dynamic_sampling_needed_streak": float(self._sampling_streak),
"dynamic_sampling_would_trigger": float(self._sampling_trigger_progress is not None),
"dynamic_sampling_trigger_progress": (
float(self._sampling_trigger_progress)
if self._sampling_trigger_progress is not None
else -1.0
),
"dynamic_rl_ready_now": float(rl_now),
"dynamic_rl_ready_streak": float(self._rl_streak),
"dynamic_rl_would_trigger": float(self._rl_trigger_progress is not None),
"dynamic_rl_trigger_progress": (
float(self._rl_trigger_progress) if self._rl_trigger_progress is not None else -1.0
),
}