Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/control/account/backends/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ def _upsert_sync(
token = AccountRecord.model_validate({"token": item.token, "pool": item.pool}).token
except ValueError:
continue
pool = item.pool if item.pool in ("basic", "super", "heavy") else "basic"
pool = item.pool if item.pool in ("basic", "lite", "super", "heavy") else "basic"
qs = default_quota_set(pool)
conn.execute(
f"""
Expand Down
2 changes: 1 addition & 1 deletion app/control/account/backends/redis.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ async def upsert_accounts(
token = AccountRecord.model_validate({"token": item.token, "pool": item.pool}).token
except ValueError:
continue
pool = item.pool if item.pool in ("basic", "super", "heavy") else "basic"
pool = item.pool if item.pool in ("basic", "lite", "super", "heavy") else "basic"
qs = default_quota_set(pool)
ts = now_ms()
record = AccountRecord(
Expand Down
2 changes: 1 addition & 1 deletion app/control/account/backends/sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -627,7 +627,7 @@ async def upsert_accounts(
token = AccountRecord.model_validate({"token": item.token, "pool": item.pool}).token
except Exception:
continue
pool = item.pool if item.pool in ("basic", "super", "heavy") else "basic"
pool = item.pool if item.pool in ("basic", "lite", "super", "heavy") else "basic"
qs = default_quota_set(pool)
row = {
"token": token,
Expand Down
8 changes: 7 additions & 1 deletion app/control/account/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,10 @@ class AccountRecord(BaseModel):
def is_nsfw(self) -> bool:
return "nsfw" in self.tags

@property
def is_lite(self) -> bool:
return self.pool == "lite"

@property
def is_super(self) -> bool:
return self.pool == "super"
Expand Down Expand Up @@ -263,7 +267,9 @@ def _normalize_token(cls, v: Any) -> str:
@classmethod
def _normalize_pool(cls, v: Any) -> str:
val = str(v or "").strip().lower()
if val in ("super"):
if val in ("lite",):
return "lite"
if val in ("super",):
return "super"
if val in ("heavy",):
return "heavy"
Expand Down
36 changes: 24 additions & 12 deletions app/control/account/quota_defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@ def _w(remaining: int, total: int, window_seconds: int) -> QuotaWindow:
expert=_w(0, 0, 0), # unsupported on basic accounts
)

LITE_QUOTA_DEFAULTS = AccountQuotaSet(
auto=_w(25, 25, 7_200), # 25 queries / 2 h
fast=_w(70, 70, 7_200), # 70 queries / 2 h
expert=_w(12, 12, 7_200), # 12 queries / 2 h
grok_4_3=_w(12, 12, 7_200), # 12 queries / 2 h
)

SUPER_QUOTA_DEFAULTS = AccountQuotaSet(
auto=_w(50, 50, 7_200), # 50 queries / 2 h
fast=_w(140, 140, 7_200), # 140 queries / 2 h
Expand All @@ -67,26 +74,18 @@ def _w(remaining: int, total: int, window_seconds: int) -> QuotaWindow:
# Map pool name → defaults object (used by backends on upsert).
_POOL_DEFAULTS: dict[str, AccountQuotaSet] = {
"basic": BASIC_QUOTA_DEFAULTS,
"lite": LITE_QUOTA_DEFAULTS,
"super": SUPER_QUOTA_DEFAULTS,
"heavy": HEAVY_QUOTA_DEFAULTS,
}

_SUPPORTED_MODE_IDS_BY_POOL: dict[str, frozenset[int]] = {
"basic": frozenset((1,)),
"lite": frozenset((0, 1, 2, 4)),
"super": frozenset((0, 1, 2, 4)),
"heavy": frozenset((0, 1, 2, 3, 4)),
}

# ---------------------------------------------------------------------------
# Pool inference — keyed on auto.total (unique across pool types)
# ---------------------------------------------------------------------------

_AUTO_TOTAL_TO_POOL: dict[int, str] = {
20: "basic",
50: "super",
150: "heavy",
}


def default_quota_set(pool: str) -> AccountQuotaSet:
"""Return a fresh copy of the default quota set for *pool*."""
Expand Down Expand Up @@ -162,17 +161,30 @@ def normalize_quota_set(pool: str, quota_set: AccountQuotaSet) -> AccountQuotaSe
def infer_pool(windows: dict[int, QuotaWindow]) -> str:
"""Infer pool type from live quota windows returned by the rate-limits API.

Uses ``auto.total`` (mode_id=0) as the discriminating signal.
Uses ``auto.total`` (mode_id=0) as the discriminating signal:
- 25 -> lite
- 50 -> super
- 150 -> heavy
- otherwise -> basic
Falls back to ``"basic"`` when the value is absent or unrecognised.
"""
auto_win = windows.get(0)
if auto_win is None:
return "basic"
return _AUTO_TOTAL_TO_POOL.get(auto_win.total, "basic")
total = auto_win.total
if total == 25:
return "lite"
elif total == 50:
return "super"
elif total >= 150:
return "heavy"
else:
return "basic"


__all__ = [
"BASIC_QUOTA_DEFAULTS",
"LITE_QUOTA_DEFAULTS",
"SUPER_QUOTA_DEFAULTS",
"HEAVY_QUOTA_DEFAULTS",
"default_quota_set",
Expand Down
1 change: 1 addition & 0 deletions app/control/account/scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
# Pool → (config key, built-in default seconds)
_POOL_CONFIG: dict[str, tuple[str, int]] = {
"basic": ("account.refresh.basic_interval_sec", 86_400),
"lite": ("account.refresh.super_interval_sec", 7_200),
"super": ("account.refresh.super_interval_sec", 7_200),
"heavy": ("account.refresh.heavy_interval_sec", 7_200),
}
Expand Down
5 changes: 3 additions & 2 deletions app/control/model/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ class Tier(IntEnum):
"""Account tier — determines which pool is selected."""

BASIC = 0 # pool="basic"
SUPER = 1 # pool="super"
HEAVY = 2 # pool="heavy"
LITE = 1 # pool="lite"
SUPER = 2 # pool="super"
HEAVY = 3 # pool="heavy"


class Capability(IntFlag):
Expand Down
24 changes: 16 additions & 8 deletions app/control/model/spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ def is_voice(self) -> bool:

def pool_name(self) -> str:
"""Return the canonical pool string for this tier."""
if self.tier == Tier.LITE:
return "lite"
if self.tier == Tier.SUPER:
return "super"
if self.tier == Tier.HEAVY:
Expand All @@ -69,26 +71,32 @@ def pool_candidates(self) -> tuple[int, ...]:
when all accounts in higher pools are exhausted).

Default (prefer_best=False):
BASIC tier → try basic first, then super, then heavy
BASIC tier → try basic first, then lite, then super, then heavy
LITE tier → try lite first, then super, then heavy
SUPER tier → try super first, then heavy
HEAVY tier → heavy only

Reversed (prefer_best=True):
BASIC tier → try heavy first, then super, then basic
BASIC tier → try heavy first, then super, then lite, then basic
LITE tier → try heavy first, then super, then lite
SUPER tier → try heavy first, then super
HEAVY tier → heavy only
"""
if self.prefer_best:
if self.tier == Tier.HEAVY:
return (2,) # heavy only
return (3,) # heavy only
if self.tier == Tier.SUPER:
return (2, 1) # heavy, super
return (2, 1, 0) # heavy, super, basic
return (3, 2, 1) # heavy, super, lite
if self.tier == Tier.LITE:
return (3, 2, 1) # heavy, super, lite
return (3, 2, 1, 0) # heavy, super, lite, basic
if self.tier == Tier.BASIC:
return (0, 1, 2) # basic, super, heavy
return (0, 1, 2, 3) # basic, lite, super, heavy
if self.tier == Tier.LITE:
return (1, 2, 3) # lite, super, heavy
if self.tier == Tier.SUPER:
return (1, 2) # super, heavy
return (2,) # heavy only
return (2, 1, 3) # super, lite, heavy
return (3,) # heavy only


__all__ = ["ModelSpec"]
1 change: 1 addition & 0 deletions app/dataplane/account/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@ def revision(self) -> int:

_POOL_INTERVAL_CONFIG: dict[str, tuple[str, int]] = {
"basic": ("account.refresh.basic_interval_sec", 86_400),
"lite": ("account.refresh.super_interval_sec", 7_200),
"super": ("account.refresh.super_interval_sec", 7_200),
"heavy": ("account.refresh.heavy_interval_sec", 7_200),
}
Expand Down
6 changes: 4 additions & 2 deletions app/dataplane/shared/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ class ModeId(IntEnum):

class PoolId(IntEnum):
BASIC = 0
SUPER = 1
HEAVY = 2
LITE = 1
SUPER = 2
HEAVY = 3


class StatusId(IntEnum):
Expand All @@ -32,6 +33,7 @@ class StatusId(IntEnum):
# Map pool string → PoolId integer (used during sync from control plane).
POOL_STR_TO_ID: dict[str, int] = {
"basic": int(PoolId.BASIC),
"lite": int(PoolId.LITE),
"super": int(PoolId.SUPER),
"heavy": int(PoolId.HEAVY),
}
Expand Down
2 changes: 1 addition & 1 deletion app/products/openai/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
from .chat import completions as chat_completions

router = APIRouter(prefix="/v1")
_POOL_ID_TO_NAME = {0: "basic", 1: "super", 2: "heavy"}
_POOL_ID_TO_NAME = {0: "basic", 1: "lite", 2: "super", 3: "heavy"}
_TAG_MODELS = "OpenAI - Models"
_TAG_CHAT = "OpenAI - Chat"
_TAG_RESPONSES = "OpenAI - Responses"
Expand Down