Files
Aether/_deprecated_py_src/services/provider/pool/cost_tracker.py

67 lines
2.0 KiB
Python
Raw Normal View History

"""Rolling-window cost tracking for the Account Pool.
Each key has a configurable token budget per rolling window (e.g. 5 hours).
When the budget is exhausted the key is marked as unschedulable by the pool
manager. A "soft threshold" (default 80 %) causes the pool to *prefer*
other keys but still allows traffic if no alternatives exist.
All state is stored in Redis sorted sets via :mod:`redis_ops`.
"""
from __future__ import annotations
from typing import TYPE_CHECKING
from src.services.provider.pool import redis_ops
if TYPE_CHECKING:
from src.services.provider.pool.config import PoolConfig
async def record_usage(
provider_id: str,
key_id: str,
tokens: int,
config: PoolConfig,
) -> None:
"""Record *tokens* used by *key_id* in the rolling cost window."""
if tokens <= 0:
return
if config.cost_limit_per_key_tokens is None:
return # cost tracking disabled
await redis_ops.add_cost_entry(provider_id, key_id, tokens, config.cost_window_seconds)
async def get_window_usage(
provider_id: str,
key_id: str,
config: PoolConfig,
) -> int:
"""Return total tokens used by *key_id* within the current window."""
return await redis_ops.get_cost_window_total(provider_id, key_id, config.cost_window_seconds)
async def is_at_limit(
provider_id: str,
key_id: str,
config: PoolConfig,
) -> bool:
"""Return ``True`` if the key has exhausted its budget."""
if config.cost_limit_per_key_tokens is None:
return False
total = await get_window_usage(provider_id, key_id, config)
return total >= config.cost_limit_per_key_tokens
async def is_approaching_limit(
provider_id: str,
key_id: str,
config: PoolConfig,
) -> bool:
"""Return ``True`` if the key is above the soft threshold."""
if config.cost_limit_per_key_tokens is None:
return False
total = await get_window_usage(provider_id, key_id, config)
threshold = config.cost_limit_per_key_tokens * config.cost_soft_threshold_percent / 100
return total >= threshold