feat: model category

This commit is contained in:
jialin
2024-12-27 19:12:51 +08:00
parent 9f40e2c71e
commit b4e30565d2
16 changed files with 68 additions and 56 deletions
@@ -163,6 +163,7 @@
} }
:global(.ant-select-selector) { :global(.ant-select-selector) {
flex: 1;
border: none !important; border: none !important;
padding-block: 5px; padding-block: 5px;
padding-inline: @input-inner-padding !important; padding-inline: @input-inner-padding !important;
+2 -1
View File
@@ -219,5 +219,6 @@ export default {
'common.button.recreate': 'Recreate', 'common.button.recreate': 'Recreate',
'common.button.delrecreate': 'Delete (Recreate)', 'common.button.delrecreate': 'Delete (Recreate)',
'common.options.all': 'All', 'common.options.all': 'All',
'common.options.none': 'None' 'common.options.none': 'None',
'common.options.auto': 'Auto'
}; };
+1
View File
@@ -44,6 +44,7 @@ export default {
'models.search.unsupport': 'models.search.unsupport':
'This model is not supported and may be unusable after deployment.', 'This model is not supported and may be unusable after deployment.',
'models.form.scheduletype': 'Schedule Type', 'models.form.scheduletype': 'Schedule Type',
'models.form.categories': 'Model Category',
'models.form.scheduletype.auto': 'Auto', 'models.form.scheduletype.auto': 'Auto',
'models.form.scheduletype.manual': 'Manual', 'models.form.scheduletype.manual': 'Manual',
'models.form.scheduletype.auto.tips': 'models.form.scheduletype.auto.tips':
+2 -1
View File
@@ -212,5 +212,6 @@ export default {
'common.button.recreate': '重新创建', 'common.button.recreate': '重新创建',
'common.button.delrecreate': '删除(重建)', 'common.button.delrecreate': '删除(重建)',
'common.options.all': '全部', 'common.options.all': '全部',
'common.options.none': '无' 'common.options.none': '无',
'common.options.auto': '自动'
}; };
+1
View File
@@ -42,6 +42,7 @@ export default {
'models.search.networkerror': '网络连接异常!', 'models.search.networkerror': '网络连接异常!',
'models.search.hfvisit': '请确保您可以访问', 'models.search.hfvisit': '请确保您可以访问',
'models.search.unsupport': '暂不支持该模型,部署后可能无法使用', 'models.search.unsupport': '暂不支持该模型,部署后可能无法使用',
'models.form.categories': '模型类别',
'models.form.scheduletype': '调度方式', 'models.form.scheduletype': '调度方式',
'models.form.scheduletype.auto': '自动', 'models.form.scheduletype.auto': '自动',
'models.form.scheduletype.manual': '手动', 'models.form.scheduletype.manual': '手动',
@@ -20,6 +20,7 @@ import React, { useCallback, useMemo } from 'react';
import { import {
backendOptionsMap, backendOptionsMap,
backendParamsHolderTips, backendParamsHolderTips,
modelCategories,
placementStrategyOptions placementStrategyOptions
} from '../config'; } from '../config';
import llamaConfig from '../config/llama-config'; import llamaConfig from '../config/llama-config';
@@ -153,21 +154,16 @@ const AdvanceConfig: React.FC<AdvanceConfigProps> = (props) => {
const collapseItems = useMemo(() => { const collapseItems = useMemo(() => {
const children = ( const children = (
<> <>
{/* <Form.Item<FormData> name="labels"> <Form.Item<FormData> name="categories">
<ListInput <SealSelect
placeholder={ allowNull
backendParamsHolderTips[backend] maxCount={1}
? intl.formatMessage({ label={intl.formatMessage({
id: backendParamsHolderTips[backend].holder id: 'models.form.categories'
}) })}
: '' options={modelCategories}
} ></SealSelect>
btnText="models.form.button.addlabel" </Form.Item>
label="Labels"
dataList={form.getFieldValue('backend_parameters') || []}
options={modelLabels}
></ListInput>
</Form.Item> */}
<Form.Item name="scheduleType"> <Form.Item name="scheduleType">
<SealSelect <SealSelect
label={intl.formatMessage({ id: 'models.form.scheduletype' })} label={intl.formatMessage({ id: 'models.form.scheduletype' })}
@@ -247,7 +243,7 @@ const AdvanceConfig: React.FC<AdvanceConfigProps> = (props) => {
)} )}
{scheduleType === 'manual' && ( {scheduleType === 'manual' && (
<Form.Item<FormData> <Form.Item<FormData>
name="gpu_selector" name={['gpu_selector', 'gpu_ids']}
rules={[ rules={[
{ {
required: true, required: true,
@@ -265,6 +261,8 @@ const AdvanceConfig: React.FC<AdvanceConfigProps> = (props) => {
<SealSelect <SealSelect
label={intl.formatMessage({ id: 'models.form.gpuselector' })} label={intl.formatMessage({ id: 'models.form.gpuselector' })}
required required
mode="multiple"
maxLength={1}
> >
{gpuOptions.map((item) => ( {gpuOptions.map((item) => (
<Select.Option key={item.value} value={item.value}> <Select.Option key={item.value} value={item.value}>
+9 -16
View File
@@ -86,7 +86,7 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
return { return {
...item, ...item,
label: item.name, label: item.name,
value: `${item.worker_name}-${item.name}-${item.index}` value: item.id
}; };
}); });
console.log('queryGPUList========', list); console.log('queryGPUList========', list);
@@ -381,23 +381,15 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
}, []); }, []);
const handleOk = (formdata: FormData) => { const handleOk = (formdata: FormData) => {
const gpu = _.find(gpuOptions, (item: any) => { let data = _.cloneDeep(formdata);
return item.value === formdata.gpu_selector; if (data.categories) {
}); data.categories = [data.categories];
if (gpu) {
onOk({
..._.omit(formdata, ['scheduleType']),
gpu_selector: {
gpu_name: gpu.name,
gpu_index: gpu.index,
worker_name: gpu.worker_name
}
});
} else { } else {
onOk({ data.categories = [];
..._.omit(formdata, ['scheduleType'])
});
} }
onOk({
..._.omit(data, ['scheduleType'])
});
}; };
useEffect(() => { useEffect(() => {
@@ -430,6 +422,7 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
placement_strategy: 'spread', placement_strategy: 'spread',
cpu_offloading: true, cpu_offloading: true,
scheduleType: 'auto', scheduleType: 'auto',
categories: null,
distributed_inference_across_workers: true distributed_inference_across_workers: true
}} }}
> >
+6 -5
View File
@@ -44,6 +44,7 @@ import {
import { import {
InstanceRealLogStatus, InstanceRealLogStatus,
getSourceRepoConfigValue, getSourceRepoConfigValue,
modelCategoriesMap,
modelSourceMap modelSourceMap
} from '../config'; } from '../config';
import { FormData, ListItem, ModelInstanceListItem } from '../config/types'; import { FormData, ListItem, ModelInstanceListItem } from '../config/types';
@@ -556,7 +557,7 @@ const Models: React.FC<ModelsProps> = ({
const renderModelTags = useCallback( const renderModelTags = useCallback(
(record: ListItem) => { (record: ListItem) => {
if (record.reranker) { if (record.categories?.includes(modelCategoriesMap.reranker)) {
return ( return (
<Tag <Tag
icon={<IconFont type="icon-rank1"></IconFont>} icon={<IconFont type="icon-rank1"></IconFont>}
@@ -574,7 +575,7 @@ const Models: React.FC<ModelsProps> = ({
); );
} }
if (record.embedding_only && !record.reranker) { if (record.categories?.includes(modelCategoriesMap.embedding)) {
return ( return (
<Tag <Tag
icon={<IconFont type="icon-cube"></IconFont>} icon={<IconFont type="icon-cube"></IconFont>}
@@ -591,7 +592,7 @@ const Models: React.FC<ModelsProps> = ({
</Tag> </Tag>
); );
} }
if (record.text_to_speech) { if (record.categories?.includes(modelCategoriesMap.text_to_speech)) {
return ( return (
<Tag <Tag
icon={<IconFont type="icon-sound-wave"></IconFont>} icon={<IconFont type="icon-sound-wave"></IconFont>}
@@ -608,7 +609,7 @@ const Models: React.FC<ModelsProps> = ({
</Tag> </Tag>
); );
} }
if (record.speech_to_text) { if (record.categories?.includes(modelCategoriesMap.speech_to_text)) {
return ( return (
<Tag <Tag
icon={<AudioOutlined />} icon={<AudioOutlined />}
@@ -625,7 +626,7 @@ const Models: React.FC<ModelsProps> = ({
</Tag> </Tag>
); );
} }
if (record.image_only) { if (record.categories?.includes(modelCategoriesMap.image)) {
return ( return (
<Tag <Tag
icon={<PictureOutlined />} icon={<PictureOutlined />}
@@ -88,6 +88,9 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
const formData = { const formData = {
...result.values, ...result.values,
..._.omit(props.data, result.omits), ..._.omit(props.data, result.omits),
categories: props.data?.categories?.length
? props.data.categories[0]
: null,
scheduleType: props.data?.gpu_selector ? 'manual' : 'auto', scheduleType: props.data?.gpu_selector ? 'manual' : 'auto',
gpu_selector: props.data?.gpu_selector gpu_selector: props.data?.gpu_selector
? `${props.data?.gpu_selector.worker_name}-${props.data?.gpu_selector.gpu_name}-${props.data?.gpu_selector.gpu_index}` ? `${props.data?.gpu_selector.worker_name}-${props.data?.gpu_selector.gpu_name}-${props.data?.gpu_selector.gpu_index}`
@@ -303,6 +306,7 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
onOk({ onOk({
..._.omit(formdata, ['scheduleType']), ..._.omit(formdata, ['scheduleType']),
categories: formdata.categories ? [formdata.categories] : [],
worker_selector: null, worker_selector: null,
gpu_selector: gpu gpu_selector: gpu
? { ? {
@@ -316,6 +320,7 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
} else { } else {
onOk({ onOk({
..._.omit(formdata, ['scheduleType']), ..._.omit(formdata, ['scheduleType']),
categories: formdata.categories ? [formdata.categories] : [],
gpu_selector: null, gpu_selector: null,
...obj ...obj
}); });
+17
View File
@@ -240,6 +240,23 @@ export const placementStrategyOptions = [
} }
]; ];
export const modelCategoriesMap = {
image: 'image',
text_to_speech: 'text_to_speech',
speech_to_text: 'speech_to_text',
embedding: 'embedding',
reranker: 'reranker'
};
export const modelCategories = [
{ label: 'common.options.auto', value: null, locale: true },
{ label: 'Image', value: 'image' },
{ label: 'Text-to-speech', value: 'text_to_speech' },
{ label: 'Speech-to-text', value: 'speech_to_text' },
{ label: 'Embedding', value: 'embedding' },
{ label: 'Reranker', value: 'reranker' }
];
export const sourceRepoConfig = { export const sourceRepoConfig = {
[modelSourceMap.huggingface_value]: { [modelSourceMap.huggingface_value]: {
repo_id: 'huggingface_repo_id', repo_id: 'huggingface_repo_id',
+4 -6
View File
@@ -1,6 +1,7 @@
export interface ListItem { export interface ListItem {
source: string; source: string;
backend: string; backend: string;
categories?: string[];
reranker: boolean; reranker: boolean;
image_only?: boolean; image_only?: boolean;
huggingface_repo_id: string; huggingface_repo_id: string;
@@ -23,15 +24,14 @@ export interface ListItem {
created_at: string; created_at: string;
updated_at: string; updated_at: string;
gpu_selector?: { gpu_selector?: {
worker_name: string; gpu_ids: string[];
gpu_index: number;
gpu_name: string;
}; };
worker_selector?: object; worker_selector?: object;
} }
export interface FormData { export interface FormData {
backend?: string; backend?: string;
categories?: string;
backend_parameters?: string[]; backend_parameters?: string[];
backend_version?: string; backend_version?: string;
source: string; source: string;
@@ -46,9 +46,7 @@ export interface FormData {
model_scope_model_id?: string; model_scope_model_id?: string;
model_scope_file_path?: string; model_scope_file_path?: string;
gpu_selector?: { gpu_selector?: {
worker_name: string; gpu_ids: string[];
gpu_index: number;
gpu_name: string;
}; };
placement_strategy?: string; placement_strategy?: string;
cpu_offloading?: boolean; cpu_offloading?: boolean;
+1 -2
View File
@@ -30,8 +30,7 @@ const PlaygroundEmbedding: React.FC = () => {
const getModelListByEmbedding = async () => { const getModelListByEmbedding = async () => {
try { try {
const params = { const params = {
embedding_only: true, categories: 'embedding'
reranker: false
}; };
const res = await queryModelsList(params); const res = await queryModelsList(params);
const list = _.map(res.data || [], (item: any) => { const list = _.map(res.data || [], (item: any) => {
+1 -1
View File
@@ -85,7 +85,7 @@ const TextToImages: React.FC = () => {
const getModelList = async () => { const getModelList = async () => {
try { try {
const params = { const params = {
image_only: true categories: 'image'
}; };
const res = await queryModelsList(params); const res = await queryModelsList(params);
const list = _.map(res.data || [], (item: any) => { const list = _.map(res.data || [], (item: any) => {
+1 -5
View File
@@ -79,11 +79,7 @@ const Playground: React.FC = () => {
const getModelList = async () => { const getModelList = async () => {
try { try {
const params = { const params = {
embedding_only: false, categories: ''
image_only: false,
reranker: false,
text_to_speech: false,
speech_to_text: false
}; };
const res = await queryModelsList(params); const res = await queryModelsList(params);
const list = _.map(res.data || [], (item: any) => { const list = _.map(res.data || [], (item: any) => {
+1 -1
View File
@@ -32,7 +32,7 @@ const PlaygroundRerank: React.FC = () => {
const getModelListByReranker = async () => { const getModelListByReranker = async () => {
try { try {
const params = { const params = {
reranker: true categories: 'reranker'
}; };
const res = await queryModelsList(params); const res = await queryModelsList(params);
const list = _.map(res.data || [], (item: any) => { const list = _.map(res.data || [], (item: any) => {
+2 -2
View File
@@ -102,7 +102,7 @@ const Playground: React.FC = () => {
const getTextToSpeechModels = async () => { const getTextToSpeechModels = async () => {
try { try {
const params = { const params = {
text_to_speech: true categories: 'text_to_speech'
}; };
const res = await queryModelsList(params); const res = await queryModelsList(params);
const list = _.map(res.data || [], (item: any) => { const list = _.map(res.data || [], (item: any) => {
@@ -120,7 +120,7 @@ const Playground: React.FC = () => {
const getSpeechToText = async () => { const getSpeechToText = async () => {
try { try {
const params = { const params = {
speech_to_text: true categories: 'speech_to_text'
}; };
const res = await queryModelsList(params); const res = await queryModelsList(params);
const list = _.map(res.data || [], (item: any) => { const list = _.map(res.data || [], (item: any) => {