Skip to content

Route free-tier users to a cheaper model on the Omni router - #2483

Open
gary149 wants to merge 7 commits into
mainfrom
claude/user-tier-deepseek-routing-7c4d90
Open

Route free-tier users to a cheaper model on the Omni router#2483
gary149 wants to merge 7 commits into
mainfrom
claude/user-tier-deepseek-routing-7c4d90

Conversation

@gary149

@gary149 gary149 commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator

What

When LLM_ROUTER_FREE_USER_MODEL is set, the Omni router pins users who can't currently pay for inference to that model instead of the normal route selection. Prod and dev set it to zai-org/GLM-5.3-Flash (served first-party by Z.ai, tool-capable, already in the model roster since the latest router sync). Leaving the variable empty (the default) disables the feature entirely, so self-hosted deployments see no change.

Why

Prod runs with USE_USER_TOKEN=true, so inference is billed to each user's own HF account. Free users only get a small amount of included monthly credits, and the default route currently sends everyone to Kimi-K2.6, which burns through those credits almost immediately and triggers the "out of credits" modal. At current pricing, an average chat message on GLM-5.3-Flash costs roughly an order of magnitude less than on Kimi-K2.6, taking a free user from ~30 messages a month to a few hundred, while paying users keep the premium routing.

How it works

  • A user counts as paid when the Hub reports isPro or canPay, or when their selected billing organization can pay (with org billing via X-HF-Bill-To, the org is the entity charged). Everyone else, including sessions without a user token, is free.
  • Payment status is read from the Hub's OAuth userinfo endpoint with the user's token (the read-billing scope is already in OPENID_SCOPES) and cached in-process for 10 minutes per user, with a 1 minute negative cache. Lookups fail open to paid, so a Hub outage never demotes a paying user.
  • The tier only affects the router alias. Directly picked models are untouched, and while the free model is text-only the lookup runs after the multimodal bypass, so image requests never pay for it.
  • Free users on the default and agentic routes get [free model, ...route's normal candidates]: if the free model errors, the request falls back to the models already configured in routes.chat.json. Image requests keep LLM_ROUTER_MULTIMODAL_MODEL unless the free model is itself multimodal-capable per the router, in which case it serves free users' images too. The served GLM-5.3-Flash is text-only today, so images stay on the premium multimodal model until Z.ai enables image input, at which point the switch is automatic.
  • Route names in the UI badge stay semantic (default / agentic / multimodal); only the served model changes.
  • Startup validation logs an error if the configured free model is missing from the model list or if read-billing is absent from the scopes.

Reviewer notes

  • Both router implementations get the tier branch: src/lib/server/router/endpoint.ts (plain generation) and src/lib/server/textGeneration/mcp/routerResolution.ts (MCP flow). The lookup, cache, and validation live in the new src/lib/server/router/userTier.ts.
  • GLM-5.3-Flash has a single serving provider (zai-org), so a Z.ai outage sends free users through the normal candidate fallback (Kimi and friends) until it recovers. Its current price is promotional through September 9, 2026; afterwards it remains several times cheaper than the default route target, but it may be worth re-checking the numbers then.
  • PRO subscribers with a depleted balance still count as paid by design; they keep premium routing until the upstream 402 shows the existing "out of credits" modal.
  • 42 new unit tests across three specs cover the paid formula, cache TTL and fail-open behavior, and the routing branches (including fallback when the free model fails, and the guarantee that image requests never trigger the billing lookup). Full suite: 1038 tests passing, npm run check and npm run lint clean.

gary149 added 2 commits August 5, 2026 15:18
When LLM_ROUTER_FREE_USER_MODEL is set, users who can't currently pay for
inference on the Hub (no PRO subscription, no prepaid credits or valid
payment method, no paying billing organization selected) are pinned to
that model on the default and agentic routes, with the route's normal
candidates as fallbacks. Image requests keep LLM_ROUTER_MULTIMODAL_MODEL
since the free model is text-only.

Payment status comes from the Hub's OAuth userinfo endpoint (requires the
read-billing scope already present in OPENID_SCOPES), cached in-process
for 10 minutes per user and failing open to paid so a Hub error never
demotes a paying user. The lookup only runs for router-alias requests,
after the tier-independent multimodal bypass, and is skipped entirely
when the feature is disabled (the default), leaving self-hosted
deployments unaffected.

Prod and dev pin free users to deepseek-ai/DeepSeek-V4-Flash-0731.
Swap the free-user model from deepseek-ai/DeepSeek-V4-Flash-0731 to
zai-org/GLM-5.3-Flash in the prod and dev charts, and add the model to
the roster with a description and artifacts support since free users
will now see it by default. GLM-5.3-Flash is served first-party by Z.ai,
supports tool calling, and is priced well below the previous default
route target, so free users' included credits last roughly an order of
magnitude longer.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fad14fde30

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/lib/server/textGeneration/mcp/routerResolution.ts
…seek-routing-7c4d90

# Conflicts:
#	chart/env/dev.yaml
#	chart/env/prod.yaml
The multimodal bypass now prefers the free-user model for free users'
image requests when the router reports it as multimodal-capable, instead
of always using LLM_ROUTER_MULTIMODAL_MODEL. With a text-only free model
(the current case for the served GLM-5.3-Flash) nothing changes and the
tier is still never resolved for image requests; the switch happens
automatically if the served model gains image support.
Concurrent cache misses for the same user each called the rate-limited
userinfo endpoint, and a late failure could overwrite a fresh successful
entry with the short-lived fail-open one. Track the in-flight lookup per
user so parallel requests share a single fetch and a single result.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8c89dd4b6b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/lib/server/router/userTier.ts
Free-tier detection calls the Hub's userinfo endpoint with the user's
OAuth token. On deployments configured with a third-party OpenID
provider that token is not a Hub credential, so the lookup now only runs
when the configured provider is huggingface.co (mirroring auth.ts's
PROVIDER_URL resolution). With any other provider the feature stays
inactive, tokens are never transmitted, and startup validation logs an
error for the misconfiguration.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 11afb74a72

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/lib/server/router/endpoint.ts Outdated
The multimodal bypass was single-shot: when a free user's image request
was served by a multimodal-capable free model, an upstream failure broke
the request even though LLM_ROUTER_MULTIMODAL_MODEL was available. The
bypass now tries an ordered candidate list (free model first for free
users, then the configured multimodal model), matching the fallback
behavior of the text routes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant