fix: display image menu
This commit is contained in:
@@ -54,6 +54,16 @@ export default [
|
||||
defaultIcon: 'icon-reranker',
|
||||
component: './playground/rerank'
|
||||
},
|
||||
{
|
||||
name: 'text2images',
|
||||
title: 'Text2Images',
|
||||
path: keepAliveRoutes.text2images,
|
||||
key: 'text2images',
|
||||
icon: 'icon-image1',
|
||||
selectedIcon: 'icon-image-filled',
|
||||
defaultIcon: 'icon-image1',
|
||||
component: './playground/images'
|
||||
},
|
||||
{
|
||||
name: 'speech',
|
||||
title: 'Speech',
|
||||
|
||||
@@ -16,6 +16,9 @@ const DropDownActions: React.FC<DropDownProps> = (props) => {
|
||||
const items = useMemo(() => {
|
||||
return menu?.items?.map((item: any) => ({
|
||||
..._.omit(item, 'locale'),
|
||||
icon: item.icon
|
||||
? React.cloneElement(item.icon, { style: { fontSize: 14 } })
|
||||
: null,
|
||||
label: item.locale ? intl.formatMessage({ id: item.label }) : item.label
|
||||
}));
|
||||
}, [menu?.items, intl]);
|
||||
|
||||
@@ -86,8 +86,8 @@ export const FilterBar: React.FC<FilterBarProps> = (props) => {
|
||||
handleInputChange,
|
||||
handleSelectChange,
|
||||
handleSearch,
|
||||
handleDeleteByBatch,
|
||||
handleClickPrimary,
|
||||
handleDeleteByBatch = null,
|
||||
handleClickPrimary = null,
|
||||
rowSelection,
|
||||
actionItems = [],
|
||||
selectOptions,
|
||||
@@ -99,8 +99,6 @@ export const FilterBar: React.FC<FilterBarProps> = (props) => {
|
||||
marginTop = 10,
|
||||
inputHolder,
|
||||
selectHolder,
|
||||
showPrimaryButton = true,
|
||||
showDeleteButton = true,
|
||||
right,
|
||||
left,
|
||||
width
|
||||
@@ -108,12 +106,12 @@ export const FilterBar: React.FC<FilterBarProps> = (props) => {
|
||||
const intl = useIntl();
|
||||
|
||||
const renderRight = useMemo(() => {
|
||||
if (!showPrimaryButton && !showDeleteButton) {
|
||||
if (!handleClickPrimary && !handleDeleteByBatch) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<Space size={20}>
|
||||
{showPrimaryButton ? (
|
||||
{handleClickPrimary ? (
|
||||
actionType === 'dropdown' ? (
|
||||
<DropDownActions
|
||||
menu={{
|
||||
@@ -139,7 +137,7 @@ export const FilterBar: React.FC<FilterBarProps> = (props) => {
|
||||
</Button>
|
||||
)
|
||||
) : null}
|
||||
{showDeleteButton && (
|
||||
{handleDeleteByBatch && (
|
||||
<Button
|
||||
icon={<DeleteOutlined />}
|
||||
danger
|
||||
|
||||
@@ -49,6 +49,7 @@ const NO_CONTAINER_PAGES = [
|
||||
'embedding',
|
||||
'speech',
|
||||
'image',
|
||||
'text2images',
|
||||
'clusterDetail',
|
||||
'clusterCreate'
|
||||
];
|
||||
|
||||
@@ -240,5 +240,7 @@ export default {
|
||||
'models.form.quantization': 'Quantization',
|
||||
'models.form.backend.custom': 'User-defined',
|
||||
'models.form.rules.name':
|
||||
'Up to 63 characters; letters, numbers, dots (.), underscores (_), and hyphens (-) only; must start and end with an alphanumeric character.'
|
||||
'Up to 63 characters; letters, numbers, dots (.), underscores (_), and hyphens (-) only; must start and end with an alphanumeric character.',
|
||||
'models.catalog.button.explore': 'Explore Other Models',
|
||||
'models.catalog.precision': 'Precision'
|
||||
};
|
||||
|
||||
@@ -240,7 +240,9 @@ export default {
|
||||
'models.form.quantization': 'Quantization',
|
||||
'models.form.backend.custom': 'User Defined',
|
||||
'models.form.rules.name':
|
||||
'Up to 63 characters; letters, numbers, dots (.), underscores (_), and hyphens (-) only; must start and end with an alphanumeric character.'
|
||||
'Up to 63 characters; letters, numbers, dots (.), underscores (_), and hyphens (-) only; must start and end with an alphanumeric character.',
|
||||
'models.catalog.button.explore': 'Explore Other Models',
|
||||
'models.catalog.precision': 'Precision'
|
||||
};
|
||||
|
||||
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
||||
@@ -309,5 +311,7 @@ export default {
|
||||
// 46. 'models.form.draftModel.tips': 'You can enter a local path (e.g., /path/to/model) or select a model from Hugging Face or ModelScope (e.g., Tengyunw/qwen3_8b_eagle3). The system will automatically match based on the primary model source.'
|
||||
// 47. 'models.form.quantization': 'Quantization',
|
||||
// 48. 'models.form.backend.custom': 'User Defined',
|
||||
// 49. 'models.form.rules.name': 'Up to 63 characters; letters, numbers, dots (.), underscores (_), and hyphens (-) only; must start and end with an alphanumeric character.'
|
||||
// 49. 'models.form.rules.name': 'Up to 63 characters; letters, numbers, dots (.), underscores (_), and hyphens (-) only; must start and end with an alphanumeric character.',
|
||||
// 50. 'models.catalog.button.explore': 'Explore Other Models',
|
||||
// 51. 'models.catalog.precision': 'Precision'
|
||||
// ========== End of To-Do List ==========
|
||||
|
||||
@@ -241,7 +241,9 @@ export default {
|
||||
'models.form.quantization': 'Квантование',
|
||||
'models.form.backend.custom': 'Пользовательский',
|
||||
'models.form.rules.name':
|
||||
'Up to 63 characters; letters, numbers, dots (.), underscores (_), and hyphens (-) only; must start and end with an alphanumeric character.'
|
||||
'Up to 63 characters; letters, numbers, dots (.), underscores (_), and hyphens (-) only; must start and end with an alphanumeric character.',
|
||||
'models.catalog.button.explore': 'Изучить другие модели',
|
||||
'models.catalog.precision': 'Точность'
|
||||
};
|
||||
|
||||
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
||||
|
||||
@@ -227,5 +227,7 @@ export default {
|
||||
'models.form.quantization': '量化',
|
||||
'models.form.backend.custom': '用户定义',
|
||||
'models.form.rules.name':
|
||||
'长度不超过 63 个字符,只能包含字母、数字、点(.)、下划线(_)和连字符(-),且必须以字母或数字开头和结尾。'
|
||||
'长度不超过 63 个字符,只能包含字母、数字、点(.)、下划线(_)和连字符(-),且必须以字母或数字开头和结尾。',
|
||||
'models.catalog.button.explore': '浏览其他模型',
|
||||
'models.catalog.precision': '精度'
|
||||
};
|
||||
|
||||
@@ -172,7 +172,6 @@ const BackendList = () => {
|
||||
return (
|
||||
<PageBox>
|
||||
<FilterBar
|
||||
showDeleteButton={false}
|
||||
marginBottom={22}
|
||||
marginTop={30}
|
||||
width={{
|
||||
@@ -180,7 +179,6 @@ const BackendList = () => {
|
||||
}}
|
||||
inputHolder={intl.formatMessage({ id: 'common.filter.name' })}
|
||||
buttonText={intl.formatMessage({ id: 'backend.button.add' })}
|
||||
handleDeleteByBatch={handleDeleteBatch}
|
||||
handleClickPrimary={handleAddBackend}
|
||||
handleSearch={handleSearch}
|
||||
handleInputChange={handleNameChange}
|
||||
|
||||
@@ -329,8 +329,6 @@ const Clusters: React.FC = () => {
|
||||
<PageBox>
|
||||
<FilterBar
|
||||
showSelect={false}
|
||||
showPrimaryButton={true}
|
||||
showDeleteButton={true}
|
||||
marginBottom={22}
|
||||
marginTop={30}
|
||||
width={{ input: 300 }}
|
||||
|
||||
@@ -136,8 +136,6 @@ const WorkerPools = () => {
|
||||
</SubTitle>
|
||||
<FilterBar
|
||||
showSelect={false}
|
||||
showPrimaryButton={true}
|
||||
showDeleteButton={true}
|
||||
marginBottom={22}
|
||||
marginTop={22}
|
||||
width={{ input: 300 }}
|
||||
|
||||
@@ -183,7 +183,6 @@ const Credentials: React.FC = () => {
|
||||
actionItems={addActions}
|
||||
actionType="dropdown"
|
||||
showSelect={false}
|
||||
showPrimaryButton={true}
|
||||
marginBottom={22}
|
||||
marginTop={0}
|
||||
buttonText={intl.formatMessage({
|
||||
|
||||
@@ -1,19 +1,17 @@
|
||||
import { modelsExpandKeysAtom } from '@/atoms/models';
|
||||
import IconFont from '@/components/icon-font';
|
||||
import PageTools from '@/components/page-tools';
|
||||
import BaseSelect from '@/components/seal-form/base/select';
|
||||
import { FilterBar } from '@/components/page-tools';
|
||||
import { PageAction } from '@/config';
|
||||
import useBodyScroll from '@/hooks/use-body-scroll';
|
||||
import { ScrollerContext } from '@/pages/_components/infinite-scroller/use-scroller-context';
|
||||
import { IS_FIRST_LOGIN, writeState } from '@/utils/localstore/index';
|
||||
import { SearchOutlined, SyncOutlined } from '@ant-design/icons';
|
||||
import { SearchOutlined } from '@ant-design/icons';
|
||||
import { useIntl, useNavigate } from '@umijs/max';
|
||||
import { useMemoizedFn } from 'ahooks';
|
||||
import { Button, Input, Space, message } from 'antd';
|
||||
import { message } from 'antd';
|
||||
import { useAtom } from 'jotai';
|
||||
import _ from 'lodash';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import NoResult from '../_components/no-result';
|
||||
import PageBox from '../_components/page-box';
|
||||
import { createModel, queryCatalogList } from './apis';
|
||||
@@ -22,11 +20,6 @@ import DelopyBuiltInModal from './components/deploy-builtin-modal';
|
||||
import { modelCategories, modelSourceMap } from './config';
|
||||
import { CatalogItem as CatalogItemType, FormData } from './config/types';
|
||||
|
||||
const PageWrapper = styled.div`
|
||||
display: none;
|
||||
margin-block: 32px 16px;
|
||||
`;
|
||||
|
||||
const Catalog: React.FC = () => {
|
||||
const intl = useIntl();
|
||||
const { saveScrollHeight, restoreScrollHeight } = useBodyScroll();
|
||||
@@ -59,7 +52,9 @@ const Catalog: React.FC = () => {
|
||||
const [modelsExpandKeys, setModelsExpandKeys] = useAtom(modelsExpandKeysAtom);
|
||||
const cacheData = React.useRef<CatalogItemType[]>([]);
|
||||
|
||||
const categoryOptions = [...modelCategories.filter((item) => item.value)];
|
||||
const categoryOptions = [
|
||||
...modelCategories.filter((item) => item.value)
|
||||
] as Global.BaseOption<string>[];
|
||||
|
||||
const fetchData = useCallback(
|
||||
async (query?: any) => {
|
||||
@@ -159,7 +154,7 @@ const Catalog: React.FC = () => {
|
||||
[openDeployModal]
|
||||
);
|
||||
|
||||
const handleSearch = (e: any) => {
|
||||
const handleSearch = () => {
|
||||
fetchData({
|
||||
...queryParams,
|
||||
page: 1
|
||||
@@ -189,6 +184,10 @@ const Catalog: React.FC = () => {
|
||||
});
|
||||
});
|
||||
|
||||
const handleDeployFromOtherHubs = () => {
|
||||
navigate('/models/deployments');
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
}, []);
|
||||
@@ -220,49 +219,20 @@ const Catalog: React.FC = () => {
|
||||
|
||||
return (
|
||||
<PageBox>
|
||||
<PageTools
|
||||
<FilterBar
|
||||
showSelect={true}
|
||||
selectHolder={intl.formatMessage({ id: 'models.filter.category' })}
|
||||
marginBottom={22}
|
||||
marginTop={0}
|
||||
left={
|
||||
<Space>
|
||||
<Input
|
||||
prefix={
|
||||
<SearchOutlined
|
||||
style={{ color: 'var(--ant-color-text-placeholder)' }}
|
||||
></SearchOutlined>
|
||||
}
|
||||
placeholder={intl.formatMessage({ id: 'common.filter.name' })}
|
||||
style={{ width: 230 }}
|
||||
size="large"
|
||||
allowClear
|
||||
onClear={() =>
|
||||
handleNameChange({
|
||||
target: {
|
||||
value: ''
|
||||
}
|
||||
})
|
||||
}
|
||||
onChange={handleNameChange}
|
||||
></Input>
|
||||
<BaseSelect
|
||||
allowClear
|
||||
showSearch={false}
|
||||
placeholder={intl.formatMessage({ id: 'models.filter.category' })}
|
||||
style={{ width: 200 }}
|
||||
size="large"
|
||||
maxTagCount={1}
|
||||
onChange={handleCategoryChange}
|
||||
options={categoryOptions}
|
||||
></BaseSelect>
|
||||
<Button
|
||||
type="text"
|
||||
style={{ color: 'var(--ant-color-text-tertiary)' }}
|
||||
icon={<SyncOutlined></SyncOutlined>}
|
||||
onClick={handleSearch}
|
||||
></Button>
|
||||
</Space>
|
||||
}
|
||||
></PageTools>
|
||||
buttonText={intl.formatMessage({ id: 'models.catalog.button.explore' })}
|
||||
handleSearch={handleSearch}
|
||||
handleSelectChange={handleCategoryChange}
|
||||
handleClickPrimary={handleDeployFromOtherHubs}
|
||||
handleInputChange={handleNameChange}
|
||||
selectOptions={categoryOptions}
|
||||
buttonIcon={<SearchOutlined />}
|
||||
width={{ input: 230, select: 200 }}
|
||||
></FilterBar>
|
||||
<ScrollerContext.Provider
|
||||
value={{
|
||||
total: dataSource.totalPage,
|
||||
|
||||
@@ -652,7 +652,6 @@ const Models: React.FC<ModelsProps> = ({
|
||||
items: sourceOptions,
|
||||
onClick: handleClickDropdown
|
||||
}}
|
||||
trigger={['hover']}
|
||||
placement="bottomRight"
|
||||
>
|
||||
<Button
|
||||
|
||||
@@ -335,6 +335,7 @@ export const DO_NOT_TRIGGER_CHECK_COMPATIBILITY = [
|
||||
'description',
|
||||
'env',
|
||||
'source',
|
||||
'cluster_id',
|
||||
'quantization',
|
||||
'size',
|
||||
'restart_on_error',
|
||||
|
||||
@@ -38,13 +38,13 @@ const CatalogForm: React.FC = () => {
|
||||
key="quantization"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: getRuleMessage('select', 'models.form.quantization', false)
|
||||
required: false,
|
||||
message: getRuleMessage('select', 'models.catalog.precision', false)
|
||||
}
|
||||
]}
|
||||
>
|
||||
<SealInput.Input
|
||||
label={intl.formatMessage({ id: 'models.form.quantization' })}
|
||||
label={intl.formatMessage({ id: 'models.catalog.precision' })}
|
||||
disabled
|
||||
></SealInput.Input>
|
||||
</Form.Item>
|
||||
|
||||
@@ -238,12 +238,16 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
|
||||
onOk(allValues);
|
||||
};
|
||||
|
||||
const handleClusterChange = (value: number) => {
|
||||
const handleClusterChange = async (value: number) => {
|
||||
getGPUOptionList({ clusterId: value });
|
||||
getBackendOptions({ cluster_id: value });
|
||||
if (scheduleType === ScheduleValueMap.Manual) {
|
||||
form.setFieldValue(['gpu_selector', 'gpu_ids'], []);
|
||||
}
|
||||
await new Promise((resolve) => {
|
||||
setTimeout(resolve, 150);
|
||||
});
|
||||
onValuesChange?.({}, form.getFieldsValue());
|
||||
};
|
||||
|
||||
const getFieldPaths = (obj: Record<string, any>, prefix = ''): string => {
|
||||
@@ -259,6 +263,12 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
|
||||
return result[0] || '';
|
||||
};
|
||||
|
||||
/**
|
||||
* auto check compatibility or notify recreate when certain fields change
|
||||
* @param changedValues
|
||||
* @param allValues
|
||||
* @returns
|
||||
*/
|
||||
const handleOnValuesChange = async (changedValues: any, allValues: any) => {
|
||||
const fieldName = getFieldPaths(changedValues);
|
||||
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
export const VLLMMetaKeys: Record<string, any> = {};
|
||||
|
||||
export const SGLangMetaKeys: Record<string, any> = {};
|
||||
|
||||
/**
|
||||
* LLM Meta Keys
|
||||
* @description Keys used for configuring large language models (LLMs)
|
||||
* These keys are from model metadata
|
||||
* These values are set to the from, use uniform keys for easier management
|
||||
*/
|
||||
export const LLM_METAKEYS: Record<string, any> = {
|
||||
seed: 'seed',
|
||||
stop: 'stop',
|
||||
@@ -8,7 +18,8 @@ export const LLM_METAKEYS: Record<string, any> = {
|
||||
max_model_len: 'max_model_len',
|
||||
frequency_penalty: 'frequency_penalty',
|
||||
presence_penalty: 'presence_penalty',
|
||||
max_total_tokens: 'max_total_tokens'
|
||||
max_total_tokens: 'max_total_tokens',
|
||||
max_stop_sequences: 'stop'
|
||||
};
|
||||
|
||||
export const precisionTwoKeys = [
|
||||
|
||||
@@ -76,6 +76,8 @@ export const useInitLLmMeta = (
|
||||
return model;
|
||||
}, [model, modelList, isChat]);
|
||||
|
||||
const getLLamaBoxMeta = (meta: any) => {};
|
||||
|
||||
const getMaxTokens = (meta: any) => {
|
||||
const { max_model_len, n_ctx, n_slot, max_total_tokens } = meta || {};
|
||||
|
||||
|
||||
@@ -138,13 +138,14 @@ const TextToImages: React.FC = () => {
|
||||
options={optionsList}
|
||||
size="middle"
|
||||
className="m-l-40 font-600"
|
||||
value={activeKey}
|
||||
onChange={(key) => setActiveKey(key)}
|
||||
></Segmented>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
};
|
||||
}, [optionsList]);
|
||||
}, [activeKey, optionsList, intl]);
|
||||
|
||||
useHotkeys(
|
||||
HotKeys.RIGHT.join(','),
|
||||
|
||||
@@ -130,13 +130,14 @@ const Playground: React.FC = () => {
|
||||
options={optionsList}
|
||||
size="middle"
|
||||
className="m-l-40 font-600"
|
||||
value={activeKey}
|
||||
onChange={(key) => setActiveKey(key)}
|
||||
></Segmented>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
};
|
||||
}, [optionsList]);
|
||||
}, [activeKey, optionsList, intl]);
|
||||
|
||||
useHotkeys(
|
||||
HotKeys.RIGHT.join(','),
|
||||
|
||||
@@ -182,7 +182,7 @@ const Playground: React.FC = () => {
|
||||
</div>
|
||||
)
|
||||
};
|
||||
}, [activeKey, optionsList]);
|
||||
}, [activeKey, optionsList, intl]);
|
||||
|
||||
useHotkeys(
|
||||
HotKeys.RIGHT.join(','),
|
||||
|
||||
@@ -92,8 +92,6 @@ const GPUList: React.FC = () => {
|
||||
handleSearch={handleSearch}
|
||||
handleInputChange={handleNameChange}
|
||||
handleSelectChange={handleClusterChange}
|
||||
showDeleteButton={false}
|
||||
showPrimaryButton={false}
|
||||
selectOptions={clusterList}
|
||||
showSelect
|
||||
width={{ input: 200 }}
|
||||
|
||||
@@ -92,8 +92,6 @@ const WorkerDetailContent: React.FC<{ worker_id: number | undefined }> = ({
|
||||
handleSearch={handleSearch}
|
||||
handleSelectChange={handleSelectChange}
|
||||
handleInputChange={handleNameChange}
|
||||
showDeleteButton={false}
|
||||
showPrimaryButton={false}
|
||||
selectHolder={intl.formatMessage({ id: 'resources.filter.status' })}
|
||||
showSelect={true}
|
||||
selectOptions={statusList}
|
||||
|
||||
@@ -229,7 +229,6 @@ const Workers: React.FC = () => {
|
||||
<PageBox>
|
||||
<FilterBar
|
||||
showSelect={true}
|
||||
showPrimaryButton={false}
|
||||
selectHolder={intl.formatMessage({ id: 'clusters.filterBy.cluster' })}
|
||||
marginBottom={22}
|
||||
marginTop={30}
|
||||
|
||||
Reference in New Issue
Block a user