chore: generate invertion mask in image editor

This commit is contained in:
jialin
2025-03-04 17:52:14 +08:00
parent 8a98aef28c
commit 9f40bf6f5d
6 changed files with 121 additions and 73 deletions
+4 -2
View File
@@ -141,7 +141,9 @@ export default {
'playground.image.fitview': 'Fit View', 'playground.image.fitview': 'Fit View',
'playground.chat.aithought': 'CoT', 'playground.chat.aithought': 'CoT',
'playground.image.mask.uploaded': 'Mask Uploaded', 'playground.image.mask.uploaded': 'Mask Uploaded',
'playground.image.mask.upload': 'Upload Mask', 'playground.image.mask.upload': 'Upload Mask: takes priority in submission.',
'playground.params.frequency_penalty.tips': `Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.`, 'playground.params.frequency_penalty.tips': `Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.`,
'playground.params.presence_penalty.tips': `Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics.` 'playground.params.presence_penalty.tips': `Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics.`,
'playground.image.origin': 'Original',
'playground.image.mask': 'Mask'
}; };
+4 -2
View File
@@ -136,7 +136,9 @@ export default {
'playground.image.fitview': '适应视图', 'playground.image.fitview': '适应视图',
'playground.chat.aithought': '思考过程', 'playground.chat.aithought': '思考过程',
'playground.image.mask.uploaded': '遮罩已上传', 'playground.image.mask.uploaded': '遮罩已上传',
'playground.image.mask.upload': '上传遮罩', 'playground.image.mask.upload': '上传遮罩:在提交时优先使用',
'playground.params.frequency_penalty.tips': `数值介于 -2.0 和 2.0 之间。正值会根据新词在文本中已出现的频率对其进行惩罚,从而降低模型逐字重复相同内容的可能性。`, 'playground.params.frequency_penalty.tips': `数值介于 -2.0 和 2.0 之间。正值会根据新词在文本中已出现的频率对其进行惩罚,从而降低模型逐字重复相同内容的可能性。`,
'playground.params.presence_penalty.tips': `数值介于 -2.0 和 2.0 之间。正值会根据新词是否已在文本中出现过对其进行惩罚,从而增加模型谈论新话题的可能性。` 'playground.params.presence_penalty.tips': `数值介于 -2.0 和 2.0 之间。正值会根据新词是否已在文本中出现过对其进行惩罚,从而增加模型谈论新话题的可能性。`,
'playground.image.origin': '原图',
'playground.image.mask': '遮罩'
}; };
+33 -17
View File
@@ -6,26 +6,42 @@ import { GPUListItem, ListItem } from '../config/types';
export const useGenerateFormEditInitialValues = () => { export const useGenerateFormEditInitialValues = () => {
const gpuDeviceList = useRef<any[]>([]); const gpuDeviceList = useRef<any[]>([]);
const generateCascaderOptions = (list: GPUListItem[]) => { const generateCascaderOptions = (list: GPUListItem[]) => {
const workerFields = ['worker_name', 'worker_id', 'worker_ip']; const workerFields = new Set(['worker_name', 'worker_id', 'worker_ip']);
const workers = _.groupBy(list, 'worker_name'); const workersMap = new Map<string, GPUListItem[]>();
for (const item of list) {
if (!workersMap.has(item.worker_name)) {
workersMap.set(item.worker_name, []);
}
workersMap.get(item.worker_name)!.push(item);
}
const workerList = _.map(workers, (value: GPUListItem[]) => { const workerList = Array.from(workersMap.entries()).map(
return { ([workerName, items]) => {
label: `${value[0].worker_name}`, const firstItem = items[0];
value: value[0].worker_name,
parent: true, return {
..._.pick(value[0], workerFields), label: workerName,
children: _.map(value, (item: GPUListItem) => { value: workerName,
return { parent: true,
label: `${item.name}`, children: items
value: item.id, .map((item) => ({
..._.omit(item, workerFields) label: item.name,
}; value: item.id,
}) index: item.index,
}; ...Object.fromEntries(
}); Object.entries(item).filter(([key]) => !workerFields.has(key))
)
}))
.sort((a, b) => a.index - b.index),
...Object.fromEntries(
Object.entries(firstItem).filter(([key]) => workerFields.has(key))
)
};
}
);
return workerList; return workerList;
}; };
+47 -32
View File
@@ -22,6 +22,7 @@ import React, {
useState useState
} from 'react'; } from 'react';
import { EDIT_IMAGE_API } from '../apis'; import { EDIT_IMAGE_API } from '../apis';
import { scaleImageSize } from '../config';
import { useInitImageMeta } from '../hooks/use-init-meta'; import { useInitImageMeta } from '../hooks/use-init-meta';
import useTextImage from '../hooks/use-text-image'; import useTextImage from '../hooks/use-text-image';
import '../style/ground-left.less'; import '../style/ground-left.less';
@@ -69,6 +70,9 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
handleToggleParamsStyle, handleToggleParamsStyle,
setParams, setParams,
updateCacheFormData, updateCacheFormData,
setInitialValues,
updateParamsConfig,
setParamsConfig,
form, form,
watchFields, watchFields,
paramsConfig, paramsConfig,
@@ -219,45 +223,51 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
}; };
const handleOnScaleImageSize = useCallback( const handleOnScaleImageSize = useCallback(
(data: { width: number; height: number }) => { (data: { rawWidth: number; rawHeight: number }) => {
const { width, height } = data; const { width, height } = scaleImageSize({
form.current?.form?.setFieldsValue({ width: data.rawWidth,
height: data.rawHeight
});
const newParamsConfig = updateParamsConfig({
size: 'custom',
isOpenaiCompatible
});
setParamsConfig(newParamsConfig);
const newParameters = {
...parameters,
size: 'custom', size: 'custom',
width: width || 512, width: width || 512,
height: height || 512 height: height || 512
}); };
setParams((pre: object) => { setParams(newParameters);
return {
...pre,
size: 'custom',
width: width || 512,
height: height || 512
};
});
updateCacheFormData({ updateCacheFormData({
size: 'custom', size: 'custom',
width: width || 512, width: width || 512,
height: height || 512 height: height || 512
}); });
setInitialValues(newParameters);
}, },
[] [parameters, isOpenaiCompatible]
); );
const handleUpdateImageList = useCallback((base64List: any) => { const handleUpdateImageList = useCallback(
const currentImg = _.get(base64List, '[0]', {}); (base64List: any) => {
const img = _.get(currentImg, 'dataUrl', ''); const currentImg = _.get(base64List, '[0]', {});
handleOnScaleImageSize(currentImg); const img = _.get(currentImg, 'dataUrl', '');
setUploadList(base64List); handleOnScaleImageSize(currentImg);
setImage(img); setUploadList(base64List);
setActiveImgUid(_.get(base64List, '[0].uid', '')); setImage(img);
setImageStatus({ setActiveImgUid(_.get(base64List, '[0].uid', ''));
isOriginal: true, setImageStatus({
isResetNeeded: true, isOriginal: true,
width: _.get(currentImg, 'width', 512), isResetNeeded: true,
height: _.get(currentImg, 'height', 512) width: _.get(currentImg, 'width', 512),
}); height: _.get(currentImg, 'height', 512)
setImageList([]); });
}, []); setImageList([]);
},
[handleOnScaleImageSize]
);
const handleUpdateMaskList = useCallback((base64List: any) => { const handleUpdateMaskList = useCallback((base64List: any) => {
setMaskUpload(base64List); setMaskUpload(base64List);
@@ -340,6 +350,7 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
</> </>
); );
}, [ }, [
intl,
image, image,
loading, loading,
maskUpload, maskUpload,
@@ -388,11 +399,13 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
editable={false} editable={false}
autoBgColor={false} autoBgColor={false}
onClick={() => handleOnImgClick(uploadList[0], true)} onClick={() => handleOnImgClick(uploadList[0], true)}
label={<span>Origin</span>} label={
<span>{intl.formatMessage({ id: 'playground.image.origin' })}</span>
}
></SingleImage> ></SingleImage>
</> </>
); );
}, [uploadList, handleOnImgClick]); }, [uploadList, intl, handleOnImgClick]);
const renderMaskImage = useMemo(() => { const renderMaskImage = useMemo(() => {
if (!maskUpload.length) { if (!maskUpload.length) {
@@ -409,11 +422,13 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
autoSize={false} autoSize={false}
editable={false} editable={false}
autoBgColor={false} autoBgColor={false}
label={<span>Mask</span>} label={
<span>{intl.formatMessage({ id: 'playground.image.mask' })}</span>
}
></SingleImage> ></SingleImage>
</> </>
); );
}, [maskUpload]); }, [maskUpload, intl]);
return ( return (
<div className="ground-left-wrapper"> <div className="ground-left-wrapper">
@@ -367,6 +367,7 @@ const MessageInput: React.FC<MessageInputProps> = forwardRef(
title={intl.formatMessage({ id: 'common.button.clear' })} title={intl.formatMessage({ id: 'common.button.clear' })}
> >
<Button <Button
disabled={loading}
type="text" type="text"
icon={<ClearOutlined />} icon={<ClearOutlined />}
size="middle" size="middle"
+32 -20
View File
@@ -297,6 +297,28 @@ export const useInitImageMeta = (props: MessageProps) => {
}; };
}; };
const updateParamsConfig = (values: {
size: string;
isOpenaiCompatible: boolean;
}) => {
// update config
if (values.size === 'custom') {
return [
...basicParamsConfig,
...ImageCustomSizeConfig,
...(values.isOpenaiCompatible
? ImageconstExtraConfig
: ImageAdvancedParamsConfig)
];
}
return [
...basicParamsConfig,
...(values.isOpenaiCompatible
? ImageconstExtraConfig
: ImageAdvancedParamsConfig)
];
};
const updateCacheFormData = (values: Record<string, any>) => { const updateCacheFormData = (values: Record<string, any>) => {
_.merge(cacheFormData.current, values); _.merge(cacheFormData.current, values);
}; };
@@ -322,28 +344,15 @@ export const useInitImageMeta = (props: MessageProps) => {
} }
// update config // update config
if (values.size === 'custom') { const newParamsConfig = updateParamsConfig({
const config = [ size: values.size,
...basicParamsConfig, isOpenaiCompatible: !isOpenaiCompatible
...ImageCustomSizeConfig, });
...(isOpenaiCompatible
? ImageAdvancedParamsConfig
: ImageconstExtraConfig)
];
setParamsConfig(config);
} else {
const config = [
...basicParamsConfig,
...(isOpenaiCompatible
? ImageAdvancedParamsConfig
: ImageconstExtraConfig)
];
setParamsConfig(config);
}
form.current?.form?.setFieldsValue({ form.current?.form?.setFieldsValue({
...values, ...values,
model: parameters.model model: parameters.model
}); });
setParamsConfig(newParamsConfig);
setParams({ setParams({
...values, ...values,
model: parameters.model model: parameters.model
@@ -357,7 +366,7 @@ export const useInitImageMeta = (props: MessageProps) => {
const handleOnModelChange = useCallback( const handleOnModelChange = useCallback(
(val: string) => { (val: string) => {
if (!val) return; if (!val || val === parameters.model) return;
const model = modelList.find((item) => item.value === val); const model = modelList.find((item) => item.value === val);
const { form: initialData, sizeOptions } = extractIMGMeta(model?.meta); const { form: initialData, sizeOptions } = extractIMGMeta(model?.meta);
const newParamsConfig = generateImageParamsConfig(model, sizeOptions); const newParamsConfig = generateImageParamsConfig(model, sizeOptions);
@@ -380,7 +389,7 @@ export const useInitImageMeta = (props: MessageProps) => {
}); });
updateCacheFormData(initialData); updateCacheFormData(initialData);
}, },
[modelList, isOpenaiCompatible] [modelList, isOpenaiCompatible, parameters.model]
); );
const handleOnValuesChange = useCallback( const handleOnValuesChange = useCallback(
@@ -446,6 +455,9 @@ export const useInitImageMeta = (props: MessageProps) => {
handleOnValuesChange, handleOnValuesChange,
handleToggleParamsStyle, handleToggleParamsStyle,
setParams, setParams,
setInitialValues,
updateParamsConfig,
setParamsConfig,
form, form,
watchFields, watchFields,
paramsConfig, paramsConfig,