fix: benchmark detail styles
This commit is contained in:
@@ -19,10 +19,21 @@ export const OverlayScroller: React.FC<
|
|||||||
OverlayScrollerOptions & {
|
OverlayScrollerOptions & {
|
||||||
maxHeight?: number;
|
maxHeight?: number;
|
||||||
style?: React.CSSProperties;
|
style?: React.CSSProperties;
|
||||||
|
styles?: {
|
||||||
|
wrapper?: React.CSSProperties;
|
||||||
|
};
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
onScroll?: (e: React.UIEvent<HTMLDivElement, UIEvent>) => void;
|
onScroll?: (e: React.UIEvent<HTMLDivElement, UIEvent>) => void;
|
||||||
}
|
}
|
||||||
> = ({ children, maxHeight, scrollbars, oppositeTheme, style, onScroll }) => {
|
> = ({
|
||||||
|
children,
|
||||||
|
maxHeight,
|
||||||
|
scrollbars,
|
||||||
|
oppositeTheme,
|
||||||
|
style,
|
||||||
|
styles,
|
||||||
|
onScroll
|
||||||
|
}) => {
|
||||||
const scroller = React.useRef<any>(null);
|
const scroller = React.useRef<any>(null);
|
||||||
const { initialize } = useOverlayScroller({
|
const { initialize } = useOverlayScroller({
|
||||||
options: {
|
options: {
|
||||||
@@ -48,7 +59,8 @@ export const OverlayScroller: React.FC<
|
|||||||
style={{
|
style={{
|
||||||
paddingInlineStart: 8,
|
paddingInlineStart: 8,
|
||||||
paddingInlineEnd: 8,
|
paddingInlineEnd: 8,
|
||||||
...style
|
...style,
|
||||||
|
...styles?.wrapper
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export default {
|
|||||||
'benchmark.form.profile.longContext': 'Long Context',
|
'benchmark.form.profile.longContext': 'Long Context',
|
||||||
'benchmark.form.profile.heavy': 'Generation Heavy',
|
'benchmark.form.profile.heavy': 'Generation Heavy',
|
||||||
'benchmark.form.profile.custom': 'Custom',
|
'benchmark.form.profile.custom': 'Custom',
|
||||||
'benchmark.table.inputTokenLength': 'Prompt Token Length',
|
'benchmark.table.inputTokenLength': 'Input Token Length',
|
||||||
'benchmark.table.outputTokenLength': 'Output Token Length',
|
'benchmark.table.outputTokenLength': 'Output Token Length',
|
||||||
'benchmark.detail.summary.title': 'Summary',
|
'benchmark.detail.summary.title': 'Summary',
|
||||||
'benchmark.detail.configure.title': 'Configure',
|
'benchmark.detail.configure.title': 'Configure',
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export default {
|
|||||||
'benchmark.form.profile.longContext': 'Long Context',
|
'benchmark.form.profile.longContext': 'Long Context',
|
||||||
'benchmark.form.profile.heavy': 'Generation Heavy',
|
'benchmark.form.profile.heavy': 'Generation Heavy',
|
||||||
'benchmark.form.profile.custom': 'Custom',
|
'benchmark.form.profile.custom': 'Custom',
|
||||||
'benchmark.table.inputTokenLength': 'Prompt Token Length',
|
'benchmark.table.inputTokenLength': 'Input Token Length',
|
||||||
'benchmark.table.outputTokenLength': 'Output Token Length',
|
'benchmark.table.outputTokenLength': 'Output Token Length',
|
||||||
'benchmark.detail.summary.title': 'Summary',
|
'benchmark.detail.summary.title': 'Summary',
|
||||||
'benchmark.detail.configure.title': 'Configure',
|
'benchmark.detail.configure.title': 'Configure',
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export default {
|
|||||||
'benchmark.form.profile.longContext': 'Long Context',
|
'benchmark.form.profile.longContext': 'Long Context',
|
||||||
'benchmark.form.profile.heavy': 'Generation Heavy',
|
'benchmark.form.profile.heavy': 'Generation Heavy',
|
||||||
'benchmark.form.profile.custom': 'Custom',
|
'benchmark.form.profile.custom': 'Custom',
|
||||||
'benchmark.table.inputTokenLength': 'Prompt Token Length',
|
'benchmark.table.inputTokenLength': 'Input Token Length',
|
||||||
'benchmark.table.outputTokenLength': 'Output Token Length',
|
'benchmark.table.outputTokenLength': 'Output Token Length',
|
||||||
'benchmark.detail.summary.title': 'Summary',
|
'benchmark.detail.summary.title': 'Summary',
|
||||||
'benchmark.detail.configure.title': 'Configure',
|
'benchmark.detail.configure.title': 'Configure',
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export default {
|
|||||||
'benchmark.form.profile.longContext': '长上下文',
|
'benchmark.form.profile.longContext': '长上下文',
|
||||||
'benchmark.form.profile.heavy': '高生成量',
|
'benchmark.form.profile.heavy': '高生成量',
|
||||||
'benchmark.form.profile.custom': '自定义',
|
'benchmark.form.profile.custom': '自定义',
|
||||||
'benchmark.table.inputTokenLength': '提示词 Token 长度',
|
'benchmark.table.inputTokenLength': '输入 Token 长度',
|
||||||
'benchmark.table.outputTokenLength': '输出 Token 长度',
|
'benchmark.table.outputTokenLength': '输出 Token 长度',
|
||||||
'benchmark.detail.summary.title': '摘要',
|
'benchmark.detail.summary.title': '摘要',
|
||||||
'benchmark.detail.configure.title': '配置',
|
'benchmark.detail.configure.title': '配置',
|
||||||
|
|||||||
@@ -0,0 +1,172 @@
|
|||||||
|
import OverlayScroller from '@/components/overlay-scroller';
|
||||||
|
import { SettingOutlined } from '@ant-design/icons';
|
||||||
|
import { useIntl } from '@umijs/max';
|
||||||
|
import { Button, Checkbox, Col, Popover, Row, Tooltip } from 'antd';
|
||||||
|
import React from 'react';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
const Container = styled.div`
|
||||||
|
padding: 8px 12px;
|
||||||
|
padding-right: 4px;
|
||||||
|
.title {
|
||||||
|
font-weight: 500;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
.btn-wrapper {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding-top: 12px;
|
||||||
|
}
|
||||||
|
.buttons {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Title = styled.div`
|
||||||
|
font-weight: 500;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
margin-top: 4px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const ColumnSettings: React.FC<{
|
||||||
|
contentHeight: number;
|
||||||
|
columns: {
|
||||||
|
title: string;
|
||||||
|
dataIndex?: string;
|
||||||
|
children?: { title: string; dataIndex?: string }[];
|
||||||
|
}[];
|
||||||
|
selectedColumns?: string[];
|
||||||
|
grouped?: boolean;
|
||||||
|
onChange?: (selectedColumns: string[]) => void;
|
||||||
|
}> = (props) => {
|
||||||
|
const intl = useIntl();
|
||||||
|
const { contentHeight, columns, selectedColumns, grouped, onChange } = props;
|
||||||
|
const [open, setOpen] = React.useState(false);
|
||||||
|
|
||||||
|
const handleToggle = () => {
|
||||||
|
setOpen(!open);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSelectAll = () => {
|
||||||
|
if (grouped) {
|
||||||
|
const allCols: string[] = [];
|
||||||
|
columns.forEach((group) => {
|
||||||
|
group.children?.forEach((col) => {
|
||||||
|
if (col.dataIndex) {
|
||||||
|
allCols.push(col.dataIndex);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
onChange?.(allCols);
|
||||||
|
} else {
|
||||||
|
const allCols = columns
|
||||||
|
.map((col) => col.dataIndex)
|
||||||
|
.filter((dataIndex): dataIndex is string => Boolean(dataIndex));
|
||||||
|
onChange?.(allCols);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleConfirm = () => {
|
||||||
|
setOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const contentRender = () => {
|
||||||
|
return (
|
||||||
|
<Container>
|
||||||
|
{!grouped && <div className="title">Column Settings</div>}
|
||||||
|
<OverlayScroller
|
||||||
|
maxHeight={contentHeight}
|
||||||
|
styles={{
|
||||||
|
wrapper: {
|
||||||
|
paddingInlineStart: 0
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Checkbox.Group
|
||||||
|
value={selectedColumns}
|
||||||
|
onChange={(checkedValues) => {
|
||||||
|
onChange?.(checkedValues as string[]);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<>
|
||||||
|
{grouped ? (
|
||||||
|
columns.map((row, index) => (
|
||||||
|
<div key={index}>
|
||||||
|
<Title>{row.title}</Title>
|
||||||
|
<Row>
|
||||||
|
{row.children?.map((col) => (
|
||||||
|
<Col key={col.dataIndex} span={12}>
|
||||||
|
<Checkbox
|
||||||
|
value={col.dataIndex}
|
||||||
|
style={{ marginBottom: 8 }}
|
||||||
|
>
|
||||||
|
<span className="text-secondary">{col.title}</span>
|
||||||
|
</Checkbox>
|
||||||
|
</Col>
|
||||||
|
))}
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<Row>
|
||||||
|
{columns.map((col) => (
|
||||||
|
<Col key={col.dataIndex} span={12}>
|
||||||
|
<Checkbox
|
||||||
|
value={col.dataIndex}
|
||||||
|
style={{ marginBottom: 8 }}
|
||||||
|
>
|
||||||
|
<span className="text-secondary">{col.title}</span>
|
||||||
|
</Checkbox>
|
||||||
|
</Col>
|
||||||
|
))}
|
||||||
|
</Row>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
</Checkbox.Group>
|
||||||
|
</OverlayScroller>
|
||||||
|
|
||||||
|
<div className="btn-wrapper">
|
||||||
|
<Button
|
||||||
|
size="middle"
|
||||||
|
onClick={() => {
|
||||||
|
onChange?.([]);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Reset
|
||||||
|
</Button>
|
||||||
|
<div className="buttons">
|
||||||
|
<Button size="middle" type="primary" onClick={handleSelectAll}>
|
||||||
|
Select All
|
||||||
|
</Button>
|
||||||
|
<Button size="middle" type="primary" onClick={handleConfirm}>
|
||||||
|
Confirm
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Popover
|
||||||
|
trigger={'click'}
|
||||||
|
arrow={false}
|
||||||
|
placement="bottomRight"
|
||||||
|
content={contentRender()}
|
||||||
|
styles={{
|
||||||
|
root: {
|
||||||
|
width: '420px'
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Tooltip title="Column Settings">
|
||||||
|
<Button onClick={handleToggle} icon={<SettingOutlined />}></Button>
|
||||||
|
</Tooltip>
|
||||||
|
</Popover>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ColumnSettings;
|
||||||
@@ -62,7 +62,7 @@ const RightActions: React.FC<RightActionsProps> = ({
|
|||||||
icon={<SettingOutlined />}
|
icon={<SettingOutlined />}
|
||||||
></Button>
|
></Button>
|
||||||
</Tooltip> */}
|
</Tooltip> */}
|
||||||
{settingButton}
|
{/* {settingButton} */}
|
||||||
<Button
|
<Button
|
||||||
icon={<PlusOutlined></PlusOutlined>}
|
icon={<PlusOutlined></PlusOutlined>}
|
||||||
type="primary"
|
type="primary"
|
||||||
|
|||||||
@@ -140,17 +140,17 @@ const Summary: React.FC = () => {
|
|||||||
{
|
{
|
||||||
key: '3',
|
key: '3',
|
||||||
label: 'Total token throughput',
|
label: 'Total token throughput',
|
||||||
children: `${round(detailData.tokens_per_second_mean || 0, 2)} t/s`
|
children: `${round(detailData.tokens_per_second_mean || 0, 2)} Tokens/s`
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: '1',
|
key: '1',
|
||||||
label: 'Request token throughput',
|
label: 'Request token throughput',
|
||||||
children: `${round(detailData.prompt_tokens_per_second_mean || 0, 2)} t/s`
|
children: `${round(detailData.input_tokens_per_second_mean || 0, 2)} Tokens/s`
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: '2',
|
key: '2',
|
||||||
label: 'Output token throughput',
|
label: 'Output token throughput',
|
||||||
children: `${round(detailData.output_tokens_per_second_mean || 0, 2)} t/s`
|
children: `${round(detailData.output_tokens_per_second_mean || 0, 2)} Tokens/s`
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -19,10 +19,10 @@ const Benchmark: React.FC = () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: '3',
|
key: '3',
|
||||||
label: 'Token Length (Prompt/Output)',
|
label: 'Token Length (Input/Output)',
|
||||||
children: (
|
children: (
|
||||||
<span>
|
<span>
|
||||||
{detailData?.dataset_prompt_tokens || '-'} /{' '}
|
{detailData?.dataset_input_tokens || '-'} /{' '}
|
||||||
{detailData?.dataset_output_tokens || '-'}
|
{detailData?.dataset_output_tokens || '-'}
|
||||||
</span>
|
</span>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ const Container = styled.div`
|
|||||||
const Summary: React.FC = () => {
|
const Summary: React.FC = () => {
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<Section title="Results">
|
<Section title="Results" minHeight={450}>
|
||||||
<MetricsResult />
|
<MetricsResult />
|
||||||
<Divider />
|
<Divider />
|
||||||
<PercentileResult />
|
<PercentileResult />
|
||||||
|
|||||||
@@ -49,9 +49,9 @@ const columns = [
|
|||||||
render: (value: number) => round(value, 2)
|
render: (value: number) => round(value, 2)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Prompt token throughput ',
|
title: 'Input token throughput ',
|
||||||
dataIndex: 'prompt_tokens_per_second_mean',
|
dataIndex: 'input_tokens_per_second_mean',
|
||||||
path: 'prompt_tokens_per_second_mean',
|
path: 'input_tokens_per_second_mean',
|
||||||
unit: 'Tokens/s',
|
unit: 'Tokens/s',
|
||||||
render: (value: number) => round(value, 2)
|
render: (value: number) => round(value, 2)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -36,17 +36,17 @@ const columns = [
|
|||||||
render: (value: number) => round(value, 0)
|
render: (value: number) => round(value, 0)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Input (t/s)',
|
title: 'Input (Tokens/s)',
|
||||||
dataIndex: 'prompt_tokens_per_second',
|
dataIndex: 'prompt_tokens_per_second',
|
||||||
render: (value: number) => round(value, 2)
|
render: (value: number) => round(value, 2)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Output (t/s)',
|
title: 'Output (Tokens/s)',
|
||||||
dataIndex: 'output_tokens_per_second',
|
dataIndex: 'output_tokens_per_second',
|
||||||
render: (value: number) => round(value, 2)
|
render: (value: number) => round(value, 2)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Total (t/s)',
|
title: 'Total (Tokens/s)',
|
||||||
dataIndex: 'tokens_per_second',
|
dataIndex: 'tokens_per_second',
|
||||||
render: (value: number) => round(value, 2)
|
render: (value: number) => round(value, 2)
|
||||||
}
|
}
|
||||||
@@ -82,10 +82,10 @@ const PercentileResult: React.FC = () => {
|
|||||||
size="small"
|
size="small"
|
||||||
columns={[
|
columns={[
|
||||||
{
|
{
|
||||||
title: 'Percentile',
|
title: <span style={{ fontWeight: 500 }}>Percentile</span>,
|
||||||
dataIndex: 'percentile',
|
dataIndex: 'percentile',
|
||||||
render: (value: string) => (
|
render: (value: string) => (
|
||||||
<span style={{ fontWeight: 400 }}>{value}</span>
|
<span style={{ fontWeight: 500 }}>{value}</span>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
...columns
|
...columns
|
||||||
|
|||||||
@@ -80,14 +80,14 @@ export interface BenchmarkDetail {
|
|||||||
time_to_first_token_mean: number;
|
time_to_first_token_mean: number;
|
||||||
tokens_per_second_mean: number;
|
tokens_per_second_mean: number;
|
||||||
output_tokens_per_second_mean: number;
|
output_tokens_per_second_mean: number;
|
||||||
prompt_tokens_per_second_mean: number;
|
input_tokens_per_second_mean: number;
|
||||||
name: string;
|
name: string;
|
||||||
description: string;
|
description: string;
|
||||||
labels: Record<string, any>;
|
labels: Record<string, any>;
|
||||||
dataset_id: number;
|
dataset_id: number;
|
||||||
dataset_name: string;
|
dataset_name: string;
|
||||||
dataset_source: string;
|
dataset_source: string;
|
||||||
dataset_prompt_tokens: number;
|
dataset_input_tokens: number;
|
||||||
dataset_output_tokens: number;
|
dataset_output_tokens: number;
|
||||||
cluster_id: number;
|
cluster_id: number;
|
||||||
model_id: number;
|
model_id: number;
|
||||||
@@ -120,6 +120,6 @@ export interface BenchmarkMetricsFormData {
|
|||||||
time_to_first_token_mean: number;
|
time_to_first_token_mean: number;
|
||||||
tokens_per_second_mean: number;
|
tokens_per_second_mean: number;
|
||||||
output_tokens_per_second_mean: number;
|
output_tokens_per_second_mean: number;
|
||||||
prompt_tokens_per_second_mean: number;
|
input_tokens_per_second_mean: number;
|
||||||
raw_metrics: Record<string, any>;
|
raw_metrics: Record<string, any>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { StatusType } from '@/config/types';
|
|||||||
|
|
||||||
export const BenchmarkStatusValueMap = {
|
export const BenchmarkStatusValueMap = {
|
||||||
Pending: 'pending',
|
Pending: 'pending',
|
||||||
Claimed: 'claimed',
|
QUEUED: 'queued',
|
||||||
Running: 'running',
|
Running: 'running',
|
||||||
Completed: 'completed',
|
Completed: 'completed',
|
||||||
Error: 'error',
|
Error: 'error',
|
||||||
@@ -13,7 +13,7 @@ export const BenchmarkStatusValueMap = {
|
|||||||
|
|
||||||
export const BenchmarkStatusLabelMap = {
|
export const BenchmarkStatusLabelMap = {
|
||||||
[BenchmarkStatusValueMap.Pending]: 'Pending',
|
[BenchmarkStatusValueMap.Pending]: 'Pending',
|
||||||
[BenchmarkStatusValueMap.Claimed]: 'Claimed',
|
[BenchmarkStatusValueMap.QUEUED]: 'Queued',
|
||||||
[BenchmarkStatusValueMap.Running]: 'Running',
|
[BenchmarkStatusValueMap.Running]: 'Running',
|
||||||
[BenchmarkStatusValueMap.Completed]: 'Completed',
|
[BenchmarkStatusValueMap.Completed]: 'Completed',
|
||||||
[BenchmarkStatusValueMap.Error]: 'Error',
|
[BenchmarkStatusValueMap.Error]: 'Error',
|
||||||
@@ -23,7 +23,7 @@ export const BenchmarkStatusLabelMap = {
|
|||||||
|
|
||||||
export const BenchmarkStatus: Record<string, StatusType> = {
|
export const BenchmarkStatus: Record<string, StatusType> = {
|
||||||
[BenchmarkStatusValueMap.Pending]: StatusMaps.transitioning,
|
[BenchmarkStatusValueMap.Pending]: StatusMaps.transitioning,
|
||||||
[BenchmarkStatusValueMap.Claimed]: StatusMaps.warning,
|
[BenchmarkStatusValueMap.QUEUED]: StatusMaps.warning,
|
||||||
[BenchmarkStatusValueMap.Running]: StatusMaps.success,
|
[BenchmarkStatusValueMap.Running]: StatusMaps.success,
|
||||||
[BenchmarkStatusValueMap.Completed]: StatusMaps.success,
|
[BenchmarkStatusValueMap.Completed]: StatusMaps.success,
|
||||||
[BenchmarkStatusValueMap.Error]: StatusMaps.error,
|
[BenchmarkStatusValueMap.Error]: StatusMaps.error,
|
||||||
@@ -74,3 +74,21 @@ export const profileOptions = [
|
|||||||
locale: true
|
locale: true
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const DatasetValueMap = {
|
||||||
|
ShareGPT: 'ShareGPT',
|
||||||
|
Random: 'Random'
|
||||||
|
};
|
||||||
|
|
||||||
|
export const datasetList = [
|
||||||
|
{
|
||||||
|
name: 'ShareGPT',
|
||||||
|
label: 'ShareGPT',
|
||||||
|
value: DatasetValueMap.ShareGPT
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Random',
|
||||||
|
label: 'Random',
|
||||||
|
value: DatasetValueMap.Random
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ export interface FormData {
|
|||||||
dataset_id: number;
|
dataset_id: number;
|
||||||
dataset_name: string;
|
dataset_name: string;
|
||||||
dataset_source: string;
|
dataset_source: string;
|
||||||
dataset_prompt_tokens: number;
|
dataset_input_tokens: number;
|
||||||
dataset_output_tokens: number;
|
dataset_output_tokens: number;
|
||||||
total_requests: number;
|
total_requests: number;
|
||||||
request_rate: number;
|
request_rate: number;
|
||||||
@@ -109,7 +109,7 @@ export interface ProfileOption {
|
|||||||
description: string;
|
description: string;
|
||||||
dataset_name: string;
|
dataset_name: string;
|
||||||
dataset_source: string;
|
dataset_source: string;
|
||||||
dataset_prompt_tokens: number;
|
dataset_input_tokens: number;
|
||||||
dataset_output_tokens: number;
|
dataset_output_tokens: number;
|
||||||
request_rate: number;
|
request_rate: number;
|
||||||
total_requests: number;
|
total_requests: number;
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import SealInput from '@/components/seal-form/seal-input';
|
|
||||||
import SealSelect from '@/components/seal-form/seal-select';
|
import SealSelect from '@/components/seal-form/seal-select';
|
||||||
import { PageAction } from '@/config';
|
import { PageAction } from '@/config';
|
||||||
import useAppUtils from '@/hooks/use-app-utils';
|
import useAppUtils from '@/hooks/use-app-utils';
|
||||||
@@ -31,16 +30,6 @@ const DatasetForm: React.FC = () => {
|
|||||||
cancelRequest: cancelProfilesRequest
|
cancelRequest: cancelProfilesRequest
|
||||||
} = useQueryProfiles();
|
} = useQueryProfiles();
|
||||||
|
|
||||||
const handleOnDataSetChange = (value: any, option: any) => {
|
|
||||||
form.setFieldsValue({
|
|
||||||
dataset_id: option?.data?.id,
|
|
||||||
dataset_prompt_tokens: option?.prompt_tokens,
|
|
||||||
dataset_output_tokens: option?.output_tokens,
|
|
||||||
request_rate: null,
|
|
||||||
total_requests: null
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleProfileChange = (value: string, option: any) => {
|
const handleProfileChange = (value: string, option: any) => {
|
||||||
if (value !== ProfileValueMap.Custom) {
|
if (value !== ProfileValueMap.Custom) {
|
||||||
const dataset_id = datasetList.find(
|
const dataset_id = datasetList.find(
|
||||||
@@ -86,13 +75,9 @@ const DatasetForm: React.FC = () => {
|
|||||||
></SealSelect>
|
></SealSelect>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item<FormData> hidden name="dataset_id">
|
|
||||||
<SealInput.Input></SealInput.Input>
|
|
||||||
</Form.Item>
|
|
||||||
<RandomSettingsForm
|
<RandomSettingsForm
|
||||||
datasetList={datasetList}
|
datasetList={datasetList}
|
||||||
datasetLoading={datasetLoading}
|
datasetLoading={datasetLoading}
|
||||||
handleOnDataSetChange={handleOnDataSetChange}
|
|
||||||
></RandomSettingsForm>
|
></RandomSettingsForm>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -93,19 +93,6 @@ const ProviderForm: React.FC<ProviderFormProps> = forwardRef((props, ref) => {
|
|||||||
}
|
}
|
||||||
}, [showAdvanced, activeKey]);
|
}, [showAdvanced, activeKey]);
|
||||||
|
|
||||||
// const advancedItems = showAdvanced
|
|
||||||
// ? [
|
|
||||||
// {
|
|
||||||
// key: TABKeysMap.ADVANCED,
|
|
||||||
// label: intl.formatMessage({ id: 'resources.form.advanced' }),
|
|
||||||
// forceRender: true,
|
|
||||||
// children: <RandomSettingsForm />
|
|
||||||
// }
|
|
||||||
// ]
|
|
||||||
// : [];
|
|
||||||
|
|
||||||
console.log('render form with profile:', showAdvanced);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ScrollSpyTabs
|
<ScrollSpyTabs
|
||||||
ref={scrollTabsRef}
|
ref={scrollTabsRef}
|
||||||
@@ -129,7 +116,7 @@ const ProviderForm: React.FC<ProviderFormProps> = forwardRef((props, ref) => {
|
|||||||
form={form}
|
form={form}
|
||||||
onFinish={onFinish}
|
onFinish={onFinish}
|
||||||
initialValues={{
|
initialValues={{
|
||||||
dataset_prompt_tokens: null,
|
dataset_input_tokens: null,
|
||||||
dataset_output_tokens: null,
|
dataset_output_tokens: null,
|
||||||
total_requests: null,
|
total_requests: null,
|
||||||
request_rate: null,
|
request_rate: null,
|
||||||
|
|||||||
@@ -101,6 +101,10 @@ const ModelInstanceForm: React.FC = () => {
|
|||||||
children: []
|
children: []
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
if (modelOptions.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// preload instances for the first model
|
// preload instances for the first model
|
||||||
const instanceList = await fetchInstanceList({ id: modelOptions[0]?.id });
|
const instanceList = await fetchInstanceList({ id: modelOptions[0]?.id });
|
||||||
const instanceOptions = instanceList.map((instance: any) =>
|
const instanceOptions = instanceList.map((instance: any) =>
|
||||||
|
|||||||
@@ -11,9 +11,8 @@ import { FormData } from '../config/types';
|
|||||||
const RandomSettingsForm: React.FC<{
|
const RandomSettingsForm: React.FC<{
|
||||||
datasetList: Global.BaseOption<number | string>[];
|
datasetList: Global.BaseOption<number | string>[];
|
||||||
datasetLoading: boolean;
|
datasetLoading: boolean;
|
||||||
handleOnDataSetChange: (value: any, option: any) => void;
|
|
||||||
}> = (props) => {
|
}> = (props) => {
|
||||||
const { datasetList, datasetLoading, handleOnDataSetChange } = props;
|
const { datasetList, datasetLoading } = props;
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const { action, open } = useFormContext();
|
const { action, open } = useFormContext();
|
||||||
const form = Form.useFormInstance();
|
const form = Form.useFormInstance();
|
||||||
@@ -45,13 +44,12 @@ const RandomSettingsForm: React.FC<{
|
|||||||
value: item.label
|
value: item.label
|
||||||
}))}
|
}))}
|
||||||
loading={datasetLoading}
|
loading={datasetLoading}
|
||||||
onChange={handleOnDataSetChange}
|
|
||||||
label={intl.formatMessage({ id: 'benchmark.table.dataset' })}
|
label={intl.formatMessage({ id: 'benchmark.table.dataset' })}
|
||||||
required
|
required
|
||||||
></SealSelect>
|
></SealSelect>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item<FormData>
|
<Form.Item<FormData>
|
||||||
name="dataset_prompt_tokens"
|
name="dataset_input_tokens"
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
@@ -99,6 +97,7 @@ const RandomSettingsForm: React.FC<{
|
|||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item<FormData>
|
<Form.Item<FormData>
|
||||||
name="request_rate"
|
name="request_rate"
|
||||||
|
getValueProps={(value) => ({ value: value < 0 ? 'Infinity' : value })}
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
@@ -107,7 +106,6 @@ const RandomSettingsForm: React.FC<{
|
|||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<SealInputNumber
|
<SealInputNumber
|
||||||
min={0}
|
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
label={intl.formatMessage({ id: 'benchmark.table.requestRate' })}
|
label={intl.formatMessage({ id: 'benchmark.table.requestRate' })}
|
||||||
required
|
required
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ const useBenchmarkColumns = (
|
|||||||
title: (
|
title: (
|
||||||
<span className="flex-column">
|
<span className="flex-column">
|
||||||
<span>{intl.formatMessage({ id: 'benchmark.table.itl' })}</span>
|
<span>{intl.formatMessage({ id: 'benchmark.table.itl' })}</span>
|
||||||
<span>avg (ms)</span>
|
<span>Avg (ms)</span>
|
||||||
</span>
|
</span>
|
||||||
),
|
),
|
||||||
dataIndex: 'inter_token_latency_mean',
|
dataIndex: 'inter_token_latency_mean',
|
||||||
@@ -117,7 +117,7 @@ const useBenchmarkColumns = (
|
|||||||
title: (
|
title: (
|
||||||
<span className="flex-column">
|
<span className="flex-column">
|
||||||
<span>{intl.formatMessage({ id: 'benchmark.table.tpot' })}</span>
|
<span>{intl.formatMessage({ id: 'benchmark.table.tpot' })}</span>
|
||||||
<span>avg (ms)</span>
|
<span>Avg (ms)</span>
|
||||||
</span>
|
</span>
|
||||||
),
|
),
|
||||||
dataIndex: 'time_per_output_token_mean',
|
dataIndex: 'time_per_output_token_mean',
|
||||||
@@ -132,7 +132,7 @@ const useBenchmarkColumns = (
|
|||||||
title: (
|
title: (
|
||||||
<span className="flex-column">
|
<span className="flex-column">
|
||||||
<span>{intl.formatMessage({ id: 'benchmark.table.ttft' })}</span>
|
<span>{intl.formatMessage({ id: 'benchmark.table.ttft' })}</span>
|
||||||
<span>avg (ms)</span>
|
<span>Avg (ms)</span>
|
||||||
</span>
|
</span>
|
||||||
),
|
),
|
||||||
dataIndex: 'time_to_first_token_mean',
|
dataIndex: 'time_to_first_token_mean',
|
||||||
|
|||||||
@@ -1,43 +1,57 @@
|
|||||||
import { SettingOutlined } from '@ant-design/icons';
|
import ColumnSettings from '@/pages/_components/column-settings';
|
||||||
import { useIntl } from '@umijs/max';
|
import { useIntl } from '@umijs/max';
|
||||||
import { Button, Checkbox, Col, Popover, Row, Tooltip } from 'antd';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import styled from 'styled-components';
|
|
||||||
|
|
||||||
const Container = styled.div`
|
const useColumnSettings = (options: { contentHeight: number }) => {
|
||||||
max-height: 450px;
|
|
||||||
overflow-y: auto;
|
|
||||||
padding: 12px;
|
|
||||||
.title {
|
|
||||||
font-weight: 500;
|
|
||||||
margin-bottom: 12px;
|
|
||||||
}
|
|
||||||
.btn-wrapper {
|
|
||||||
margin-top: 12px;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
border-top: 1px solid var(--ant-color-split);
|
|
||||||
padding-top: 12px;
|
|
||||||
}
|
|
||||||
.buttons {
|
|
||||||
display: flex;
|
|
||||||
gap: 8px;
|
|
||||||
justify-content: flex-end;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const useColumnSettings = () => {
|
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
const { contentHeight } = options;
|
||||||
const [open, setOpen] = React.useState(false);
|
|
||||||
const [selectedColumns, setSelectedColumns] = React.useState<string[]>([]);
|
const [selectedColumns, setSelectedColumns] = React.useState<string[]>([]);
|
||||||
|
|
||||||
const handleToggle = () => {
|
const handleOnChange = (columns: string[]) => {
|
||||||
setOpen(!open);
|
setSelectedColumns(columns);
|
||||||
|
console.log('selected columns:', columns);
|
||||||
};
|
};
|
||||||
|
|
||||||
const allColumns = [
|
const resultColumns = [
|
||||||
|
{
|
||||||
|
title: intl.formatMessage({ id: 'benchmark.table.rps' }),
|
||||||
|
dataIndex: 'requests_per_second_mean'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Throughput',
|
||||||
|
dataIndex: 'throughput_mean'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Throughput request',
|
||||||
|
dataIndex: 'throughput_request_mean'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Generated Tokens',
|
||||||
|
dataIndex: 'generated_tokens_mean'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: intl.formatMessage({ id: 'benchmark.table.tps' }),
|
||||||
|
dataIndex: 'tokens_per_second_mean'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: intl.formatMessage({ id: 'benchmark.table.itl' }),
|
||||||
|
dataIndex: 'inter_token_latency_mean'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: intl.formatMessage({ id: 'benchmark.table.tpot' }),
|
||||||
|
dataIndex: 'time_per_output_token_mean'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: intl.formatMessage({ id: 'benchmark.table.ttft' }),
|
||||||
|
dataIndex: 'time_to_first_token_mean'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Latency Avg',
|
||||||
|
dataIndex: 'latency_mean'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const metadataColumns = [
|
||||||
{
|
{
|
||||||
title: intl.formatMessage({ id: 'clusters.title' }),
|
title: intl.formatMessage({ id: 'clusters.title' }),
|
||||||
dataIndex: 'cluster_id'
|
dataIndex: 'cluster_id'
|
||||||
@@ -58,26 +72,6 @@ const useColumnSettings = () => {
|
|||||||
title: intl.formatMessage({ id: 'benchmark.table.dataset' }),
|
title: intl.formatMessage({ id: 'benchmark.table.dataset' }),
|
||||||
dataIndex: 'dataset_name'
|
dataIndex: 'dataset_name'
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: 'Latency',
|
|
||||||
dataIndex: 'latency_mean'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Throughput',
|
|
||||||
dataIndex: 'throughput_mean'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Throughput request',
|
|
||||||
dataIndex: 'throughput_request_mean'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'generated tokens',
|
|
||||||
dataIndex: 'generated_tokens_mean'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'ITL Avg',
|
|
||||||
dataIndex: 'inter_token_latency_mean'
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: intl.formatMessage({ id: 'common.table.status' }),
|
title: intl.formatMessage({ id: 'common.table.status' }),
|
||||||
dataIndex: 'state'
|
dataIndex: 'state'
|
||||||
@@ -90,26 +84,6 @@ const useColumnSettings = () => {
|
|||||||
title: intl.formatMessage({ id: 'benchmark.table.gpu' }),
|
title: intl.formatMessage({ id: 'benchmark.table.gpu' }),
|
||||||
dataIndex: 'gpu_summary'
|
dataIndex: 'gpu_summary'
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: intl.formatMessage({ id: 'benchmark.table.itl' }),
|
|
||||||
dataIndex: 'inter_token_latency_mean'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: intl.formatMessage({ id: 'benchmark.table.tpot' }),
|
|
||||||
dataIndex: 'time_per_output_token_mean'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: intl.formatMessage({ id: 'benchmark.table.ttft' }),
|
|
||||||
dataIndex: 'time_to_first_token_mean'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: intl.formatMessage({ id: 'benchmark.table.rps' }),
|
|
||||||
dataIndex: 'requests_per_second_mean'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: intl.formatMessage({ id: 'benchmark.table.tps' }),
|
|
||||||
dataIndex: 'tokens_per_second_mean'
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: intl.formatMessage({ id: 'common.table.createTime' }),
|
title: intl.formatMessage({ id: 'common.table.createTime' }),
|
||||||
dataIndex: 'created_at'
|
dataIndex: 'created_at'
|
||||||
@@ -120,76 +94,23 @@ const useColumnSettings = () => {
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
const contentRender = () => {
|
|
||||||
return (
|
|
||||||
<Container>
|
|
||||||
<div className="title">Column Settings</div>
|
|
||||||
<Checkbox.Group
|
|
||||||
value={selectedColumns}
|
|
||||||
onChange={(checkedValues) => {
|
|
||||||
setSelectedColumns(checkedValues as string[]);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Row>
|
|
||||||
{allColumns.map((col) => (
|
|
||||||
<Col key={col.dataIndex} span={12}>
|
|
||||||
<Checkbox value={col.dataIndex} style={{ marginBottom: 8 }}>
|
|
||||||
<span className="text-secondary">{col.title}</span>
|
|
||||||
</Checkbox>
|
|
||||||
</Col>
|
|
||||||
))}
|
|
||||||
</Row>
|
|
||||||
</Checkbox.Group>
|
|
||||||
<div className="btn-wrapper">
|
|
||||||
<Button
|
|
||||||
size="middle"
|
|
||||||
onClick={() => {
|
|
||||||
setSelectedColumns([]);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Clear All
|
|
||||||
</Button>
|
|
||||||
<div className="buttons">
|
|
||||||
<Button
|
|
||||||
size="middle"
|
|
||||||
type="primary"
|
|
||||||
onClick={() => {
|
|
||||||
setSelectedColumns(allColumns.map((col) => col.dataIndex));
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Select All
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
size="middle"
|
|
||||||
type="primary"
|
|
||||||
onClick={() => {
|
|
||||||
setSelectedColumns(allColumns.map((col) => col.dataIndex));
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Confirm
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Container>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const SettingsButton = (
|
const SettingsButton = (
|
||||||
<Popover
|
<ColumnSettings
|
||||||
trigger={'click'}
|
contentHeight={contentHeight}
|
||||||
arrow={false}
|
selectedColumns={selectedColumns}
|
||||||
placement="bottomRight"
|
onChange={handleOnChange}
|
||||||
content={contentRender()}
|
grouped={true}
|
||||||
styles={{
|
columns={[
|
||||||
root: {
|
{
|
||||||
width: '420px'
|
title: 'Benchmark Results',
|
||||||
|
children: resultColumns
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Metadata',
|
||||||
|
children: metadataColumns
|
||||||
}
|
}
|
||||||
}}
|
]}
|
||||||
>
|
></ColumnSettings>
|
||||||
<Tooltip title="Column Settings">
|
|
||||||
<Button onClick={handleToggle} icon={<SettingOutlined />}></Button>
|
|
||||||
</Tooltip>
|
|
||||||
</Popover>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -63,7 +63,9 @@ const Benchmark: React.FC = () => {
|
|||||||
});
|
});
|
||||||
const { openViewLogsModal, closeViewLogsModal, openViewLogsModalStatus } =
|
const { openViewLogsModal, closeViewLogsModal, openViewLogsModalStatus } =
|
||||||
useViewLogs();
|
useViewLogs();
|
||||||
const { SettingsButton, selectedColumns } = useColumnSettings();
|
const { SettingsButton, selectedColumns } = useColumnSettings({
|
||||||
|
contentHeight: 320
|
||||||
|
});
|
||||||
const { handleStopBenchmark } = useStopBenchmark();
|
const { handleStopBenchmark } = useStopBenchmark();
|
||||||
|
|
||||||
const { datasetList, fetchDatasetData } = useQueryDataset();
|
const { datasetList, fetchDatasetData } = useQueryDataset();
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useQueryDataList } from '@/hooks/use-query-data-list';
|
import { useQueryDataList } from '@/hooks/use-query-data-list';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { queryDatasetList } from '../apis';
|
import { queryDatasetList } from '../apis';
|
||||||
|
import { datasetList as datasetOptions } from '../config';
|
||||||
import { DatasetListItem } from '../config/types';
|
import { DatasetListItem } from '../config/types';
|
||||||
|
|
||||||
const useQueryDataset = () => {
|
const useQueryDataset = () => {
|
||||||
@@ -17,17 +18,9 @@ const useQueryDataset = () => {
|
|||||||
>([]);
|
>([]);
|
||||||
|
|
||||||
const fetchDatasetData = async () => {
|
const fetchDatasetData = async () => {
|
||||||
const items = await fetchData({
|
// TODO: may be fetch data from server in the future.
|
||||||
page: -1
|
|
||||||
});
|
|
||||||
const list =
|
|
||||||
items?.map((item) => ({
|
|
||||||
...item,
|
|
||||||
label: item.name,
|
|
||||||
value: item.id
|
|
||||||
})) || [];
|
|
||||||
|
|
||||||
setDatasetList([...list]);
|
setDatasetList([...datasetOptions]);
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ export default function useQueryProfiles() {
|
|||||||
value: 'Custom',
|
value: 'Custom',
|
||||||
config: {
|
config: {
|
||||||
dataset_name: '',
|
dataset_name: '',
|
||||||
dataset_prompt_tokens: null,
|
dataset_input_tokens: null,
|
||||||
dataset_output_tokens: null,
|
dataset_output_tokens: null,
|
||||||
request_rate: null,
|
request_rate: null,
|
||||||
total_requests: null
|
total_requests: null
|
||||||
|
|||||||
Reference in New Issue
Block a user