fix: benchmark detail styles
This commit is contained in:
@@ -19,10 +19,21 @@ export const OverlayScroller: React.FC<
|
||||
OverlayScrollerOptions & {
|
||||
maxHeight?: number;
|
||||
style?: React.CSSProperties;
|
||||
styles?: {
|
||||
wrapper?: React.CSSProperties;
|
||||
};
|
||||
children: React.ReactNode;
|
||||
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 { initialize } = useOverlayScroller({
|
||||
options: {
|
||||
@@ -48,7 +59,8 @@ export const OverlayScroller: React.FC<
|
||||
style={{
|
||||
paddingInlineStart: 8,
|
||||
paddingInlineEnd: 8,
|
||||
...style
|
||||
...style,
|
||||
...styles?.wrapper
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
||||
@@ -21,7 +21,7 @@ export default {
|
||||
'benchmark.form.profile.longContext': 'Long Context',
|
||||
'benchmark.form.profile.heavy': 'Generation Heavy',
|
||||
'benchmark.form.profile.custom': 'Custom',
|
||||
'benchmark.table.inputTokenLength': 'Prompt Token Length',
|
||||
'benchmark.table.inputTokenLength': 'Input Token Length',
|
||||
'benchmark.table.outputTokenLength': 'Output Token Length',
|
||||
'benchmark.detail.summary.title': 'Summary',
|
||||
'benchmark.detail.configure.title': 'Configure',
|
||||
|
||||
@@ -21,7 +21,7 @@ export default {
|
||||
'benchmark.form.profile.longContext': 'Long Context',
|
||||
'benchmark.form.profile.heavy': 'Generation Heavy',
|
||||
'benchmark.form.profile.custom': 'Custom',
|
||||
'benchmark.table.inputTokenLength': 'Prompt Token Length',
|
||||
'benchmark.table.inputTokenLength': 'Input Token Length',
|
||||
'benchmark.table.outputTokenLength': 'Output Token Length',
|
||||
'benchmark.detail.summary.title': 'Summary',
|
||||
'benchmark.detail.configure.title': 'Configure',
|
||||
|
||||
@@ -21,7 +21,7 @@ export default {
|
||||
'benchmark.form.profile.longContext': 'Long Context',
|
||||
'benchmark.form.profile.heavy': 'Generation Heavy',
|
||||
'benchmark.form.profile.custom': 'Custom',
|
||||
'benchmark.table.inputTokenLength': 'Prompt Token Length',
|
||||
'benchmark.table.inputTokenLength': 'Input Token Length',
|
||||
'benchmark.table.outputTokenLength': 'Output Token Length',
|
||||
'benchmark.detail.summary.title': 'Summary',
|
||||
'benchmark.detail.configure.title': 'Configure',
|
||||
|
||||
@@ -21,7 +21,7 @@ export default {
|
||||
'benchmark.form.profile.longContext': '长上下文',
|
||||
'benchmark.form.profile.heavy': '高生成量',
|
||||
'benchmark.form.profile.custom': '自定义',
|
||||
'benchmark.table.inputTokenLength': '提示词 Token 长度',
|
||||
'benchmark.table.inputTokenLength': '输入 Token 长度',
|
||||
'benchmark.table.outputTokenLength': '输出 Token 长度',
|
||||
'benchmark.detail.summary.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 />}
|
||||
></Button>
|
||||
</Tooltip> */}
|
||||
{settingButton}
|
||||
{/* {settingButton} */}
|
||||
<Button
|
||||
icon={<PlusOutlined></PlusOutlined>}
|
||||
type="primary"
|
||||
|
||||
@@ -140,17 +140,17 @@ const Summary: React.FC = () => {
|
||||
{
|
||||
key: '3',
|
||||
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',
|
||||
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',
|
||||
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',
|
||||
label: 'Token Length (Prompt/Output)',
|
||||
label: 'Token Length (Input/Output)',
|
||||
children: (
|
||||
<span>
|
||||
{detailData?.dataset_prompt_tokens || '-'} /{' '}
|
||||
{detailData?.dataset_input_tokens || '-'} /{' '}
|
||||
{detailData?.dataset_output_tokens || '-'}
|
||||
</span>
|
||||
)
|
||||
|
||||
@@ -16,7 +16,7 @@ const Container = styled.div`
|
||||
const Summary: React.FC = () => {
|
||||
return (
|
||||
<Container>
|
||||
<Section title="Results">
|
||||
<Section title="Results" minHeight={450}>
|
||||
<MetricsResult />
|
||||
<Divider />
|
||||
<PercentileResult />
|
||||
|
||||
@@ -49,9 +49,9 @@ const columns = [
|
||||
render: (value: number) => round(value, 2)
|
||||
},
|
||||
{
|
||||
title: 'Prompt token throughput ',
|
||||
dataIndex: 'prompt_tokens_per_second_mean',
|
||||
path: 'prompt_tokens_per_second_mean',
|
||||
title: 'Input token throughput ',
|
||||
dataIndex: 'input_tokens_per_second_mean',
|
||||
path: 'input_tokens_per_second_mean',
|
||||
unit: 'Tokens/s',
|
||||
render: (value: number) => round(value, 2)
|
||||
},
|
||||
|
||||
@@ -36,17 +36,17 @@ const columns = [
|
||||
render: (value: number) => round(value, 0)
|
||||
},
|
||||
{
|
||||
title: 'Input (t/s)',
|
||||
title: 'Input (Tokens/s)',
|
||||
dataIndex: 'prompt_tokens_per_second',
|
||||
render: (value: number) => round(value, 2)
|
||||
},
|
||||
{
|
||||
title: 'Output (t/s)',
|
||||
title: 'Output (Tokens/s)',
|
||||
dataIndex: 'output_tokens_per_second',
|
||||
render: (value: number) => round(value, 2)
|
||||
},
|
||||
{
|
||||
title: 'Total (t/s)',
|
||||
title: 'Total (Tokens/s)',
|
||||
dataIndex: 'tokens_per_second',
|
||||
render: (value: number) => round(value, 2)
|
||||
}
|
||||
@@ -82,10 +82,10 @@ const PercentileResult: React.FC = () => {
|
||||
size="small"
|
||||
columns={[
|
||||
{
|
||||
title: 'Percentile',
|
||||
title: <span style={{ fontWeight: 500 }}>Percentile</span>,
|
||||
dataIndex: 'percentile',
|
||||
render: (value: string) => (
|
||||
<span style={{ fontWeight: 400 }}>{value}</span>
|
||||
<span style={{ fontWeight: 500 }}>{value}</span>
|
||||
)
|
||||
},
|
||||
...columns
|
||||
|
||||
@@ -80,14 +80,14 @@ export interface BenchmarkDetail {
|
||||
time_to_first_token_mean: number;
|
||||
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;
|
||||
description: string;
|
||||
labels: Record<string, any>;
|
||||
dataset_id: number;
|
||||
dataset_name: string;
|
||||
dataset_source: string;
|
||||
dataset_prompt_tokens: number;
|
||||
dataset_input_tokens: number;
|
||||
dataset_output_tokens: number;
|
||||
cluster_id: number;
|
||||
model_id: number;
|
||||
@@ -120,6 +120,6 @@ export interface BenchmarkMetricsFormData {
|
||||
time_to_first_token_mean: number;
|
||||
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>;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { StatusType } from '@/config/types';
|
||||
|
||||
export const BenchmarkStatusValueMap = {
|
||||
Pending: 'pending',
|
||||
Claimed: 'claimed',
|
||||
QUEUED: 'queued',
|
||||
Running: 'running',
|
||||
Completed: 'completed',
|
||||
Error: 'error',
|
||||
@@ -13,7 +13,7 @@ export const BenchmarkStatusValueMap = {
|
||||
|
||||
export const BenchmarkStatusLabelMap = {
|
||||
[BenchmarkStatusValueMap.Pending]: 'Pending',
|
||||
[BenchmarkStatusValueMap.Claimed]: 'Claimed',
|
||||
[BenchmarkStatusValueMap.QUEUED]: 'Queued',
|
||||
[BenchmarkStatusValueMap.Running]: 'Running',
|
||||
[BenchmarkStatusValueMap.Completed]: 'Completed',
|
||||
[BenchmarkStatusValueMap.Error]: 'Error',
|
||||
@@ -23,7 +23,7 @@ export const BenchmarkStatusLabelMap = {
|
||||
|
||||
export const BenchmarkStatus: Record<string, StatusType> = {
|
||||
[BenchmarkStatusValueMap.Pending]: StatusMaps.transitioning,
|
||||
[BenchmarkStatusValueMap.Claimed]: StatusMaps.warning,
|
||||
[BenchmarkStatusValueMap.QUEUED]: StatusMaps.warning,
|
||||
[BenchmarkStatusValueMap.Running]: StatusMaps.success,
|
||||
[BenchmarkStatusValueMap.Completed]: StatusMaps.success,
|
||||
[BenchmarkStatusValueMap.Error]: StatusMaps.error,
|
||||
@@ -74,3 +74,21 @@ export const profileOptions = [
|
||||
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_name: string;
|
||||
dataset_source: string;
|
||||
dataset_prompt_tokens: number;
|
||||
dataset_input_tokens: number;
|
||||
dataset_output_tokens: number;
|
||||
total_requests: number;
|
||||
request_rate: number;
|
||||
@@ -109,7 +109,7 @@ export interface ProfileOption {
|
||||
description: string;
|
||||
dataset_name: string;
|
||||
dataset_source: string;
|
||||
dataset_prompt_tokens: number;
|
||||
dataset_input_tokens: number;
|
||||
dataset_output_tokens: number;
|
||||
request_rate: 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 { PageAction } from '@/config';
|
||||
import useAppUtils from '@/hooks/use-app-utils';
|
||||
@@ -31,16 +30,6 @@ const DatasetForm: React.FC = () => {
|
||||
cancelRequest: cancelProfilesRequest
|
||||
} = 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) => {
|
||||
if (value !== ProfileValueMap.Custom) {
|
||||
const dataset_id = datasetList.find(
|
||||
@@ -86,13 +75,9 @@ const DatasetForm: React.FC = () => {
|
||||
></SealSelect>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item<FormData> hidden name="dataset_id">
|
||||
<SealInput.Input></SealInput.Input>
|
||||
</Form.Item>
|
||||
<RandomSettingsForm
|
||||
datasetList={datasetList}
|
||||
datasetLoading={datasetLoading}
|
||||
handleOnDataSetChange={handleOnDataSetChange}
|
||||
></RandomSettingsForm>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -93,19 +93,6 @@ const ProviderForm: React.FC<ProviderFormProps> = forwardRef((props, ref) => {
|
||||
}
|
||||
}, [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 (
|
||||
<ScrollSpyTabs
|
||||
ref={scrollTabsRef}
|
||||
@@ -129,7 +116,7 @@ const ProviderForm: React.FC<ProviderFormProps> = forwardRef((props, ref) => {
|
||||
form={form}
|
||||
onFinish={onFinish}
|
||||
initialValues={{
|
||||
dataset_prompt_tokens: null,
|
||||
dataset_input_tokens: null,
|
||||
dataset_output_tokens: null,
|
||||
total_requests: null,
|
||||
request_rate: null,
|
||||
|
||||
@@ -101,6 +101,10 @@ const ModelInstanceForm: React.FC = () => {
|
||||
children: []
|
||||
}));
|
||||
|
||||
if (modelOptions.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// preload instances for the first model
|
||||
const instanceList = await fetchInstanceList({ id: modelOptions[0]?.id });
|
||||
const instanceOptions = instanceList.map((instance: any) =>
|
||||
|
||||
@@ -11,9 +11,8 @@ import { FormData } from '../config/types';
|
||||
const RandomSettingsForm: React.FC<{
|
||||
datasetList: Global.BaseOption<number | string>[];
|
||||
datasetLoading: boolean;
|
||||
handleOnDataSetChange: (value: any, option: any) => void;
|
||||
}> = (props) => {
|
||||
const { datasetList, datasetLoading, handleOnDataSetChange } = props;
|
||||
const { datasetList, datasetLoading } = props;
|
||||
const intl = useIntl();
|
||||
const { action, open } = useFormContext();
|
||||
const form = Form.useFormInstance();
|
||||
@@ -45,13 +44,12 @@ const RandomSettingsForm: React.FC<{
|
||||
value: item.label
|
||||
}))}
|
||||
loading={datasetLoading}
|
||||
onChange={handleOnDataSetChange}
|
||||
label={intl.formatMessage({ id: 'benchmark.table.dataset' })}
|
||||
required
|
||||
></SealSelect>
|
||||
</Form.Item>
|
||||
<Form.Item<FormData>
|
||||
name="dataset_prompt_tokens"
|
||||
name="dataset_input_tokens"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
@@ -99,6 +97,7 @@ const RandomSettingsForm: React.FC<{
|
||||
</Form.Item>
|
||||
<Form.Item<FormData>
|
||||
name="request_rate"
|
||||
getValueProps={(value) => ({ value: value < 0 ? 'Infinity' : value })}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
@@ -107,7 +106,6 @@ const RandomSettingsForm: React.FC<{
|
||||
]}
|
||||
>
|
||||
<SealInputNumber
|
||||
min={0}
|
||||
disabled={disabled}
|
||||
label={intl.formatMessage({ id: 'benchmark.table.requestRate' })}
|
||||
required
|
||||
|
||||
@@ -102,7 +102,7 @@ const useBenchmarkColumns = (
|
||||
title: (
|
||||
<span className="flex-column">
|
||||
<span>{intl.formatMessage({ id: 'benchmark.table.itl' })}</span>
|
||||
<span>avg (ms)</span>
|
||||
<span>Avg (ms)</span>
|
||||
</span>
|
||||
),
|
||||
dataIndex: 'inter_token_latency_mean',
|
||||
@@ -117,7 +117,7 @@ const useBenchmarkColumns = (
|
||||
title: (
|
||||
<span className="flex-column">
|
||||
<span>{intl.formatMessage({ id: 'benchmark.table.tpot' })}</span>
|
||||
<span>avg (ms)</span>
|
||||
<span>Avg (ms)</span>
|
||||
</span>
|
||||
),
|
||||
dataIndex: 'time_per_output_token_mean',
|
||||
@@ -132,7 +132,7 @@ const useBenchmarkColumns = (
|
||||
title: (
|
||||
<span className="flex-column">
|
||||
<span>{intl.formatMessage({ id: 'benchmark.table.ttft' })}</span>
|
||||
<span>avg (ms)</span>
|
||||
<span>Avg (ms)</span>
|
||||
</span>
|
||||
),
|
||||
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 { Button, Checkbox, Col, Popover, Row, Tooltip } from 'antd';
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
const Container = styled.div`
|
||||
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 useColumnSettings = (options: { contentHeight: number }) => {
|
||||
const intl = useIntl();
|
||||
|
||||
const [open, setOpen] = React.useState(false);
|
||||
const { contentHeight } = options;
|
||||
const [selectedColumns, setSelectedColumns] = React.useState<string[]>([]);
|
||||
|
||||
const handleToggle = () => {
|
||||
setOpen(!open);
|
||||
const handleOnChange = (columns: string[]) => {
|
||||
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' }),
|
||||
dataIndex: 'cluster_id'
|
||||
@@ -58,26 +72,6 @@ const useColumnSettings = () => {
|
||||
title: intl.formatMessage({ id: 'benchmark.table.dataset' }),
|
||||
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' }),
|
||||
dataIndex: 'state'
|
||||
@@ -90,26 +84,6 @@ const useColumnSettings = () => {
|
||||
title: intl.formatMessage({ id: 'benchmark.table.gpu' }),
|
||||
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' }),
|
||||
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 = (
|
||||
<Popover
|
||||
trigger={'click'}
|
||||
arrow={false}
|
||||
placement="bottomRight"
|
||||
content={contentRender()}
|
||||
styles={{
|
||||
root: {
|
||||
width: '420px'
|
||||
<ColumnSettings
|
||||
contentHeight={contentHeight}
|
||||
selectedColumns={selectedColumns}
|
||||
onChange={handleOnChange}
|
||||
grouped={true}
|
||||
columns={[
|
||||
{
|
||||
title: 'Benchmark Results',
|
||||
children: resultColumns
|
||||
},
|
||||
{
|
||||
title: 'Metadata',
|
||||
children: metadataColumns
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Tooltip title="Column Settings">
|
||||
<Button onClick={handleToggle} icon={<SettingOutlined />}></Button>
|
||||
</Tooltip>
|
||||
</Popover>
|
||||
]}
|
||||
></ColumnSettings>
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
@@ -63,7 +63,9 @@ const Benchmark: React.FC = () => {
|
||||
});
|
||||
const { openViewLogsModal, closeViewLogsModal, openViewLogsModalStatus } =
|
||||
useViewLogs();
|
||||
const { SettingsButton, selectedColumns } = useColumnSettings();
|
||||
const { SettingsButton, selectedColumns } = useColumnSettings({
|
||||
contentHeight: 320
|
||||
});
|
||||
const { handleStopBenchmark } = useStopBenchmark();
|
||||
|
||||
const { datasetList, fetchDatasetData } = useQueryDataset();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useQueryDataList } from '@/hooks/use-query-data-list';
|
||||
import { useState } from 'react';
|
||||
import { queryDatasetList } from '../apis';
|
||||
import { datasetList as datasetOptions } from '../config';
|
||||
import { DatasetListItem } from '../config/types';
|
||||
|
||||
const useQueryDataset = () => {
|
||||
@@ -17,17 +18,9 @@ const useQueryDataset = () => {
|
||||
>([]);
|
||||
|
||||
const fetchDatasetData = async () => {
|
||||
const items = await fetchData({
|
||||
page: -1
|
||||
});
|
||||
const list =
|
||||
items?.map((item) => ({
|
||||
...item,
|
||||
label: item.name,
|
||||
value: item.id
|
||||
})) || [];
|
||||
// TODO: may be fetch data from server in the future.
|
||||
|
||||
setDatasetList([...list]);
|
||||
setDatasetList([...datasetOptions]);
|
||||
};
|
||||
|
||||
return {
|
||||
|
||||
@@ -41,7 +41,7 @@ export default function useQueryProfiles() {
|
||||
value: 'Custom',
|
||||
config: {
|
||||
dataset_name: '',
|
||||
dataset_prompt_tokens: null,
|
||||
dataset_input_tokens: null,
|
||||
dataset_output_tokens: null,
|
||||
request_rate: null,
|
||||
total_requests: null
|
||||
|
||||
Reference in New Issue
Block a user