{{define "admin_quotas"}} Quotas · llmgw {{/* Links and forms work as plain navigation; htmx, when it loads, swaps only #quotas so opening a form or saving one does not jump the page. */}}

Quotas

What each organization, team and project may use · spend over the last {{.Since}}

{{template "nav" .Nav}}
{{if not .BudgetsBind}} {{/* A budget is spend per period and spend comes from a price table. With no prices every request costs nothing, so these numbers read as limits and bind on nothing. Self-hosted models having no per-token price is ordinary; showing somebody a budget without saying so is not. */}} {{end}} {{if .Error}}{{end}} {{if .Message}}

{{.Message}}

{{end}} {{if .Rows}} {{/* The tree is the interface. A quota belongs to a branch, so the form to set one opens on that branch rather than asking somebody to name it again in a box at the bottom. */}} {{range .Rows}} {{if .MemberEditing}} {{end}} {{if .Editing}} {{end}} {{end}}
WhereRequests/minTokens/min BudgetSpent
{{.Path}} {{.Scope}} {{if .Models}}
only {{.Models}}
{{else if .ModelsFrom}}
models limited by {{.ModelsFrom}}
{{end}} {{if .Member}}
each member here: {{.Member}}
{{end}} {{if .Shadowed}} {{/* A value that is written here and never reached. Resolution takes the most restrictive along the chain, so without saying so the page would show a number as though it applied. */}}
{{.Shadowed}}
{{end}}
{{template "quota-value" dict "Own" .RPM "Up" .RPMUp "From" .RPMFrom}} {{template "quota-value" dict "Own" .TPM "Up" .TPMUp "From" .TPMFrom}} {{if .Budget}}{{.Budget}}{{if .Period}}/{{.Period}}{{end}} {{else}}{{template "quota-value" dict "Own" "" "Up" .BudgetUp "From" .BudgetFrom}}{{end}} {{.Spend}} {{if .HasPct}} {{.Percent}}%{{end}} {{if .Editing}}close {{else}}{{if .HasAny}}change{{else}}set{{end}}{{end}} {{if .MemberEditing}}close {{else}}per member{{end}}
{{template "quota-form" (dict "Scope" (printf "%s-member" .Scope) "ID" .ID "F" .MemberRaw "CSRF" $.CSRF "Title" (printf "Each member of %s, separately" .Crumb) "Note" "Every member gets this much here, counted apart from the others — a fair share rather than one pool.")}}

Quota for {{.Crumb}}, shared by everything beneath it. A blank field means no limit of that kind, not a limit of zero.

Cancel

60 ↑ is held by a limit set higher up — hover it to see where. A value set here is in normal type.

{{else}}

Nothing to give a quota to yet. Make an organization on the people page first.

{{end}}

People

A person's own limit covers everything they do, across all their keys, projects and the chat page. {{.Personal}}

{{if .People}} {{range .People}} {{if .Editing}} {{end}} {{end}}
PersonRequests/minTokens/min BudgetSpent
{{.Email}} {{if .Models}}
only {{.Models}}
{{end}}
{{or .RPM "—"}} {{or .TPM "—"}} {{if .Budget}}{{.Budget}}{{if .Period}}/{{.Period}}{{end}}{{else}}—{{end}} {{.Spend}} {{if .HasPct}} {{.Percent}}%{{end}} {{if .Editing}}close {{else}}{{if .HasAny}}change{{else}}set{{end}}{{end}}
{{template "quota-form" (dict "Scope" "user" "ID" .ID "CSRF" $.CSRF "F" (dict "RPM" .RPM "TPM" .TPM "Budget" .Budget "Period" .Period "Models" .Models "HasAny" .HasAny) "Title" (printf "%s, everywhere" .Email) "Note" "Across every key this person holds, every project they use and the chat page.")}}
{{else}}

Nobody has been approved yet.

{{end}}
How limits combine

Along a branch the most restrictive value wins, so a team cannot raise what its organization set and a project cannot raise its team's. Only an organization's own limit is bounded by nothing. Model lists intersect: a project cannot allow a model its team withheld.

Per-key limits are not set here: a key is bounded by its project, and putting every caller's throughput one click from an admin session is more than this page should do — llmgw keys limits --scope key.

{{end}} {{/* A limit as the table shows it: the row's own value, else the one it is held to from above, marked as inherited and saying from where. */}} {{/* The form for a limit that is not a branch's own: per member, or a person. */}} {{define "quota-form"}}

{{.Title}}. {{.Note}} A blank field means no limit of that kind.

Cancel
{{end}} {{define "quota-value"}}{{if .Own}}{{.Own}}{{else if .Up}}{{.Up}} ↑{{else}}—{{end}}{{end}}