diff --git a/src/locales/en-US/benchmark.ts b/src/locales/en-US/benchmark.ts index 3b9359e4..7df21552 100644 --- a/src/locales/en-US/benchmark.ts +++ b/src/locales/en-US/benchmark.ts @@ -3,6 +3,7 @@ export default { 'benchmark.button.add': 'Add Benchmark', 'benchmark.button.compare': 'Compare', 'benchmark.table.model': 'Model', + 'benchmark.table.instance': 'Endpoint', 'benchmark.table.dataset': 'Dataset', 'benchmark.table.requestRate': 'Request Rate', 'benchmark.table.gpu': 'GPU ', @@ -12,5 +13,14 @@ export default { 'benchmark.table.rps': 'Requests/s', 'benchmark.table.tps': 'Tokens/s', 'benchmark.table.inputLen': 'Input Length', - 'benchmark.table.outputLen': 'Output Length' + 'benchmark.table.outputLen': 'Output Length', + 'benchmark.form.profile': 'Profile', + 'benchmark.form.totalRequests': 'Total Requests', + 'benchmark.form.profile.latency': 'Latency', + 'benchmark.form.profile.throughput': 'Throughput', + 'benchmark.form.profile.longContext': 'Long Context', + 'benchmark.form.profile.heavy': 'Generation Heavy', + 'benchmark.form.profile.custom': 'Custom', + 'benchmark.table.inputTokenLength': 'Input Token Length', + 'benchmark.table.outputTokenLength': 'Output Token Length' }; diff --git a/src/locales/ja-JP/benchmark.ts b/src/locales/ja-JP/benchmark.ts index 3b9359e4..7df21552 100644 --- a/src/locales/ja-JP/benchmark.ts +++ b/src/locales/ja-JP/benchmark.ts @@ -3,6 +3,7 @@ export default { 'benchmark.button.add': 'Add Benchmark', 'benchmark.button.compare': 'Compare', 'benchmark.table.model': 'Model', + 'benchmark.table.instance': 'Endpoint', 'benchmark.table.dataset': 'Dataset', 'benchmark.table.requestRate': 'Request Rate', 'benchmark.table.gpu': 'GPU ', @@ -12,5 +13,14 @@ export default { 'benchmark.table.rps': 'Requests/s', 'benchmark.table.tps': 'Tokens/s', 'benchmark.table.inputLen': 'Input Length', - 'benchmark.table.outputLen': 'Output Length' + 'benchmark.table.outputLen': 'Output Length', + 'benchmark.form.profile': 'Profile', + 'benchmark.form.totalRequests': 'Total Requests', + 'benchmark.form.profile.latency': 'Latency', + 'benchmark.form.profile.throughput': 'Throughput', + 'benchmark.form.profile.longContext': 'Long Context', + 'benchmark.form.profile.heavy': 'Generation Heavy', + 'benchmark.form.profile.custom': 'Custom', + 'benchmark.table.inputTokenLength': 'Input Token Length', + 'benchmark.table.outputTokenLength': 'Output Token Length' }; diff --git a/src/locales/ru-RU/benchmark.ts b/src/locales/ru-RU/benchmark.ts index 3b9359e4..7df21552 100644 --- a/src/locales/ru-RU/benchmark.ts +++ b/src/locales/ru-RU/benchmark.ts @@ -3,6 +3,7 @@ export default { 'benchmark.button.add': 'Add Benchmark', 'benchmark.button.compare': 'Compare', 'benchmark.table.model': 'Model', + 'benchmark.table.instance': 'Endpoint', 'benchmark.table.dataset': 'Dataset', 'benchmark.table.requestRate': 'Request Rate', 'benchmark.table.gpu': 'GPU ', @@ -12,5 +13,14 @@ export default { 'benchmark.table.rps': 'Requests/s', 'benchmark.table.tps': 'Tokens/s', 'benchmark.table.inputLen': 'Input Length', - 'benchmark.table.outputLen': 'Output Length' + 'benchmark.table.outputLen': 'Output Length', + 'benchmark.form.profile': 'Profile', + 'benchmark.form.totalRequests': 'Total Requests', + 'benchmark.form.profile.latency': 'Latency', + 'benchmark.form.profile.throughput': 'Throughput', + 'benchmark.form.profile.longContext': 'Long Context', + 'benchmark.form.profile.heavy': 'Generation Heavy', + 'benchmark.form.profile.custom': 'Custom', + 'benchmark.table.inputTokenLength': 'Input Token Length', + 'benchmark.table.outputTokenLength': 'Output Token Length' }; diff --git a/src/locales/zh-CN/benchmark.ts b/src/locales/zh-CN/benchmark.ts index be72935e..90f56ba9 100644 --- a/src/locales/zh-CN/benchmark.ts +++ b/src/locales/zh-CN/benchmark.ts @@ -3,6 +3,7 @@ export default { 'benchmark.button.add': '添加基准测试', 'benchmark.button.compare': '对比', 'benchmark.table.model': '模型', + 'benchmark.table.instance': '目标实例', 'benchmark.table.dataset': '数据集', 'benchmark.table.requestRate': '请求率', 'benchmark.table.gpu': 'GPU ', @@ -12,5 +13,14 @@ export default { 'benchmark.table.rps': '请求数/秒', 'benchmark.table.tps': 'Tokens/秒', 'benchmark.table.inputLen': '输入长度', - 'benchmark.table.outputLen': '输出长度' + 'benchmark.table.outputLen': '输出长度', + 'benchmark.form.profile': '模式', + 'benchmark.form.totalRequests': '总请求数', + 'benchmark.form.profile.latency': '延迟', + 'benchmark.form.profile.throughput': '吞吐', + 'benchmark.form.profile.longContext': '长上下文', + 'benchmark.form.profile.heavy': '高生成量', + 'benchmark.form.profile.custom': '自定义', + 'benchmark.table.inputTokenLength': '输入 Token 长度', + 'benchmark.table.outputTokenLength': '输出 Token 长度' }; diff --git a/src/pages/benchmark/config/form-context.ts b/src/pages/benchmark/config/form-context.ts index 0458c77b..12386fbc 100644 --- a/src/pages/benchmark/config/form-context.ts +++ b/src/pages/benchmark/config/form-context.ts @@ -3,6 +3,9 @@ import { createContext, useContext } from 'react'; interface FormContextProps { action: PageActionType; + clusterList: Global.BaseOption[]; + modelList: Global.BaseOption[]; + modelInstanceList: Global.BaseOption[]; } const FormContext = createContext({} as FormContextProps); diff --git a/src/pages/benchmark/config/index.ts b/src/pages/benchmark/config/index.ts index 61c56468..f0d33315 100644 --- a/src/pages/benchmark/config/index.ts +++ b/src/pages/benchmark/config/index.ts @@ -27,3 +27,27 @@ export const BenchmarkStatus: Record = { [BenchmarkStatusValueMap.Error]: StatusMaps.error, [BenchmarkStatusValueMap.Unreachable]: StatusMaps.error }; + +export const profileOptions = [ + { + label: 'benchmark.form.profile.latency', + value: 'latency_short', + locale: true + }, + { + label: 'benchmark.form.profile.throughput', + value: 'throughput_medium', + locale: true + }, + { + label: 'benchmark.form.profile.longContext', + value: 'long_context_stress', + locale: true + }, + { + label: 'benchmark.form.profile.heavy', + value: 'generation_heavy', + locale: true + }, + { label: 'benchmark.form.profile.custom', value: 'custom', locale: true } +]; diff --git a/src/pages/benchmark/forms/basic.tsx b/src/pages/benchmark/forms/basic.tsx index 2eee5175..257c6721 100644 --- a/src/pages/benchmark/forms/basic.tsx +++ b/src/pages/benchmark/forms/basic.tsx @@ -1,33 +1,131 @@ +import LabelSelector from '@/components/label-selector'; import SealInput from '@/components/seal-form/seal-input'; +import SealSelect from '@/components/seal-form/seal-select'; +import useAppUtils from '@/hooks/use-app-utils'; import { useIntl } from '@umijs/max'; import { Form } from 'antd'; +import _ from 'lodash'; import React from 'react'; +import { useFormContext } from '../config/form-context'; import { FormData } from '../config/types'; const BasicForm: React.FC = () => { const intl = useIntl(); const form = Form.useFormInstance(); + const labels = Form.useWatch('labels', form); + const { getRuleMessage } = useAppUtils(); + const { modelList, modelInstanceList, clusterList } = useFormContext(); + + const handleLabelsChange = (labels: object) => { + form.setFieldValue('labels', labels); + }; return ( - - name="name" - rules={[ - { - required: true, - message: intl.formatMessage( - { id: 'common.form.rule.input' }, - { - name: intl.formatMessage({ id: 'common.table.name' }) + <> + + data-field="name" + name="name" + rules={[ + { + required: true, + message: getRuleMessage('input', 'common.table.name') + } + ]} + > + + + + name="cluster_id" + rules={[ + { + required: true, + message: getRuleMessage('select', 'clusters.title') + } + ]} + > + + + + name="model_id" + rules={[ + { + required: true, + message: getRuleMessage('select', 'benchmark.table.model') + } + ]} + > + + + + name="model_instance_name" + rules={[ + { + required: true, + message: getRuleMessage('select', 'benchmark.table.instance') + } + ]} + > + + + + name="labels" + rules={[ + () => ({ + validator(rule, value) { + if (_.keys(value).length > 0) { + if (_.some(_.keys(value), (k: string) => !value[k])) { + return Promise.reject( + intl.formatMessage( + { + id: 'common.validate.value' + }, + { + name: intl.formatMessage({ + id: 'resources.form.label' + }) + } + ) + ); + } + } + return Promise.resolve(); } - ) - } - ]} - > - - + }) + ]} + > + + + name="description"> + + + ); }; diff --git a/src/pages/benchmark/forms/dataset.tsx b/src/pages/benchmark/forms/dataset.tsx new file mode 100644 index 00000000..5670fedf --- /dev/null +++ b/src/pages/benchmark/forms/dataset.tsx @@ -0,0 +1,83 @@ +import SealSelect from '@/components/seal-form/seal-select'; +import useAppUtils from '@/hooks/use-app-utils'; +import { useIntl } from '@umijs/max'; +import { Form } from 'antd'; +import React from 'react'; +import { profileOptions } from '../config'; +import { FormData } from '../config/types'; +import RandomSettingsForm from './random-settings'; + +const DatasetForm: React.FC = () => { + const intl = useIntl(); + const form = Form.useFormInstance(); + const { getRuleMessage } = useAppUtils(); + + return ( + <> + + data-field="profile" + name="profile" + rules={[ + { + required: true, + message: getRuleMessage('select', 'benchmark.form.profile') + } + ]} + > + + + + name="dataset_name" + rules={[ + { + required: true, + message: getRuleMessage('select', 'benchmark.table.dataset') + } + ]} + > + + + + + name="request_rate" + rules={[ + { + required: true, + message: getRuleMessage('select', 'benchmark.table.requestRate') + } + ]} + > + + + + name="total_requests" + rules={[ + { + required: true, + message: getRuleMessage('select', 'benchmark.form.totalRequests') + } + ]} + > + + + + ); +}; + +export default DatasetForm; diff --git a/src/pages/benchmark/forms/index.tsx b/src/pages/benchmark/forms/index.tsx index 9b57e21f..b09c71dd 100644 --- a/src/pages/benchmark/forms/index.tsx +++ b/src/pages/benchmark/forms/index.tsx @@ -1,6 +1,7 @@ import IconFont from '@/components/icon-font'; import { PageAction } from '@/config'; import { PageActionType } from '@/config/types'; +import CollapsePanel from '@/pages/_components/collapse-panel'; import { useWrapperContext } from '@/pages/_components/column-wrapper/use-wrapper-context'; import ScrollSpyTabs from '@/pages/_components/scroll-spy-tabs'; import { useIntl } from '@umijs/max'; @@ -15,6 +16,7 @@ import { import FormContext from '../config/form-context'; import { FormData, BenchmarkListItem as ListItem } from '../config/types'; import Basic from './basic'; +import DatasetForm from './dataset'; interface ProviderFormProps { ref?: any; @@ -25,9 +27,7 @@ interface ProviderFormProps { const TABKeysMap = { BASIC: 'basic', - SUPPORTEDMODELS: 'supportedModels', - CUSTOMCONFIG: 'customConfig', - ADVANCED: 'advanced' + PROFILE: 'profile' }; const ProviderForm: React.FC = forwardRef((props, ref) => { @@ -35,27 +35,21 @@ const ProviderForm: React.FC = forwardRef((props, ref) => { const intl = useIntl(); const [form] = Form.useForm(); const { getScrollElementScrollableHeight } = useWrapperContext(); - const [activeKey, setActiveKey] = useState([TABKeysMap.BASIC]); + const [activeKey, setActiveKey] = useState([TABKeysMap.PROFILE]); const scrollTabsRef = useRef(null); const segmentOptions = [ { value: TABKeysMap.BASIC, - label: 'Basic', + label: intl.formatMessage({ id: 'common.title.basicInfo' }), icon: , field: 'name' }, { - value: TABKeysMap.SUPPORTEDMODELS, - label: 'Supported Models', - icon: , - field: 'supportedModels' - }, - { - value: TABKeysMap.ADVANCED, - label: intl.formatMessage({ id: 'resources.form.advanced' }), + value: TABKeysMap.PROFILE, + label: intl.formatMessage({ id: 'common.title.config' }), icon: , - field: 'advanceConfig' + field: 'profile' } ]; @@ -88,7 +82,7 @@ const ProviderForm: React.FC = forwardRef((props, ref) => { = forwardRef((props, ref) => {
+ + } + ]} + >
diff --git a/src/pages/benchmark/forms/random-settings.tsx b/src/pages/benchmark/forms/random-settings.tsx new file mode 100644 index 00000000..9cadbb23 --- /dev/null +++ b/src/pages/benchmark/forms/random-settings.tsx @@ -0,0 +1,64 @@ +import SealInputNumber from '@/components/seal-form/input-number'; +import SealSelect from '@/components/seal-form/seal-select'; +import useAppUtils from '@/hooks/use-app-utils'; +import { useIntl } from '@umijs/max'; +import { Form } from 'antd'; +import React from 'react'; +import { FormData } from '../config/types'; + +const DatasetForm: React.FC = () => { + const intl = useIntl(); + const form = Form.useFormInstance(); + const { getRuleMessage } = useAppUtils(); + + return ( + <> + + name="input_length" + rules={[ + { + required: true, + message: getRuleMessage( + 'select', + 'benchmark.table.inputTokenLength' + ) + } + ]} + > + + + + name="output_length" + rules={[ + { + required: true, + message: getRuleMessage( + 'select', + 'benchmark.table.outputTokenLength' + ) + } + ]} + > + + + name="seed"> + + + + ); +}; + +export default DatasetForm;