Zum Inhalt springen

Token usage

Dieser Inhalt ist noch nicht in deiner Sprache verfügbar.

Token Usage (/admin/token-usage) accounts for what this instance spends on models. Every request the AI proxy completes writes one row: who made it, which model answered, how many input, output and cached tokens it took, and how it finished. The board is built on those rows.

Until the first request lands the page shows No token usage recorded yet — with a Refresh button, because that is exactly the moment an admin would otherwise sit on F5.

Six figures, all over the last 7 days: total tokens, requests, active users, average tokens per request, the share of input tokens served from the provider’s cache, and the model with the most tokens.

A high cached percentage is a good sign — it means prompt prefixes are being reused upstream rather than re-billed. Cached tokens are a slice of the input tokens, not an extra bucket beside them, so the share is cached ÷ input and can reach 100%.

Every column on this page is raw TOKENS, as the provider billed them. What a request costs against the member’s group ceiling is a separate figure — CREDITS, priced by the answering provider’s rate card — and lives on the Weekly budget tab and in the Credits column of a user’s request log.

The Token volume chart plots total, input and output tokens over 24H, 7D or 30D; the 24-hour range buckets by hour, the others by day. Hover a band for the exact figures.

Below it, three cards with independent range toggles:

Card Shows
Usage by model Every model’s share of tokens in the range
Usage by user The top 5 users
Usage by group All groups

The Refresh control sits on the tab row rather than inside a table, because one load feeds every panel. It re-reads in place, so the open tab, the three range toggles and any search term survive; a browser reload discards them. It also takes a 30-second or 5-minute interval.

Four sub-tabs, all searchable.

By User — tokens over the last hour, day and week per user, with a link through to that user’s request log.

By Group — the same three windows plus distinct users, request count, input/output/cached splits, and each group’s share of the 7-day total. This is the tab for chargeback questions.

Expect to see a bucket called Ungrouped, often holding everything. Each usage row is stamped with the group that was charged at the time of the request, and any row whose group can no longer be resolved — because the request predates group management being used, or the group has since been deleted — lands there. It is a real bucket, not an error, and it exists so group totals always add up to the grand total. Two consequences worth knowing: historic rows keep the group they were charged under, so moving a user between groups never rewrites their past usage; and several deleted groups merge into the single Ungrouped row rather than staying distinguishable. Rows written before the group stamp existed have no group of their own and fall back to the member’s group today, which is the one case where moving a user does move old usage.

By Model — the same, per model, for comparing what each model actually costs in traffic.

Heaviest · 24h — the 50 largest single requests of the last day: time, user, template, model, the token splits, the total, the finish reason, and a Tools column. It answers “what blew up the bill this morning” faster than any aggregate. A finish reason of length on the heaviest rows usually means the answer was truncated against the output cap rather than completed — see Policies.

The Tools column counts the server-side tool calls resolved during that turn — knowledge-base retrievals, image descriptions and web searches together. It is a call count, not a token figure: the tokens those calls produced are already inside the input column. To see which tool it was, read the per-feature rows in the template column below. See Knowledge bases.

A different measure from the two tabs above it: credits over calendar weeks, where Charts and Breakdown are raw tokens over rolling windows. The two are not meant to reconcile, and the tab says so on its face.

Pick a group and the tab opens with two meters for the current week, in the order the money is spent. The first is the carried-over sliding pool; the second is this week’s allowances. They are separate bars because they are separate budgets — the pool is last week’s under-use, not a slice of this week’s baseline — and each is scaled to its own ceiling.

Because the pool is drawn down first, the allowance meter stays empty until the pool runs out. A group mid-week with a full allowance bar and a spent pool has not stopped working; it has not started paying for itself yet. The allowance meter’s unused figure is the one that feeds next week’s pool, and it is the same number as the week table’s Allowance unused column.

Under the meters: the monthly fee baseline (members × 4 × weekly credits, and the same figure per member), the last eight weeks as a pool bar and an allowance bar per week with each week’s baseline marked, and a table of every member’s pool draws, own use and current state.

Week labels are rendered in the server’s TokenUsage:WeekStartTimeZone, which is where the Monday boundary actually falls.

The row link on By User, or /admin/token-usage/{userId} directly, opens every request recorded for that user — paged server-side, so it stays usable on accounts with a long history.

Its KPI row repeats the 7-day figures for that user alone and adds the top template. The grid lists time, template, model, finish reason, the token splits, the Credits the row cost against the group budget, and the Tools count; the search box filters by template, model or finish reason.

The Finish Reason column is the provider’s own finish_reason, passed through verbatim, so the exact vocabulary is the upstream provider’s. On the OpenAI-compatible providers Pia talks to, you will see:

Value Meaning Worth investigating?
stop The model finished on its own No — this is the normal ending
tool_calls The model asked to call a tool and the turn handed off to it No. A tool-using turn is recorded as several rows — one small tool_calls row per hop, then a final stop row. A log that is mostly tool_calls means the assistant is using tools, not that anything failed
length Output hit the token ceiling and was cut off Often yes — the answer was truncated. Check the Chat max_tokens cap on Policies
content_filter The provider’s own safety filter stopped the response Yes, if unexpected. This is the provider’s filter, not Pia guardrails, which appear as their own guardrail:<key> template rows

Counting requests by row therefore overstates conversations. One user question that touches two tools is four or five rows here, which is also why Avg / request looks low on tool-heavy instances.

The template id records which path produced the request. Alongside the ordinary optimize templates, these rows are worth recognising:

  • guardrail:<guard-key> — a classifier call made by guardrails, one row per guard per guarded request. Charged to the user whose request triggered it.
  • vision:describe_image — one row per image a text-only model had described for it, charged against the vision provider that looked at it.
  • websearch:search_web — one row per web search a model without native search made, charged against the web search provider that ran it. Its token counts are zero on purpose: a search is billed in searches, not tokens, and this row is what makes the count attributable.
  • Assistant and research traffic, which carries the template the client sent.

Usage rows and the frozen weekly pool rows are pruned by TokenUsage:RetentionDays (default 365), on a six-hourly background sweep; Audit:RetentionDays covers the audit log only. 0 disables the sweep and keeps every row forever. To clear the log outright rather than by age, Settings → Data → Token Usage deletes it for every user and takes the history on this page with it.