Skip to content

Commit

Permalink
feat: add bot token usage analyzer
Browse files Browse the repository at this point in the history
  • Loading branch information
RaoHai committed Dec 24, 2024
1 parent 3749394 commit ac07ebc
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 0 deletions.
103 changes: 103 additions & 0 deletions client/app/admin/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
'use client';

import React from 'react';
import dayjs from 'dayjs';
import { Column } from '@ant-design/charts';
import { Card, Progress } from '@nextui-org/react';
import { useAnalyze, useTopBots, useTopUsers } from '../hooks/useAnalyze';
import { maxBy, sortBy } from 'lodash';

export default function AdminPage() {
const { data = [], isLoading } = useAnalyze();
const { data: topBots = [] } = useTopBots();
const { data: topUsers = [] } = useTopUsers();

const chartProps = {
xField: d => new Date(d.usage_date),
colorField: 'bot_name',
height: 400,
stack: true,
legend: false,
sort: { by: 'x' },
scale: { color: { palette: 'tableau10' }},
axis: {
x: {
labelFormatter: x => dayjs(x).format('MM-DD'),
}
},
}

return (
<div className="min-h-screen p-8">
{/* Header */}
<div className="flex justify-between items-center mb-8">
<h1 className="text-2xl font-bold">Usage: Tokens</h1>
</div>

{/* Charts Section */}
<div className="grid grid-cols-3 gap-8 mb-8">
<div className="col-span-2 grid grid-rows-2 gap-8">
<Card className="p-6">
<h2 className="text-lg font-semibold mb-4">Input Tokens</h2>
<div className="text-gray-400">
<Column
{...chartProps}
data={sortBy(data, ['usage_date', 'input_tokens'])}
yField={'input_tokens'}
/>
</div>
</Card>

<Card className="p-6">
<h2 className="text-lg font-semibold mb-4">Output Tokens</h2>
<div className="text-gray-400">
<Column
{...chartProps}
data={sortBy(data, ['usage_date', 'output_tokens'])}
yField={'output_tokens'}
/>
</div>
</Card>
</div>
<div>
<Card className="p-6 mb-8">
<h2 className="text-lg font-semibold mb-4">Top Bots</h2>
<div className="text-gray-400">
{topBots.map(record => {
return <Progress
className="max-w-md"
color="primary"
formatOptions={{ style: "decimal"}}
label={record.bot_name}
maxValue={maxBy(topBots, 'total_tokens')?.total_tokens}
value={record.total_tokens}
showValueLabel={true}
size="sm"
/>
})}
</div>
</Card>

<Card className="p-6">
<h2 className="text-lg font-semibold mb-4">Top Users</h2>
<div className="text-gray-400">
{topUsers.map(record => {
return <Progress
className="max-w-md"
color="primary"
formatOptions={{ style: "decimal"}}
label={record.user_name}
maxValue={maxBy(topBots, 'total_tokens')?.total_tokens}
value={record.total_tokens}
showValueLabel={true}
size="sm"
/>
})}
</div>
</Card>
</div>
</div>

</div>
);
}
27 changes: 27 additions & 0 deletions client/app/hooks/useAnalyze.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { useQuery } from '@tanstack/react-query';
import { analyzeTokenUsage, analyzeTopBots, analyzeTopUsers } from '../services/TokensController';


export function useAnalyze() {
return useQuery({
queryKey: [`usage.analyze`],
queryFn: async () => analyzeTokenUsage(),
retry: false,
});
}

export function useTopBots() {
return useQuery<{ bot_name: string; total_tokens: number;}[]>({
queryKey: [`usage.top.bots`],
queryFn: async () => analyzeTopBots(),
retry: false,
});
}

export function useTopUsers() {
return useQuery<{ user_name: string; total_tokens: number;}[]>({
queryKey: [`usage.top.users`],
queryFn: async () => analyzeTopUsers(),
retry: false,
});
}

0 comments on commit ac07ebc

Please sign in to comment.