fix: default spec by mode
This commit is contained in:
@@ -3,11 +3,11 @@ import { downloadFile, listFiles, listModels } from '@huggingface/hub';
|
|||||||
import { PipelineType } from '@huggingface/tasks';
|
import { PipelineType } from '@huggingface/tasks';
|
||||||
import { request } from '@umijs/max';
|
import { request } from '@umijs/max';
|
||||||
import qs from 'query-string';
|
import qs from 'query-string';
|
||||||
|
import testSpecs from '../config/test';
|
||||||
import {
|
import {
|
||||||
AccessControlFormData,
|
AccessControlFormData,
|
||||||
BackendItem,
|
BackendItem,
|
||||||
CatalogItem,
|
CatalogItem,
|
||||||
CatalogSpec,
|
|
||||||
DraftModelItem,
|
DraftModelItem,
|
||||||
EvaluateResult,
|
EvaluateResult,
|
||||||
EvaluateSpec,
|
EvaluateSpec,
|
||||||
@@ -370,14 +370,15 @@ export async function queryCatalogItemSpec(
|
|||||||
params: { id: number },
|
params: { id: number },
|
||||||
options?: any
|
options?: any
|
||||||
) {
|
) {
|
||||||
return await request<Global.PageResponse<CatalogSpec>>(
|
// return await request<Global.PageResponse<CatalogSpec>>(
|
||||||
`/model-sets/${params.id}/specs`,
|
// `/model-sets/${params.id}/specs`,
|
||||||
{
|
// {
|
||||||
method: 'GET',
|
// method: 'GET',
|
||||||
...options,
|
// ...options,
|
||||||
params
|
// params
|
||||||
}
|
// }
|
||||||
);
|
// );
|
||||||
|
return testSpecs;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function evaluationsModelSpec(
|
export async function evaluationsModelSpec(
|
||||||
|
|||||||
@@ -25,12 +25,28 @@ import { useCheckCompatibility } from '../hooks';
|
|||||||
import useFormInitialValues from '../hooks/use-form-initial-values';
|
import useFormInitialValues from '../hooks/use-form-initial-values';
|
||||||
import CompatibilityAlert from './compatible-alert';
|
import CompatibilityAlert from './compatible-alert';
|
||||||
|
|
||||||
|
const ModesMap: Record<string, string> = {
|
||||||
|
latency: 'models.form.mode.latency',
|
||||||
|
reference: 'models.form.mode.reference',
|
||||||
|
throughput: 'models.form.mode.throughput'
|
||||||
|
};
|
||||||
|
|
||||||
|
const ModesTipsMap: Record<string, string> = {
|
||||||
|
latency: 'models.form.mode.latency.tips',
|
||||||
|
reference: 'models.form.mode.reference.tips',
|
||||||
|
throughput: 'models.form.mode.throughput.tips'
|
||||||
|
};
|
||||||
|
|
||||||
const pickFieldsFromSpec = [
|
const pickFieldsFromSpec = [
|
||||||
'backend_version',
|
|
||||||
'backend_parameters',
|
|
||||||
'env',
|
'env',
|
||||||
'size',
|
'size',
|
||||||
'quantization'
|
'source',
|
||||||
|
'quantization',
|
||||||
|
'backend_version',
|
||||||
|
'backend_parameters',
|
||||||
|
'backend',
|
||||||
|
'extended_kv_cache',
|
||||||
|
'speculative_config'
|
||||||
];
|
];
|
||||||
|
|
||||||
type AddModalProps = {
|
type AddModalProps = {
|
||||||
@@ -115,6 +131,7 @@ const AddModal: React.FC<AddModalProps> = (props) => {
|
|||||||
const [quantizationOptions, setQuantizationOptions] = useState<
|
const [quantizationOptions, setQuantizationOptions] = useState<
|
||||||
Global.BaseOption<string>[]
|
Global.BaseOption<string>[]
|
||||||
>([]);
|
>([]);
|
||||||
|
const [modeList, setModeList] = useState<Global.BaseOption<string>[]>([]);
|
||||||
const sourceGroupMap = useRef<any>({});
|
const sourceGroupMap = useRef<any>({});
|
||||||
const axiosToken = useRef<any>(null);
|
const axiosToken = useRef<any>(null);
|
||||||
const selectSpecRef = useRef<CatalogSpec>({} as CatalogSpec);
|
const selectSpecRef = useRef<CatalogSpec>({} as CatalogSpec);
|
||||||
@@ -167,32 +184,37 @@ const AddModal: React.FC<AddModalProps> = (props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getModelSpec = (data: {
|
const getModelSpec = (data: {
|
||||||
|
mode?: string;
|
||||||
backend: string;
|
backend: string;
|
||||||
size: number;
|
size: number;
|
||||||
quantization: string;
|
quantization: string;
|
||||||
}) => {
|
}) => {
|
||||||
const spec = _.find(specListRef.current, (item: CatalogSpec) => {
|
// const spec = _.find(specListRef.current, (item: CatalogSpec) => {
|
||||||
if (data.size && data.quantization) {
|
// if (data.size && data.quantization) {
|
||||||
return (
|
// return (
|
||||||
item.size === data.size &&
|
// item.size === data.size &&
|
||||||
item.backend === data.backend &&
|
// item.backend === data.backend &&
|
||||||
item.quantization === data.quantization
|
// item.quantization === data.quantization
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
if (data.size) {
|
// if (data.size) {
|
||||||
return item.size === data.size && item.backend === data.backend;
|
// return item.size === data.size && item.backend === data.backend;
|
||||||
}
|
// }
|
||||||
if (data.quantization) {
|
// if (data.quantization) {
|
||||||
return (
|
// return (
|
||||||
item.quantization === data.quantization &&
|
// item.quantization === data.quantization &&
|
||||||
item.backend === data.backend
|
// item.backend === data.backend
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
return item.backend === data.backend;
|
// return item.backend === data.backend;
|
||||||
});
|
// });
|
||||||
selectSpecRef.current = spec;
|
const defaultSpec = _.find(
|
||||||
|
specListRef.current,
|
||||||
|
(item: CatalogSpec) => item.mode === data.mode
|
||||||
|
);
|
||||||
|
selectSpecRef.current = defaultSpec;
|
||||||
return {
|
return {
|
||||||
..._.pick(spec, pickFieldsFromSpec),
|
..._.pick(defaultSpec, pickFieldsFromSpec),
|
||||||
categories: _.get(current, 'categories.0', null)
|
categories: _.get(current, 'categories.0', null)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -242,6 +264,7 @@ const AddModal: React.FC<AddModalProps> = (props) => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
const result = _.uniqBy(quantizationList, 'value');
|
const result = _.uniqBy(quantizationList, 'value');
|
||||||
|
console.log('quantization options:', result);
|
||||||
setQuantizationOptions(result);
|
setQuantizationOptions(result);
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
@@ -376,6 +399,16 @@ const AddModal: React.FC<AddModalProps> = (props) => {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
const groupList = _.groupBy(res.items, 'source');
|
const groupList = _.groupBy(res.items, 'source');
|
||||||
|
const modes = _.groupBy(res.items, 'mode');
|
||||||
|
|
||||||
|
const modeDataList = _.map(modes, (item: CatalogSpec, key: string) => {
|
||||||
|
return {
|
||||||
|
label: ModesMap[key] || key,
|
||||||
|
isBuiltIn: ModesMap[key] ? true : false,
|
||||||
|
value: key,
|
||||||
|
tips: ModesTipsMap[key] || ''
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
sourceGroupMap.current = groupList;
|
sourceGroupMap.current = groupList;
|
||||||
|
|
||||||
@@ -387,20 +420,21 @@ const AddModal: React.FC<AddModalProps> = (props) => {
|
|||||||
|
|
||||||
const list = _.sortBy(res.items, 'size');
|
const list = _.sortBy(res.items, 'size');
|
||||||
|
|
||||||
|
console.log('spec items:', res.items);
|
||||||
hasF16Ref.current = _.some(res.items, (item: CatalogSpec) => {
|
hasF16Ref.current = _.some(res.items, (item: CatalogSpec) => {
|
||||||
return AscendNPUQuant_F16.includes(_.toUpper(item.quantization));
|
return AscendNPUQuant_F16.includes(_.toUpper(item.quantization));
|
||||||
});
|
});
|
||||||
|
|
||||||
const defaultSpec =
|
const defaultSpec = _.find(
|
||||||
_.find(list, (item: CatalogSpec) => {
|
list,
|
||||||
return getDefaultQuant({
|
(item: CatalogSpec) => item.mode === modeDataList[0]?.value
|
||||||
category: _.get(current, 'categories.0', ''),
|
);
|
||||||
quantOption: item.quantization,
|
|
||||||
backend: item.backend
|
console.log('default spec:', defaultSpec);
|
||||||
});
|
|
||||||
}) || _.get(res.items, `0`, {});
|
|
||||||
|
|
||||||
selectSpecRef.current = defaultSpec;
|
selectSpecRef.current = defaultSpec;
|
||||||
|
|
||||||
|
setModeList(modeDataList);
|
||||||
setSourceList(sources);
|
setSourceList(sources);
|
||||||
handleSetBackendOptions();
|
handleSetBackendOptions();
|
||||||
handleSetSizeOptions({
|
handleSetSizeOptions({
|
||||||
@@ -472,6 +506,22 @@ const AddModal: React.FC<AddModalProps> = (props) => {
|
|||||||
handleCheckFormData();
|
handleCheckFormData();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleOnModeChange = (val: string) => {
|
||||||
|
const data = getModelSpec({
|
||||||
|
mode: val,
|
||||||
|
backend: form.current.getFieldValue('backend'),
|
||||||
|
size: 0,
|
||||||
|
quantization: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('mode change data:', data);
|
||||||
|
|
||||||
|
form.current.setFieldsValue({
|
||||||
|
...data
|
||||||
|
});
|
||||||
|
handleCheckFormData();
|
||||||
|
};
|
||||||
|
|
||||||
const handleOk = async (values: FormData) => {
|
const handleOk = async (values: FormData) => {
|
||||||
const data = {
|
const data = {
|
||||||
..._.omit(selectSpecRef.current, ['name']),
|
..._.omit(selectSpecRef.current, ['name']),
|
||||||
@@ -542,6 +592,8 @@ const AddModal: React.FC<AddModalProps> = (props) => {
|
|||||||
value={{
|
value={{
|
||||||
sizeOptions: [],
|
sizeOptions: [],
|
||||||
quantizationOptions: [],
|
quantizationOptions: [],
|
||||||
|
modeList: modeList,
|
||||||
|
onModeChange: handleOnModeChange,
|
||||||
onSizeChange: handleOnSizeChange,
|
onSizeChange: handleOnSizeChange,
|
||||||
onQuantizationChange: handleOnQuantizationChange
|
onQuantizationChange: handleOnQuantizationChange
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ interface FormContextProps {
|
|||||||
interface CatalogFormContextProps {
|
interface CatalogFormContextProps {
|
||||||
sizeOptions: Global.BaseOption<number>[];
|
sizeOptions: Global.BaseOption<number>[];
|
||||||
quantizationOptions: Global.BaseOption<string>[];
|
quantizationOptions: Global.BaseOption<string>[];
|
||||||
|
modeList: Global.BaseOption<string & { isBuiltIn: boolean; tips: string }>[];
|
||||||
|
onModeChange: (val: string) => void;
|
||||||
onSizeChange: (val: number) => void;
|
onSizeChange: (val: number) => void;
|
||||||
onQuantizationChange: (val: string) => void;
|
onQuantizationChange: (val: string) => void;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,138 @@
|
|||||||
|
export default {
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
source: 'model_scope',
|
||||||
|
huggingface_repo_id: null,
|
||||||
|
huggingface_filename: null,
|
||||||
|
ollama_library_model_name: null,
|
||||||
|
model_scope_model_id: 'Qwen/Qwen3-30B-A3B-FP8',
|
||||||
|
model_scope_file_path: null,
|
||||||
|
local_path: null,
|
||||||
|
name: null,
|
||||||
|
description: null,
|
||||||
|
meta: {},
|
||||||
|
replicas: 1,
|
||||||
|
ready_replicas: 0,
|
||||||
|
categories: [],
|
||||||
|
embedding_only: false,
|
||||||
|
image_only: false,
|
||||||
|
reranker: false,
|
||||||
|
speech_to_text: false,
|
||||||
|
text_to_speech: false,
|
||||||
|
placement_strategy: 'spread',
|
||||||
|
cpu_offloading: false,
|
||||||
|
distributed_inference_across_workers: false,
|
||||||
|
worker_selector: {},
|
||||||
|
gpu_selector: null,
|
||||||
|
backend: 'SGLang',
|
||||||
|
backend_version: null,
|
||||||
|
backend_parameters: [
|
||||||
|
'--reasoning-parser=qwen3',
|
||||||
|
'--tool-call-parser=qwen25'
|
||||||
|
],
|
||||||
|
image_name: null,
|
||||||
|
run_command: null,
|
||||||
|
env: null,
|
||||||
|
restart_on_error: true,
|
||||||
|
distributable: false,
|
||||||
|
extended_kv_cache: null,
|
||||||
|
speculative_config: null,
|
||||||
|
quantization: 'FP8',
|
||||||
|
mode: 'throughput'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
source: 'model_scope',
|
||||||
|
huggingface_repo_id: null,
|
||||||
|
huggingface_filename: null,
|
||||||
|
ollama_library_model_name: null,
|
||||||
|
model_scope_model_id: 'Qwen/Qwen3-30B-A3B-FP8',
|
||||||
|
model_scope_file_path: null,
|
||||||
|
local_path: null,
|
||||||
|
name: null,
|
||||||
|
description: null,
|
||||||
|
meta: {},
|
||||||
|
replicas: 1,
|
||||||
|
ready_replicas: 0,
|
||||||
|
categories: [],
|
||||||
|
embedding_only: false,
|
||||||
|
image_only: false,
|
||||||
|
reranker: false,
|
||||||
|
speech_to_text: false,
|
||||||
|
text_to_speech: false,
|
||||||
|
placement_strategy: 'spread',
|
||||||
|
cpu_offloading: false,
|
||||||
|
distributed_inference_across_workers: false,
|
||||||
|
worker_selector: {},
|
||||||
|
gpu_selector: null,
|
||||||
|
backend: 'SGLang',
|
||||||
|
backend_version: null,
|
||||||
|
backend_parameters: [
|
||||||
|
'--reasoning-parser=qwen3',
|
||||||
|
'--tool-call-parser=qwen25',
|
||||||
|
'--speculative-algorithm=EAGLE3',
|
||||||
|
'--speculative-draft-model-path=Tengyunw/qwen3_30b_moe_eagle3',
|
||||||
|
'--speculative-num-steps=6',
|
||||||
|
'--speculative-eagle-topk=10',
|
||||||
|
'--speculative-num-draft-tokens=32'
|
||||||
|
],
|
||||||
|
image_name: null,
|
||||||
|
run_command: null,
|
||||||
|
env: null,
|
||||||
|
restart_on_error: true,
|
||||||
|
distributable: false,
|
||||||
|
extended_kv_cache: null,
|
||||||
|
speculative_config: {
|
||||||
|
enabled: true,
|
||||||
|
algorithm: 'eagle3',
|
||||||
|
draft_model_name: 'Qwen3-30B-A3B-EAGLE3',
|
||||||
|
num_draft_tokens: 8,
|
||||||
|
ngram_min_match_length: null,
|
||||||
|
ngram_max_match_length: null
|
||||||
|
},
|
||||||
|
quantization: 'FP8',
|
||||||
|
mode: 'latency'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
source: 'model_scope',
|
||||||
|
huggingface_repo_id: null,
|
||||||
|
huggingface_filename: null,
|
||||||
|
ollama_library_model_name: null,
|
||||||
|
model_scope_model_id: 'Qwen/Qwen3-30B-A3B',
|
||||||
|
model_scope_file_path: null,
|
||||||
|
local_path: null,
|
||||||
|
name: null,
|
||||||
|
description: null,
|
||||||
|
meta: {},
|
||||||
|
replicas: 1,
|
||||||
|
ready_replicas: 0,
|
||||||
|
categories: [],
|
||||||
|
embedding_only: false,
|
||||||
|
image_only: false,
|
||||||
|
reranker: false,
|
||||||
|
speech_to_text: false,
|
||||||
|
text_to_speech: false,
|
||||||
|
placement_strategy: 'spread',
|
||||||
|
cpu_offloading: false,
|
||||||
|
distributed_inference_across_workers: true,
|
||||||
|
worker_selector: {},
|
||||||
|
gpu_selector: null,
|
||||||
|
backend: 'vLLM',
|
||||||
|
backend_version: null,
|
||||||
|
backend_parameters: [
|
||||||
|
'--tool-call-parser=hermes',
|
||||||
|
'--enable-auto-tool-choice',
|
||||||
|
'--max-model-len=32768'
|
||||||
|
],
|
||||||
|
image_name: null,
|
||||||
|
run_command: null,
|
||||||
|
env: null,
|
||||||
|
restart_on_error: true,
|
||||||
|
distributable: false,
|
||||||
|
extended_kv_cache: null,
|
||||||
|
speculative_config: null,
|
||||||
|
quantization: 'BF16',
|
||||||
|
mode: 'reference'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
pagination: { page: 1, perPage: 100, total: 3, totalPage: 1 }
|
||||||
|
};
|
||||||
@@ -198,12 +198,27 @@ export interface CatalogSpec {
|
|||||||
categories: any[];
|
categories: any[];
|
||||||
placement_strategy: string;
|
placement_strategy: string;
|
||||||
cpu_offloading: boolean;
|
cpu_offloading: boolean;
|
||||||
|
mode: string;
|
||||||
distributed_inference_across_workers: boolean;
|
distributed_inference_across_workers: boolean;
|
||||||
worker_selector: Record<string, any>;
|
worker_selector: Record<string, any>;
|
||||||
gpu_selector: {
|
gpu_selector: {
|
||||||
gpu_ids: string[];
|
gpu_ids: string[];
|
||||||
gpus_per_replica: number;
|
gpus_per_replica: number;
|
||||||
};
|
};
|
||||||
|
extended_kv_cache: {
|
||||||
|
enabled: boolean;
|
||||||
|
chunk_size: number;
|
||||||
|
max_local_cpu_size: number;
|
||||||
|
remote_url: string;
|
||||||
|
};
|
||||||
|
speculative_config: {
|
||||||
|
enabled: boolean;
|
||||||
|
algorithm: string;
|
||||||
|
draft_model_name: string;
|
||||||
|
num_draft_tokens: number;
|
||||||
|
ngram_min_match_length: number;
|
||||||
|
ngram_max_match_length: number;
|
||||||
|
};
|
||||||
backend: string;
|
backend: string;
|
||||||
backend_version: string;
|
backend_version: string;
|
||||||
backend_parameters: any[];
|
backend_parameters: any[];
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
|
import AutoTooltip from '@/components/auto-tooltip';
|
||||||
import SealSelect from '@/components/seal-form/seal-select';
|
import SealSelect from '@/components/seal-form/seal-select';
|
||||||
import TooltipList from '@/components/tooltip-list';
|
import TooltipList from '@/components/tooltip-list';
|
||||||
import { useIntl } from '@umijs/max';
|
import { useIntl } from '@umijs/max';
|
||||||
import { Form } from 'antd';
|
import { Form, Select } from 'antd';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { deployFormKeyMap } from '../config';
|
import { deployFormKeyMap } from '../config';
|
||||||
import { useFormContext } from '../config/form-context';
|
import { useCatalogFormContext, useFormContext } from '../config/form-context';
|
||||||
import KVCacheForm from './kv-cache';
|
import KVCacheForm from './kv-cache';
|
||||||
import SpeculativeDecode from './speculative-decode';
|
import SpeculativeDecode from './speculative-decode';
|
||||||
|
|
||||||
@@ -36,6 +37,7 @@ const Performance: React.FC = () => {
|
|||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const form = Form.useFormInstance();
|
const form = Form.useFormInstance();
|
||||||
const { formKey } = useFormContext();
|
const { formKey } = useFormContext();
|
||||||
|
const { modeList, onModeChange } = useCatalogFormContext();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -43,25 +45,24 @@ const Performance: React.FC = () => {
|
|||||||
{formKey === deployFormKeyMap.catalog && (
|
{formKey === deployFormKeyMap.catalog && (
|
||||||
<Form.Item name="mode">
|
<Form.Item name="mode">
|
||||||
<SealSelect
|
<SealSelect
|
||||||
|
onChange={onModeChange}
|
||||||
description={<TooltipList list={modeTipsList}></TooltipList>}
|
description={<TooltipList list={modeTipsList}></TooltipList>}
|
||||||
label={intl.formatMessage({ id: 'models.form.mode' })}
|
label={intl.formatMessage({ id: 'models.form.mode' })}
|
||||||
options={[
|
>
|
||||||
{
|
{modeList.map((item: any) => (
|
||||||
label: intl.formatMessage({
|
<Select.Option key={item.value} value={item.value}>
|
||||||
id: 'models.form.mode.throughput'
|
<AutoTooltip
|
||||||
}),
|
showTitle={item.isBuiltIn}
|
||||||
value: 'throughput'
|
ghost
|
||||||
},
|
title={intl.formatMessage({ id: item.tips })}
|
||||||
{
|
>
|
||||||
label: intl.formatMessage({ id: 'models.form.mode.latency' }),
|
{item.isBuiltIn
|
||||||
value: 'latency'
|
? intl.formatMessage({ id: item.label })
|
||||||
},
|
: item.label}
|
||||||
{
|
</AutoTooltip>
|
||||||
label: intl.formatMessage({ id: 'models.form.mode.reference' }),
|
</Select.Option>
|
||||||
value: 'reference'
|
))}
|
||||||
}
|
</SealSelect>
|
||||||
]}
|
|
||||||
></SealSelect>
|
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
)}
|
)}
|
||||||
<KVCacheForm></KVCacheForm>
|
<KVCacheForm></KVCacheForm>
|
||||||
|
|||||||
Reference in New Issue
Block a user