chore: model item action list order

main
jialin 1 year ago
parent b40bf76270
commit 4391705c9a

@ -35,6 +35,7 @@
"clipboard": "^2.0.11",
"crypto-js": "^4.2.0",
"dayjs": "^1.11.11",
"driver.js": "^1.3.1",
"echarts": "^5.5.1",
"epubjs": "^0.3.93",
"has-ansi": "^5.0.1",

@ -68,6 +68,9 @@ dependencies:
dayjs:
specifier: ^1.11.11
version: 1.11.11
driver.js:
specifier: ^1.3.1
version: 1.3.1
echarts:
specifier: ^5.5.1
version: 5.5.1
@ -9330,6 +9333,10 @@ packages:
tslib: 2.6.2
dev: false
/driver.js@1.3.1:
resolution: {integrity: sha512-MvUdXbqSgEsgS/H9KyWb5Rxy0aE6BhOVT4cssi2x2XjmXea6qQfgdx32XKVLLSqTaIw7q/uxU5Xl3NV7+cN6FQ==, tarball: https://registry.npmjs.org/driver.js/-/driver.js-1.3.1.tgz}
dev: false
/duck@0.1.12:
resolution: {integrity: sha512-wkctla1O6VfP89gQ+J/yDesM0S7B7XLXjKGzXxMDVFg7uEn706niAtyYovKbyq1oT9YwDcly721/iUWoc8MVRg==, tarball: https://registry.npmjs.org/duck/-/duck-0.1.12.tgz}
dependencies:

@ -0,0 +1,35 @@
import { useIntl } from '@umijs/max';
import { driver, type Config } from 'driver.js';
import { useEffect, useRef } from 'react';
export const useDriver = (config?: Config) => {
const intl = useIntl();
const driverRef = useRef<any>(null);
const handleDoNotShowAgain = () => {};
const init = () => {
driverRef.current = driver({
overlayOpacity: 0.2,
animate: false,
...config
});
};
const start = () => {
if (!driverRef.current) {
init();
}
driverRef.current.drive();
};
useEffect(() => {
return () => {
driverRef.current?.destroy();
};
}, []);
return { start, initDriver: init, driver: driverRef.current };
};
export default useDriver;

@ -23,6 +23,7 @@ import {
type IRoute
} from '@umijs/max';
import { Button, Modal } from 'antd';
import 'driver.js/dist/driver.css';
import { useAtom } from 'jotai';
import 'overlayscrollbars/overlayscrollbars.css';
import { useCallback, useEffect, useMemo, useState } from 'react';

@ -77,5 +77,6 @@ export default {
'models.form.filePath': 'Model Path',
'models.form.backendVersion': 'Backend Version',
'models.form.backendVersion.tips':
'Pin a specific version to keep the backend stable across GPUStack upgrades.'
'Pin a specific version to keep the backend stable across GPUStack upgrades.',
'models.form.gpuselector': 'GPU Selector'
};

@ -98,8 +98,8 @@ export default {
'playground.multiple.on': 'Enable',
'playground.multiple.off': 'Disable',
'playground.image.params.sampler': 'Sampler',
'playground.image.params.schedule': 'Schedule',
'playground.image.params.samplerSteps': 'Sampler Steps',
'playground.image.params.schedule': 'Scheduler',
'playground.image.params.samplerSteps': 'Sampling Steps',
'playground.image.params.seed': 'Seed',
'playground.image.params.randomseed': 'Random Seed',
'playground.image.params.negativePrompt': 'Negative Prompt',

@ -74,5 +74,6 @@ export default {
'models.form.filePath': '模型路径',
'models.form.backendVersion': '后端版本',
'models.form.backendVersion.tips':
'固定指定版本以保持后端在 GPUStack 升级过程中的稳定性'
'固定指定版本以保持后端在 GPUStack 升级过程中的稳定性',
'models.form.gpuselector': 'GPU 选择器'
};

@ -95,7 +95,7 @@ export default {
'playground.multiple.on': '开启',
'playground.multiple.off': '关闭',
'playground.image.params.sampler': '采样方法',
'playground.image.params.schedule': '调度',
'playground.image.params.schedule': '调度',
'playground.image.params.samplerSteps': '迭代步数',
'playground.image.params.seed': '种子',
'playground.image.params.randomseed': '随机种子',

@ -2,7 +2,6 @@ import LabelSelector from '@/components/label-selector';
import ListInput from '@/components/list-input';
import SealInput from '@/components/seal-form/seal-input';
import SealSelect from '@/components/seal-form/seal-select';
import { PageAction } from '@/config';
import { PageActionType } from '@/config/types';
import { InfoCircleOutlined, RightOutlined } from '@ant-design/icons';
import { useIntl } from '@umijs/max';
@ -21,7 +20,6 @@ import React, { useCallback, useMemo } from 'react';
import {
backendOptionsMap,
backendParamsHolderTips,
modelSourceMap,
placementStrategyOptions
} from '../config';
import llamaConfig from '../config/llama-config';
@ -249,7 +247,10 @@ const AdvanceConfig: React.FC<AdvanceConfigProps> = (props) => {
}
]}
>
<SealSelect label="GPU Selector" required>
<SealSelect
label={intl.formatMessage({ id: 'models.form.gpuselector' })}
required
>
{gpuOptions.map((item) => (
<Select.Option key={item.value} value={item.value}>
<GPUCard data={item}></GPUCard>
@ -258,35 +259,6 @@ const AdvanceConfig: React.FC<AdvanceConfigProps> = (props) => {
</SealSelect>
</Form.Item>
)}
<Form.Item name="backend">
<SealSelect
onChange={handleBackendChange}
label={intl.formatMessage({ id: 'models.form.backend' })}
options={[
{
label: `llama-box`,
value: backendOptionsMap.llamaBox,
disabled:
source === modelSourceMap.local_path_value ? false : !isGGUF
},
{
label: 'vLLM',
value: backendOptionsMap.vllm,
disabled:
source === modelSourceMap.local_path_value ? false : isGGUF
},
{
label: 'vox-box',
value: backendOptionsMap.voxBox,
disabled: source === modelSourceMap.ollama_library_value
}
]}
disabled={
action === PageAction.EDIT &&
source !== modelSourceMap.local_path_value
}
></SealSelect>
</Form.Item>
<Form.Item name="backend_version">
<SealInput.Input
label={intl.formatMessage({ id: 'models.form.backendVersion' })}

@ -9,6 +9,7 @@ import { Form, Tooltip, Typography } from 'antd';
import _ from 'lodash';
import React, {
forwardRef,
useCallback,
useEffect,
useImperativeHandle,
useMemo,
@ -369,6 +370,16 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
return null;
}, [props.source, isGGUF, intl]);
const handleBackendChange = useCallback((val: string) => {
if (val === backendOptionsMap.llamaBox) {
form.setFieldsValue({
distributed_inference_across_workers: true,
cpu_offloading: true
});
}
form.setFieldValue('backend_version', '');
}, []);
const handleOk = (formdata: FormData) => {
const gpu = _.find(gpuOptions, (item: any) => {
return item.value === formdata.gpu_selector;
@ -400,6 +411,7 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
);
}
}, [isGGUF, modelTask]);
useEffect(() => {
handleOnSelectModel();
}, [props.selectedModel.name]);
@ -496,6 +508,39 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
min={0}
></SealInput.Number>
</Form.Item>
<Form.Item name="backend" id="backend-field">
<SealSelect
onChange={handleBackendChange}
label={intl.formatMessage({ id: 'models.form.backend' })}
options={[
{
label: `llama-box`,
value: backendOptionsMap.llamaBox,
disabled:
props.source === modelSourceMap.local_path_value
? false
: !isGGUF
},
{
label: 'vLLM',
value: backendOptionsMap.vllm,
disabled:
props.source === modelSourceMap.local_path_value
? false
: isGGUF
},
{
label: 'vox-box',
value: backendOptionsMap.voxBox,
disabled: props.source === modelSourceMap.ollama_library_value
}
]}
disabled={
action === PageAction.EDIT &&
props.source !== modelSourceMap.local_path_value
}
></SealSelect>
</Form.Item>
<Form.Item<FormData> name="description">
<SealInput.TextArea
label={intl.formatMessage({

@ -1,10 +1,11 @@
import ModalFooter from '@/components/modal-footer';
import { PageActionType } from '@/config/types';
import useDriver from '@/hooks/use-driver';
import { CloseOutlined } from '@ant-design/icons';
import { useIntl } from '@umijs/max';
import { Button, Drawer } from 'antd';
import { debounce } from 'lodash';
import { memo, useCallback, useEffect, useId, useRef, useState } from 'react';
import { memo, useCallback, useEffect, useRef, useState } from 'react';
import { backendOptionsMap, modelSourceMap } from '../config';
import { FormData, ListItem } from '../config/types';
import ColumnWrapper from './column-wrapper';
@ -26,6 +27,23 @@ type AddModalProps = {
onCancel: () => void;
};
const steps = [
{
element: '#filterGGUF',
popover: {
title: '筛选模型',
description: 'Select a model from the list'
}
},
{
element: '#backend-field',
popover: {
title: '选择推理后端',
description: 'Select a model from the list'
}
}
];
const AddModal: React.FC<AddModalProps> = (props) => {
const {
title,
@ -40,7 +58,9 @@ const AddModal: React.FC<AddModalProps> = (props) => {
modelSourceMap.huggingface_value,
modelSourceMap.modelscope_value
];
const uid = useId();
const { start } = useDriver({
steps
});
const form = useRef<any>({});
const intl = useIntl();
const [selectedModel, setSelectedModel] = useState<any>({});
@ -48,9 +68,11 @@ const AddModal: React.FC<AddModalProps> = (props) => {
const [loadingModel, setLoadingModel] = useState<boolean>(false);
const [isGGUF, setIsGGUF] = useState<boolean>(false);
const modelFileRef = useRef<any>(null);
const [loadfinish, setLoadfinish] = useState<boolean>(false);
const handleSelectModelFile = useCallback((item: any) => {
form.current?.setFieldValue?.('file_name', item.fakeName);
setLoadfinish(true);
}, []);
const handleOnSelectModel = (item: any) => {
@ -104,6 +126,12 @@ const AddModal: React.FC<AddModalProps> = (props) => {
};
}, [open, source]);
// useEffect(() => {
// if (open && loadfinish) {
// start();
// }
// }, [loadfinish, open]);
return (
<Drawer
title={

@ -41,7 +41,7 @@ const GPUCard: React.FC<{
</span>
{data?.memory?.used
? _.round(data?.memory?.utilization_rate || 0, 2)
: _.round(data.memory?.allocated / data.memory?.total, 2)}
: _.round(data.memory?.allocated / data.memory?.total, 2) * 100}
%
</span>
</>

@ -243,31 +243,35 @@ const SearchModel: React.FC<SearchInputProps> = (props) => {
</span>
</span>
<span>
<Checkbox
onChange={handleFilterGGUFChange}
className="m-r-5"
checked={filterGGUFRef.current}
>
<Tooltip
overlayInnerStyle={{ width: 'max-content' }}
title={
<div>
<div>
{intl.formatMessage({ id: 'models.search.gguf.tips' })}
</div>
<div>
{intl.formatMessage({ id: 'models.search.vllm.tips' })}
</div>
<span id="filterGGUF">
<Checkbox
onChange={handleFilterGGUFChange}
className="m-r-5"
checked={filterGGUFRef.current}
>
<Tooltip
overlayInnerStyle={{ width: 'max-content' }}
title={
<div>
{intl.formatMessage({ id: 'models.search.voxbox.tips' })}
<div>
{intl.formatMessage({ id: 'models.search.gguf.tips' })}
</div>
<div>
{intl.formatMessage({ id: 'models.search.vllm.tips' })}
</div>
<div>
{intl.formatMessage({
id: 'models.search.voxbox.tips'
})}
</div>
</div>
</div>
}
>
GGUF
<InfoCircleOutlined className="m-l-4" />
</Tooltip>
</Checkbox>
}
>
GGUF
<InfoCircleOutlined className="m-l-4" />
</Tooltip>
</Checkbox>
</span>
<Select
value={dataSource.sortType}
onChange={handleSortChange}

@ -70,6 +70,37 @@ interface ModelsProps {
total: number;
}
const ActionList = [
{
label: 'common.button.edit',
key: 'edit',
icon: <EditOutlined />
},
{
label: 'models.openinplayground',
key: 'chat',
icon: <ExperimentOutlined />
},
{
label: 'common.button.stop',
key: 'stop',
icon: <IconFont type="icon-stop1"></IconFont>
},
{
label: 'common.button.start',
key: 'start',
icon: <IconFont type="icon-playcircle"></IconFont>
},
{
label: 'common.button.delete',
key: 'delete',
props: {
danger: true
},
icon: <DeleteOutlined />
}
];
const Models: React.FC<ModelsProps> = ({
handleNameChange,
handleSearch,
@ -234,37 +265,6 @@ const Models: React.FC<ModelsProps> = ({
}
];
const ActionList = [
{
label: 'common.button.edit',
key: 'edit',
icon: <EditOutlined />
},
{
label: 'common.button.stop',
key: 'stop',
icon: <IconFont type="icon-stop1"></IconFont>
},
{
label: 'common.button.start',
key: 'start',
icon: <IconFont type="icon-playcircle"></IconFont>
},
{
label: 'models.openinplayground',
key: 'chat',
icon: <ExperimentOutlined />
},
{
label: 'common.button.delete',
key: 'delete',
props: {
danger: true
},
icon: <DeleteOutlined />
}
];
const setActionList = useCallback((record: ListItem) => {
return _.filter(ActionList, (action: any) => {
if (action.key === 'chat') {

@ -8,7 +8,7 @@ import { PageActionType } from '@/config/types';
import { useIntl } from '@umijs/max';
import { Form, Modal, Tooltip, Typography } from 'antd';
import _ from 'lodash';
import React, { memo, useEffect, useMemo, useState } from 'react';
import React, { memo, useCallback, useEffect, useMemo, useState } from 'react';
import SimpleBar from 'simplebar-react';
import 'simplebar-react/dist/simplebar.min.css';
import { queryGPUList } from '../apis';
@ -278,6 +278,16 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
form.submit();
};
const handleBackendChange = useCallback((val: string) => {
if (val === backendOptionsMap.llamaBox) {
form.setFieldsValue({
distributed_inference_across_workers: true,
cpu_offloading: true
});
}
form.setFieldValue('backend_version', '');
}, []);
const handleOk = (formdata: FormData) => {
let obj = {};
if (formdata.backend === backendOptionsMap.vllm) {
@ -439,6 +449,40 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
min={0}
></SealInput.Number>
</Form.Item>
<Form.Item name="backend">
<SealSelect
onChange={handleBackendChange}
label={intl.formatMessage({ id: 'models.form.backend' })}
options={[
{
label: `llama-box`,
value: backendOptionsMap.llamaBox,
disabled:
props.data?.source === modelSourceMap.local_path_value
? false
: !isGGUF
},
{
label: 'vLLM',
value: backendOptionsMap.vllm,
disabled:
props.data?.source === modelSourceMap.local_path_value
? false
: isGGUF
},
{
label: 'vox-box',
value: backendOptionsMap.voxBox,
disabled:
props.data?.source === modelSourceMap.ollama_library_value
}
]}
disabled={
action === PageAction.EDIT &&
props.data?.source !== modelSourceMap.local_path_value
}
></SealSelect>
</Form.Item>
<Form.Item<FormData> name="description">
<SealInput.TextArea
label={intl.formatMessage({

@ -213,7 +213,7 @@ const GPUList: React.FC = () => {
: _.round(
record.memory?.allocated / record.memory?.total,
0
)
) * 100
}
label={
<span className="flex-column">

Loading…
Cancel
Save