From 2084e6e06e3e9ff8c852cf26bd87b2665be060d6 Mon Sep 17 00:00:00 2001 From: majdyz Date: Sun, 12 Apr 2026 23:51:04 +0000 Subject: [PATCH] feat(platform/admin): enhance cost dashboard with token breakdown and per-request averages Add deeper cost visibility to the admin platform cost dashboard: - Show prompt vs completion tokens separately in provider table - Add summary cards for avg cost/request, avg input/output tokens, total token split - Add avg cost per request column to the per-user table - Compute aggregate token totals and per-request averages in backend --- .../backend/backend/data/platform_cost.py | 24 ++++++++++++- .../components/PlatformCostContent.tsx | 34 +++++++++++++++++-- .../components/ProviderTable.tsx | 19 ++++++++++- .../platform-costs/components/UserTable.tsx | 14 +++++++- .../frontend/src/app/api/openapi.json | 7 +++- 5 files changed, 92 insertions(+), 6 deletions(-) diff --git a/autogpt_platform/backend/backend/data/platform_cost.py b/autogpt_platform/backend/backend/data/platform_cost.py index 17915e115c..3c2c0179d2 100644 --- a/autogpt_platform/backend/backend/data/platform_cost.py +++ b/autogpt_platform/backend/backend/data/platform_cost.py @@ -167,6 +167,11 @@ class PlatformCostDashboard(BaseModel): total_cost_microdollars: int total_requests: int total_users: int + total_input_tokens: int = 0 + total_output_tokens: int = 0 + avg_input_tokens_per_request: float = 0.0 + avg_output_tokens_per_request: float = 0.0 + avg_cost_microdollars_per_request: float = 0.0 def _si(row: dict, field: str) -> int: @@ -293,7 +298,11 @@ async def get_platform_cost_dashboard( PrismaLog.prisma().group_by( by=["provider"], where=where, - sum={"costMicrodollars": True}, + sum={ + "costMicrodollars": True, + "inputTokens": True, + "outputTokens": True, + }, count=True, ), ) @@ -322,6 +331,8 @@ async def get_platform_cost_dashboard( # Grand totals — sum across all provider groups (no LIMIT applied above). total_cost = sum(_si(r, "costMicrodollars") for r in total_agg_groups) total_requests = sum(_ca(r) for r in total_agg_groups) + total_input_tokens = sum(_si(r, "inputTokens") for r in total_agg_groups) + total_output_tokens = sum(_si(r, "outputTokens") for r in total_agg_groups) return PlatformCostDashboard( by_provider=[ @@ -354,6 +365,17 @@ async def get_platform_cost_dashboard( total_cost_microdollars=total_cost, total_requests=total_requests, total_users=total_users, + total_input_tokens=total_input_tokens, + total_output_tokens=total_output_tokens, + avg_input_tokens_per_request=( + total_input_tokens / total_requests if total_requests > 0 else 0.0 + ), + avg_output_tokens_per_request=( + total_output_tokens / total_requests if total_requests > 0 else 0.0 + ), + avg_cost_microdollars_per_request=( + total_cost / total_requests if total_requests > 0 else 0.0 + ), ) diff --git a/autogpt_platform/frontend/src/app/(platform)/admin/platform-costs/components/PlatformCostContent.tsx b/autogpt_platform/frontend/src/app/(platform)/admin/platform-costs/components/PlatformCostContent.tsx index 749a2136a3..3c68f30014 100644 --- a/autogpt_platform/frontend/src/app/(platform)/admin/platform-costs/components/PlatformCostContent.tsx +++ b/autogpt_platform/frontend/src/app/(platform)/admin/platform-costs/components/PlatformCostContent.tsx @@ -2,7 +2,7 @@ import { Alert, AlertDescription } from "@/components/molecules/Alert/Alert"; import { Skeleton } from "@/components/atoms/Skeleton/Skeleton"; -import { formatMicrodollars } from "../helpers"; +import { formatMicrodollars, formatTokens } from "../helpers"; import { SummaryCard } from "./SummaryCard"; import { ProviderTable } from "./ProviderTable"; import { UserTable } from "./UserTable"; @@ -215,7 +215,7 @@ export function PlatformCostContent({ searchParams }: Props) { ) : ( <> {dashboard && ( -
+
+ + + +
)} diff --git a/autogpt_platform/frontend/src/app/(platform)/admin/platform-costs/components/ProviderTable.tsx b/autogpt_platform/frontend/src/app/(platform)/admin/platform-costs/components/ProviderTable.tsx index db100e0220..4e4e171747 100644 --- a/autogpt_platform/frontend/src/app/(platform)/admin/platform-costs/components/ProviderTable.tsx +++ b/autogpt_platform/frontend/src/app/(platform)/admin/platform-costs/components/ProviderTable.tsx @@ -3,6 +3,7 @@ import { defaultRateFor, estimateCostForRow, formatMicrodollars, + formatTokens, rateKey, rateUnitLabel, trackingValue, @@ -33,6 +34,12 @@ function ProviderTable({ data, rateOverrides, onRateOverride }: Props) { Usage + + Input Tokens + + + Output Tokens + Requests @@ -74,6 +81,16 @@ function ProviderTable({ data, rateOverrides, onRateOverride }: Props) { {trackingValue(row)} + + {row.total_input_tokens > 0 + ? formatTokens(row.total_input_tokens) + : "-"} + + + {row.total_output_tokens > 0 + ? formatTokens(row.total_output_tokens) + : "-"} + {row.request_count.toLocaleString()} @@ -124,7 +141,7 @@ function ProviderTable({ data, rateOverrides, onRateOverride }: Props) { {data.length === 0 && ( No cost data yet diff --git a/autogpt_platform/frontend/src/app/(platform)/admin/platform-costs/components/UserTable.tsx b/autogpt_platform/frontend/src/app/(platform)/admin/platform-costs/components/UserTable.tsx index 7c08f85e1b..7e8032fd2f 100644 --- a/autogpt_platform/frontend/src/app/(platform)/admin/platform-costs/components/UserTable.tsx +++ b/autogpt_platform/frontend/src/app/(platform)/admin/platform-costs/components/UserTable.tsx @@ -26,6 +26,9 @@ function UserTable({ data }: Props) { Output Tokens + + Avg Cost / Req + @@ -54,12 +57,21 @@ function UserTable({ data }: Props) { {formatTokens(row.total_output_tokens)} + + {row.request_count > 0 && row.total_cost_microdollars > 0 + ? formatMicrodollars( + Math.round( + row.total_cost_microdollars / row.request_count, + ), + ) + : "-"} + ))} {data.length === 0 && ( No cost data yet diff --git a/autogpt_platform/frontend/src/app/api/openapi.json b/autogpt_platform/frontend/src/app/api/openapi.json index 446b2eb079..36ed0e68f0 100644 --- a/autogpt_platform/frontend/src/app/api/openapi.json +++ b/autogpt_platform/frontend/src/app/api/openapi.json @@ -12141,7 +12141,12 @@ "title": "Total Cost Microdollars" }, "total_requests": { "type": "integer", "title": "Total Requests" }, - "total_users": { "type": "integer", "title": "Total Users" } + "total_users": { "type": "integer", "title": "Total Users" }, + "total_input_tokens": { "type": "integer", "title": "Total Input Tokens", "default": 0 }, + "total_output_tokens": { "type": "integer", "title": "Total Output Tokens", "default": 0 }, + "avg_input_tokens_per_request": { "type": "number", "title": "Avg Input Tokens Per Request", "default": 0.0 }, + "avg_output_tokens_per_request": { "type": "number", "title": "Avg Output Tokens Per Request", "default": 0.0 }, + "avg_cost_microdollars_per_request": { "type": "number", "title": "Avg Cost Microdollars Per Request", "default": 0.0 } }, "type": "object", "required": [