chore: list state merge

This commit is contained in:
jialin
2024-08-09 10:26:46 +08:00
parent 77f38394e6
commit dea99ff70a
19 changed files with 246 additions and 96 deletions
@@ -1,14 +1,11 @@
import { convertFileSize } from '@/utils';
import { SearchOutlined } from '@ant-design/icons';
import {
GGMLQuantizationType,
GGUF_QUANT_DESCRIPTIONS
} from '@huggingface/gguf';
import { Button, Col, Empty, Row, Space, Spin } from 'antd';
import classNames from 'classnames';
import _ from 'lodash';
import { useEffect, useState } from 'react';
import { queryHuggingfaceModelFiles } from '../apis';
import FileType from '../config/file-type';
import '../style/hf-model-file.less';
import TitleWrapper from './title-wrapper';
@@ -32,6 +29,7 @@ const HFModelFile: React.FC<HFModelFileProps> = (props) => {
const handleFetchModelFiles = async () => {
if (!props.repo) {
setDataSource({ fileList: [], loading: false });
handleSelectModelFile({});
return;
}
setDataSource({ ...dataSource, loading: true });
@@ -54,9 +52,10 @@ const HFModelFile: React.FC<HFModelFileProps> = (props) => {
const name = _.split(item.path, '.').slice(0, -1).join('.');
let quanType = _.toUpper(name.split('-').slice(-1)[0]);
if (quanType.indexOf('.') > -1) {
quanType = _.split(quanType, '.')[1];
quanType = _.split(quanType, '.').pop();
}
if (_.get(GGUF_QUANT_DESCRIPTIONS, GGMLQuantizationType[quanType])) {
console.log('quanType', quanType, FileType[quanType]);
if (FileType[quanType] !== undefined) {
return <span className="tag-item">{quanType}</span>;
}
return null;
@@ -25,6 +25,7 @@ interface HFModelItemProps {
const HFModelItem: React.FC<HFModelItemProps> = (props) => {
return (
<div
tabIndex={0}
className={classNames('hf-model-item', {
active: props.active
})}
@@ -41,8 +42,8 @@ const HFModelItem: React.FC<HFModelItemProps> = (props) => {
<Space size={16}>
{props.task && (
<Tag
color="rgb(236, 240, 242)"
style={{
backgroundColor: 'var(--color-white-1)',
marginRight: 0
}}
>
@@ -68,9 +69,10 @@ const HFModelItem: React.FC<HFModelItemProps> = (props) => {
) : (
<div className="flex-between">
<Space size={10}>
{_.map(props.tags, (tag: string) => {
{_.map(props.tags, (tag: string, index: string) => {
return (
<Tag
key={index}
style={{
backgroundColor: 'var(--color-white-1)',
marginRight: 0
+24 -11
View File
@@ -1,4 +1,5 @@
import { Space, Tag } from 'antd';
import IconFont from '@/components/icon-font';
import { Button, Empty, Tag } from 'antd';
import React, { useEffect, useState } from 'react';
import { queryHuggingfaceModelDetail } from '../apis';
import '../style/model-card.less';
@@ -10,11 +11,11 @@ const ModelCard: React.FC<{ repo: string }> = (props) => {
const getModelCardData = async () => {
if (!repo) {
setModelData(null);
return;
}
try {
const res = await queryHuggingfaceModelDetail({ repo });
console.log('modelcarddata==========', res);
setModelData(res);
} catch (error) {
setModelData({});
@@ -31,15 +32,27 @@ const ModelCard: React.FC<{ repo: string }> = (props) => {
<span>Model Card</span>
</TitleWrapper>
<div className="wrapper">
<div className="model-card-wrap">
<div className="title">{modelData.id}</div>
<Space>
<Tag className="tag-item">
<span className="m-r-5">Architecture:</span>
{modelData.config?.model_type}
</Tag>
</Space>
</div>
{modelData ? (
<div className="model-card-wrap">
<div className="title">{modelData.id}</div>
<div className="flex-between flex-center">
<Tag className="tag-item">
<span className="m-r-5">Architecture:</span>
{modelData.config?.model_type}
</Tag>
<Button
type="link"
target="_blank"
href={`https://huggingface.co/${modelData.id}`}
>
View in Hugging Face
<IconFont type="icon-external-link"></IconFont>
</Button>
</div>
</div>
) : (
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE}></Empty>
)}
</div>
</>
);
@@ -2,6 +2,7 @@ import IconFont from '@/components/icon-font';
import hotkeys from '@/config/hotkeys';
import { platformCall } from '@/utils';
import { SearchOutlined } from '@ant-design/icons';
import { useIntl } from '@umijs/max';
import { Input, Tag } from 'antd';
import React, { useRef, useState } from 'react';
import { useHotkeys } from 'react-hotkeys-hook';
@@ -10,6 +11,7 @@ const SearchInput: React.FC<{
onSearch: (e: any) => void;
}> = (props) => {
const { onSearch } = props;
const intl = useIntl();
const [isFocus, setIsFocus] = useState(false);
const inputRef = useRef<any>(null);
const platform = platformCall();
@@ -26,7 +28,9 @@ const SearchInput: React.FC<{
onFocus={() => setIsFocus(true)}
onBlur={() => setIsFocus(false)}
allowClear
placeholder="Search models from Hugging Face"
placeholder={intl.formatMessage({
id: 'model.deploy.search.placeholder'
})}
suffix={
!isFocus && (
<Tag style={{ marginRight: 0 }}>
@@ -165,7 +165,11 @@ const SearchModel: React.FC<SearchInputProps> = (props) => {
value={sortType}
onChange={handleSortChange}
labelRender={({ label }) => {
return <span>Sort: {label}</span>;
return (
<span>
{intl.formatMessage({ id: 'model.deploy.sort' })}: {label}
</span>
);
}}
options={modelFilesSortOptions}
size="middle"
@@ -203,11 +207,6 @@ const SearchModel: React.FC<SearchInputProps> = (props) => {
return (
<div style={{ flex: 1 }}>
<div className={SearchStyle['search-bar']}>
{/* <RadioButtons
options={sourceList}
value={modelSource}
onChange={handleSourceChange}
></RadioButtons> */}
{modelSource === modelSourceMap.huggingface_value ? (
renderHFSearch()
) : (
@@ -27,7 +27,7 @@ const SearchResult: React.FC<SearchResultProps> = (props) => {
<Row gutter={[16, 16]}>
{resultList.map((item, index) => (
<Col span={24} key={item.name}>
<div onClick={(e) => handleSelect(e, item)} tabIndex={0}>
<div onClick={(e) => handleSelect(e, item)}>
<HFModelItem
source={source}
tags={item.tags}
+2 -2
View File
@@ -22,7 +22,7 @@ import { Access, useAccess, useIntl, useNavigate } from '@umijs/max';
import { Button, Dropdown, Input, Space, Tag, message } from 'antd';
import dayjs from 'dayjs';
import _ from 'lodash';
import { useCallback, useRef, useState } from 'react';
import { memo, useCallback, useRef, useState } from 'react';
import {
MODELS_API,
MODEL_INSTANCE_API,
@@ -502,4 +502,4 @@ const Models: React.FC<ModelsProps> = ({
);
};
export default Models;
export default memo(Models);
+35
View File
@@ -0,0 +1,35 @@
enum FileType {
F32 = 0,
F16 = 1,
Q4_0 = 2,
Q4_1 = 3,
Q4_1_SOME_F16 = 4,
Q8_0 = 7,
Q5_0 = 8,
Q5_1 = 9,
Q2_K = 10,
Q3_K_S = 11,
Q3_K_M = 12,
Q3_K_L = 13,
Q4_K_S = 14,
Q4_K_M = 15,
Q5_K_S = 16,
Q5_K_M = 17,
Q6_K = 18,
IQ2_XXS = 19,
IQ2_XS = 20,
Q2_K_S = 21,
IQ3_XS = 22,
IQ3_XXS = 23,
IQ1_S = 24,
IQ4_NL = 25,
IQ3_S = 26,
IQ3_M = 27,
IQ2_S = 28,
IQ2_M = 29,
IQ4_XS = 30,
IQ1_M = 31,
BF16 = 32
}
export default FileType;
+14
View File
@@ -23,6 +23,20 @@ export const ollamaModelOptions = [
tags: ['9B', '27B'],
id: 'gemma2'
},
{
label: 'mistral-nemo',
value: 'mistral-nemo',
name: 'mistral-nemo',
tags: ['12B'],
id: 'mistral-nemo'
},
{
label: 'mistral-large',
value: 'mistral-large',
name: 'mistral-large',
tags: ['123B'],
id: 'mistral-large'
},
{
label: 'mistral',
value: 'mistral',
+35 -12
View File
@@ -16,9 +16,17 @@ const Models: React.FC = () => {
const { setChunkRequest: setModelInstanceChunkRequest } =
useSetChunkRequest();
const [total, setTotal] = useState(0);
const [modelInstances, setModelInstances] = useState<any[]>([]);
const [loading, setLoading] = useState(false);
const [dataSource, setDataSource] = useState<ListItem[]>([]);
const [modelInstances, setModelInstances] = useState<any[]>([]);
const [dataSource, setDataSource] = useState<{
dataList: ListItem[];
loading: boolean;
total: number;
}>({
dataList: [],
loading: false,
total: 0
});
const [firstLoad, setFirstLoad] = useState(true);
const chunkRequedtRef = useRef<any>();
const chunkInstanceRequedtRef = useRef<any>();
@@ -30,14 +38,23 @@ const Models: React.FC = () => {
});
const { updateChunkedList, cacheDataListRef } = useUpdateChunkedList({
dataList: dataSource,
setDataList: setDataSource
dataList: dataSource.dataList,
setDataList(list) {
setDataSource({
total: dataSource.total,
loading: false,
dataList: list
});
}
});
const fetchData = useCallback(async () => {
axiosToken?.cancel?.();
axiosToken = createAxiosToken();
setLoading(true);
setDataSource((pre) => {
pre.loading = true;
return pre;
});
try {
const params = {
..._.pickBy(queryParams, (val: any) => !!val)
@@ -46,14 +63,20 @@ const Models: React.FC = () => {
cancelToken: axiosToken.token
});
if (!firstLoad) {
setDataSource(res.items);
setDataSource({
dataList: res.items || [],
loading: false,
total: res.pagination.total
});
}
setTotal(res.pagination.total);
} catch (error) {
setDataSource([]);
setDataSource({
dataList: [],
loading: false,
total: dataSource.total
});
console.log('error', error);
} finally {
setLoading(false);
setFirstLoad(false);
}
}, [queryParams]);
@@ -146,13 +169,13 @@ const Models: React.FC = () => {
}}
>
<TableList
dataSource={dataSource}
dataSource={dataSource.dataList}
handleNameChange={handleNameChange}
handleSearch={handleSearch}
handlePageChange={handlePageChange}
queryParams={queryParams}
loading={loading}
total={total}
loading={dataSource.loading}
total={dataSource.total}
></TableList>
</TableContext.Provider>
);
+1
View File
@@ -1,6 +1,7 @@
.model-card-wrap {
display: flex;
flex-direction: column;
min-height: 72px;
padding: 10px;
border: 1px solid var(--ant-color-border);
border-radius: var(--border-radius-base);