Skip to content

Commit 10c3f7a

Browse files
authored
Create usage.py
1 parent ec48995 commit 10c3f7a

1 file changed

Lines changed: 55 additions & 0 deletions

File tree

‎app/controllers/usage.py‎

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
"""Usage business logic: aggregate the token ledger for a user."""
2+
3+
from __future__ import annotations
4+
5+
from dataclasses import dataclass, field
6+
7+
from sqlalchemy import func, select
8+
from sqlalchemy.orm import Session
9+
10+
from ..models import Conversation, Run, UsageEvent, User
11+
12+
13+
@dataclass
14+
class UsageTotals:
15+
"""A user's billed totals, plus a per-conversation token breakdown."""
16+
17+
input_tokens: int = 0
18+
output_tokens: int = 0
19+
rounds: int = 0
20+
runs: int = 0
21+
by_conversation: dict[str, int] = field(default_factory=dict)
22+
23+
24+
def summary(db: Session, user: User) -> UsageTotals:
25+
"""Totals over the user's usage events, grouped per conversation.
26+
27+
``by_conversation`` carries combined input+output tokens, which is
28+
what a bill is drawn on; the run count comes from the Run table so
29+
runs that recorded no usage (failures) are still counted.
30+
"""
31+
totals = UsageTotals()
32+
rows = db.execute(
33+
select(
34+
UsageEvent.conversation_id,
35+
func.sum(UsageEvent.input_tokens),
36+
func.sum(UsageEvent.output_tokens),
37+
func.sum(UsageEvent.rounds),
38+
)
39+
.where(UsageEvent.user_id == user.id)
40+
.group_by(UsageEvent.conversation_id)
41+
).all()
42+
for conversation_id, inp, out, rounds in rows:
43+
inp_i, out_i, rounds_i = int(inp or 0), int(out or 0), int(rounds or 0)
44+
totals.input_tokens += inp_i
45+
totals.output_tokens += out_i
46+
totals.rounds += rounds_i
47+
totals.by_conversation[conversation_id] = inp_i + out_i
48+
totals.runs = int(
49+
db.query(func.count(Run.id))
50+
.join(Conversation, Run.conversation_id == Conversation.id)
51+
.filter(Conversation.user_id == user.id)
52+
.scalar()
53+
or 0
54+
)
55+
return totals

0 commit comments

Comments
 (0)