Bases: Metric
Base class for LanguageModel runtime-counter metrics.
Subclasses set _phase to one of "inference", "reward", or
"optimizer" to read from the corresponding counter set on each
bound LM. Counters are populated by the LM based on the active
op_scope (contextvar) the trainer sets for each phase.
The metric binds itself automatically to every LanguageModel
reachable from the program (and their .fallback chains) when
program.compile() is called, and counters are summed across all.
Example:
program.compile(
metrics=[
synalinks.metrics.LMOperationalMetric(),
],
)
Source code in synalinks/src/metrics/lm_metrics.py
| @synalinks_export(
[
"synalinks.metrics.LMOperationalMetric",
"synalinks.LMOperationalMetric",
]
)
class LMOperationalMetric(Metric):
"""Base class for `LanguageModel` runtime-counter metrics.
Subclasses set `_phase` to one of ``"inference"``, ``"reward"``, or
``"optimizer"`` to read from the corresponding counter set on each
bound LM. Counters are populated by the LM based on the active
``op_scope`` (contextvar) the trainer sets for each phase.
The metric binds itself automatically to every `LanguageModel`
reachable from the program (and their `.fallback` chains) when
`program.compile()` is called, and counters are summed across all.
Example:
```python
program.compile(
metrics=[
synalinks.metrics.LMOperationalMetric(),
],
)
```
"""
_phase = "inference"
def __init__(self, name=None):
super().__init__(name=name)
self._language_models = []
self._baselines = {suffix: 0 for suffix in _TRACKED_SUFFIXES}
self._wall_baseline = 0.0
@property
def language_models(self):
return list(self._language_models)
def bind_program(self, program):
self._language_models = _collect_language_models(program)
self._snapshot()
def _attr(self, suffix):
return f"{self._phase}_cumulated_{suffix}"
def _read(self, suffix):
attr = self._attr(suffix)
return sum(getattr(lm, attr, 0) for lm in self._language_models)
def _snapshot(self):
for suffix in _TRACKED_SUFFIXES:
self._baselines[suffix] = self._read(suffix)
self._wall_baseline = read_phase_wall_clock_s(self._phase)
def _delta(self, suffix):
return self._read(suffix) - self._baselines.get(suffix, 0)
def _wall_clock_delta(self):
"""Wall-clock seconds the trainer spent in this metric's phase since
the last snapshot. Used as the throughput denominator so concurrent
(overlapping) calls don't inflate it the way summed `elapsed_s` does.
"""
return read_phase_wall_clock_s(self._phase) - self._wall_baseline
def reset_state(self):
self._snapshot()
async def update_state(self, *args, **kwargs):
return
def result(self):
raise NotImplementedError
def get_config(self):
return {"name": self.name}
|