Skip to content

symfonic.services.budget.registry

registry

Provider-aware exact counting: registered by the adopter, never fetched here.

The demand is real — an operator reconciling invoices, or trimming to the last token of a 200k window, needs the provider's own arithmetic, not four characters per token. The usual way to serve it is to import a tokenizer library and let it fetch an encoding on first use, and that turns prompt assembly into a network operation: the first request after a cold deploy blocks on a download, and on a container with no egress it fails outright, in the budget layer, with a stack trace that names a vocabulary file.

So exactness arrives from the outside. An adopter constructs their counter — with whatever SDK, cache warming, or vendored vocabulary they choose — and registers it. This package holds the seam and refuses anything that admits it would download, at registration time, on the machine that wrote the config.

ExactCounterRegistry

ExactCounterRegistry()

The adopter's provider-exact counters, by provider name.

Mutable by design and by construction order: registration happens once, at assembly time, before any policy is resolved against it. Lookup is read-only, so a resolved :class:~.values.CounterResolution cannot change under a running request.

Source code in src/symfonic/services/budget/registry.py
def __init__(self) -> None:
    self._specs: dict[str, ExactCounterSpec] = {}

get

get(provider: str) -> ExactCounterSpec | None

The registered spec for provider, or None.

Source code in src/symfonic/services/budget/registry.py
def get(self, provider: str) -> ExactCounterSpec | None:
    """The registered spec for ``provider``, or ``None``."""
    return self._specs.get(_key(provider))

providers

providers() -> tuple[str, ...]

Every registered provider, in registration order.

Source code in src/symfonic/services/budget/registry.py
def providers(self) -> tuple[str, ...]:
    """Every registered provider, in registration order."""
    return tuple(spec.provider for spec in self._specs.values())

register

register(spec: ExactCounterSpec, *, replace: bool = False) -> None

Accept a counter for spec.provider.

Refuses a spec that does not claim to be offline, and refuses to silently shadow an existing registration — a second registration for the same provider is either a bug or an intentional override, and only the caller knows which, so replace makes them say.

Source code in src/symfonic/services/budget/registry.py
def register(self, spec: ExactCounterSpec, *, replace: bool = False) -> None:
    """Accept a counter for ``spec.provider``.

    Refuses a spec that does not claim to be offline, and refuses to
    silently shadow an existing registration — a second registration for
    the same provider is either a bug or an intentional override, and only
    the caller knows which, so ``replace`` makes them say.
    """
    if not spec.offline:
        raise ExactCounterUnavailableError(
            f"counter for {spec.provider!r} does not declare itself offline. "
            "Budgeting must not fetch a tokenizer: warm the vocabulary at "
            "build time and register a counter that reads it locally."
        )
    key = _key(spec.provider)
    if key in self._specs and not replace:
        raise ExactCounterUnavailableError(
            f"a counter for {spec.provider!r} is already registered; pass "
            "replace=True to override it deliberately."
        )
    self._specs[key] = spec

resolve_counter

resolve_counter(policy: BudgetPolicy, registry: ExactCounterRegistry | None) -> CounterResolution

Pick the counter policy asked for, or say why it could not be had.

Three modes, three different failure stances, and the differences are the reason the enum has three members rather than a boolean:

  • HEURISTIC never consults the registry at all — a policy that asked for the cheap deterministic counter gets it even where an exact one exists, because reproducibility was the thing it wanted.
  • EXACT raises when nothing is registered. Estimating for an operator who asked for exact arithmetic is wrong in a direction nobody can see.
  • EXACT_PREFERRED falls back and records the degradation, so the difference between "precise" and "close enough" survives into the diagnostics instead of being lost at the call site.
Source code in src/symfonic/services/budget/registry.py
def resolve_counter(
    policy: BudgetPolicy, registry: ExactCounterRegistry | None
) -> CounterResolution:
    """Pick the counter ``policy`` asked for, or say why it could not be had.

    Three modes, three different failure stances, and the differences are the
    reason the enum has three members rather than a boolean:

    * ``HEURISTIC`` never consults the registry at all — a policy that asked
      for the cheap deterministic counter gets it even where an exact one
      exists, because reproducibility was the thing it wanted.
    * ``EXACT`` raises when nothing is registered. Estimating for an operator
      who asked for exact arithmetic is wrong in a direction nobody can see.
    * ``EXACT_PREFERRED`` falls back **and records the degradation**, so the
      difference between "precise" and "close enough" survives into the
      diagnostics instead of being lost at the call site.
    """
    fallback = HeuristicTokenCounter(chars_per_token=policy.chars_per_token)
    if policy.mode is CountingMode.HEURISTIC:
        return CounterResolution(counter=fallback, mode=CountingMode.HEURISTIC)

    spec = registry.get(policy.provider) if registry is not None else None
    if spec is not None:
        return CounterResolution(
            counter=spec.counter,
            mode=CountingMode.EXACT,
            provider=spec.provider,
            revision=spec.revision,
        )

    if policy.mode is CountingMode.EXACT:
        raise ExactCounterUnavailableError(
            f"no exact token counter is registered for provider {policy.provider!r}. "
            "Register one with ExactCounterRegistry.register(...), or declare "
            "mode=CountingMode.EXACT_PREFERRED to accept the offline estimate."
        )

    return CounterResolution(
        counter=fallback,
        mode=CountingMode.HEURISTIC,
        provider=policy.provider,
        degraded=True,
        reason=(
            f"no exact counter registered for {policy.provider!r}; budgeting with "
            f"the offline estimate at {policy.chars_per_token} chars/token."
        ),
    )