Konfigurerbare brukerklasser (Basis, Proff(ish), Superduper ultra premium, Admin) med token-budsjett per dag, modellnivå-tilgang og feature-gates. Budsjettsjekk før hvert LLM-kall. Admin-forbruk vises med kostnadsestimat. Automatiske triggere teller mot brukerens budsjett. Klasser og brukere som noder i grafen. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
13 KiB
Brukerklasser og AI-budsjettering
Konsept
Brukerklasser styrer tilgang til AI-ressurser. Hver klasse definerer token-budsjett, tilgjengelige modellnivåer og hvilke AI-features brukeren kan trigge. Admin konfigurerer klasser og tildeler brukere.
Brukerklasser som noder
node_kind: 'user_class'
title: "Proff(ish)"
metadata: {
budget_tokens_per_day: 500000,
model_access: ["synops/low", "synops/medium"],
features: ["chat_bot", "summarize", "suggest_edges", "ai_process"],
priority: 2, // høyere = finere (for sortering)
description: "For de som mener alvor. Noen ganger."
}
Default-klasser
| Klasse | Budsjett/dag | Modeller | Features |
|---|---|---|---|
| Basis | 50k tokens | low | chat-bot |
| Proff(ish) | 500k tokens | low, medium | chat-bot, oppsummering, suggest-edges, ai-prosessering |
| Superduper ultra premium | 5M tokens | low, medium, high | alt unntatt modellvalg og konfig |
| Admin | ubegrenset | alle inkl. extreme | alt + modellvalg (/claude, /grok) + konfig |
Klassenavnene er konfigurerbare. Default-navnene er selvironiske i tråd med plattformens tone. Admin kan opprette, endre, slette og omdøpe klasser fritt.
Tildeling
Bruker → klasse via edge:
person_node --[has_class]--> user_class_node
Én klasse per bruker. Default for nye brukere: "Basis" (eller konfigurerbar i admin). Admin kan endre klasse per bruker.
Budsjettsjekk
Maskinrommet sjekker budsjett før hvert LLM-kall:
async fn check_budget(user_node_id: Uuid, pool: &PgPool) -> Result<bool> {
// Hent brukerens klasse
let class = get_user_class(user_node_id, pool).await?;
// Ubegrenset? Alltid OK.
if class.budget_tokens_per_day == 0 { return Ok(true); }
// Hent forbruk siste 24 timer
let used = sqlx::query_scalar!(
"SELECT COALESCE(SUM(input_tokens + output_tokens), 0)
FROM ai_usage_log
WHERE user_node_id = $1
AND created_at > now() - interval '1 day'",
user_node_id
).fetch_one(pool).await?;
Ok(used < class.budget_tokens_per_day)
}
Ved overskridelse:
- LLM-kall avvises
- Bruker får melding: "Daglig budsjett brukt opp. Tilbakestilles kl. 00:00."
- Admin varsles hvis ønskelig
- Jobber som trigger for brukeren køes til neste dag (eller droppes)
Modellnivå-gate
I tillegg til token-budsjett: brukerens klasse bestemmer hvilke modellnivåer (synops/low, medium, high, extreme) de kan bruke.
async fn check_model_access(user_node_id: Uuid, model_alias: &str, pool: &PgPool) -> bool {
let class = get_user_class(user_node_id, pool).await.unwrap();
class.model_access.contains(model_alias)
}
"Basis"-brukere får alltid synops/low. Prøver de en feature
som krever synops/high, downgrades modellen automatisk til
det høyeste nivået de har tilgang til — med varsel om at
resultatet kan være dårligere.
Automatiske triggere og budsjett
Når en orkestrering (som suggest-edges) trigger på en brukers handling, teller kostnadene mot brukerens budsjett:
Trond oppretter en innholds-node
→ orkestrering: suggest-edges triggers
→ budsjettsjekk: har Trond (Proff(ish)) tokens igjen?
→ ja: kjør suggest-edges, logg mot Trond
→ nei: dropp, logg "skipped:budget"
Systemjobber (RSS, rendering) som ikke er bruker-initiert kjører under et "system"-budsjett som admin styrer separat.
Feature-gate
Hver AI-feature har et navn brukt i feature-listen:
| Feature-nøkkel | Beskrivelse |
|---|---|
chat_bot |
@bot i samtaler |
summarize |
AI-oppsummering |
suggest_edges |
Automatisk foreslåtte relasjoner |
ai_process |
AI-prosessering (verktøy-panel) |
transcribe |
Whisper-transkribering |
tts |
Tekst-til-tale |
clip |
Web clipper med AI-oppsummering |
orchestration |
AI-steg i orkestreringer |
model_select |
Eksplisitt modellvalg (/claude, /grok) |
admin_config |
Konfigurasjon av klasser og ruting |
Klassen lister hvilke features den har tilgang til. Maskinrommet sjekker feature-tilgang før det tillater operasjonen.
Admin-UI: Brukerpanel
Brukeroversikt (/admin/users)
┌─ Brukere ──────────────────────────────────────────┐
│ │
│ Navn Klasse Forbruk Status │
│ Vegard Admin 1.2M i dag ✅ │
│ Trond Superduper ultra.. 2.1M/5M ✅ │
│ Arne Proff(ish) 430k/500k ⚠️ │
│ Lise Basis 48k/50k ⚠️ │
│ Gjest Basis 0/50k ✅ │
│ │
│ Klikk bruker → detaljer med klasse-endring │
└─────────────────────────────────────────────────────┘
Brukerdetaljer
┌─ Arne ─────────────────────────────────────────────┐
│ │
│ Klasse: [Proff(ish) ▼] │
│ │
│ Forbruk i dag: 430,000 / 500,000 tokens (86%) │
│ Forbruk denne uken: 1.8M tokens │
│ ████████████████████░░░ │
│ │
│ Modellfordeling i dag: │
│ synops/low: 380k tokens (88%) │
│ synops/medium: 50k tokens (12%) │
│ │
│ Siste AI-kall: │
│ 14:30 chat_bot (synops/low) 1.2k tokens │
│ 14:15 suggest_edges (synops/low) 800 tokens │
│ 13:50 summarize (synops/medium) 3.5k tokens │
│ │
│ [Overstyr budsjett] [Deaktiver bruker] │
└─────────────────────────────────────────────────────┘
Admin-forbruk
Admin har ubegrenset budsjett, men forbruket vises like fullt:
┌─ Vegard (Admin) ───────────────────────────────────┐
│ │
│ Forbruk i dag: 1,200,000 tokens │
│ Forbruk denne uken: 8.3M tokens │
│ Forbruk denne måneden: 31M tokens │
│ │
│ Estimert kostnad (basert på modellpriser): │
│ synops/low: 800k × $0.10/M = $0.08 │
│ synops/medium: 300k × $0.50/M = $0.15 │
│ synops/high: 100k × $3.00/M = $0.30 │
│ ───────────────────────────────── │
│ Total i dag: ~$0.53 │
│ Total denne uken: ~$3.70 │
│ Total denne måneden: ~$14.20 │
│ │
│ Claude Code (abonnement, ikke tokens): │
│ Sesjoner i dag: 3 │
│ Total tid: 4t 20min │
└─────────────────────────────────────────────────────┘
Klasse-konfigurasjon (/admin/classes)
┌─ Brukerklasser ────────────────────────────────────┐
│ │
│ Navn Budsjett Modeller │
│ Basis 50k/dag low │
│ Proff(ish) 500k/dag low+medium │
│ Superduper ultra premium 5M/dag low+med+high │
│ Admin ∞ alle │
│ │
│ [+ Ny klasse] │
└─────────────────────────────────────────────────────┘
Klikk en klasse → rediger:
┌─ Rediger: Proff(ish) ─────────────────────────────┐
│ │
│ Navn: [Proff(ish) ] │
│ Beskrivelse: [For de som mener alvor. ] │
│ │
│ Budsjett: [500000] tokens per [dag ▼] │
│ │
│ Modellnivåer: │
│ ☑ synops/low │
│ ☑ synops/medium │
│ ☐ synops/high │
│ ☐ synops/extreme │
│ │
│ Features: │
│ ☑ chat_bot ☑ summarize │
│ ☑ suggest_edges ☑ ai_process │
│ ☐ transcribe ☐ tts │
│ ☐ model_select ☐ admin_config │
│ │
│ Brukere i denne klassen: 2 (Arne, Lise) │
│ │
│ [Lagre] [Avbryt] │
└─────────────────────────────────────────────────────┘
Systembudsjett
Jobber som ikke tilhører en spesifikk bruker (RSS-generering, planlagt publisering, system-orkestreringer) kjører under et eget systembudsjett:
metadata på system-config-node: {
system_budget_tokens_per_day: 1000000,
system_model_level: "synops/low"
}
Vises i admin-panelet under "Systemforbruk".
Implementering
Database
Ingen ny tabell — brukerklasser er noder:
-- Opprett default-klasser (seed)
INSERT INTO nodes (node_kind, title, visibility, metadata) VALUES
('user_class', 'Basis', 'readable', '{"budget_tokens_per_day":50000,"model_access":["synops/low"],"features":["chat_bot"],"priority":1,"description":"Grunnpakken. Du får en bot. Vær takknemlig."}'),
('user_class', 'Proff(ish)', 'readable', '{"budget_tokens_per_day":500000,"model_access":["synops/low","synops/medium"],"features":["chat_bot","summarize","suggest_edges","ai_process"],"priority":2,"description":"For de som mener alvor. Noen ganger."}'),
('user_class', 'Superduper ultra premium', 'readable', '{"budget_tokens_per_day":5000000,"model_access":["synops/low","synops/medium","synops/high"],"features":["chat_bot","summarize","suggest_edges","ai_process","transcribe","tts","clip","orchestration"],"priority":3,"description":"Alt du kan drømme om. Nesten."}'),
('user_class', 'Admin', 'readable', '{"budget_tokens_per_day":0,"model_access":["synops/low","synops/medium","synops/high","synops/extreme"],"features":["chat_bot","summarize","suggest_edges","ai_process","transcribe","tts","clip","orchestration","model_select","admin_config"],"priority":99,"description":"Hersker over alt. Betaler regningen."}');
(budget_tokens_per_day: 0 = ubegrenset for Admin)
Maskinrommet
check_ai_budget(user_node_id, estimated_tokens)— kall før LLMcheck_model_access(user_node_id, model_alias)— kall før LLMcheck_feature_access(user_node_id, feature_key)— kall før feature- Alle bruker
get_user_class()som cacher i minne (invalideres ved endring)
Frontend
/admin/users— utvidet med klasse, forbruk, statusindikator/admin/classes— ny side for klasse-konfigurasjon- Brukerens egen profil viser forbruk og gjenstående budsjett
Modellpris-tabell
For å estimere kostnad i admin-UI:
CREATE TABLE model_pricing (
model_alias TEXT PRIMARY KEY,
input_price_per_m NUMERIC, -- pris per million input-tokens
output_price_per_m NUMERIC, -- pris per million output-tokens
updated_at TIMESTAMPTZ DEFAULT now()
);
Admin oppdaterer priser manuelt (de endres sjelden). Brukes kun for visning — ikke for faktisk fakturering.