style: gguf model ux
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
@@ -79,7 +79,7 @@ const StatusTag: React.FC<StatusTagProps> = ({
|
|||||||
if (link) {
|
if (link) {
|
||||||
return statusValue.message?.replace(
|
return statusValue.message?.replace(
|
||||||
linkReg,
|
linkReg,
|
||||||
'<a $1 target="_blank">$2</a>'
|
`<a $1 target="_blank">$2</a>`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return statusValue.message;
|
return statusValue.message;
|
||||||
|
|||||||
@@ -23,5 +23,6 @@ export default {
|
|||||||
'backend.form.versionConfig': 'Versions Config',
|
'backend.form.versionConfig': 'Versions Config',
|
||||||
'backend.form.addParameter': 'Add Parameter',
|
'backend.form.addParameter': 'Add Parameter',
|
||||||
'backend.form.noVersion': 'No versions added',
|
'backend.form.noVersion': 'No versions added',
|
||||||
'backend.noVersion': 'No versions found'
|
'backend.noVersion': 'No versions found',
|
||||||
|
'backend.versionInfo.autoImage': 'Automatically selected at runtime'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -23,5 +23,6 @@ export default {
|
|||||||
'backend.form.versionConfig': 'Versions Config',
|
'backend.form.versionConfig': 'Versions Config',
|
||||||
'backend.form.addParameter': 'Add Parameter',
|
'backend.form.addParameter': 'Add Parameter',
|
||||||
'backend.form.noVersion': 'No versions added',
|
'backend.form.noVersion': 'No versions added',
|
||||||
'backend.noVersion': 'No versions found'
|
'backend.noVersion': 'No versions found',
|
||||||
|
'backend.versionInfo.autoImage': 'Automatically selected at runtime'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -23,5 +23,6 @@ export default {
|
|||||||
'backend.form.versionConfig': 'Versions Config',
|
'backend.form.versionConfig': 'Versions Config',
|
||||||
'backend.form.addParameter': 'Add Parameter',
|
'backend.form.addParameter': 'Add Parameter',
|
||||||
'backend.form.noVersion': 'No versions added',
|
'backend.form.noVersion': 'No versions added',
|
||||||
'backend.noVersion': 'No versions found'
|
'backend.noVersion': 'No versions found',
|
||||||
|
'backend.versionInfo.autoImage': 'Automatically selected at runtime'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -23,5 +23,6 @@ export default {
|
|||||||
'backend.form.versionConfig': '版本配置',
|
'backend.form.versionConfig': '版本配置',
|
||||||
'backend.form.addParameter': '添加参数',
|
'backend.form.addParameter': '添加参数',
|
||||||
'backend.form.noVersion': '未添加版本',
|
'backend.form.noVersion': '未添加版本',
|
||||||
'backend.noVersion': '未找到版本'
|
'backend.noVersion': '未找到版本',
|
||||||
|
'backend.versionInfo.autoImage': '运行时自动选择'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
.column-wrapper {
|
.column-wrapper {
|
||||||
border-left: none;
|
border-left: none;
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ export const VersionItem: React.FC<VersionItemProps> = ({ data }) => {
|
|||||||
</span>
|
</span>
|
||||||
<AutoTooltip ghost minWidth={20}>
|
<AutoTooltip ghost minWidth={20}>
|
||||||
{data.is_built_in
|
{data.is_built_in
|
||||||
? 'Selected dynamically at runtime'
|
? intl.formatMessage({ id: 'backend.versionInfo.autoImage' })
|
||||||
: data.image_name}
|
: data.image_name}
|
||||||
</AutoTooltip>
|
</AutoTooltip>
|
||||||
</InfoItem>
|
</InfoItem>
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
|
import { getRequestId } from '@/atoms/models';
|
||||||
import ModalFooter from '@/components/modal-footer';
|
import ModalFooter from '@/components/modal-footer';
|
||||||
import GSDrawer from '@/components/scroller-modal/gs-drawer';
|
import GSDrawer from '@/components/scroller-modal/gs-drawer';
|
||||||
import { PageActionType } from '@/config/types';
|
import { PageActionType } from '@/config/types';
|
||||||
|
import useDeferredRequest from '@/hooks/use-deferred-request';
|
||||||
import { ProviderValueMap } from '@/pages/cluster-management/config';
|
import { ProviderValueMap } from '@/pages/cluster-management/config';
|
||||||
import { useIntl } from '@umijs/max';
|
import { useIntl } from '@umijs/max';
|
||||||
|
import { useMemoizedFn } from 'ahooks';
|
||||||
import { Button } from 'antd';
|
import { Button } from 'antd';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { FC, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
import { FC, useEffect, useMemo, useRef, useState } from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import ColumnWrapper from '../../_components/column-wrapper';
|
import ColumnWrapper from '../../_components/column-wrapper';
|
||||||
import { defaultFormValues, deployFormKeyMap, modelSourceMap } from '../config';
|
import { defaultFormValues, deployFormKeyMap, modelSourceMap } from '../config';
|
||||||
@@ -20,14 +23,21 @@ import {
|
|||||||
} from '../hooks';
|
} from '../hooks';
|
||||||
import useCheckBackend from '../hooks/use-check-backend';
|
import useCheckBackend from '../hooks/use-check-backend';
|
||||||
import CompatibilityAlert from './compatible-alert';
|
import CompatibilityAlert from './compatible-alert';
|
||||||
import GGUFResult from './gguf-result';
|
import HFModelFile from './hf-model-file';
|
||||||
import ModelCard from './model-card';
|
import ModelCard from './model-card';
|
||||||
import SearchModel from './search-model';
|
import SearchModel from './search-model';
|
||||||
import Separator from './separator';
|
import Separator from './separator';
|
||||||
import TitleWrapper from './title-wrapper';
|
import TitleWrapper from './title-wrapper';
|
||||||
|
|
||||||
const pickFieldsFromSpec = ['backend_version', 'backend_parameters', 'env'];
|
const pickFieldsFromSpec = ['backend_version', 'backend_parameters', 'env'];
|
||||||
const dropFieldsFromForm = ['name', 'file_name', 'repo_id', 'backend'];
|
const dropFieldsFromForm = [
|
||||||
|
'name',
|
||||||
|
'huggingface_filename',
|
||||||
|
'model_scope_file_path',
|
||||||
|
'model_scope_model_id',
|
||||||
|
'huggingface_repo_id',
|
||||||
|
'backend'
|
||||||
|
];
|
||||||
const resetFields = ['worker_selector', 'env'];
|
const resetFields = ['worker_selector', 'env'];
|
||||||
|
|
||||||
const ModalFooterStyle = {
|
const ModalFooterStyle = {
|
||||||
@@ -127,6 +137,11 @@ const AddModal: FC<AddModalProps> = (props) => {
|
|||||||
const requestModelIdRef = useRef<number>(0);
|
const requestModelIdRef = useRef<number>(0);
|
||||||
const currentSelectedModel = useRef<any>({});
|
const currentSelectedModel = useRef<any>({});
|
||||||
|
|
||||||
|
const { run: fetchModelFiles } = useDeferredRequest(
|
||||||
|
() => modelFileRef.current?.fetchModelFiles?.(),
|
||||||
|
100
|
||||||
|
);
|
||||||
|
|
||||||
const updateSelectedModel = (model: any) => {
|
const updateSelectedModel = (model: any) => {
|
||||||
currentSelectedModel.current = model;
|
currentSelectedModel.current = model;
|
||||||
setSelectedModel(model);
|
setSelectedModel(model);
|
||||||
@@ -182,6 +197,78 @@ const AddModal: FC<AddModalProps> = (props) => {
|
|||||||
return categories || null;
|
return categories || null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const { run: onSelectFile } = useDeferredRequest(
|
||||||
|
async (item: any, modelInfo: any, manual?: boolean) => {
|
||||||
|
unlockWarningStatus();
|
||||||
|
|
||||||
|
const evaluateRes = await handleOnValuesChangeBefore?.({
|
||||||
|
changedValues: {},
|
||||||
|
allValues: form.current?.form?.getFieldsValue?.(),
|
||||||
|
source: props.source
|
||||||
|
});
|
||||||
|
console.log('onSelectFile:', item, modelInfo, evaluateRes);
|
||||||
|
|
||||||
|
// for cancel evaluate request case
|
||||||
|
if (!evaluateRes) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultSpec = getDefaultSpec({
|
||||||
|
evaluateResult: evaluateRes
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* do not reset backend_parameters when select a model file
|
||||||
|
*/
|
||||||
|
const formValues = form.current?.getFieldsValue?.(pickFieldsFromSpec);
|
||||||
|
|
||||||
|
form.current?.setFieldsValue?.({
|
||||||
|
..._.omit(modelInfo, ['name']),
|
||||||
|
huggingface_filename: item.fakeName,
|
||||||
|
model_scope_file_path: item.fakeName,
|
||||||
|
backend_parameters:
|
||||||
|
formValues.backend_parameters?.length > 0
|
||||||
|
? formValues.backend_parameters
|
||||||
|
: defaultSpec.backend_parameters || [],
|
||||||
|
backend_version:
|
||||||
|
formValues.backend_version || defaultSpec.backend_version,
|
||||||
|
env: formValues.env || defaultSpec.env,
|
||||||
|
categories: getCategory(item)
|
||||||
|
});
|
||||||
|
},
|
||||||
|
100
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleSelectModelFile = async (
|
||||||
|
item: any,
|
||||||
|
options: { requestModelId: number; manual?: boolean }
|
||||||
|
) => {
|
||||||
|
const { requestModelId, manual } = options || {};
|
||||||
|
if (requestModelId !== getRequestId()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log('handleSelectModelFile:', item, selectedModel);
|
||||||
|
|
||||||
|
const modelInfo = onSelectModel(selectedModel, props.source);
|
||||||
|
|
||||||
|
form.current?.setFieldsValue?.({
|
||||||
|
..._.omit(modelInfo, ['name']),
|
||||||
|
huggingface_filename: item.fakeName,
|
||||||
|
model_scope_file_path: item.fakeName,
|
||||||
|
backend_parameters: [],
|
||||||
|
backend_version: '',
|
||||||
|
backend: '',
|
||||||
|
env: {},
|
||||||
|
categories: getCategory(item)
|
||||||
|
});
|
||||||
|
|
||||||
|
// evaluate the form data when select a model file
|
||||||
|
// TODO: reset backend related fields when select a GGUF file
|
||||||
|
if (item.fakeName) {
|
||||||
|
// onSelectFile(item, modelInfo, manual);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleCancelFiles = () => {
|
const handleCancelFiles = () => {
|
||||||
cancelEvaluate();
|
cancelEvaluate();
|
||||||
modelFileRef.current?.cancelRequest();
|
modelFileRef.current?.cancelRequest();
|
||||||
@@ -242,8 +329,7 @@ const AddModal: FC<AddModalProps> = (props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (item.isGGUF) {
|
if (item.isGGUF) {
|
||||||
warningStatus.type = 'danger';
|
fetchModelFiles();
|
||||||
warningStatus.message = 'GGUF model is not supported.';
|
|
||||||
}
|
}
|
||||||
setWarningStatus(warningStatus, { override: true });
|
setWarningStatus(warningStatus, { override: true });
|
||||||
};
|
};
|
||||||
@@ -317,25 +403,21 @@ const AddModal: FC<AddModalProps> = (props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleBackendChange = async (backend: string) => {
|
const handleBackendChange = async (backend: string) => {
|
||||||
setIsGGUF(false);
|
|
||||||
|
|
||||||
const data = form.current.form.getFieldsValue?.();
|
const data = form.current.form.getFieldsValue?.();
|
||||||
const res = handleBackendChangeBefore(data);
|
const res = handleBackendChangeBefore(data);
|
||||||
if (res.show) {
|
if (res.show) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (data.local_path || props.source !== modelSourceMap.local_path_value) {
|
if (data.local_path || props.source !== modelSourceMap.local_path_value) {
|
||||||
// TODO confirm wheather it is gguf by model file not by backend
|
// TODO confirm whether it is gguf by model file not by backend
|
||||||
handleOnValuesChange?.({
|
handleOnValuesChange?.({
|
||||||
changedValues: {},
|
changedValues: {},
|
||||||
// allValues:
|
allValues: isGGUF
|
||||||
// backend === backendOptionsMap.llamaBox
|
? data
|
||||||
// ? data
|
: _.omit(data, [
|
||||||
// : _.omit(data, [
|
'cpu_offloading',
|
||||||
// 'cpu_offloading',
|
'distributed_inference_across_workers'
|
||||||
// 'distributed_inference_across_workers'
|
]),
|
||||||
// ]),
|
|
||||||
allValues: data,
|
|
||||||
source: props.source
|
source: props.source
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -349,9 +431,9 @@ const AddModal: FC<AddModalProps> = (props) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCancel = useCallback(() => {
|
const handleCancel = useMemoizedFn(() => {
|
||||||
onCancel?.();
|
onCancel?.();
|
||||||
}, [onCancel]);
|
});
|
||||||
|
|
||||||
const initClusterId = () => {
|
const initClusterId = () => {
|
||||||
if (initialValues?.cluster_id) {
|
if (initialValues?.cluster_id) {
|
||||||
@@ -492,7 +574,7 @@ const AddModal: FC<AddModalProps> = (props) => {
|
|||||||
<Separator></Separator>
|
<Separator></Separator>
|
||||||
</ColWrapper>
|
</ColWrapper>
|
||||||
<ColWrapper>
|
<ColWrapper>
|
||||||
<ColumnWrapper styles={{ container: { paddingTop: 0 } }}>
|
<ColumnWrapper styles={{ container: { padding: 0 } }}>
|
||||||
<ModelCard
|
<ModelCard
|
||||||
selectedModel={selectedModel}
|
selectedModel={selectedModel}
|
||||||
onCollapse={setCollapsed}
|
onCollapse={setCollapsed}
|
||||||
@@ -500,7 +582,16 @@ const AddModal: FC<AddModalProps> = (props) => {
|
|||||||
modelSource={props.source}
|
modelSource={props.source}
|
||||||
setIsGGUF={handleSetIsGGUF}
|
setIsGGUF={handleSetIsGGUF}
|
||||||
></ModelCard>
|
></ModelCard>
|
||||||
{isGGUF && <GGUFResult></GGUFResult>}
|
|
||||||
|
{isGGUF && (
|
||||||
|
<HFModelFile
|
||||||
|
ref={modelFileRef}
|
||||||
|
selectedModel={selectedModel}
|
||||||
|
modelSource={props.source}
|
||||||
|
onSelectFile={handleSelectModelFile}
|
||||||
|
collapsed={collapsed}
|
||||||
|
></HFModelFile>
|
||||||
|
)}
|
||||||
</ColumnWrapper>
|
</ColumnWrapper>
|
||||||
<Separator></Separator>
|
<Separator></Separator>
|
||||||
</ColWrapper>
|
</ColWrapper>
|
||||||
@@ -532,11 +623,7 @@ const AddModal: FC<AddModalProps> = (props) => {
|
|||||||
showOkBtn={!showExtraButton}
|
showOkBtn={!showExtraButton}
|
||||||
extra={
|
extra={
|
||||||
showExtraButton && (
|
showExtraButton && (
|
||||||
<Button
|
<Button type="primary" onClick={handleSubmitAnyway}>
|
||||||
type="primary"
|
|
||||||
onClick={handleSubmitAnyway}
|
|
||||||
disabled={isGGUF}
|
|
||||||
>
|
|
||||||
{intl.formatMessage({
|
{intl.formatMessage({
|
||||||
id: 'models.form.submit.anyway'
|
id: 'models.form.submit.anyway'
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ import {
|
|||||||
queryHuggingfaceModelFiles,
|
queryHuggingfaceModelFiles,
|
||||||
queryModelScopeModelFiles
|
queryModelScopeModelFiles
|
||||||
} from '../apis';
|
} from '../apis';
|
||||||
import { backendOptionsMap, modelSourceMap } from '../config';
|
import { modelSourceMap } from '../config';
|
||||||
|
import { backendOptionsMap } from '../config/backend-parameters';
|
||||||
import '../style/hf-model-file.less';
|
import '../style/hf-model-file.less';
|
||||||
import FileSkeleton from './file-skeleton';
|
import FileSkeleton from './file-skeleton';
|
||||||
import ModelFileItem from './model-file-item';
|
import ModelFileItem from './model-file-item';
|
||||||
@@ -40,7 +41,6 @@ interface HFModelFileProps {
|
|||||||
loadingModel?: boolean;
|
loadingModel?: boolean;
|
||||||
modelSource: string;
|
modelSource: string;
|
||||||
ref: any;
|
ref: any;
|
||||||
gpuOptions?: any[];
|
|
||||||
onSelectFile?: (
|
onSelectFile?: (
|
||||||
file: any,
|
file: any,
|
||||||
options: { requestModelId: number; manual?: boolean }
|
options: { requestModelId: number; manual?: boolean }
|
||||||
@@ -250,6 +250,7 @@ const HFModelFile: React.FC<HFModelFileProps> = forwardRef((props, ref) => {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const evaluateFileList = list.map((item: any) => {
|
const evaluateFileList = list.map((item: any) => {
|
||||||
|
// TODO: llamabox is remove from backend options, user should select a available backend
|
||||||
return {
|
return {
|
||||||
backend: backendOptionsMap.llamaBox,
|
backend: backendOptionsMap.llamaBox,
|
||||||
source: modelSource,
|
source: modelSource,
|
||||||
@@ -363,7 +364,7 @@ const HFModelFile: React.FC<HFModelFileProps> = forwardRef((props, ref) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="files-wrap">
|
<div className="files-wrap">
|
||||||
<TitleWrapper>
|
<TitleWrapper style={{ paddingInline: '24px' }}>
|
||||||
<span className="title">
|
<span className="title">
|
||||||
{intl.formatMessage({ id: 'models.available.files' })} (
|
{intl.formatMessage({ id: 'models.available.files' })} (
|
||||||
{dataSource.fileList.length || 0})
|
{dataSource.fileList.length || 0})
|
||||||
|
|||||||
@@ -311,7 +311,7 @@ const ModelCard: React.FC<{
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TitleWrapper>
|
<TitleWrapper style={{ paddingInline: 24 }}>
|
||||||
<div className="title">{modelData?.id || modelData?.name} </div>
|
<div className="title">{modelData?.id || modelData?.name} </div>
|
||||||
{generateModelLink()}
|
{generateModelLink()}
|
||||||
</TitleWrapper>
|
</TitleWrapper>
|
||||||
@@ -392,7 +392,7 @@ const ModelCard: React.FC<{
|
|||||||
<div style={{ minHeight: 200 }}>
|
<div style={{ minHeight: 200 }}>
|
||||||
{readmeText && (
|
{readmeText && (
|
||||||
<>
|
<>
|
||||||
<TitleWrapper>
|
<TitleWrapper style={{ paddingInline: 24 }}>
|
||||||
<span className="title">README.md</span>
|
<span className="title">README.md</span>
|
||||||
</TitleWrapper>
|
</TitleWrapper>
|
||||||
<div className="card-wrapper">
|
<div className="card-wrapper">
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ import SearchResult from './search-result';
|
|||||||
|
|
||||||
const filterOptions = [
|
const filterOptions = [
|
||||||
{ label: 'AWQ', value: 'awq' },
|
{ label: 'AWQ', value: 'awq' },
|
||||||
{ label: 'GPTQ', value: 'gptq' }
|
{ label: 'GPTQ', value: 'gptq' },
|
||||||
// { label: 'GGUF', value: 'gguf' }
|
{ label: 'GGUF', value: 'gguf' }
|
||||||
];
|
];
|
||||||
const PaginationMain = styled(Pagination)`
|
const PaginationMain = styled(Pagination)`
|
||||||
.ant-pagination-slash {
|
.ant-pagination-slash {
|
||||||
@@ -523,11 +523,6 @@ const SearchModel: React.FC<SearchInputProps> = (props) => {
|
|||||||
onChange={handleSearchInputChange}
|
onChange={handleSearchInputChange}
|
||||||
modelSource={modelSource}
|
modelSource={modelSource}
|
||||||
></SearchInput>
|
></SearchInput>
|
||||||
{/* <div className="gguf-tips">
|
|
||||||
<span>
|
|
||||||
{intl.formatMessage({ id: 'models.form.search.gguftips' })}
|
|
||||||
</span>
|
|
||||||
</div> */}
|
|
||||||
<div className={SearchStyle.filter}>
|
<div className={SearchStyle.filter}>
|
||||||
<span className="flex-center gap-8">
|
<span className="flex-center gap-8">
|
||||||
<BaseSelect
|
<BaseSelect
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import '../style/title-wrapper.less';
|
import '../style/title-wrapper.less';
|
||||||
|
|
||||||
const TitleWrapper: React.FC<any> = ({ children }) => {
|
const TitleWrapper: React.FC<any> = ({ children, style }) => {
|
||||||
return (
|
return (
|
||||||
<h3 className="h3" style={{ height: 50 }}>
|
<h3 className="h3" style={{ height: 50, ...style }}>
|
||||||
{children}
|
{children}
|
||||||
</h3>
|
</h3>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -306,8 +306,10 @@ export const modelLabels = [
|
|||||||
|
|
||||||
// do not trigger form check compatibility
|
// do not trigger form check compatibility
|
||||||
export const excludeFields = [
|
export const excludeFields = [
|
||||||
'repo_id',
|
'model_scope_model_id',
|
||||||
'file_name',
|
'huggingface_repo_id',
|
||||||
|
'huggingface_filename',
|
||||||
|
'model_scope_file_path',
|
||||||
'replicas',
|
'replicas',
|
||||||
'name',
|
'name',
|
||||||
'description',
|
'description',
|
||||||
@@ -334,8 +336,10 @@ export const updateIgnoreFields = ['categories', 'replicas', 'description'];
|
|||||||
|
|
||||||
// if some fields need to trigger manual check, add them here
|
// if some fields need to trigger manual check, add them here
|
||||||
export const updateExcludeFields = [
|
export const updateExcludeFields = [
|
||||||
'repo_id',
|
'model_scope_model_id',
|
||||||
'file_name',
|
'huggingface_repo_id',
|
||||||
|
'huggingface_filename',
|
||||||
|
'model_scope_file_path',
|
||||||
'description',
|
'description',
|
||||||
'source',
|
'source',
|
||||||
'worker_selector',
|
'worker_selector',
|
||||||
@@ -352,8 +356,10 @@ export const updateExcludeFields = [
|
|||||||
|
|
||||||
export const formFields = [
|
export const formFields = [
|
||||||
'name',
|
'name',
|
||||||
'repo_id',
|
'model_scope_model_id',
|
||||||
'file_name',
|
'huggingface_repo_id',
|
||||||
|
'huggingface_filename',
|
||||||
|
'model_scope_file_path',
|
||||||
'local_path',
|
'local_path',
|
||||||
'ollama_library_model_name',
|
'ollama_library_model_name',
|
||||||
'backend',
|
'backend',
|
||||||
|
|||||||
@@ -51,8 +51,6 @@ export interface FormData {
|
|||||||
backend_parameters?: string[];
|
backend_parameters?: string[];
|
||||||
backend_version?: string;
|
backend_version?: string;
|
||||||
source: SourceType;
|
source: SourceType;
|
||||||
repo_id: string;
|
|
||||||
file_name: string;
|
|
||||||
huggingface_repo_id: string;
|
huggingface_repo_id: string;
|
||||||
huggingface_filename: string;
|
huggingface_filename: string;
|
||||||
s3_address: string;
|
s3_address: string;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { debounce } from 'lodash';
|
|||||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import ColumnWrapper from '../../_components/column-wrapper';
|
import ColumnWrapper from '../../_components/column-wrapper';
|
||||||
import CompatibilityAlert from '../components/compatible-alert';
|
import HFModelFile from '../components/hf-model-file';
|
||||||
import ModelCard from '../components/model-card';
|
import ModelCard from '../components/model-card';
|
||||||
import SearchModel from '../components/search-model';
|
import SearchModel from '../components/search-model';
|
||||||
import Separator from '../components/separator';
|
import Separator from '../components/separator';
|
||||||
@@ -59,6 +59,7 @@ const DownloadModel: React.FC<AddModalProps> = (props) => {
|
|||||||
const [selectedModel, setSelectedModel] = useState<any>({});
|
const [selectedModel, setSelectedModel] = useState<any>({});
|
||||||
const [collapsed, setCollapsed] = useState<boolean>(false);
|
const [collapsed, setCollapsed] = useState<boolean>(false);
|
||||||
const [isGGUF, setIsGGUF] = useState<boolean>(false);
|
const [isGGUF, setIsGGUF] = useState<boolean>(false);
|
||||||
|
const [fileName, setFileName] = useState<string>('');
|
||||||
const modelFileRef = useRef<any>(null);
|
const modelFileRef = useRef<any>(null);
|
||||||
|
|
||||||
const generateModelInfo = () => {
|
const generateModelInfo = () => {
|
||||||
@@ -106,6 +107,9 @@ const DownloadModel: React.FC<AddModalProps> = (props) => {
|
|||||||
debounceFetchModelFiles();
|
debounceFetchModelFiles();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const handleSelectModelFile = useCallback((item: any) => {
|
||||||
|
setFileName(item.fakeName);
|
||||||
|
}, []);
|
||||||
|
|
||||||
const handleCancel = useCallback(() => {
|
const handleCancel = useCallback(() => {
|
||||||
onCancel?.();
|
onCancel?.();
|
||||||
@@ -178,7 +182,7 @@ const DownloadModel: React.FC<AddModalProps> = (props) => {
|
|||||||
<Separator></Separator>
|
<Separator></Separator>
|
||||||
</ColWrapper>
|
</ColWrapper>
|
||||||
<ColWrapper>
|
<ColWrapper>
|
||||||
<ColumnWrapper styles={{ container: { paddingTop: 0 } }}>
|
<ColumnWrapper styles={{ container: { padding: 0 } }}>
|
||||||
<ModelCard
|
<ModelCard
|
||||||
selectedModel={selectedModel}
|
selectedModel={selectedModel}
|
||||||
onCollapse={setCollapsed}
|
onCollapse={setCollapsed}
|
||||||
@@ -186,6 +190,16 @@ const DownloadModel: React.FC<AddModalProps> = (props) => {
|
|||||||
modelSource={props.source}
|
modelSource={props.source}
|
||||||
setIsGGUF={handleSetIsGGUF}
|
setIsGGUF={handleSetIsGGUF}
|
||||||
></ModelCard>
|
></ModelCard>
|
||||||
|
{isGGUF && (
|
||||||
|
<HFModelFile
|
||||||
|
ref={modelFileRef}
|
||||||
|
selectedModel={selectedModel}
|
||||||
|
modelSource={props.source}
|
||||||
|
onSelectFile={handleSelectModelFile}
|
||||||
|
collapsed={collapsed}
|
||||||
|
isDownload={true}
|
||||||
|
></HFModelFile>
|
||||||
|
)}
|
||||||
</ColumnWrapper>
|
</ColumnWrapper>
|
||||||
<Separator></Separator>
|
<Separator></Separator>
|
||||||
</ColWrapper>
|
</ColWrapper>
|
||||||
@@ -199,21 +213,9 @@ const DownloadModel: React.FC<AddModalProps> = (props) => {
|
|||||||
}}
|
}}
|
||||||
footer={
|
footer={
|
||||||
<>
|
<>
|
||||||
<CompatibilityAlert
|
|
||||||
showClose={false}
|
|
||||||
warningStatus={{
|
|
||||||
show: isGGUF,
|
|
||||||
type: 'danger',
|
|
||||||
message: 'GGUF is not supported'
|
|
||||||
}}
|
|
||||||
contentStyle={{ paddingInline: 0 }}
|
|
||||||
></CompatibilityAlert>
|
|
||||||
<ModalFooter
|
<ModalFooter
|
||||||
onCancel={handleCancel}
|
onCancel={handleCancel}
|
||||||
onOk={handleSumit}
|
onOk={handleSumit}
|
||||||
okBtnProps={{
|
|
||||||
disabled: isGGUF
|
|
||||||
}}
|
|
||||||
style={{
|
style={{
|
||||||
padding: '16px 24px',
|
padding: '16px 24px',
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
|
|||||||
@@ -33,6 +33,15 @@ const LocalPathForm: React.FC = () => {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleOnBlur = (e: any) => {
|
||||||
|
form.setFieldsValue({
|
||||||
|
backend_parameters: [],
|
||||||
|
backend_version: '',
|
||||||
|
backend: '',
|
||||||
|
env: {}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const handleLocalPathBlur = async (e: any) => {
|
const handleLocalPathBlur = async (e: any) => {
|
||||||
const value = e.target.value;
|
const value = e.target.value;
|
||||||
if (value === localPathCache.current || !value) {
|
if (value === localPathCache.current || !value) {
|
||||||
@@ -89,7 +98,7 @@ const LocalPathForm: React.FC = () => {
|
|||||||
<SealInput.Input
|
<SealInput.Input
|
||||||
allowClear
|
allowClear
|
||||||
required
|
required
|
||||||
onBlur={handleLocalPathBlur}
|
onBlur={handleOnBlur}
|
||||||
onFocus={handleOnFocus}
|
onFocus={handleOnFocus}
|
||||||
label={intl.formatMessage({ id: 'models.form.filePath' })}
|
label={intl.formatMessage({ id: 'models.form.filePath' })}
|
||||||
description={<TooltipList list={localPathTipsList}></TooltipList>}
|
description={<TooltipList list={localPathTipsList}></TooltipList>}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import SealInput from '@/components/seal-form/seal-input';
|
import SealInput from '@/components/seal-form/seal-input';
|
||||||
import { PageAction } from '@/config';
|
import { PageAction } from '@/config';
|
||||||
import useAppUtils from '@/hooks/use-app-utils';
|
import useAppUtils from '@/hooks/use-app-utils';
|
||||||
|
import { useIntl } from '@umijs/max';
|
||||||
import { Form } from 'antd';
|
import { Form } from 'antd';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { deployFormKeyMap, modelSourceMap } from '../config';
|
import { deployFormKeyMap, modelSourceMap } from '../config';
|
||||||
@@ -8,10 +9,11 @@ import { useFormContext } from '../config/form-context';
|
|||||||
import { FormData } from '../config/types';
|
import { FormData } from '../config/types';
|
||||||
|
|
||||||
const HuggingFaceForm: React.FC = () => {
|
const HuggingFaceForm: React.FC = () => {
|
||||||
|
const intl = useIntl();
|
||||||
const formInstance = Form.useFormInstance();
|
const formInstance = Form.useFormInstance();
|
||||||
const formCtx = useFormContext();
|
const formCtx = useFormContext();
|
||||||
const { getRuleMessage } = useAppUtils();
|
const { getRuleMessage } = useAppUtils();
|
||||||
const { formKey, pageAction, onValuesChange } = formCtx;
|
const { formKey, pageAction, isGGUF, onValuesChange } = formCtx;
|
||||||
const source = Form.useWatch('source');
|
const source = Form.useWatch('source');
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@@ -43,21 +45,23 @@ const HuggingFaceForm: React.FC = () => {
|
|||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<SealInput.Input
|
<SealInput.Input
|
||||||
label="Base Model"
|
label={intl.formatMessage({ id: 'models.form.repoid' })}
|
||||||
required
|
required
|
||||||
disabled={pageAction === PageAction.CREATE}
|
disabled={pageAction === PageAction.CREATE}
|
||||||
onBlur={handleOnBlur}
|
onBlur={handleOnBlur}
|
||||||
></SealInput.Input>
|
></SealInput.Input>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item<FormData>
|
{isGGUF && (
|
||||||
hidden
|
<Form.Item<FormData>
|
||||||
name="huggingface_filename"
|
name="huggingface_filename"
|
||||||
key="huggingface_filename"
|
key="huggingface_filename"
|
||||||
>
|
>
|
||||||
<SealInput.Input
|
<SealInput.Input
|
||||||
disabled={pageAction === PageAction.CREATE}
|
label={intl.formatMessage({ id: 'models.form.filename' })}
|
||||||
></SealInput.Input>
|
disabled={pageAction === PageAction.CREATE}
|
||||||
</Form.Item>
|
></SealInput.Input>
|
||||||
|
</Form.Item>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
@@ -72,21 +76,23 @@ const HuggingFaceForm: React.FC = () => {
|
|||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<SealInput.Input
|
<SealInput.Input
|
||||||
label="Base Model"
|
|
||||||
required
|
required
|
||||||
|
label={intl.formatMessage({ id: 'models.form.repoid' })}
|
||||||
disabled={pageAction === PageAction.CREATE}
|
disabled={pageAction === PageAction.CREATE}
|
||||||
onBlur={handleOnBlur}
|
onBlur={handleOnBlur}
|
||||||
></SealInput.Input>
|
></SealInput.Input>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item<FormData>
|
{isGGUF && (
|
||||||
hidden
|
<Form.Item<FormData>
|
||||||
name="model_scope_file_path"
|
name="model_scope_file_path"
|
||||||
key="model_scope_file_path"
|
key="model_scope_file_path"
|
||||||
>
|
>
|
||||||
<SealInput.Input
|
<SealInput.Input
|
||||||
disabled={pageAction === PageAction.CREATE}
|
label={intl.formatMessage({ id: 'models.form.filename' })}
|
||||||
></SealInput.Input>
|
disabled={pageAction === PageAction.CREATE}
|
||||||
</Form.Item>
|
></SealInput.Input>
|
||||||
|
</Form.Item>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -26,3 +26,8 @@
|
|||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.card-wrapper {
|
||||||
|
padding: 16px 24px;
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user