refactor: summary
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
|
||||
interface CollapseProps {
|
||||
open: boolean;
|
||||
children: React.ReactNode;
|
||||
duration?: number;
|
||||
minHeight?: number;
|
||||
}
|
||||
|
||||
export default function Collapse({
|
||||
open,
|
||||
children,
|
||||
minHeight = 0,
|
||||
duration = 200
|
||||
}: CollapseProps) {
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
const [height, setHeight] = useState<number | 'auto'>(minHeight);
|
||||
|
||||
useEffect(() => {
|
||||
const el = ref.current;
|
||||
if (!el) return;
|
||||
|
||||
if (open) {
|
||||
const h = el.scrollHeight;
|
||||
setHeight(h);
|
||||
|
||||
const timer = setTimeout(() => {
|
||||
setHeight('auto');
|
||||
}, duration);
|
||||
|
||||
return () => clearTimeout(timer);
|
||||
} else {
|
||||
const h = el.scrollHeight;
|
||||
setHeight(h);
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
requestAnimationFrame(() => {
|
||||
setHeight(0);
|
||||
});
|
||||
});
|
||||
}
|
||||
return undefined;
|
||||
}, [open, duration]);
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
style={{
|
||||
height,
|
||||
overflow: 'hidden',
|
||||
transition: `height ${duration}ms ease`
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { useDetailContext } from '../../config/detail-context';
|
||||
import Benchmark from './benchmark';
|
||||
import Instance from './instance';
|
||||
|
||||
const Container = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
`;
|
||||
|
||||
const Configure: React.FC = () => {
|
||||
const { detailData } = useDetailContext();
|
||||
return (
|
||||
<Container>
|
||||
<Instance />
|
||||
<Benchmark />
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
export default Configure;
|
||||
@@ -6,7 +6,6 @@ import React, { useEffect, useState } from 'react';
|
||||
import DetailContext from '../config/detail-context';
|
||||
import { BenchmarkListItem } from '../config/types';
|
||||
import useQueryDetail from '../services/use-query-detail';
|
||||
import Configure from './configure';
|
||||
import Environment from './environment';
|
||||
import Summary from './summary';
|
||||
|
||||
@@ -31,12 +30,6 @@ const Details: React.FC<{ currentData?: BenchmarkListItem }> = ({
|
||||
children: <Summary />,
|
||||
icon: <IconFont type="icon-basic" />
|
||||
},
|
||||
{
|
||||
key: 'configure',
|
||||
label: intl.formatMessage({ id: 'benchmark.detail.configure.title' }),
|
||||
children: <Configure />,
|
||||
icon: <IconFont type="icon-settings-02" />
|
||||
},
|
||||
{
|
||||
key: 'environment',
|
||||
label: intl.formatMessage({ id: 'benchmark.detail.environment.title' }),
|
||||
|
||||
@@ -6,7 +6,6 @@ import _, { round } from 'lodash';
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { useDetailContext } from '../../config/detail-context';
|
||||
import PercentileResult from './percentile-result';
|
||||
import Section from './section';
|
||||
|
||||
const Container = styled.div`
|
||||
@@ -239,7 +238,6 @@ const Summary: React.FC = () => {
|
||||
></Descriptions>
|
||||
</Section>
|
||||
</Box>
|
||||
<PercentileResult />
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import { Descriptions, DescriptionsProps } from 'antd';
|
||||
import React from 'react';
|
||||
import { useDetailContext } from '../../config/detail-context';
|
||||
import Section from '../summary/section';
|
||||
import Section from './section';
|
||||
|
||||
const Benchmark: React.FC = () => {
|
||||
const { detailData } = useDetailContext();
|
||||
@@ -19,7 +19,7 @@ const Benchmark: React.FC = () => {
|
||||
},
|
||||
{
|
||||
key: '3',
|
||||
label: 'Token Length (In/Out)',
|
||||
label: 'Token Length (Prompt/Out)',
|
||||
children: (
|
||||
<span>
|
||||
{detailData?.dataset_prompt_tokens || '-'} /{' '}
|
||||
@@ -1,19 +1,23 @@
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import BasicInfo from './basic';
|
||||
import MetricsInfo from './metrics';
|
||||
import BenchMark from './benchmark';
|
||||
import Instance from './instance';
|
||||
import MetricsResult from './metrics-result';
|
||||
import PercentileResult from './percentile-result';
|
||||
|
||||
const Container = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24px;
|
||||
gap: 16px;
|
||||
`;
|
||||
|
||||
const Summary: React.FC = () => {
|
||||
return (
|
||||
<Container>
|
||||
<BasicInfo />
|
||||
<MetricsInfo />
|
||||
<Instance />
|
||||
<BenchMark />
|
||||
<MetricsResult />
|
||||
<PercentileResult />
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
+10
-42
@@ -1,11 +1,8 @@
|
||||
import StatusTag from '@/components/status-tag';
|
||||
import { InstanceStatusMapValue, status } from '@/pages/llmodels/config';
|
||||
import { convertFileSize } from '@/utils';
|
||||
import { Descriptions, Flex, Tag } from 'antd';
|
||||
import _ from 'lodash';
|
||||
import React, { useMemo } from 'react';
|
||||
import { useDetailContext } from '../../config/detail-context';
|
||||
import Section from '../summary/section';
|
||||
import Section from './section';
|
||||
|
||||
const calcTotalVram = (vram: Record<string, number>) => {
|
||||
return _.sum(_.values(vram));
|
||||
@@ -17,21 +14,16 @@ const Instance: React.FC = () => {
|
||||
const items = useMemo(() => {
|
||||
const { snapshot } = detailData;
|
||||
const [instanceName, instanceData] =
|
||||
Object.entries(snapshot.instances || {})[0] || [];
|
||||
Object.entries(snapshot?.instances || {})[0] || [];
|
||||
return [
|
||||
{
|
||||
key: '1',
|
||||
label: 'Instance Name',
|
||||
children: (
|
||||
<div className="flex-center gap-8">
|
||||
<span>{instanceName}</span>
|
||||
<StatusTag
|
||||
statusValue={{
|
||||
status: status[instanceData.state],
|
||||
text: InstanceStatusMapValue[instanceData.state],
|
||||
message: detailData.state_message || undefined
|
||||
}}
|
||||
/>
|
||||
<span>
|
||||
{detailData?.model_name}/{detailData?.model_instance_name}
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
@@ -39,42 +31,18 @@ const Instance: React.FC = () => {
|
||||
key: '2',
|
||||
label: 'Worker',
|
||||
children: instanceData?.worker_name || '-'
|
||||
// children:
|
||||
// instanceData?.ports?.length > 0
|
||||
// ? `${instanceData.worker_ip}:${instanceData.ports[0]}`
|
||||
// : instanceData.worker_ip || '-'
|
||||
},
|
||||
{
|
||||
key: '3',
|
||||
label: 'GPU Indexes',
|
||||
children:
|
||||
_.join(
|
||||
instanceData.gpu_indexes?.sort?.((a, b) => a - b),
|
||||
','
|
||||
) || '-'
|
||||
},
|
||||
{
|
||||
key: '6',
|
||||
label: 'GPU Type',
|
||||
children: instanceData?.gpu_type || '-'
|
||||
},
|
||||
{
|
||||
key: '4',
|
||||
label: 'Allocated VRAM',
|
||||
children:
|
||||
convertFileSize(
|
||||
instanceData.computed_resource_claim?.vram
|
||||
? calcTotalVram(instanceData.computed_resource_claim?.vram)
|
||||
: 0,
|
||||
1
|
||||
) || '-'
|
||||
},
|
||||
{
|
||||
key: '5',
|
||||
label: 'Backend',
|
||||
children: `${instanceData?.backend || '-'} ${
|
||||
instanceData.backend_version
|
||||
? `(${instanceData.backend_version})`
|
||||
instanceData?.backend_version
|
||||
? `(${instanceData?.backend_version})`
|
||||
: ''
|
||||
}`
|
||||
}
|
||||
@@ -84,14 +52,14 @@ const Instance: React.FC = () => {
|
||||
const paramsItems = useMemo(() => {
|
||||
const { snapshot } = detailData;
|
||||
const [instanceName, instanceData] =
|
||||
Object.entries(snapshot.instances || {})[0] || [];
|
||||
Object.entries(snapshot?.instances || {})[0] || [];
|
||||
return [
|
||||
{
|
||||
key: '1',
|
||||
label: 'Backend Parameters',
|
||||
children: (
|
||||
<Flex gap={8} wrap="wrap">
|
||||
{instanceData?.backend_parameters.map(
|
||||
{instanceData?.backend_parameters?.map(
|
||||
(param: string, index: number) => (
|
||||
<Tag key={index} style={{ margin: 0 }}>
|
||||
{param}
|
||||
@@ -180,7 +148,7 @@ const Instance: React.FC = () => {
|
||||
<Descriptions
|
||||
items={items}
|
||||
colon={false}
|
||||
column={3}
|
||||
column={4}
|
||||
layout="vertical"
|
||||
styles={{
|
||||
content: {
|
||||
@@ -0,0 +1,180 @@
|
||||
import { Descriptions } from 'antd';
|
||||
import _, { round } from 'lodash';
|
||||
import React from 'react';
|
||||
import { useDetailContext } from '../../config/detail-context';
|
||||
import Section from './section';
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: 'Duration (s)',
|
||||
dataIndex: 'duration',
|
||||
path: ['raw_metrics', 'benchmarks', '0', 'duration'],
|
||||
unit: 's',
|
||||
render: (value: number) => round(value, 2)
|
||||
},
|
||||
{
|
||||
title: 'Concurrency',
|
||||
dataIndex: 'request_concurrency',
|
||||
path: ['raw_metrics', 'benchmarks', '0'],
|
||||
unit: '',
|
||||
render: (value: number) => {
|
||||
return round(
|
||||
_.get(value, 'metrics.request_concurrency.successful.mean'),
|
||||
0
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Total Requests',
|
||||
dataIndex: 'total_requests',
|
||||
path: 'total_requests',
|
||||
unit: '',
|
||||
render: (value: number) => round(value, 0)
|
||||
},
|
||||
{
|
||||
title: 'Success Requests',
|
||||
dataIndex: 'successful_requests',
|
||||
path: ['raw_metrics', 'benchmarks', '0'],
|
||||
unit: '',
|
||||
render: (value: number) => {
|
||||
return (
|
||||
<span style={{ color: 'var(--ant-color-success)' }}>
|
||||
{_.get(value, 'metrics.request_totals.successful')}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Failed Requests',
|
||||
dataIndex: 'failed_requests',
|
||||
path: ['raw_metrics', 'benchmarks', '0'],
|
||||
unit: '',
|
||||
render: (value: number) => {
|
||||
return (
|
||||
<span style={{ color: 'var(--ant-color-error)' }}>
|
||||
{_.get(value, 'metrics.request_totals.errored')}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Output token throughput (t/s)',
|
||||
dataIndex: 'output_tokens_per_second_mean',
|
||||
path: 'output_tokens_per_second_mean',
|
||||
unit: 't/s',
|
||||
render: (value: number) => round(value, 2)
|
||||
}
|
||||
];
|
||||
|
||||
const columnsSub = [
|
||||
{
|
||||
title: 'Total token throughput (t/s)',
|
||||
dataIndex: 'tokens_per_second_mean',
|
||||
path: 'tokens_per_second_mean',
|
||||
unit: 't/s',
|
||||
render: (value: number) => round(value, 2)
|
||||
},
|
||||
{
|
||||
title: 'Request token throughput (t/s)',
|
||||
dataIndex: 'prompt_tokens_per_second_mean',
|
||||
path: 'prompt_tokens_per_second_mean',
|
||||
unit: 't/s',
|
||||
render: (value: number) => round(value, 2)
|
||||
},
|
||||
{
|
||||
title: 'Average Request Latency (ms)',
|
||||
dataIndex: 'request_latency_mean',
|
||||
path: 'request_latency_mean',
|
||||
unit: 'ms',
|
||||
render: (value: number) => round(value, 2)
|
||||
},
|
||||
{
|
||||
title: 'Average Time To First Token (ms)',
|
||||
dataIndex: 'time_to_first_token_mean',
|
||||
path: 'time_to_first_token_mean',
|
||||
unit: 'ms',
|
||||
render: (value: number) => round(value, 2)
|
||||
},
|
||||
{
|
||||
title: 'Average Time Per Output Token (ms)',
|
||||
dataIndex: 'time_per_output_token_mean',
|
||||
path: 'time_per_output_token_mean',
|
||||
unit: 'ms',
|
||||
render: (value: number) => round(value, 2)
|
||||
},
|
||||
{
|
||||
title: '',
|
||||
dataIndex: '',
|
||||
path: '',
|
||||
unit: '',
|
||||
render: (_: number) => ''
|
||||
}
|
||||
];
|
||||
|
||||
const PERCENTILES = [
|
||||
{ key: 'metrics', label: 'Metrics', title: 'N/A' }
|
||||
] as const;
|
||||
|
||||
const PercentileResult: React.FC = () => {
|
||||
const { detailData } = useDetailContext();
|
||||
const metrics = detailData?.raw_metrics?.benchmarks?.[0]?.metrics || {};
|
||||
|
||||
const buildPercentileTable = (metrics: any) => {
|
||||
return PERCENTILES.map(({ key, title }) => {
|
||||
const row: any = { metrics: title };
|
||||
|
||||
[...columns, ...columnsSub].forEach(({ dataIndex, path }) => {
|
||||
row[dataIndex] = _.get(detailData, path) ?? 0;
|
||||
});
|
||||
|
||||
return row;
|
||||
});
|
||||
};
|
||||
|
||||
const items = [...columns, ...columnsSub].map(
|
||||
({ title, dataIndex, path, render, unit }) => ({
|
||||
key: dataIndex,
|
||||
label: title,
|
||||
children: unit
|
||||
? render(_.get(detailData, path) ?? 0) + ` (${unit})`
|
||||
: render(_.get(detailData, path) ?? 0)
|
||||
})
|
||||
);
|
||||
|
||||
return (
|
||||
<Section title="Metrics Result" minHeight={200}>
|
||||
{/* <Table
|
||||
size="small"
|
||||
columns={[
|
||||
{
|
||||
title: 'Metrics',
|
||||
dataIndex: 'metrics'
|
||||
},
|
||||
...columns
|
||||
]}
|
||||
dataSource={buildPercentileTable(metrics)}
|
||||
rowKey="percentile"
|
||||
pagination={false}
|
||||
styles={{
|
||||
body: {
|
||||
cell: {
|
||||
height: 54
|
||||
}
|
||||
}
|
||||
}}
|
||||
></Table> */}
|
||||
<Descriptions
|
||||
items={items}
|
||||
colon={false}
|
||||
column={2}
|
||||
styles={{
|
||||
content: {
|
||||
justifyContent: 'flex-end'
|
||||
}
|
||||
}}
|
||||
></Descriptions>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
export default PercentileResult;
|
||||
@@ -1,20 +0,0 @@
|
||||
import React from 'react';
|
||||
import { useDetailContext } from '../../config/detail-context';
|
||||
|
||||
const fields = [
|
||||
'requests_per_second_mean',
|
||||
'request_latency_mean',
|
||||
'time_per_output_token_mean',
|
||||
'inter_token_latency_mean',
|
||||
'time_to_first_token_mean',
|
||||
'tokens_per_second_mean',
|
||||
'output_tokens_per_second_mean',
|
||||
'prompt_tokens_per_second_mean'
|
||||
];
|
||||
|
||||
const Summary: React.FC = () => {
|
||||
const { detailData } = useDetailContext();
|
||||
return <div></div>;
|
||||
};
|
||||
|
||||
export default Summary;
|
||||
@@ -1,107 +1,92 @@
|
||||
import { Table } from 'antd';
|
||||
import { round } from 'lodash';
|
||||
import React from 'react';
|
||||
import { useDetailContext } from '../../config/detail-context';
|
||||
import Section from './section';
|
||||
|
||||
// Define table columns: Percentile、 TTFT (ms) 、 ITL (ms) 、TPOT (ms)、Latency (ms)、Input Tokens (t/s)、 Output Tokens (t/s)、 Output (t/s)、Total (t/s)
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: 'Percentile',
|
||||
dataIndex: 'percentile',
|
||||
key: 'percentile'
|
||||
},
|
||||
{
|
||||
title: 'TTFT (ms)',
|
||||
dataIndex: 'ttft',
|
||||
key: 'ttft'
|
||||
dataIndex: 'time_to_first_token_ms',
|
||||
render: (value: number) => round(value, 2)
|
||||
},
|
||||
{
|
||||
title: 'ITL (ms)',
|
||||
dataIndex: 'itl',
|
||||
key: 'itl'
|
||||
dataIndex: 'inter_token_latency_ms',
|
||||
render: (value: number) => round(value, 2)
|
||||
},
|
||||
{
|
||||
title: 'TPOT (ms)',
|
||||
dataIndex: 'tpot',
|
||||
key: 'tpot'
|
||||
dataIndex: 'time_per_output_token_ms',
|
||||
render: (value: number) => round(value, 2)
|
||||
},
|
||||
{
|
||||
title: 'Latency (ms)',
|
||||
dataIndex: 'latency',
|
||||
key: 'latency'
|
||||
title: 'Latency (s)',
|
||||
dataIndex: 'request_latency',
|
||||
render: (value: number) => round(value, 2)
|
||||
},
|
||||
{
|
||||
title: 'Input Tokens (t/s)',
|
||||
dataIndex: 'inputTokens',
|
||||
key: 'inputTokens'
|
||||
title: 'Input tokens',
|
||||
dataIndex: 'prompt_token_count',
|
||||
render: (value: number) => round(value, 0)
|
||||
},
|
||||
{
|
||||
title: 'Output Tokens (t/s)',
|
||||
dataIndex: 'outputTokens',
|
||||
key: 'outputTokens'
|
||||
title: 'Output tokens',
|
||||
dataIndex: 'output_token_count',
|
||||
render: (value: number) => round(value, 0)
|
||||
},
|
||||
{
|
||||
title: 'Input (t/s)',
|
||||
dataIndex: 'prompt_tokens_per_second',
|
||||
render: (value: number) => round(value, 2)
|
||||
},
|
||||
{
|
||||
title: 'Output (t/s)',
|
||||
dataIndex: 'output',
|
||||
key: 'output'
|
||||
dataIndex: 'output_tokens_per_second',
|
||||
render: (value: number) => round(value, 2)
|
||||
},
|
||||
{
|
||||
title: 'Total (t/s)',
|
||||
dataIndex: 'total',
|
||||
key: 'total'
|
||||
dataIndex: 'tokens_per_second',
|
||||
render: (value: number) => round(value, 2)
|
||||
}
|
||||
];
|
||||
|
||||
// mock data example: three rows of percentiles: 50th, 90th, 99th
|
||||
const data = [
|
||||
{
|
||||
key: '1',
|
||||
percentile: '50%',
|
||||
ttft: 100,
|
||||
itl: 50,
|
||||
tpot: 20,
|
||||
latency: 200,
|
||||
inputTokens: 300,
|
||||
outputTokens: 400,
|
||||
output: 500,
|
||||
total: 600
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
percentile: '90%',
|
||||
ttft: 150,
|
||||
itl: 70,
|
||||
tpot: 30,
|
||||
latency: 250,
|
||||
inputTokens: 350,
|
||||
outputTokens: 450,
|
||||
output: 550,
|
||||
total: 650
|
||||
},
|
||||
{
|
||||
key: '3',
|
||||
percentile: '99%',
|
||||
ttft: 200,
|
||||
itl: 90,
|
||||
tpot: 40,
|
||||
latency: 300,
|
||||
inputTokens: 400,
|
||||
outputTokens: 500,
|
||||
output: 600,
|
||||
total: 700
|
||||
}
|
||||
];
|
||||
const PERCENTILES = [
|
||||
{ key: 'p50', label: '50%' },
|
||||
{ key: 'p90', label: '90%' },
|
||||
{ key: 'p99', label: '99%' }
|
||||
] as const;
|
||||
|
||||
const PercentileResult: React.FC = () => {
|
||||
const { detailData, id } = useDetailContext();
|
||||
const { detailData } = useDetailContext();
|
||||
const metrics = detailData?.raw_metrics?.benchmarks?.[0]?.metrics || {};
|
||||
|
||||
const buildPercentileTable = (metrics: any) => {
|
||||
return PERCENTILES.map(({ key, label }) => {
|
||||
const row: any = { percentile: label };
|
||||
|
||||
columns.forEach(({ dataIndex }) => {
|
||||
row[dataIndex] =
|
||||
metrics?.[dataIndex]?.successful?.percentiles?.[key] ?? 0;
|
||||
});
|
||||
|
||||
return row;
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Section title="Percentiles Result">
|
||||
<Table
|
||||
size="small"
|
||||
columns={columns}
|
||||
dataSource={data}
|
||||
columns={[
|
||||
{
|
||||
title: 'Percentile',
|
||||
dataIndex: 'percentile'
|
||||
},
|
||||
...columns
|
||||
]}
|
||||
dataSource={buildPercentileTable(metrics)}
|
||||
rowKey="percentile"
|
||||
pagination={false}
|
||||
styles={{
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import HeadlessCollapse from '@/components/collapse-container/headless-collapse';
|
||||
import IconFont from '@/components/icon-font';
|
||||
import { useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
const Wrapper = styled.div`
|
||||
@@ -21,9 +24,10 @@ const Container = styled.div`
|
||||
`;
|
||||
|
||||
const Title = styled.div`
|
||||
justify-content: space-between;
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
font-weight: 500;
|
||||
// margin-bottom: 12px;
|
||||
font-size: 14px;
|
||||
gap: 8px;
|
||||
padding: 12px 16px;
|
||||
@@ -35,16 +39,31 @@ const Title = styled.div`
|
||||
const DetailSection: React.FC<{
|
||||
children: React.ReactNode;
|
||||
title?: React.ReactNode;
|
||||
minHeight?: number;
|
||||
styles?: {
|
||||
wraper?: React.CSSProperties;
|
||||
container?: React.CSSProperties;
|
||||
title?: React.CSSProperties;
|
||||
};
|
||||
}> = ({ children, title, styles }) => {
|
||||
}> = ({ children, title, styles, minHeight = 100 }) => {
|
||||
const [open, setOpen] = useState(true);
|
||||
return (
|
||||
<Wrapper style={styles?.wraper}>
|
||||
{title && <Title style={styles?.title}>{title}</Title>}
|
||||
<Container style={styles?.container}>{children}</Container>
|
||||
{title && (
|
||||
<Title style={styles?.title} onClick={() => setOpen(!open)}>
|
||||
{title}
|
||||
<IconFont
|
||||
type={'icon-down'}
|
||||
rotate={open ? 0 : -90}
|
||||
style={{
|
||||
transition: 'transform 0.2s'
|
||||
}}
|
||||
></IconFont>
|
||||
</Title>
|
||||
)}
|
||||
<HeadlessCollapse open={open} minHeight={minHeight}>
|
||||
<Container style={styles?.container}>{children}</Container>
|
||||
</HeadlessCollapse>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -67,6 +67,12 @@ export interface GPUData {
|
||||
export interface BenchmarkDetail {
|
||||
profile: string;
|
||||
seed: number;
|
||||
raw_metrics: {
|
||||
benchmarks: Array<{
|
||||
metrics: Record<string, any>;
|
||||
}>;
|
||||
[key: string]: any;
|
||||
};
|
||||
requests_per_second_mean: number;
|
||||
request_latency_mean: number;
|
||||
time_per_output_token_mean: number;
|
||||
|
||||
@@ -132,6 +132,7 @@ const ModelInstanceForm: React.FC = () => {
|
||||
>
|
||||
<SealCascader
|
||||
required
|
||||
showSearch
|
||||
loading={modelLoading || instanceLoading}
|
||||
changeOnSelect={false}
|
||||
expandTrigger="hover"
|
||||
|
||||
@@ -13,6 +13,7 @@ import { useEffect } from 'react';
|
||||
import NoResult from '../_components/no-result';
|
||||
import PageBox from '../_components/page-box';
|
||||
import {
|
||||
BENCHMARKS_API,
|
||||
createBenchmark,
|
||||
deleteBenchmark,
|
||||
queryBenchmarkList,
|
||||
@@ -48,6 +49,8 @@ const Benchmark: React.FC = () => {
|
||||
} = useTableFetch<ListItem>({
|
||||
fetchAPI: queryBenchmarkList,
|
||||
deleteAPI: deleteBenchmark,
|
||||
API: BENCHMARKS_API,
|
||||
watch: true,
|
||||
contentForDelete: 'menu.models.benchmark'
|
||||
});
|
||||
const intl = useIntl();
|
||||
|
||||
Reference in New Issue
Block a user