chore: deploy model state merge

main
jialin 2 years ago
parent dea99ff70a
commit 0a47c4c067

@ -60,7 +60,7 @@ const APIKeys: React.FC = () => {
const fetchData = async () => {
setDataSource((pre) => {
pre.loading = true;
return pre;
return { ...pre };
});
try {
const params = {

@ -4,8 +4,9 @@ import SealSelect from '@/components/seal-form/seal-select';
import { PageAction } from '@/config';
import { PageActionType } from '@/config/types';
import { convertFileSize } from '@/utils';
import { CloseOutlined } from '@ant-design/icons';
import { useIntl } from '@umijs/max';
import { Drawer, Form } from 'antd';
import { Button, Drawer, Form } from 'antd';
import _ from 'lodash';
import { memo, useCallback, useEffect, useState } from 'react';
import { queryHuggingfaceModelFiles, queryHuggingfaceModels } from '../apis';
@ -276,17 +277,35 @@ const AddModal: React.FC<AddModalProps> = (props) => {
return (
<Drawer
title={title}
title={
<div className="flex-between flex-center">
<span
style={{
color: 'var(--ant-color-text)',
fontWeight: 'var(--font-weight-medium)',
fontSize: 'var(--font-size-middle)'
}}
>
{title}
</span>
<Button type="text" size="small" onClick={onCancel}>
<CloseOutlined></CloseOutlined>
</Button>
</div>
}
open={open}
onClose={onCancel}
destroyOnClose={true}
closeIcon={true}
closeIcon={false}
maskClosable={false}
keyboard={false}
styles={{
body: {
height: 'calc(100vh - 53px)',
height: 'calc(100vh - 57px)',
padding: '16px 0'
},
content: {
borderRadius: '8px 0 0 8px'
}
}}
width="90%"

@ -35,75 +35,97 @@ const sourceList = [
];
const SearchModel: React.FC<SearchInputProps> = (props) => {
console.log('SearchModel======');
const intl = useIntl();
const { modelSource, onSourceChange, onSelectModel } = props;
const [repoOptions, setRepoOptions] = useState<any[]>([]);
const [loading, setLoading] = useState(false);
const [dataSource, setDataSource] = useState<{
repoOptions: any[];
loading: boolean;
}>({
repoOptions: [],
loading: false
});
const [current, setCurrent] = useState<string>('');
const [sortType, setSortType] = useState<string>('downloads');
const cacheRepoOptions = useRef<any[]>([]);
const axiosTokenRef = useRef<any>(null);
const customOllamaModelRef = useRef<any>(null);
const handleOnSelectModel = (item: any) => {
const handleOnSelectModel = useCallback((item: any) => {
onSelectModel(item);
setCurrent(item.id);
};
}, []);
const handleOnSearchRepo = async (text: string) => {
axiosTokenRef.current?.abort?.();
axiosTokenRef.current = new AbortController();
if (loading) return;
try {
setLoading(true);
cacheRepoOptions.current = [];
const params = {
search: {
query: text,
tags: ['gguf']
}
};
const models = await queryHuggingfaceModels(params, {
signal: axiosTokenRef.current.signal
});
const list = _.map(models || [], (item: any) => {
return {
...item,
value: item.name,
label: item.name
const handleOnSearchRepo = useCallback(
async (text: string) => {
axiosTokenRef.current?.abort?.();
axiosTokenRef.current = new AbortController();
if (dataSource.loading) return;
try {
setDataSource((pre) => {
pre.loading = true;
return { ...pre };
});
cacheRepoOptions.current = [];
const params = {
search: {
query: text,
tags: ['gguf']
}
};
});
const sortedList = _.sortBy(
list,
(item: any) => item[sortType]
).reverse();
cacheRepoOptions.current = sortedList;
setRepoOptions(sortedList);
handleOnSelectModel(sortedList[0]);
} catch (error) {
setRepoOptions([]);
handleOnSelectModel({});
cacheRepoOptions.current = [];
} finally {
setLoading(false);
}
};
const models = await queryHuggingfaceModels(params, {
signal: axiosTokenRef.current.signal
});
const list = _.map(models || [], (item: any) => {
return {
...item,
value: item.name,
label: item.name
};
});
const sortedList = _.sortBy(
list,
(item: any) => item[sortType]
).reverse();
cacheRepoOptions.current = sortedList;
setDataSource({
repoOptions: sortedList,
loading: false
});
handleOnSelectModel(sortedList[0]);
} catch (error) {
setDataSource({
repoOptions: [],
loading: false
});
handleOnSelectModel({});
cacheRepoOptions.current = [];
}
},
[dataSource]
);
const handlerSearchModels = useCallback(async (e: any) => {
const text = e.target.value;
handleOnSearchRepo(text);
}, []);
const handlerSearchModels = useCallback(
async (e: any) => {
const text = e.target.value;
handleOnSearchRepo(text);
},
[handleOnSearchRepo]
);
const handleOnOpen = () => {
if (
!repoOptions.length &&
!dataSource.repoOptions.length &&
!cacheRepoOptions.current.length &&
modelSource === modelSourceMap.huggingface_value
) {
handleOnSearchRepo('');
}
if (modelSourceMap.ollama_library_value === modelSource) {
setRepoOptions(ollamaModelOptions);
setDataSource({
repoOptions: ollamaModelOptions,
loading: false
});
cacheRepoOptions.current = ollamaModelOptions;
handleOnSelectModel(ollamaModelOptions[0]);
}
@ -114,7 +136,10 @@ const SearchModel: React.FC<SearchInputProps> = (props) => {
const list = _.filter(cacheRepoOptions.current, (item: any) => {
return item.name.includes(text);
});
setRepoOptions(list);
setDataSource({
repoOptions: list,
loading: false
});
};
const debounceFilter = _.debounce((e: any) => {
@ -124,7 +149,10 @@ const SearchModel: React.FC<SearchInputProps> = (props) => {
const handleSourceChange = (source: string) => {
axiosTokenRef.current?.abort?.();
onSourceChange?.(source);
setRepoOptions([]);
setDataSource({
repoOptions: [],
loading: false
});
cacheRepoOptions.current = [];
};
@ -146,11 +174,14 @@ const SearchModel: React.FC<SearchInputProps> = (props) => {
const handleSortChange = (value: string) => {
const sortedList = _.sortBy(
repoOptions,
dataSource.repoOptions,
(item: any) => item[value]
).reverse();
setSortType(value);
setRepoOptions(sortedList);
setDataSource({
repoOptions: sortedList,
loading: false
});
};
const renderHFSearch = () => {
@ -159,7 +190,8 @@ const SearchModel: React.FC<SearchInputProps> = (props) => {
<SearchInput onSearch={handlerSearchModels}></SearchInput>
<div className={SearchStyle.filter}>
<span>
<span className="value">{repoOptions.length}</span>results
<span className="value">{dataSource.repoOptions.length}</span>
results
</span>
<Select
value={sortType}
@ -220,8 +252,8 @@ const SearchModel: React.FC<SearchInputProps> = (props) => {
</div>
{
<SearchResult
loading={loading}
resultList={repoOptions}
loading={dataSource.loading}
resultList={dataSource.repoOptions}
current={current}
source={modelSource}
onSelect={handleOnSelectModel}

@ -14,6 +14,7 @@ interface SearchResultProps {
}
const SearchResult: React.FC<SearchResultProps> = (props) => {
console.log('SearchResult======');
const { resultList, onSelect, source } = props;
const handleSelect = (e: any, item: any) => {
@ -22,41 +23,43 @@ const SearchResult: React.FC<SearchResultProps> = (props) => {
};
return (
<div style={{ ...props.style }} className="search-result-wrap">
<Spin spinning={props.loading} style={{ minHeight: 100 }}>
{resultList.length ? (
<Row gutter={[16, 16]}>
{resultList.map((item, index) => (
<Col span={24} key={item.name}>
<div onClick={(e) => handleSelect(e, item)}>
<HFModelItem
source={source}
tags={item.tags}
key={index}
title={item.name}
downloads={item.downloads}
likes={item.likes}
task={item.task}
updatedAt={item.updatedAt}
active={item.id === props.current}
/>
</div>
</Col>
))}
</Row>
) : (
!props.loading && (
<Empty
imageStyle={{ height: 'auto', marginTop: '20px' }}
image={
<SearchOutlined
className="font-size-16"
style={{ color: 'var(--ant-color-text-tertiary)' }}
></SearchOutlined>
}
description="No models found"
/>
)
)}
<Spin spinning={props.loading}>
<div style={{ minHeight: 200 }}>
{resultList.length ? (
<Row gutter={[16, 16]}>
{resultList.map((item, index) => (
<Col span={24} key={item.name}>
<div onClick={(e) => handleSelect(e, item)}>
<HFModelItem
source={source}
tags={item.tags}
key={index}
title={item.name}
downloads={item.downloads}
likes={item.likes}
task={item.task}
updatedAt={item.updatedAt}
active={item.id === props.current}
/>
</div>
</Col>
))}
</Row>
) : (
!props.loading && (
<Empty
imageStyle={{ height: 'auto', marginTop: '20px' }}
image={
<SearchOutlined
className="font-size-16"
style={{ color: 'var(--ant-color-text-tertiary)' }}
></SearchOutlined>
}
description="No models found"
/>
)
)}
</div>
</Spin>
</div>
);

@ -34,9 +34,9 @@ import {
} from '../apis';
import { modelSourceMap } from '../config';
import { FormData, ListItem, ModelInstanceListItem } from '../config/types';
import AddModal from './add-modal';
import DeployModal from './deploy-modal';
import InstanceItem from './instance-item';
import UpdateModel from './update-modal';
import ViewLogsModal from './view-logs-modal';
interface ModelsProps {
@ -467,14 +467,14 @@ const Models: React.FC<ModelsProps> = ({
/>
</SealTable>
</PageContainer>
<AddModal
<UpdateModel
open={openAddModal}
action={PageAction.EDIT}
title={title}
data={currentData}
onCancel={handleModalCancel}
onOk={handleModalOk}
></AddModal>
></UpdateModel>
<DeployModal
open={openDeployModal}
action={PageAction.CREATE}

@ -4,7 +4,7 @@ import useSetChunkRequest, {
} from '@/hooks/use-chunk-request';
import useUpdateChunkedList from '@/hooks/use-update-chunk-list';
import _ from 'lodash';
import { useCallback, useEffect, useRef, useState } from 'react';
import { memo, useCallback, useEffect, useRef, useState } from 'react';
import { MODELS_API, MODEL_INSTANCE_API, queryModelsList } from './apis';
import TableList from './components/table-list';
import { ListItem } from './config/types';
@ -15,8 +15,6 @@ const Models: React.FC = () => {
const { setChunkRequest } = useSetChunkRequest();
const { setChunkRequest: setModelInstanceChunkRequest } =
useSetChunkRequest();
const [total, setTotal] = useState(0);
const [loading, setLoading] = useState(false);
const [modelInstances, setModelInstances] = useState<any[]>([]);
const [dataSource, setDataSource] = useState<{
dataList: ListItem[];
@ -53,7 +51,7 @@ const Models: React.FC = () => {
axiosToken = createAxiosToken();
setDataSource((pre) => {
pre.loading = true;
return pre;
return { ...pre };
});
try {
const params = {
@ -68,6 +66,11 @@ const Models: React.FC = () => {
loading: false,
total: res.pagination.total
});
} else {
setDataSource({
...dataSource,
total: res.pagination.total
});
}
} catch (error) {
setDataSource({
@ -79,7 +82,7 @@ const Models: React.FC = () => {
} finally {
setFirstLoad(false);
}
}, [queryParams]);
}, [queryParams, firstLoad]);
const handlePageChange = useCallback(
(page: number, pageSize: number | undefined) => {
@ -129,9 +132,12 @@ const Models: React.FC = () => {
}
};
const handleSearch = useCallback((e: any) => {
fetchData();
}, []);
const handleSearch = useCallback(
(e: any) => {
fetchData();
},
[fetchData]
);
const handleNameChange = useCallback(
(e: any) => {
@ -181,4 +187,4 @@ const Models: React.FC = () => {
);
};
export default Models;
export default memo(Models);

@ -1,6 +1,6 @@
.column-wrapper {
flex: 1;
height: calc(100vh - 85px);
height: calc(100vh - 89px);
overflow-y: auto;
overflow-x: hidden;
border-left: 1px solid var(--ant-color-split);

@ -48,7 +48,7 @@ const GPUList: React.FC = () => {
const fetchData = async () => {
setDataSource((pre) => {
pre.loading = true;
return pre;
return { ...pre };
});
try {
const params = {

@ -49,7 +49,7 @@ const Resources: React.FC = () => {
const fetchData = async () => {
setDataSource((pre) => {
pre.loading = true;
return pre;
return { ...pre };
});
try {
const params = {

@ -72,7 +72,7 @@ const Users: React.FC = () => {
const fetchData = async () => {
setDataSource((pre) => {
pre.loading = true;
return pre;
return { ...pre };
});
try {
const params = {

Loading…
Cancel
Save