diff --git a/web/default/src/features/dashboard/components/models/performance-overview.tsx b/web/default/src/features/dashboard/components/models/performance-overview.tsx new file mode 100644 index 00000000..98745c01 --- /dev/null +++ b/web/default/src/features/dashboard/components/models/performance-overview.tsx @@ -0,0 +1,298 @@ +import { useMemo } from 'react' +import { useQuery } from '@tanstack/react-query' +import { Activity, Gauge, HeartPulse, Timer } from 'lucide-react' +import { useTranslation } from 'react-i18next' +import { formatNumber } from '@/lib/format' +import { cn } from '@/lib/utils' +import { Skeleton } from '@/components/ui/skeleton' +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from '@/components/ui/table' +import { getPerfMetricsSummary } from '@/features/performance-metrics/api' +import { + formatLatency, + formatThroughput, + formatUptimePct, +} from '@/features/performance-metrics/lib/format' +import type { PerfModelSummary } from '@/features/performance-metrics/types' + +const PERFORMANCE_WINDOW_HOURS = 24 +const TOP_MODEL_LIMIT = 8 + +type WeightedMetric = 'avg_latency_ms' | 'avg_tps' | 'success_rate' + +type PerformanceSummary = { + totalRequests: number + avgLatencyMs: number + avgTps: number + successRate: number +} + +function weightedAverage( + rows: PerfModelSummary[], + metric: WeightedMetric, + isValid: (value: number) => boolean +): number { + let total = 0 + let weight = 0 + + for (const row of rows) { + const value = Number(row[metric]) + const requestCount = Number(row.request_count) || 0 + if (requestCount <= 0 || !isValid(value)) continue + + total += value * requestCount + weight += requestCount + } + + return weight > 0 ? total / weight : 0 +} + +function buildPerformanceSummary(rows: PerfModelSummary[]): PerformanceSummary { + const totalRequests = rows.reduce( + (sum, row) => sum + (Number(row.request_count) || 0), + 0 + ) + + return { + totalRequests, + avgLatencyMs: Math.round( + weightedAverage( + rows, + 'avg_latency_ms', + (value) => Number.isFinite(value) && value > 0 + ) + ), + avgTps: weightedAverage( + rows, + 'avg_tps', + (value) => Number.isFinite(value) && value > 0 + ), + successRate: weightedAverage(rows, 'success_rate', Number.isFinite), + } +} + +function successRateClassName(successRate: number): string { + if (successRate >= 99.9) return 'text-emerald-600 dark:text-emerald-400' + if (successRate >= 99) return 'text-amber-600 dark:text-amber-400' + return 'text-rose-600 dark:text-rose-400' +} + +function successDotClassName(successRate: number): string { + if (successRate >= 99.9) return 'bg-emerald-500' + if (successRate >= 99) return 'bg-amber-500' + return 'bg-rose-500' +} + +function PerformanceMetricItem(props: { + icon: React.ComponentType<{ className?: string }> + label: string + value: string + hint: string + loading?: boolean + valueClassName?: string +}) { + const Icon = props.icon + + return ( +
+
+
+ {props.loading ? ( +
+ + +
+ ) : ( + <> +
+ {props.value} +
+
+ {props.hint} +
+ + )} +
+ ) +} + +function PerformanceTableHeader(props: { description: string }) { + const { t } = useTranslation() + + return ( +
+
+ +
+ {t('Model performance metrics')} +
+
+ {props.description} +
+ ) +} + +export function PerformanceOverview() { + const { t } = useTranslation() + const metricsQuery = useQuery({ + queryKey: ['perf-metrics-summary', PERFORMANCE_WINDOW_HOURS], + queryFn: () => getPerfMetricsSummary(PERFORMANCE_WINDOW_HOURS), + staleTime: 60 * 1000, + retry: false, + }) + + const models = useMemo( + () => + [...(metricsQuery.data?.data.models ?? [])] + .filter((model) => Number(model.request_count) > 0) + .sort((a, b) => b.request_count - a.request_count), + [metricsQuery.data] + ) + const summary = useMemo(() => buildPerformanceSummary(models), [models]) + const topModels = useMemo(() => models.slice(0, TOP_MODEL_LIMIT), [models]) + const loading = metricsQuery.isLoading + const hasData = models.length > 0 + const description = t('Performance metrics for the last 24 hours') + + return ( +
+
+
+ + + + +
+
+ +
+ + {!loading && !hasData ? ( +
+ {t('No performance data available')} +
+ ) : ( +
+ + + + {t('Model')} + + {t('Requests (24h)')} + + + {t('Average latency')} + + + {t('Throughput')} + + + {t('Success rate')} + + + + + {loading + ? Array.from({ length: 4 }).map((_, index) => ( + + + + + + + + + + + + + + + + + + )) + : topModels.map((model) => ( + + + {model.model_name} + + + {formatNumber(model.request_count)} + + + {formatLatency(model.avg_latency_ms)} + + + {formatThroughput(model.avg_tps)} + + + + + + + ))} + +
+
+ )} +
+
+ ) +} diff --git a/web/default/src/features/dashboard/index.tsx b/web/default/src/features/dashboard/index.tsx index b4ed7d16..ed9f3e24 100644 --- a/web/default/src/features/dashboard/index.tsx +++ b/web/default/src/features/dashboard/index.tsx @@ -47,6 +47,12 @@ const LazyConsumptionDistributionChart = lazy(() => })) ) +const LazyPerformanceOverview = lazy(() => + import('./components/models/performance-overview').then((m) => ({ + default: m.PerformanceOverview, + })) +) + const LazyUserCharts = lazy(() => import('./components/users/user-charts').then((m) => ({ default: m.UserCharts, @@ -83,6 +89,31 @@ function ModelChartsFallback() { ) } +function PerformanceOverviewFallback() { + return ( +
+
+
+ {Array.from({ length: 4 }).map((_, i) => ( +
+ + + +
+ ))} +
+
+
+
+ + +
+ +
+
+ ) +} + const SECTION_META: Record< DashboardSectionId, { titleKey: string; descriptionKey: string } @@ -219,6 +250,11 @@ export function Dashboard() { + }> + + + + }> - + }> { + const res = await api.get('/api/perf-metrics/summary', { + params: { hours }, + }) + return res.data +} + +export async function getPerfMetrics( + modelName: string, + hours = 24 +): Promise { + const res = await api.get('/api/perf-metrics', { + params: { + model: modelName, + hours, + }, + }) + return res.data +} diff --git a/web/default/src/features/performance-metrics/lib/format.ts b/web/default/src/features/performance-metrics/lib/format.ts new file mode 100644 index 00000000..3983007c --- /dev/null +++ b/web/default/src/features/performance-metrics/lib/format.ts @@ -0,0 +1,16 @@ +export function formatThroughput(tps: number): string { + if (tps <= 0) return '—' + if (tps >= 1_000) return `${(tps / 1_000).toFixed(1)}K t/s` + return `${tps.toFixed(tps < 10 ? 2 : 1)} t/s` +} + +export function formatLatency(ms: number): string { + if (!Number.isFinite(ms) || ms <= 0) return '—' + if (ms >= 1_000) return `${(ms / 1_000).toFixed(2)}s` + return `${Math.round(ms)}ms` +} + +export function formatUptimePct(pct: number): string { + if (!Number.isFinite(pct)) return '—' + return `${pct.toFixed(2)}%` +} diff --git a/web/default/src/features/performance-metrics/types.ts b/web/default/src/features/performance-metrics/types.ts new file mode 100644 index 00000000..74c64904 --- /dev/null +++ b/web/default/src/features/performance-metrics/types.ts @@ -0,0 +1,42 @@ +export type PerformanceSeriesPoint = { + ts: number + avg_ttft_ms: number + avg_latency_ms: number + success_rate: number + avg_tps: number +} + +export type PerformanceGroup = { + group: string + avg_ttft_ms: number + avg_latency_ms: number + success_rate: number + avg_tps: number + series: PerformanceSeriesPoint[] +} + +export type PerformanceMetricsData = { + success: boolean + message?: string + data: { + model_name: string + series_schema?: string + groups: PerformanceGroup[] + } +} + +export type PerfModelSummary = { + model_name: string + avg_latency_ms: number + success_rate: number + avg_tps: number + request_count: number +} + +export type PerfSummaryAllData = { + success: boolean + message?: string + data: { + models: PerfModelSummary[] + } +} diff --git a/web/default/src/features/pricing/api.ts b/web/default/src/features/pricing/api.ts index ac9a88de..1cf6f8fd 100644 --- a/web/default/src/features/pricing/api.ts +++ b/web/default/src/features/pricing/api.ts @@ -10,65 +10,3 @@ export async function getPricing(): Promise { const res = await api.get('/api/pricing') return res.data } - -export type PerformanceSeriesPoint = { - ts: number - avg_ttft_ms: number - avg_latency_ms: number - success_rate: number - avg_tps: number -} - -export type PerformanceGroup = { - group: string - avg_ttft_ms: number - avg_latency_ms: number - success_rate: number - avg_tps: number - series: PerformanceSeriesPoint[] -} - -export type PerformanceMetricsData = { - success: boolean - message?: string - data: { - model_name: string - series_schema?: string - groups: PerformanceGroup[] - } -} - -export type PerfModelSummary = { - model_name: string - avg_latency_ms: number - success_rate: number - avg_tps: number - request_count: number -} - -export type PerfSummaryAllData = { - success: boolean - message?: string - data: { - models: PerfModelSummary[] - } -} - -export async function getPerfMetricsSummary( - hours = 24 -): Promise { - const res = await api.get(`/api/perf-metrics/summary?hours=${hours}`) - return res.data -} - -export async function getPerfMetrics( - modelName: string, - hours = 24 -): Promise { - const params = new URLSearchParams({ - model: modelName, - hours: String(hours), - }) - const res = await api.get(`/api/perf-metrics?${params.toString()}`) - return res.data -} diff --git a/web/default/src/features/pricing/components/model-card-grid.tsx b/web/default/src/features/pricing/components/model-card-grid.tsx index 3ee63c81..648fc173 100644 --- a/web/default/src/features/pricing/components/model-card-grid.tsx +++ b/web/default/src/features/pricing/components/model-card-grid.tsx @@ -1,9 +1,9 @@ -import { useEffect, useMemo, useState } from 'react' +import { useMemo, useState } from 'react' import { useQuery } from '@tanstack/react-query' import { ChevronLeft, ChevronRight } from 'lucide-react' import { useTranslation } from 'react-i18next' import { Button } from '@/components/ui/button' -import { getPerfMetricsSummary } from '../api' +import { getPerfMetricsSummary } from '@/features/performance-metrics/api' import { DEFAULT_PRICING_PAGE_SIZE, DEFAULT_TOKEN_UNIT } from '../constants' import type { PricingModel, TokenUnit } from '../types' import { ModelCard } from './model-card' @@ -24,22 +24,19 @@ export function ModelCardGrid(props: ModelCardGridProps) { const pageSize = DEFAULT_PRICING_PAGE_SIZE const tokenUnit = props.tokenUnit ?? DEFAULT_TOKEN_UNIT const totalPages = Math.max(1, Math.ceil(props.models.length / pageSize)) + const currentPage = Math.min(page, totalPages) const perfQuery = useQuery({ - queryKey: ['perf-metrics-summary'], + queryKey: ['perf-metrics-summary', 24], queryFn: () => getPerfMetricsSummary(24), staleTime: 60 * 1000, retry: false, }) - useEffect(() => { - setPage(1) - }, [props.models]) - const pagedModels = useMemo(() => { - const start = (page - 1) * pageSize + const start = (currentPage - 1) * pageSize return props.models.slice(start, start + pageSize) - }, [page, pageSize, props.models]) + }, [currentPage, pageSize, props.models]) const perfMap = useMemo(() => { const map = new Map() @@ -76,7 +73,7 @@ export function ModelCardGrid(props: ModelCardGridProps) {

{t('Page {{current}} of {{total}}', { - current: page, + current: currentPage, total: totalPages, })}

@@ -86,7 +83,7 @@ export function ModelCardGrid(props: ModelCardGridProps) { variant='outline' size='sm' onClick={() => setPage((current) => Math.max(1, current - 1))} - disabled={page <= 1} + disabled={currentPage <= 1} className='gap-1.5' > @@ -99,7 +96,7 @@ export function ModelCardGrid(props: ModelCardGridProps) { onClick={() => setPage((current) => Math.min(totalPages, current + 1)) } - disabled={page >= totalPages} + disabled={currentPage >= totalPages} className='gap-1.5' > {t('Next')} diff --git a/web/default/src/features/pricing/components/model-card.tsx b/web/default/src/features/pricing/components/model-card.tsx index b5c64300..38d37136 100644 --- a/web/default/src/features/pricing/components/model-card.tsx +++ b/web/default/src/features/pricing/components/model-card.tsx @@ -14,8 +14,7 @@ import { parseTags } from '../lib/filters' import { isTokenBasedModel } from '../lib/model-helpers' import { formatPrice, formatRequestPrice } from '../lib/price' import type { PricingModel, TokenUnit } from '../types' -import { ModelPerfBadge } from './model-perf-badge' -import type { ModelPerfBadgeData } from './model-perf-badge' +import { ModelPerfBadge, type ModelPerfBadgeData } from './model-perf-badge' export interface ModelCardProps { model: PricingModel diff --git a/web/default/src/features/pricing/components/model-details-performance.tsx b/web/default/src/features/pricing/components/model-details-performance.tsx index a0d43ffd..9b8de39c 100644 --- a/web/default/src/features/pricing/components/model-details-performance.tsx +++ b/web/default/src/features/pricing/components/model-details-performance.tsx @@ -12,13 +12,14 @@ import { TableRow, } from '@/components/ui/table' import { GroupBadge } from '@/components/group-badge' -import { getPerfMetrics, type PerformanceGroup } from '../api' +import { getPerfMetrics } from '@/features/performance-metrics/api' import { formatLatency, formatThroughput, formatUptimePct, - type UptimeDayPoint, -} from '../lib/mock-stats' +} from '@/features/performance-metrics/lib/format' +import type { PerformanceGroup } from '@/features/performance-metrics/types' +import { type UptimeDayPoint } from '../lib/mock-stats' import type { PricingModel } from '../types' import { LatencyTrendChart, UptimeTrendChart } from './model-details-charts' import { UptimeSparkline } from './model-details-uptime-sparkline' @@ -142,7 +143,10 @@ export function ModelDetailsPerformance(props: { model: PricingModel }) { queryFn: () => getPerfMetrics(props.model.model_name, 24), staleTime: 60 * 1000, }) - const groups = metricsQuery.data?.data.groups ?? [] + const groups = useMemo( + () => metricsQuery.data?.data.groups ?? [], + [metricsQuery.data] + ) const performances = useMemo( () => groups.map((group) => ({ diff --git a/web/default/src/features/pricing/components/model-details-uptime-sparkline.tsx b/web/default/src/features/pricing/components/model-details-uptime-sparkline.tsx index 932a52ee..0dc9063c 100644 --- a/web/default/src/features/pricing/components/model-details-uptime-sparkline.tsx +++ b/web/default/src/features/pricing/components/model-details-uptime-sparkline.tsx @@ -7,11 +7,8 @@ import { TooltipContent, TooltipTrigger, } from '@/components/ui/tooltip' -import { - aggregateUptime, - formatUptimePct, - type UptimeDayPoint, -} from '../lib/mock-stats' +import { formatUptimePct } from '@/features/performance-metrics/lib/format' +import { aggregateUptime, type UptimeDayPoint } from '../lib/mock-stats' // --------------------------------------------------------------------------- // Uptime sparkline diff --git a/web/default/src/features/pricing/components/model-details.tsx b/web/default/src/features/pricing/components/model-details.tsx index 054eed35..59904cad 100644 --- a/web/default/src/features/pricing/components/model-details.tsx +++ b/web/default/src/features/pricing/components/model-details.tsx @@ -26,7 +26,12 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs' import { CopyButton } from '@/components/copy-button' import { GroupBadge } from '@/components/group-badge' import { PublicLayout } from '@/components/layout' -import { getPerfMetrics } from '../api' +import { getPerfMetrics } from '@/features/performance-metrics/api' +import { + formatLatency, + formatThroughput, + formatUptimePct, +} from '@/features/performance-metrics/lib/format' import { DEFAULT_TOKEN_UNIT, QUOTA_TYPE_VALUES } from '../constants' import { usePricingData } from '../hooks/use-pricing-data' import { @@ -36,11 +41,6 @@ import { isDynamicPricingModel, } from '../lib/dynamic-price' import { parseTags } from '../lib/filters' -import { - formatLatency, - formatThroughput, - formatUptimePct, -} from '../lib/mock-stats' import { getAvailableGroups, isTokenBasedModel } from '../lib/model-helpers' import { inferModelMetadata } from '../lib/model-metadata' import { formatFixedPrice, formatGroupPrice } from '../lib/price' diff --git a/web/default/src/features/pricing/components/model-perf-badge.tsx b/web/default/src/features/pricing/components/model-perf-badge.tsx index f98afafd..40aca10e 100644 --- a/web/default/src/features/pricing/components/model-perf-badge.tsx +++ b/web/default/src/features/pricing/components/model-perf-badge.tsx @@ -1,7 +1,10 @@ import { memo } from 'react' import { useTranslation } from 'react-i18next' import { cn } from '@/lib/utils' -import { formatLatency, formatThroughput } from '../lib/mock-stats' +import { + formatLatency, + formatThroughput, +} from '@/features/performance-metrics/lib/format' export type ModelPerfBadgeData = { avg_latency_ms: number diff --git a/web/default/src/features/pricing/lib/mock-stats.ts b/web/default/src/features/pricing/lib/mock-stats.ts index c92e5d14..b25d6b02 100644 --- a/web/default/src/features/pricing/lib/mock-stats.ts +++ b/web/default/src/features/pricing/lib/mock-stats.ts @@ -464,26 +464,6 @@ export function aggregateUptime(points: UptimeDayPoint[]): { } } -/** Format throughput for display: "0" → "—". */ -export function formatThroughput(tps: number): string { - if (tps <= 0) return '—' - if (tps >= 1_000) return `${(tps / 1_000).toFixed(1)}K t/s` - return `${tps.toFixed(tps < 10 ? 2 : 1)} t/s` -} - -/** Format latency in ms with proper unit selection. */ -export function formatLatency(ms: number): string { - if (!Number.isFinite(ms) || ms <= 0) return '—' - if (ms >= 1_000) return `${(ms / 1_000).toFixed(2)}s` - return `${Math.round(ms)}ms` -} - -/** Format uptime percentage with 2 decimal places. */ -export function formatUptimePct(pct: number): string { - if (!Number.isFinite(pct)) return '—' - return `${pct.toFixed(2)}%` -} - /** Compact integer formatter for token counts in apps tab. */ export function formatTokenVolume(n: number): string { if (!Number.isFinite(n) || n <= 0) return '0' diff --git a/web/default/src/i18n/locales/en.json b/web/default/src/i18n/locales/en.json index 413d70f8..05e8c5bd 100644 --- a/web/default/src/i18n/locales/en.json +++ b/web/default/src/i18n/locales/en.json @@ -2383,6 +2383,7 @@ "More templates...": "More templates...", "More...": "More...", "Most-used models in the selected period and category": "Most-used models in the selected period and category", + "Monitored relay requests": "Monitored relay requests", "Move": "Move", "Move a request header": "Move a request header", "Move affiliate rewards to your main balance": "Move affiliate rewards to your main balance", @@ -2555,6 +2556,7 @@ "No payment methods configured": "No payment methods configured", "No payment methods configured. Click \"Add method\" or use templates to get started.": "No payment methods configured. Click \"Add method\" or use templates to get started.", "No payment methods match your search": "No payment methods match your search", + "No performance data available": "No performance data available", "No plans available": "No plans available", "No preference": "No preference", "No prefill groups yet": "No prefill groups yet", @@ -2849,6 +2851,7 @@ "Percentage:": "Percentage:", "Performance": "Performance", "Performance data is not yet available for this model.": "Performance data is not yet available for this model.", + "Performance metrics for the last 24 hours": "Performance metrics for the last 24 hours", "Performance metrics shown here are simulated for preview purposes and will be replaced with live observability data once the backend integration is complete.": "Performance metrics shown here are simulated for preview purposes and will be replaced with live observability data once the backend integration is complete.", "Performance Monitor": "Performance Monitor", "Performance Settings": "Performance Settings", @@ -4330,6 +4333,7 @@ "Weekly token usage by model since launch": "Weekly token usage by model since launch", "Weekly Window": "Weekly Window", "Weight": "Weight", + "Weighted by request count": "Weighted by request count", "Welcome back!": "Welcome back!", "Welcome to our New API...": "Welcome to our New API...", "Well-Known URL": "Well-Known URL", diff --git a/web/default/src/i18n/locales/fr.json b/web/default/src/i18n/locales/fr.json index c26f7933..f13d1b8b 100644 --- a/web/default/src/i18n/locales/fr.json +++ b/web/default/src/i18n/locales/fr.json @@ -2383,6 +2383,7 @@ "More templates...": "Autres modèles…", "More...": "Plus...", "Most-used models in the selected period and category": "Modèles les plus utilisés dans la période et catégorie choisies", + "Monitored relay requests": "Requêtes relais surveillées", "Move": "Déplacer", "Move a request header": "Déplacer un en-tête de requête", "Move affiliate rewards to your main balance": "Transférer les récompenses d'affiliation vers votre solde principal", @@ -2555,6 +2556,7 @@ "No payment methods configured": "Aucun mode de paiement configuré", "No payment methods configured. Click \"Add method\" or use templates to get started.": "Aucune méthode de paiement configurée. Cliquez sur \"Ajouter une méthode\" ou utilisez des modèles pour commencer.", "No payment methods match your search": "Aucune méthode de paiement ne correspond à votre recherche", + "No performance data available": "Aucune donnée de performance disponible", "No plans available": "Aucun plan disponible", "No preference": "Aucune préférence", "No prefill groups yet": "Aucun groupe de préremplissage pour l'instant", @@ -2849,6 +2851,7 @@ "Percentage:": "Pourcentage :", "Performance": "Performances", "Performance data is not yet available for this model.": "Aucune donnée de performance n'est encore disponible pour ce modèle.", + "Performance metrics for the last 24 hours": "Indicateurs de performance des dernières 24 heures", "Performance metrics shown here are simulated for preview purposes and will be replaced with live observability data once the backend integration is complete.": "Les indicateurs de performance présentés ici sont simulés à des fins de prévisualisation et seront remplacés par des données d'observabilité réelles une fois l'intégration du backend terminée.", "Performance Monitor": "Moniteur de performances", "Performance Settings": "Paramètres de performances", @@ -4330,6 +4333,7 @@ "Weekly token usage by model since launch": "Utilisation hebdomadaire de tokens par modèle depuis le lancement", "Weekly Window": "Fenêtre hebdomadaire", "Weight": "Poids", + "Weighted by request count": "Pondéré par le nombre de requêtes", "Welcome back!": "Bienvenue de retour !", "Welcome to our New API...": "Bienvenue sur notre New API...", "Well-Known URL": "URL bien connue", diff --git a/web/default/src/i18n/locales/ja.json b/web/default/src/i18n/locales/ja.json index 3b7a824b..7a17e1cd 100644 --- a/web/default/src/i18n/locales/ja.json +++ b/web/default/src/i18n/locales/ja.json @@ -2383,6 +2383,7 @@ "More templates...": "ほかのテンプレート…", "More...": "その他...", "Most-used models in the selected period and category": "選択した期間とカテゴリで最も使われているモデル", + "Monitored relay requests": "監視対象のリレーリクエスト", "Move": "移動", "Move a request header": "リクエストヘッダーを移動", "Move affiliate rewards to your main balance": "アフィリエイト報酬をメイン残高に移動する", @@ -2555,6 +2556,7 @@ "No payment methods configured": "決済方法が設定されていません", "No payment methods configured. Click \"Add method\" or use templates to get started.": "支払い方法が設定されていません。「メソッドを追加」をクリックするか、テンプレートを使用して開始してください。", "No payment methods match your search": "検索に一致する支払い方法がありません", + "No performance data available": "利用可能なパフォーマンスデータはありません", "No plans available": "利用可能なプランがありません", "No preference": "設定なし", "No prefill groups yet": "まだ事前入力グループはありません", @@ -2849,6 +2851,7 @@ "Percentage:": "パーセンテージ:", "Performance": "パフォーマンス", "Performance data is not yet available for this model.": "このモデルのパフォーマンスデータはまだ利用できません。", + "Performance metrics for the last 24 hours": "直近24時間のパフォーマンス指標", "Performance metrics shown here are simulated for preview purposes and will be replaced with live observability data once the backend integration is complete.": "ここに表示されているパフォーマンス指標はプレビュー用のシミュレーションデータです。バックエンド連携の完了後、実データに置き換えられます。", "Performance Monitor": "パフォーマンス監視", "Performance Settings": "パフォーマンス設定", @@ -4330,6 +4333,7 @@ "Weekly token usage by model since launch": "ローンチ以降のモデル別週次トークン使用量", "Weekly Window": "週間ウィンドウ", "Weight": "ウェイト", + "Weighted by request count": "リクエスト数で加重", "Welcome back!": "おかえりなさい!", "Welcome to our New API...": "New API へようこそ...", "Well-Known URL": "よく知られたURL", diff --git a/web/default/src/i18n/locales/ru.json b/web/default/src/i18n/locales/ru.json index e316832b..91f8030e 100644 --- a/web/default/src/i18n/locales/ru.json +++ b/web/default/src/i18n/locales/ru.json @@ -2383,6 +2383,7 @@ "More templates...": "Другие шаблоны…", "More...": "Подробнее...", "Most-used models in the selected period and category": "Самые используемые модели в выбранном периоде и категории", + "Monitored relay requests": "Отслеживаемые ретрансляционные запросы", "Move": "Переместить", "Move a request header": "Переместить заголовок запроса", "Move affiliate rewards to your main balance": "Перевести партнерские вознаграждения на основной баланс", @@ -2555,6 +2556,7 @@ "No payment methods configured": "Способы оплаты не настроены", "No payment methods configured. Click \"Add method\" or use templates to get started.": "Способы оплаты не настроены. Нажмите \"Добавить способ\" или используйте шаблоны, чтобы начать.", "No payment methods match your search": "Нет способов оплаты, соответствующих вашему поиску", + "No performance data available": "Нет доступных данных о производительности", "No plans available": "Нет доступных планов", "No preference": "Без предпочтений", "No prefill groups yet": "Пока нет групп предзаполнения", @@ -2849,6 +2851,7 @@ "Percentage:": "Процент:", "Performance": "Производительность", "Performance data is not yet available for this model.": "Данные о производительности этой модели пока недоступны.", + "Performance metrics for the last 24 hours": "Метрики производительности за последние 24 часа", "Performance metrics shown here are simulated for preview purposes and will be replaced with live observability data once the backend integration is complete.": "Показанные метрики производительности сгенерированы для предпросмотра и будут заменены реальными данными наблюдаемости после интеграции бэкенда.", "Performance Monitor": "Монитор производительности", "Performance Settings": "Настройки производительности", @@ -4330,6 +4333,7 @@ "Weekly token usage by model since launch": "Еженедельное использование токенов по моделям с момента запуска", "Weekly Window": "Недельное окно", "Weight": "Вес", + "Weighted by request count": "Взвешено по количеству запросов", "Welcome back!": "Добро пожаловать обратно!", "Welcome to our New API...": "Добро пожаловать в наш New API...", "Well-Known URL": "Известный эксперт", diff --git a/web/default/src/i18n/locales/vi.json b/web/default/src/i18n/locales/vi.json index 15fadb5f..1e5fede3 100644 --- a/web/default/src/i18n/locales/vi.json +++ b/web/default/src/i18n/locales/vi.json @@ -2383,6 +2383,7 @@ "More templates...": "Thêm mẫu...", "More...": "Thêm...", "Most-used models in the selected period and category": "Mô hình được dùng nhiều nhất trong khoảng thời gian và danh mục đã chọn", + "Monitored relay requests": "Yêu cầu relay được giám sát", "Move": "Di chuyển", "Move a request header": "Di chuyển header yêu cầu", "Move affiliate rewards to your main balance": "Chuyển phần thưởng liên kết vào số dư chính của bạn", @@ -2555,6 +2556,7 @@ "No payment methods configured": "Chưa cấu hình phương thức thanh toán", "No payment methods configured. Click \"Add method\" or use templates to get started.": "Chưa cấu hình phương thức thanh toán. Nhấp vào \"Thêm phương thức\" hoặc sử dụng mẫu để bắt đầu.", "No payment methods match your search": "Không có phương thức thanh toán nào khớp với tìm kiếm của bạn", + "No performance data available": "Không có dữ liệu hiệu năng", "No plans available": "Không có gói nào khả dụng", "No preference": "Không có ưu tiên", "No prefill groups yet": "Chưa có nhóm điền sẵn nào", @@ -2849,6 +2851,7 @@ "Percentage:": "Phần trăm:", "Performance": "Hiệu suất", "Performance data is not yet available for this model.": "Chưa có dữ liệu hiệu năng cho mô hình này.", + "Performance metrics for the last 24 hours": "Chỉ số hiệu năng trong 24 giờ qua", "Performance metrics shown here are simulated for preview purposes and will be replaced with live observability data once the backend integration is complete.": "Các chỉ số hiệu năng hiển thị tại đây là dữ liệu mô phỏng để xem trước và sẽ được thay thế bằng dữ liệu thực sau khi tích hợp backend.", "Performance Monitor": "Giám sát hiệu suất", "Performance Settings": "Cài đặt hiệu suất", @@ -4330,6 +4333,7 @@ "Weekly token usage by model since launch": "Sử dụng token theo mô hình hàng tuần kể từ khi ra mắt", "Weekly Window": "Cửa sổ hàng tuần", "Weight": "Trọng lượng", + "Weighted by request count": "Có trọng số theo số yêu cầu", "Welcome back!": "Chào mừng trở lại!", "Welcome to our New API...": "Chào mừng bạn đến với API mới của chúng tôi...", "Well-Known URL": "URL đã biết", diff --git a/web/default/src/i18n/locales/zh.json b/web/default/src/i18n/locales/zh.json index e9fa9844..5d3014ce 100644 --- a/web/default/src/i18n/locales/zh.json +++ b/web/default/src/i18n/locales/zh.json @@ -2383,6 +2383,7 @@ "More templates...": "更多模板...", "More...": "更多...", "Most-used models in the selected period and category": "所选时间范围与分类下使用率最高的模型", + "Monitored relay requests": "已监控的中继请求", "Move": "移动", "Move a request header": "移动请求头", "Move affiliate rewards to your main balance": "将推广奖励转移到您的主余额", @@ -2555,6 +2556,7 @@ "No payment methods configured": "暂无支付方式", "No payment methods configured. Click \"Add method\" or use templates to get started.": "未配置支付方式。点击\"添加方式\"或使用模板开始。", "No payment methods match your search": "没有匹配的支付方式", + "No performance data available": "暂无性能数据", "No plans available": "暂无可购买套餐", "No preference": "无偏好", "No prefill groups yet": "暂无预填充分组", @@ -2849,6 +2851,7 @@ "Percentage:": "百分比:", "Performance": "性能", "Performance data is not yet available for this model.": "该模型暂无性能数据。", + "Performance metrics for the last 24 hours": "最近 24 小时的性能指标", "Performance metrics shown here are simulated for preview purposes and will be replaced with live observability data once the backend integration is complete.": "此处展示的性能指标为预览模拟数据,待后端对接完成后将替换为真实可观测数据。", "Performance Monitor": "性能监控", "Performance Settings": "性能设置", @@ -4330,6 +4333,7 @@ "Weekly token usage by model since launch": "自上线以来按模型分布的每周 Token 使用量", "Weekly Window": "每周窗口", "Weight": "权重", + "Weighted by request count": "按请求数加权", "Welcome back!": "欢迎回来!", "Welcome to our New API...": "欢迎使用我们的 New API...", "Well-Known URL": "Well-Known URL",