Revert the following commits: -308e3e347feat(web): polish themed data views and add task log details -b2a890e75fix: Fontsource asset resolution across workspace layouts -9d1ca545erefactor(web): refine data-table cards and pricing page layout -0918bdb49refactor(web): consolidate design-system primitives and responsive data views -262ab9312style(web): unify design system across default frontend
126 lines
4.1 KiB
TypeScript
Vendored
126 lines
4.1 KiB
TypeScript
Vendored
/*
|
|
Copyright (C) 2023-2026 QuantumNous
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU Affero General Public License as
|
|
published by the Free Software Foundation, either version 3 of the
|
|
License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU Affero General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Affero General Public License
|
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
For commercial licensing, please contact support@quantumnous.com
|
|
*/
|
|
import { memo } from 'react'
|
|
import { useTranslation } from 'react-i18next'
|
|
|
|
import { getSuccessRateDotClass } from '@/features/performance-metrics/lib/format'
|
|
import { cn } from '@/lib/utils'
|
|
|
|
export type ModelPerfBadgeData = {
|
|
avg_latency_ms: number
|
|
success_rate: number
|
|
avg_tps: number
|
|
recent_success_rates?: number[]
|
|
}
|
|
|
|
export interface ModelPerfBadgeProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
perf: ModelPerfBadgeData | undefined
|
|
}
|
|
|
|
function formatCompactNumber(value: number): string {
|
|
if (!Number.isFinite(value) || value <= 0) return '—'
|
|
return value > 1 ? String(Math.round(value)) : value.toFixed(1)
|
|
}
|
|
|
|
function formatCompactLatency(ms: number): string {
|
|
if (!Number.isFinite(ms) || ms <= 0) return '—'
|
|
if (ms >= 1_000) return `${formatCompactNumber(ms / 1_000)}s`
|
|
return `${formatCompactNumber(ms)}ms`
|
|
}
|
|
|
|
function formatCompactThroughput(tps: number): string {
|
|
if (!Number.isFinite(tps) || tps <= 0) return '—'
|
|
if (tps >= 1_000) return `${formatCompactNumber(tps / 1_000)}Kt`
|
|
return `${formatCompactNumber(tps)}t`
|
|
}
|
|
|
|
export const ModelPerfBadge = memo(function ModelPerfBadge(
|
|
props: ModelPerfBadgeProps
|
|
) {
|
|
const { t } = useTranslation()
|
|
|
|
if (!props.perf) {
|
|
return null
|
|
}
|
|
|
|
const { avg_latency_ms, avg_tps, success_rate } = props.perf
|
|
|
|
const recentRates =
|
|
props.perf.recent_success_rates?.filter((rate) => Number.isFinite(rate)) ??
|
|
[]
|
|
const statusRates =
|
|
recentRates.length > 0 ? recentRates.slice(-3) : [success_rate]
|
|
const statusBars = [
|
|
...Array(Math.max(0, 3 - statusRates.length)).fill(null),
|
|
...statusRates,
|
|
].slice(-3)
|
|
|
|
return (
|
|
<div
|
|
className={cn(
|
|
'hidden w-[132px] grid-cols-[38px_48px_30px] gap-x-2 text-right tabular-nums min-[460px]:grid',
|
|
props.className
|
|
)}
|
|
>
|
|
<div title={t('Average latency')} className='min-w-0'>
|
|
<div className='text-muted-foreground/55 text-[10px] leading-4'>
|
|
{t('Latency short')}
|
|
</div>
|
|
<div className='text-muted-foreground/80 font-mono text-xs leading-4 whitespace-nowrap'>
|
|
{formatCompactLatency(avg_latency_ms)}
|
|
</div>
|
|
</div>
|
|
<div title={t('Throughput')} className='min-w-0'>
|
|
<div className='text-muted-foreground/55 truncate text-[10px] leading-4'>
|
|
{t('Throughput short')}
|
|
</div>
|
|
<div className='text-muted-foreground/80 font-mono text-xs leading-4 whitespace-nowrap'>
|
|
{formatCompactThroughput(avg_tps)}
|
|
</div>
|
|
</div>
|
|
<div
|
|
title={`${t('Success rate')}: ${success_rate.toFixed(1)}%`}
|
|
className='min-w-0'
|
|
>
|
|
<div className='text-muted-foreground/55 truncate text-[10px] leading-4'>
|
|
{t('Status short')}
|
|
</div>
|
|
<div className='flex h-4 items-center justify-end gap-0.5'>
|
|
{statusBars.map((rate, index) => (
|
|
<span
|
|
key={`${index}-${rate ?? 'empty'}`}
|
|
className={cn(
|
|
'w-1 rounded-full',
|
|
index === 0 && 'h-2',
|
|
index === 1 && 'h-2.5',
|
|
index === 2 && 'h-3',
|
|
rate == null
|
|
? index === 0
|
|
? 'bg-muted-foreground/10'
|
|
: 'bg-muted-foreground/15'
|
|
: getSuccessRateDotClass(rate)
|
|
)}
|
|
/>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
})
|