chore: model meta data

This commit is contained in:
jialin
2024-12-30 16:07:30 +08:00
parent a24b7433a5
commit aed7267253
20 changed files with 445 additions and 177 deletions
+11 -7
View File
@@ -119,13 +119,17 @@ const AutoTooltip: React.FC<AutoTooltipProps> = ({
borderRadius: 12 borderRadius: 12
}} }}
closeIcon={ closeIcon={
<CloseOutlined tagProps.closable ? (
style={{ <CloseOutlined
position: 'absolute', style={{
right: 8, position: 'absolute',
top: 8 right: 8,
}} top: 8
/> }}
/>
) : (
false
)
} }
> >
{children} {children}
-1
View File
@@ -199,7 +199,6 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = ({
ctx.beginPath(); ctx.beginPath();
stroke.forEach((point, i) => { stroke.forEach((point, i) => {
console.log('Drawing Point:', point);
if (i === 0) { if (i === 0) {
ctx.moveTo(point.x, point.y); ctx.moveTo(point.x, point.y);
} else { } else {
+1
View File
@@ -32,6 +32,7 @@ declare namespace Global {
label: string; label: string;
locale?: boolean; locale?: boolean;
value: T; value: T;
meta?: Record<string, any>;
} }
interface HintOptions { interface HintOptions {
+1 -1
View File
@@ -1,3 +1,3 @@
export default { export default {
playgroundTextToImage: '/playground/text-to-image' '/playground/text-to-image': '/playground/text-to-image'
}; };
+12 -6
View File
@@ -1,11 +1,12 @@
// @ts-nocheck // @ts-nocheck
import { routeCacheAtom } from '@/atoms/route-cache'; import { routeCacheAtom, setRouteCache } from '@/atoms/route-cache';
import { GPUStackVersionAtom, UpdateCheckAtom, userAtom } from '@/atoms/user'; import { GPUStackVersionAtom, UpdateCheckAtom, userAtom } from '@/atoms/user';
import ShortCuts, { import ShortCuts, {
modalConfig as ShortCutsConfig modalConfig as ShortCutsConfig
} from '@/components/short-cuts'; } from '@/components/short-cuts';
import VersionInfo, { modalConfig } from '@/components/version-info'; import VersionInfo, { modalConfig } from '@/components/version-info';
import routeCachekey from '@/config/route-cachekey';
import useOverlayScroller from '@/hooks/use-overlay-scroller'; import useOverlayScroller from '@/hooks/use-overlay-scroller';
import { logout } from '@/pages/login/apis'; import { logout } from '@/pages/login/apis';
import { useAccessMarkedRoutes } from '@@/plugin-access'; import { useAccessMarkedRoutes } from '@@/plugin-access';
@@ -106,8 +107,6 @@ export default (props: any) => {
const [collapsed, setCollapsed] = useState(false); const [collapsed, setCollapsed] = useState(false);
const [collapseValue, setCollapseValue] = useState(false); const [collapseValue, setCollapseValue] = useState(false);
console.log('routeCache========', routeCache);
const initialInfo = (useModel && useModel('@@initialState')) || { const initialInfo = (useModel && useModel('@@initialState')) || {
initialState: undefined, initialState: undefined,
loading: false, loading: false,
@@ -140,10 +139,15 @@ export default (props: any) => {
}); });
}; };
const initRouteCacheValue = (pathname) => {
if (routeCache.get(pathname) === undefined && routeCachekey[pathname]) {
setRouteCache(pathname, false);
}
};
const dropRouteCache = (pathname) => { const dropRouteCache = (pathname) => {
console.log('routeCache.keys()========', routeCache.keys());
for (let key of routeCache.keys()) { for (let key of routeCache.keys()) {
if (key !== pathname && !routeCache.get(key)) { if (key !== pathname && !routeCache.get(key) && routeCachekey[key]) {
dropByCacheKey(key); dropByCacheKey(key);
routeCache.delete(key); routeCache.delete(key);
} }
@@ -302,6 +306,9 @@ export default (props: any) => {
const { location } = history; const { location } = history;
const { pathname } = location; const { pathname } = location;
initRouteCacheValue(pathname);
dropRouteCache(pathname);
// if user is not change password, redirect to change password page // if user is not change password, redirect to change password page
if ( if (
location.pathname !== loginPath && location.pathname !== loginPath &&
@@ -321,7 +328,6 @@ export default (props: any) => {
: '/playground'; : '/playground';
history.push(pathname); history.push(pathname);
} }
dropRouteCache(pathname);
}} }}
formatMessage={formatMessage} formatMessage={formatMessage}
menu={{ menu={{
+7 -1
View File
@@ -124,5 +124,11 @@ export default {
'playground.params.size.description': 'playground.params.size.description':
'The maximum size of the generated image is controlled by the deployment parameters of the model. <a href="https://github.com/gpustack/llama-box" target="_blank">Refer to</a>', 'The maximum size of the generated image is controlled by the deployment parameters of the model. <a href="https://github.com/gpustack/llama-box" target="_blank">Refer to</a>',
'playground.documents.verify.embedding': 'At least add two pieces of text.', 'playground.documents.verify.embedding': 'At least add two pieces of text.',
'playground.documents.verify.rerank': 'The documents cannot be empty.' 'playground.documents.verify.rerank': 'The documents cannot be empty.',
'playground.image.guidance.tip':
'The lower the value, the higher the diversity, and the lower the adherence to the prompt.',
'playground.image.cfg_scale.tip':
'The lower the value, the higher the diversity.',
'playground.image.strength.tip':
'The higher the value, the greater the modification to the original image.'
}; };
+4 -1
View File
@@ -121,5 +121,8 @@ export default {
'playground.params.size.description': 'playground.params.size.description':
'图片生成的最大尺寸受控于模型的部署参数。<a href="https://github.com/gpustack/llama-box" target="_blank">参考文档</a>', '图片生成的最大尺寸受控于模型的部署参数。<a href="https://github.com/gpustack/llama-box" target="_blank">参考文档</a>',
'playground.documents.verify.embedding': '至少输入两条文本', 'playground.documents.verify.embedding': '至少输入两条文本',
'playground.documents.verify.rerank': '文档不能为空' 'playground.documents.verify.rerank': '文档不能为空',
'playground.image.guidance.tip': '值越低,多样性越高,对提示词的贴合度越低',
'playground.image.cfg_scale.tip': '值越低,多样性越高',
'playground.image.strength.tip': '值越高,它对原图的修改越大'
}; };
@@ -156,7 +156,6 @@ const AdvanceConfig: React.FC<AdvanceConfigProps> = (props) => {
<Form.Item<FormData> name="categories"> <Form.Item<FormData> name="categories">
<SealSelect <SealSelect
allowNull allowNull
maxCount={1}
label={intl.formatMessage({ label={intl.formatMessage({
id: 'models.form.categories' id: 'models.form.categories'
})} })}
+34 -22
View File
@@ -13,6 +13,7 @@ import React, {
useEffect, useEffect,
useImperativeHandle, useImperativeHandle,
useMemo, useMemo,
useRef,
useState useState
} from 'react'; } from 'react';
import { queryGPUList } from '../apis'; import { queryGPUList } from '../apis';
@@ -43,6 +44,30 @@ const SEARCH_SOURCE = [
modelSourceMap.modelscope_value modelSourceMap.modelscope_value
]; ];
const sourceOptions = [
{
label: 'Hugging Face',
value: modelSourceMap.huggingface_value,
key: 'huggingface'
},
{
label: 'Ollama Library',
value: modelSourceMap.ollama_library_value,
key: 'ollama_library'
},
{
label: 'ModelScope',
value: modelSourceMap.modelscope_value,
key: 'model_scope'
},
{
label: 'models.form.localPath',
locale: true,
value: modelSourceMap.local_path_value,
key: 'local_path'
}
];
const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => { const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
const { action, isGGUF, onOk } = props; const { action, isGGUF, onOk } = props;
const [form] = Form.useForm(); const [form] = Form.useForm();
@@ -57,28 +82,7 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
speech2text: false speech2text: false
}); });
const sourceOptions = [ const localPathCache = useRef<string>('');
{
label: 'Hugging Face',
value: modelSourceMap.huggingface_value,
key: 'huggingface'
},
{
label: 'Ollama Library',
value: modelSourceMap.ollama_library_value,
key: 'ollama_library'
},
{
label: 'ModelScope',
value: modelSourceMap.modelscope_value,
key: 'model_scope'
},
{
label: intl.formatMessage({ id: 'models.form.localPath' }),
value: modelSourceMap.local_path_value,
key: 'local_path'
}
];
const getGPUList = async () => { const getGPUList = async () => {
const data = await queryGPUList(); const data = await queryGPUList();
@@ -186,8 +190,15 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
} }
}; };
const handleOnFocus = () => {
localPathCache.current = form.getFieldValue('local_path');
};
const handleLocalPathBlur = (e: any) => { const handleLocalPathBlur = (e: any) => {
const value = e.target.value; const value = e.target.value;
if (value === localPathCache.current && value) {
return;
}
const isEndwithGGUF = _.endsWith(value, '.gguf'); const isEndwithGGUF = _.endsWith(value, '.gguf');
let backend = backendOptionsMap.llamaBox; let backend = backendOptionsMap.llamaBox;
if (!isEndwithGGUF) { if (!isEndwithGGUF) {
@@ -344,6 +355,7 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
> >
<SealInput.Input <SealInput.Input
onBlur={handleLocalPathBlur} onBlur={handleLocalPathBlur}
onFocus={handleOnFocus}
label={intl.formatMessage({ id: 'models.form.filePath' })} label={intl.formatMessage({ id: 'models.form.filePath' })}
required required
></SealInput.Input> ></SealInput.Input>
@@ -69,6 +69,7 @@ const InstanceItem: React.FC<InstanceItemProps> = ({
InstanceStatusMap.Initializing, InstanceStatusMap.Initializing,
InstanceStatusMap.Running, InstanceStatusMap.Running,
InstanceStatusMap.Error, InstanceStatusMap.Error,
InstanceStatusMap.Starting,
InstanceStatusMap.Downloading InstanceStatusMap.Downloading
], ],
icon: <IconFont type="icon-logs" /> icon: <IconFont type="icon-logs" />
+62 -34
View File
@@ -8,7 +8,14 @@ import { PageActionType } from '@/config/types';
import { useIntl } from '@umijs/max'; import { useIntl } from '@umijs/max';
import { Form, Modal, Tooltip, Typography } from 'antd'; import { Form, Modal, Tooltip, Typography } from 'antd';
import _ from 'lodash'; import _ from 'lodash';
import React, { memo, useCallback, useEffect, useMemo, useState } from 'react'; import React, {
memo,
useCallback,
useEffect,
useMemo,
useRef,
useState
} from 'react';
import SimpleBar from 'simplebar-react'; import SimpleBar from 'simplebar-react';
import 'simplebar-react/dist/simplebar.min.css'; import 'simplebar-react/dist/simplebar.min.css';
import { queryGPUList } from '../apis'; import { queryGPUList } from '../apis';
@@ -35,6 +42,29 @@ const SEARCH_SOURCE = [
modelSourceMap.modelscope_value modelSourceMap.modelscope_value
]; ];
const sourceOptions = [
{
label: 'Hugging Face',
value: modelSourceMap.huggingface_value,
key: 'huggingface'
},
{
label: 'Ollama Library',
value: modelSourceMap.ollama_library_value,
key: 'ollama_library'
},
{
label: 'ModelScope',
value: modelSourceMap.modelscope_value,
key: 'model_scope'
},
{
label: 'models.form.localPath',
value: modelSourceMap.local_path_value,
key: 'local_path'
}
];
const UpdateModal: React.FC<AddModalProps> = (props) => { const UpdateModal: React.FC<AddModalProps> = (props) => {
const { title, action, open, onOk, onCancel } = props || {}; const { title, action, open, onOk, onCancel } = props || {};
const [form] = Form.useForm(); const [form] = Form.useForm();
@@ -42,6 +72,7 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
const [gpuOptions, setGpuOptions] = useState<any[]>([]); const [gpuOptions, setGpuOptions] = useState<any[]>([]);
const [isGGUF, setIsGGUF] = useState<boolean>(false); const [isGGUF, setIsGGUF] = useState<boolean>(false);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const localPathCache = useRef<string>('');
const getGPUList = async () => { const getGPUList = async () => {
const data = await queryGPUList(); const data = await queryGPUList();
@@ -57,29 +88,6 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
setGpuOptions(list); setGpuOptions(list);
}; };
const sourceOptions = [
{
label: 'Hugging Face',
value: modelSourceMap.huggingface_value,
key: 'huggingface'
},
{
label: 'Ollama Library',
value: modelSourceMap.ollama_library_value,
key: 'ollama_library'
},
{
label: 'ModelScope',
value: modelSourceMap.modelscope_value,
key: 'model_scope'
},
{
label: intl.formatMessage({ id: 'models.form.localPath' }),
value: modelSourceMap.local_path_value,
key: 'local_path'
}
];
useEffect(() => { useEffect(() => {
if (action === PageAction.EDIT && open) { if (action === PageAction.EDIT && open) {
const result = setSourceRepoConfigValue( const result = setSourceRepoConfigValue(
@@ -106,6 +114,34 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
setIsGGUF(props.data?.backend === backendOptionsMap.llamaBox); setIsGGUF(props.data?.backend === backendOptionsMap.llamaBox);
}, [props.data?.backend]); }, [props.data?.backend]);
const handleBackendChange = useCallback((val: string) => {
if (val === backendOptionsMap.llamaBox) {
form.setFieldsValue({
distributed_inference_across_workers: true,
cpu_offloading: true
});
}
form.setFieldValue('backend_version', '');
}, []);
const handleOnFocus = () => {
localPathCache.current = form.getFieldValue('local_path');
};
const handleLocalPathBlur = (e: any) => {
const value = e.target.value;
if (value === localPathCache.current && value) {
return;
}
const isEndwithGGUF = _.endsWith(value, '.gguf');
let backend = backendOptionsMap.llamaBox;
if (!isEndwithGGUF) {
backend = backendOptionsMap.vllm;
}
handleBackendChange?.(backend);
form.setFieldValue('backend', backend);
};
const renderHuggingfaceFields = () => { const renderHuggingfaceFields = () => {
return ( return (
<> <>
@@ -250,6 +286,8 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
]} ]}
> >
<SealInput.Input <SealInput.Input
onBlur={handleLocalPathBlur}
onFocus={handleOnFocus}
disabled={false} disabled={false}
label={intl.formatMessage({ id: 'models.form.filePath' })} label={intl.formatMessage({ id: 'models.form.filePath' })}
required required
@@ -283,16 +321,6 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
form.submit(); 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) => { const handleOk = (formdata: FormData) => {
let obj = {}; let obj = {};
if (formdata.backend === backendOptionsMap.vllm) { if (formdata.backend === backendOptionsMap.vllm) {
+5 -2
View File
@@ -161,6 +161,7 @@ export const modelSourceValueMap = {
export const InstanceStatusMap = { export const InstanceStatusMap = {
Initializing: 'initializing', Initializing: 'initializing',
Starting: 'starting',
Pending: 'pending', Pending: 'pending',
Running: 'running', Running: 'running',
Scheduled: 'scheduled', Scheduled: 'scheduled',
@@ -183,7 +184,8 @@ export const InstanceStatusMapValue = {
[InstanceStatusMap.Error]: 'Error', [InstanceStatusMap.Error]: 'Error',
[InstanceStatusMap.Downloading]: 'Downloading', [InstanceStatusMap.Downloading]: 'Downloading',
[InstanceStatusMap.Unknown]: 'Unknown', [InstanceStatusMap.Unknown]: 'Unknown',
[InstanceStatusMap.Analyzing]: 'Analyzing' [InstanceStatusMap.Analyzing]: 'Analyzing',
[InstanceStatusMap.Starting]: 'Starting'
}; };
export const status: any = { export const status: any = {
@@ -194,7 +196,8 @@ export const status: any = {
[InstanceStatusMap.Error]: StatusMaps.error, [InstanceStatusMap.Error]: StatusMaps.error,
[InstanceStatusMap.Downloading]: StatusMaps.transitioning, [InstanceStatusMap.Downloading]: StatusMaps.transitioning,
[InstanceStatusMap.Unknown]: StatusMaps.inactive, [InstanceStatusMap.Unknown]: StatusMaps.inactive,
[InstanceStatusMap.Analyzing]: StatusMaps.transitioning [InstanceStatusMap.Analyzing]: StatusMaps.transitioning,
[InstanceStatusMap.Starting]: StatusMaps.transitioning
}; };
export const ActionList = [ export const ActionList = [
+1 -1
View File
@@ -31,7 +31,7 @@ export interface ListItem {
export interface FormData { export interface FormData {
backend?: string; backend?: string;
categories?: string; categories?: string[];
backend_parameters?: string[]; backend_parameters?: string[];
backend_version?: string; backend_version?: string;
source: string; source: string;
@@ -67,25 +67,21 @@ const ParamsSettings: React.FC<ParamsSettingsProps> = forwardRef(
})); }));
useEffect(() => { useEffect(() => {
let model = selectedModel || '';
if (showModelSelector) { if (showModelSelector) {
form.setFieldsValue({ model = model || _.get(modelList, '[0].value');
model: selectedModel || _.get(modelList, '[0].value'),
...initialValues
});
setParams({
model: selectedModel || _.get(modelList, '[0].value'),
...initialValues
});
} else {
form.setFieldsValue({
model: selectedModel || '',
...initialValues
});
setParams({
model: selectedModel || '',
...initialValues
});
} }
form.setFieldsValue({
model: model,
...initialValues
});
setParams({
model: model,
...initialValues
});
onModelChange?.(model);
}, [modelList, showModelSelector, selectedModel, initialValues]); }, [modelList, showModelSelector, selectedModel, initialValues]);
const handleModelChange = useCallback( const handleModelChange = useCallback(
+105 -32
View File
@@ -13,7 +13,7 @@ import {
} from '@/utils/fetch-chunk-data'; } from '@/utils/fetch-chunk-data';
import { FileImageOutlined, SwapOutlined } from '@ant-design/icons'; import { FileImageOutlined, SwapOutlined } from '@ant-design/icons';
import { useIntl, useSearchParams } from '@umijs/max'; import { useIntl, useSearchParams } from '@umijs/max';
import { Button, Checkbox, Form, Tooltip } from 'antd'; import { Button, Form, Tooltip } from 'antd';
import classNames from 'classnames'; import classNames from 'classnames';
import _ from 'lodash'; import _ from 'lodash';
import 'overlayscrollbars/overlayscrollbars.css'; import 'overlayscrollbars/overlayscrollbars.css';
@@ -32,8 +32,9 @@ import { promptList } from '../config';
import { import {
ImageAdvancedParamsConfig, ImageAdvancedParamsConfig,
ImageCustomSizeConfig, ImageCustomSizeConfig,
ImageParamsConfig,
ImageconstExtraConfig, ImageconstExtraConfig,
ImageParamsConfig as paramsConfig imageSizeOptions
} from '../config/params-config'; } from '../config/params-config';
import { MessageItem, ParamsSchema } from '../config/types'; import { MessageItem, ParamsSchema } from '../config/types';
import '../style/ground-left.less'; import '../style/ground-left.less';
@@ -48,6 +49,17 @@ interface MessageProps {
loaded?: boolean; loaded?: boolean;
ref?: any; ref?: any;
} }
// for advanced fields
const METAKEYS = [
'sample_method',
'sampling_steps',
'schedule_method',
'cfg_scale',
'guidance',
'negative_prompt'
];
const advancedFieldsDefaultValus = { const advancedFieldsDefaultValus = {
seed: null, seed: null,
sample_method: 'euler_a', sample_method: 'euler_a',
@@ -55,7 +67,7 @@ const advancedFieldsDefaultValus = {
guidance: 3.5, guidance: 3.5,
sampling_steps: 10, sampling_steps: 10,
negative_prompt: null, negative_prompt: null,
schedule_method: 'discrete', schedule_method: 'default',
preview: null preview: null
}; };
@@ -101,12 +113,10 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
const messageListLengthCache = useRef<number>(0); const messageListLengthCache = useRef<number>(0);
const requestToken = useRef<any>(null); const requestToken = useRef<any>(null);
const [currentPrompt, setCurrentPrompt] = useState<string>(''); const [currentPrompt, setCurrentPrompt] = useState<string>('');
const [modelMeta, setModelMeta] = useState<any>({});
const form = useRef<any>(null); const form = useRef<any>(null);
const inputRef = useRef<any>(null); const inputRef = useRef<any>(null);
const previewRef = useRef<any>({ const cacheFormData = useRef<Record<string, any>>({});
preview: false,
preview_faster: false
});
const size = Form.useWatch('size', form.current?.form); const size = Form.useWatch('size', form.current?.form);
@@ -125,10 +135,52 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
}; };
}); });
const paramsConfig = useMemo(() => {
const { max_height, max_width } = modelMeta || {};
if (
!max_height ||
!max_width ||
(max_height === 1024 && max_width === 1024)
) {
return ImageParamsConfig;
}
const newImageSizeOptions = imageSizeOptions.filter((item) => {
return item.width <= max_width && item.height <= max_height;
});
if (
!newImageSizeOptions.find(
(item) => item.width === max_width && item.height === max_height
)
) {
newImageSizeOptions.push({
width: max_width,
height: max_height,
label: `${max_width}x${max_height}`,
value: `${max_width}x${max_height}`
});
}
return ImageParamsConfig.map((item) => {
if (item.name === 'size') {
return {
...item,
options: newImageSizeOptions
};
}
return item;
});
}, [modelMeta]);
const generateNumber = (min: number, max: number) => { const generateNumber = (min: number, max: number) => {
return Math.floor(Math.random() * (max - min + 1) + min); return Math.floor(Math.random() * (max - min + 1) + min);
}; };
const updateCacheFormData = (values: Record<string, any>) => {
cacheFormData.current = {
...cacheFormData.current,
...values
};
};
const handleRandomPrompt = useCallback(() => { const handleRandomPrompt = useCallback(() => {
const randomIndex = generateNumber(0, promptList.length - 1); const randomIndex = generateNumber(0, promptList.length - 1);
const randomPrompt = promptList[randomIndex]; const randomPrompt = promptList[randomIndex];
@@ -211,8 +263,10 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
setMessageId(); setMessageId();
setTokenResult(null); setTokenResult(null);
setCurrentPrompt(current?.content || ''); setCurrentPrompt(current?.content || '');
setRouteCache(routeCachekey.playgroundTextToImage, true); setRouteCache(routeCachekey['/playground/text-to-image'], true);
const imgSize = _.split(finalParameters.size, 'x'); const imgSize = _.split(finalParameters.size, 'x').map((item: number) =>
_.toNumber(item)
);
// preview // preview
let stream_options: Record<string, any> = { let stream_options: Record<string, any> = {
@@ -320,7 +374,7 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
setImageList([]); setImageList([]);
} finally { } finally {
setLoading(false); setLoading(false);
setRouteCache(routeCachekey.playgroundTextToImage, false); setRouteCache(routeCachekey['/playground/text-to-image'], false);
} }
}; };
const handleClear = () => { const handleClear = () => {
@@ -345,12 +399,14 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
const handleToggleParamsStyle = () => { const handleToggleParamsStyle = () => {
if (isOpenaiCompatible) { if (isOpenaiCompatible) {
form.current?.form?.setFieldsValue({ form.current?.form?.setFieldsValue({
...advancedFieldsDefaultValus ...advancedFieldsDefaultValus,
..._.pick(cacheFormData.current, _.keys(advancedFieldsDefaultValus))
}); });
setParams((pre: object) => { setParams((pre: object) => {
return { return {
..._.omit(pre, _.keys(openaiCompatibleFieldsDefaultValus)), ..._.omit(pre, _.keys(openaiCompatibleFieldsDefaultValus)),
...advancedFieldsDefaultValus ...advancedFieldsDefaultValus,
..._.pick(cacheFormData.current, _.keys(advancedFieldsDefaultValus))
}; };
}); });
} else { } else {
@@ -365,6 +421,7 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
}); });
} }
setIsOpenaiCompatible(!isOpenaiCompatible); setIsOpenaiCompatible(!isOpenaiCompatible);
updateCacheFormData(parameters);
}; };
const renderExtra = useMemo(() => { const renderExtra = useMemo(() => {
@@ -428,7 +485,12 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
: item.description?.text : item.description?.text
} }
onChange={item.name === 'random_seed' ? handleFieldChange : null} onChange={item.name === 'random_seed' ? handleFieldChange : null}
{..._.omit(item, ['name', 'rules', 'disabledConfig'])} {..._.omit(item, [
'name',
'rules',
'disabledConfig',
'description'
])}
></FieldComponent> ></FieldComponent>
</Form.Item> </Form.Item>
); );
@@ -470,34 +532,44 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
'rules', 'rules',
'disabledConfig' 'disabledConfig'
])} ])}
max={
item.name === 'height'
? modelMeta.max_height || item.attrs?.max
: modelMeta.max_width || item.attrs?.max
}
></FieldComponent> ></FieldComponent>
</Form.Item> </Form.Item>
); );
}); });
} }
return null; return null;
}, [size, intl]); }, [size, intl, modelMeta]);
const hanldeOnPreview = (e: any) => { const handleOnModelChange = useCallback(
previewRef.current.preview = e.target.checked; (val: string) => {
}; if (!val) return;
const hanldeOnPreviewFaster = (e: any) => { const model = modelList.find((item) => item.value === val);
previewRef.current.preview_faster = e.target.checked;
};
const renderPreview = useMemo(() => { setModelMeta(model?.meta || {});
return (
<> if (!isOpenaiCompatible) {
<Checkbox onChange={hanldeOnPreview} defaultChecked={false}> setParams((pre: object) => {
Preview return {
</Checkbox> ...pre,
<Checkbox onChange={hanldeOnPreviewFaster} defaultChecked={false}> ..._.pick(model?.meta, METAKEYS, {})
Preview Faster };
</Checkbox> });
</> form.current?.form?.setFieldsValue({
); ..._.pick(model?.meta, METAKEYS, {})
}, []); });
}
updateCacheFormData({
..._.pick(model?.meta, METAKEYS, {})
});
},
[modelList, isOpenaiCompatible]
);
useEffect(() => { useEffect(() => {
return () => { return () => {
@@ -672,6 +744,7 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
</Tooltip> </Tooltip>
</div> </div>
} }
onModelChange={handleOnModelChange}
setParams={setParams} setParams={setParams}
paramsConfig={paramsConfig} paramsConfig={paramsConfig}
initialValues={initialValues} initialValues={initialValues}
+101 -10
View File
@@ -33,8 +33,9 @@ import { EDIT_IMAGE_API } from '../apis';
import { import {
ImageAdvancedParamsConfig, ImageAdvancedParamsConfig,
ImageCustomSizeConfig, ImageCustomSizeConfig,
ImageParamsConfig,
ImageconstExtraConfig, ImageconstExtraConfig,
ImageEidtParamsConfig as paramsConfig imageSizeOptions
} from '../config/params-config'; } from '../config/params-config';
import { MessageItem, ParamsSchema } from '../config/types'; import { MessageItem, ParamsSchema } from '../config/types';
import '../style/ground-left.less'; import '../style/ground-left.less';
@@ -49,6 +50,18 @@ interface MessageProps {
loaded?: boolean; loaded?: boolean;
ref?: any; ref?: any;
} }
// for advanced fields
const METAKEYS = [
'sample_method',
'sampling_steps',
'schedule_method',
'cfg_scale',
'guidance',
'negative_prompt',
'strength'
];
const advancedFieldsDefaultValus = { const advancedFieldsDefaultValus = {
seed: 1, seed: 1,
sample_method: 'euler_a', sample_method: 'euler_a',
@@ -58,7 +71,7 @@ const advancedFieldsDefaultValus = {
sampling_steps: 10, sampling_steps: 10,
negative_prompt: null, negative_prompt: null,
preview: null, preview: null,
schedule_method: 'discrete' schedule_method: 'default'
}; };
const openaiCompatibleFieldsDefaultValus = { const openaiCompatibleFieldsDefaultValus = {
@@ -109,6 +122,7 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
const [image, setImage] = useState<string>(''); const [image, setImage] = useState<string>('');
const [mask, setMask] = useState<string>(''); const [mask, setMask] = useState<string>('');
const [uploadList, setUploadList] = useState<any[]>([]); const [uploadList, setUploadList] = useState<any[]>([]);
const [modelMeta, setModelMeta] = useState<any>({});
const [imageStatus, setImageStatus] = useState<{ const [imageStatus, setImageStatus] = useState<{
isOriginal: boolean; isOriginal: boolean;
isResetNeeded: boolean; isResetNeeded: boolean;
@@ -116,7 +130,7 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
isOriginal: false, isOriginal: false,
isResetNeeded: false isResetNeeded: false
}); });
const cacheFormData = useRef<any>({});
const size = Form.useWatch('size', form.current?.form); const size = Form.useWatch('size', form.current?.form);
const { initialize, updateScrollerPosition } = useOverlayScroller(); const { initialize, updateScrollerPosition } = useOverlayScroller();
@@ -134,6 +148,48 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
}; };
}); });
const updateCacheFormData = (values: Record<string, any>) => {
cacheFormData.current = {
...cacheFormData.current,
...values
};
};
const paramsConfig = useMemo(() => {
const { max_height, max_width } = modelMeta || {};
if (
!max_height ||
!max_width ||
(max_height === 1024 && max_width === 1024)
) {
return ImageParamsConfig;
}
const newImageSizeOptions = imageSizeOptions.filter((item) => {
return item.width <= max_width && item.height <= max_height;
});
if (
!newImageSizeOptions.find(
(item) => item.width === max_width && item.height === max_height
)
) {
newImageSizeOptions.push({
width: max_width,
height: max_height,
label: `${max_width}x${max_height}`,
value: `${max_width}x${max_height}`
});
}
return ImageParamsConfig.map((item) => {
if (item.name === 'size') {
return {
...item,
options: newImageSizeOptions
};
}
return item;
});
}, [modelMeta]);
const setImageSize = useCallback(() => { const setImageSize = useCallback(() => {
let size: Record<string, string | number> = { let size: Record<string, string | number> = {
span: 12 span: 12
@@ -154,12 +210,10 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
}, [parameters.n]); }, [parameters.n]);
const imageFile = useMemo(() => { const imageFile = useMemo(() => {
console.log('image:', image);
return base64ToFile(image, 'image'); return base64ToFile(image, 'image');
}, [image]); }, [image]);
const maskFile = useMemo(() => { const maskFile = useMemo(() => {
console.log('mask:', mask);
return base64ToFile(mask, 'mask'); return base64ToFile(mask, 'mask');
}, [mask]); }, [mask]);
@@ -224,7 +278,7 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
setMessageId(); setMessageId();
setTokenResult(null); setTokenResult(null);
setCurrentPrompt(current?.content || ''); setCurrentPrompt(current?.content || '');
setRouteCache(routeCachekey.playgroundTextToImage, true); setRouteCache(routeCachekey['/playground/text-to-image'], true);
const imgSize = _.split(finalParameters.size, 'x').map((item: string) => const imgSize = _.split(finalParameters.size, 'x').map((item: string) =>
_.toNumber(item) _.toNumber(item)
@@ -284,7 +338,7 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
const result: any = await fetchChunkedData({ const result: any = await fetchChunkedData({
data: params, data: params,
// url: `http://192.168.50.174:40935/v1/images/edits?t=${Date.now()}`, // url: `http:///v1/images/edits?t=${Date.now()}`,
url: `${EDIT_IMAGE_API}?t=${Date.now()}`, url: `${EDIT_IMAGE_API}?t=${Date.now()}`,
signal: requestToken.current.signal signal: requestToken.current.signal
}); });
@@ -339,7 +393,7 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
setImageList([]); setImageList([]);
} finally { } finally {
setLoading(false); setLoading(false);
setRouteCache(routeCachekey.playgroundTextToImage, false); setRouteCache(routeCachekey['/playground/text-to-image'], false);
} }
}; };
const handleClear = () => { const handleClear = () => {
@@ -447,7 +501,12 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
: item.description?.text || '' : item.description?.text || ''
} }
onChange={item.name === 'random_seed' ? handleFieldChange : null} onChange={item.name === 'random_seed' ? handleFieldChange : null}
{..._.omit(item, ['name', 'rules', 'disabledConfig'])} {..._.omit(item, [
'name',
'rules',
'disabledConfig',
'description'
])}
></FieldComponent> ></FieldComponent>
</Form.Item> </Form.Item>
); );
@@ -489,13 +548,44 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
'rules', 'rules',
'disabledConfig' 'disabledConfig'
])} ])}
max={
item.name === 'height'
? modelMeta.max_height || item.attrs?.max
: modelMeta.max_width || item.attrs?.max
}
></FieldComponent> ></FieldComponent>
</Form.Item> </Form.Item>
); );
}); });
} }
return null; return null;
}, [size, intl]); }, [size, intl, modelMeta]);
const handleOnModelChange = useCallback(
(val: string) => {
if (!val) return;
const model = modelList.find((item) => item.value === val);
setModelMeta(model?.meta || {});
if (!isOpenaiCompatible) {
setParams((pre: object) => {
return {
...pre,
..._.pick(model?.meta, METAKEYS, {})
};
});
form.current?.form?.setFieldsValue({
..._.pick(model?.meta, METAKEYS, {})
});
}
updateCacheFormData({
..._.pick(model?.meta, METAKEYS, {})
});
},
[modelList, isOpenaiCompatible]
);
const handleUpdateImageList = useCallback((base64List: any) => { const handleUpdateImageList = useCallback((base64List: any) => {
const img = _.get(base64List, '[0].dataUrl', ''); const img = _.get(base64List, '[0].dataUrl', '');
@@ -758,6 +848,7 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
</Tooltip> </Tooltip>
</div> </div>
} }
onModelChange={handleOnModelChange}
setParams={setParams} setParams={setParams}
paramsConfig={paramsConfig} paramsConfig={paramsConfig}
initialValues={initialValues} initialValues={initialValues}
@@ -29,6 +29,14 @@ type ParamsSettingsProps = {
globalParams?: ParamsSettingsFormProps; globalParams?: ParamsSettingsFormProps;
}; };
const METAKEYS: Record<string, string> = {
seed: 'seed',
stop: 'stop',
temperature: 'temperature',
top_p: 'top_p',
max_tokens: 'n_ctx'
};
const ParamsSettings: React.FC<ParamsSettingsProps> = ({ const ParamsSettings: React.FC<ParamsSettingsProps> = ({
selectedModel, selectedModel,
setParams, setParams,
@@ -49,28 +57,6 @@ const ParamsSettings: React.FC<ParamsSettingsProps> = ({
const [form] = Form.useForm(); const [form] = Form.useForm();
const formId = useId(); const formId = useId();
useEffect(() => {
if (showModelSelector) {
form.setFieldsValue({
...initialValues,
model: selectedModel || _.get(modelList, '[0].value')
});
setParams({
...initialValues,
model: selectedModel || _.get(modelList, '[0].value')
});
} else {
form.setFieldsValue({
...initialValues,
model: selectedModel || ''
});
setParams({
...initialValues,
model: selectedModel || ''
});
}
}, [modelList, showModelSelector, selectedModel]);
const handleOnFinish = (values: any) => { const handleOnFinish = (values: any) => {
console.log('handleOnFinish', values); console.log('handleOnFinish', values);
}; };
@@ -108,11 +94,42 @@ const ParamsSettings: React.FC<ParamsSettingsProps> = ({
[form, setParams, onValuesChange] [form, setParams, onValuesChange]
); );
const handleResetParams = () => { const handleModelChange = (val: string) => {
form.setFieldsValue(initialValues); const model = _.find(modelList, { value: val });
setParams(initialValues); const modelMeta = model?.meta || {};
const keys = Object.keys(METAKEYS).map((k: string) => {
return METAKEYS[k];
});
const modelMetaKeys = _.pick(modelMeta, keys);
const obj = _.reduce(
METAKEYS,
(result: any, value: any, key: string) => {
result[key] = modelMetaKeys[value];
return result;
},
{}
);
return obj;
}; };
useEffect(() => {
let model = selectedModel || '';
if (showModelSelector) {
model = model || _.get(modelList, '[0].value');
}
const modelMetaData = handleModelChange(model);
form.setFieldsValue({
...initialValues,
...modelMetaData,
model: model
});
setParams({
...initialValues,
...modelMetaData,
model: model
});
}, [modelList, showModelSelector, selectedModel]);
useEffect(() => { useEffect(() => {
form.setFieldsValue(globalParams); form.setFieldsValue(globalParams);
}, [globalParams]); }, [globalParams]);
+37 -12
View File
@@ -1,5 +1,25 @@
import { ParamsSchema } from './types'; import { ParamsSchema } from './types';
export const imageSizeOptions: {
label: string;
value: string;
width: number;
height: number;
locale?: boolean;
}[] = [
{
label: 'playground.params.custom',
value: 'custom',
locale: true,
width: 0,
height: 0
},
{ label: '512x512', value: '512x512', width: 512, height: 512 },
{ label: '768x1024', value: '768x1024', width: 768, height: 1024 },
{ label: '1024x768', value: '1024x768', width: 1024, height: 768 },
{ label: '1024x1024', value: '1024x1024', width: 1024, height: 1024 }
];
export const TTSParamsConfig: ParamsSchema[] = [ export const TTSParamsConfig: ParamsSchema[] = [
{ {
type: 'Select', type: 'Select',
@@ -104,13 +124,7 @@ export const ImageParamsConfig: ParamsSchema[] = [
{ {
type: 'Select', type: 'Select',
name: 'size', name: 'size',
options: [ options: imageSizeOptions,
{ label: 'playground.params.custom', value: 'custom', locale: true },
{ label: '512x512', value: '512x512' },
{ label: '768x1024', value: '768x1024' },
{ label: '1024x768', value: '1024x768' },
{ label: '1024x1024', value: '1024x1024' }
],
description: { description: {
text: 'playground.params.size.description', text: 'playground.params.size.description',
html: true, html: true,
@@ -264,6 +278,7 @@ export const ImageAdvancedParamsConfig: ParamsSchema[] = [
type: 'Select', type: 'Select',
name: 'schedule_method', name: 'schedule_method',
options: [ options: [
{ label: 'default', value: 'default' },
{ label: 'discrete', value: 'discrete' }, { label: 'discrete', value: 'discrete' },
{ label: 'karras', value: 'karras' }, { label: 'karras', value: 'karras' },
{ label: 'exponential', value: 'exponential' }, { label: 'exponential', value: 'exponential' },
@@ -304,6 +319,11 @@ export const ImageAdvancedParamsConfig: ParamsSchema[] = [
text: 'Guidance', text: 'Guidance',
isLocalized: false isLocalized: false
}, },
description: {
text: 'playground.image.guidance.tip',
html: false,
isLocalized: true
},
attrs: { attrs: {
min: 1.0, min: 1.0,
max: 10, max: 10,
@@ -322,11 +342,11 @@ export const ImageAdvancedParamsConfig: ParamsSchema[] = [
text: 'Strength', text: 'Strength',
isLocalized: false isLocalized: false
}, },
// description: { description: {
// text: '值越高,它对原图的修改越大,更多变化', text: 'playground.image.strength.tip',
// html: false, html: false,
// isLocalized: false isLocalized: true
// }, },
attrs: { attrs: {
min: 0, min: 0,
max: 1, max: 1,
@@ -345,6 +365,11 @@ export const ImageAdvancedParamsConfig: ParamsSchema[] = [
text: 'CFG Scale', text: 'CFG Scale',
isLocalized: false isLocalized: false
}, },
description: {
text: 'playground.image.cfg_scale.tip',
html: false,
isLocalized: true
},
attrs: { attrs: {
min: 1.0, min: 1.0,
max: 10, max: 10,
+4 -2
View File
@@ -85,13 +85,15 @@ const TextToImages: React.FC = () => {
const getModelList = async () => { const getModelList = async () => {
try { try {
const params = { const params = {
categories: 'image' categories: 'image',
with_meta: true
}; };
const res = await queryModelsList(params); const res = await queryModelsList(params);
const list = _.map(res.data || [], (item: any) => { const list = _.map(res.data || [], (item: any) => {
return { return {
value: item.id, value: item.id,
label: item.id label: item.id,
meta: item.meta
}; };
}) as Global.BaseOption<string>[]; }) as Global.BaseOption<string>[];
return list; return list;
+4 -2
View File
@@ -79,13 +79,15 @@ const Playground: React.FC = () => {
const getModelList = async () => { const getModelList = async () => {
try { try {
const params = { const params = {
categories: '' categories: '',
with_meta: true
}; };
const res = await queryModelsList(params); const res = await queryModelsList(params);
const list = _.map(res.data || [], (item: any) => { const list = _.map(res.data || [], (item: any) => {
return { return {
value: item.id, value: item.id,
label: item.id label: item.id,
meta: item.meta
}; };
}) as Global.BaseOption<string>[]; }) as Global.BaseOption<string>[];
return list; return list;