feat: manually mirror opencoze's code from bytedance
Change-Id: I09a73aadda978ad9511264a756b2ce51f5761adf
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 6.7 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 7.2 KiB |
|
After Width: | Height: | Size: 8.0 KiB |
|
After Width: | Height: | Size: 5.8 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 7.4 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 5.8 KiB |
|
After Width: | Height: | Size: 4.7 KiB |
|
After Width: | Height: | Size: 9.5 KiB |
|
After Width: | Height: | Size: 9.5 KiB |
|
After Width: | Height: | Size: 8.4 KiB |
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export { ModelSettingField } from './model-setting-field';
|
||||
export { ReferencesField } from './references-field';
|
||||
export { PromptField } from './prompt-field';
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { I18n, type I18nKeysNoOptionsType } from '@coze-arch/i18n';
|
||||
|
||||
import thumbnail8 from '../../assets/8.png';
|
||||
import thumbnail7 from '../../assets/7.jpg';
|
||||
import thumbnail6 from '../../assets/6.jpg';
|
||||
import thumbnail5 from '../../assets/5.jpg';
|
||||
import thumbnail4 from '../../assets/4.jpg';
|
||||
import thumbnail3 from '../../assets/3.jpg';
|
||||
import thumbnail2 from '../../assets/2.jpg';
|
||||
import thumbnail1 from '../../assets/1.jpg';
|
||||
|
||||
const thumbnails = [
|
||||
thumbnail1,
|
||||
thumbnail2,
|
||||
thumbnail3,
|
||||
thumbnail4,
|
||||
thumbnail5,
|
||||
thumbnail6,
|
||||
thumbnail7,
|
||||
thumbnail8,
|
||||
];
|
||||
|
||||
export function createModelOptions() {
|
||||
let models = [1, 8, 2, 3, 4, 5, 6, 7];
|
||||
|
||||
if (IS_OVERSEA) {
|
||||
models = models.filter(model => ![6].includes(model));
|
||||
}
|
||||
|
||||
return models.map(model => ({
|
||||
label: I18n.t(`Imageflow_model${model}` as I18nKeysNoOptionsType),
|
||||
value: model,
|
||||
thumbnail: thumbnails[model - 1],
|
||||
}));
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export { ModelSettingField } from './model-setting-field';
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ImageModelSelectField } from '@/node-registries/common/components';
|
||||
import { type FieldProps } from '@/form';
|
||||
|
||||
import { createModelOptions } from './create-model-options';
|
||||
|
||||
export const ModelField = (props: Omit<FieldProps, 'children'>) => (
|
||||
<ImageModelSelectField options={createModelOptions()} {...props} />
|
||||
);
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
|
||||
import { Section, SliderField, type FieldProps } from '@/form';
|
||||
|
||||
import { RatioField } from './ratio-field';
|
||||
import { ModelField } from './model-field';
|
||||
|
||||
export const ModelSettingField = ({ name }: Pick<FieldProps, 'name'>) => (
|
||||
<Section title={I18n.t('Imageflow_model_deploy')}>
|
||||
<div className="flex flex-col gap-[8px]">
|
||||
<ModelField
|
||||
name={`${name}.model`}
|
||||
layout="vertical"
|
||||
label={I18n.t('Imageflow_model')}
|
||||
/>
|
||||
<RatioField
|
||||
name={`${name}.custom_ratio`}
|
||||
layout="vertical"
|
||||
label={I18n.t('Imageflow_ratio')}
|
||||
tooltip={I18n.t('Imageflow_size_range')}
|
||||
/>
|
||||
<SliderField
|
||||
name={`${name}.ddim_steps`}
|
||||
layout="vertical"
|
||||
label={I18n.t('Imageflow_generate_standard')}
|
||||
tooltip={I18n.t('imageflow_generation_desc1')}
|
||||
min={1}
|
||||
max={40}
|
||||
step={1}
|
||||
/>
|
||||
</div>
|
||||
</Section>
|
||||
);
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { SizeSelect } from '@coze-workflow/components';
|
||||
|
||||
import { withField, useField } from '@/form';
|
||||
|
||||
const ratioOptions = [
|
||||
{
|
||||
label: '16:9 (1024*576)',
|
||||
value: {
|
||||
width: 1024,
|
||||
height: 576,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '3:2 (1024*682)',
|
||||
value: {
|
||||
width: 1024,
|
||||
height: 682,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '4:3 (1024*768)',
|
||||
value: {
|
||||
width: 1024,
|
||||
height: 768,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '1:1 (1024*1024)',
|
||||
value: {
|
||||
width: 1024,
|
||||
height: 1024,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '3:4 (768*1024)',
|
||||
value: {
|
||||
width: 768,
|
||||
height: 1024,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '2:3 (682*1024)',
|
||||
value: {
|
||||
width: 682,
|
||||
height: 1024,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '9:16 (576*1024)',
|
||||
value: {
|
||||
width: 576,
|
||||
height: 1024,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
export const RatioField = withField(() => {
|
||||
const { value, readonly, onChange } = useField<{
|
||||
width?: number;
|
||||
height?: number;
|
||||
}>();
|
||||
|
||||
return (
|
||||
<SizeSelect
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
readonly={readonly}
|
||||
minWidth={512}
|
||||
maxWidth={1536}
|
||||
minHeight={512}
|
||||
maxHeight={1536}
|
||||
options={ratioOptions}
|
||||
layoutStyle="vertical"
|
||||
/>
|
||||
);
|
||||
});
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
|
||||
import { ExpressionEditorField } from '@/node-registries/common/components';
|
||||
import { withField, useField, Section } from '@/form';
|
||||
|
||||
export const PromptField = withField(
|
||||
() => {
|
||||
const { name } = useField();
|
||||
const promptName = `${name}.prompt`;
|
||||
const negativePromptName = `${name}.negative_prompt`;
|
||||
// 保障和之前节点testID不变
|
||||
const promptTestIDSuffix = name.replace('inputs.', '');
|
||||
const negativePromptTestIDSuffix = name.replace('inputs.', '');
|
||||
|
||||
return (
|
||||
<Section
|
||||
title={I18n.t('Imageflow_prompt')}
|
||||
tooltip={I18n.t('imageflow_generation_desc4')}
|
||||
>
|
||||
<ExpressionEditorField
|
||||
name={promptName}
|
||||
testIDSuffix={promptTestIDSuffix}
|
||||
label={I18n.t('Imageflow_positive')}
|
||||
placeholder={I18n.t('Imageflow_positive_placeholder')}
|
||||
required={true}
|
||||
layout="vertical"
|
||||
/>
|
||||
<ExpressionEditorField
|
||||
name={negativePromptName}
|
||||
testIDSuffix={negativePromptTestIDSuffix}
|
||||
label={I18n.t('Imageflow_negative')}
|
||||
placeholder={I18n.t('Imageflow_negative_placeholder')}
|
||||
layout="vertical"
|
||||
/>
|
||||
</Section>
|
||||
);
|
||||
},
|
||||
{
|
||||
hasFeedback: false,
|
||||
},
|
||||
);
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { I18n, type I18nKeysNoOptionsType } from '@coze-arch/i18n';
|
||||
|
||||
import thumbnail7 from '../../assets/reference-7.png';
|
||||
import thumbnail6 from '../../assets/reference-6.jpg';
|
||||
import thumbnail5 from '../../assets/reference-5.jpg';
|
||||
import thumbnail4 from '../../assets/reference-4.jpg';
|
||||
import thumbnail3 from '../../assets/reference-3.jpg';
|
||||
import thumbnail2 from '../../assets/reference-2.jpg';
|
||||
import thumbnail1 from '../../assets/reference-1.jpg';
|
||||
|
||||
const thumbnails = [
|
||||
thumbnail1,
|
||||
thumbnail2,
|
||||
thumbnail3,
|
||||
thumbnail4,
|
||||
thumbnail5,
|
||||
thumbnail6,
|
||||
thumbnail7,
|
||||
];
|
||||
|
||||
export function createPreprocessorOptions({
|
||||
currentPreprocessor,
|
||||
allSelectedPreprocessor = [],
|
||||
}: {
|
||||
currentPreprocessor?: number;
|
||||
allSelectedPreprocessor: number[];
|
||||
}) {
|
||||
const options = [1, 2, 3, 4, 5, 7, 6].map(index => ({
|
||||
label: I18n.t(`Imageflow_reference${index}` as I18nKeysNoOptionsType),
|
||||
value: index,
|
||||
tooltip: I18n.t(
|
||||
`imageflow_reference_desc${index}` as I18nKeysNoOptionsType,
|
||||
),
|
||||
thumbnail: thumbnails[index - 1],
|
||||
disabled: isPreprocessorDisabled({
|
||||
currentItemPreprocessor: currentPreprocessor,
|
||||
currentOptionPreprocessor: index,
|
||||
allSelectedPreprocessor,
|
||||
}),
|
||||
}));
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
function isPreprocessorDisabled({
|
||||
currentItemPreprocessor,
|
||||
currentOptionPreprocessor,
|
||||
allSelectedPreprocessor,
|
||||
}: {
|
||||
currentItemPreprocessor?: number;
|
||||
currentOptionPreprocessor: number;
|
||||
allSelectedPreprocessor: number[];
|
||||
}) {
|
||||
let disabled = false;
|
||||
|
||||
// 如果当前选项的预处理器已经被当前项选中 从allSelectedPreprocessor中移除
|
||||
allSelectedPreprocessor = allSelectedPreprocessor.filter(
|
||||
item =>
|
||||
!(
|
||||
item === currentItemPreprocessor &&
|
||||
currentItemPreprocessor === currentOptionPreprocessor
|
||||
),
|
||||
);
|
||||
|
||||
// 不能添加相同的模型
|
||||
if (allSelectedPreprocessor.includes(currentOptionPreprocessor)) {
|
||||
disabled = true;
|
||||
}
|
||||
|
||||
// 1到4编号最多只能出现两个 4以上编号的模型不做限制
|
||||
const group = [1, 2, 3, 4];
|
||||
if (group.includes(currentOptionPreprocessor)) {
|
||||
const isPreprocessorGroup =
|
||||
allSelectedPreprocessor.filter(item => group.includes(item)).length === 2;
|
||||
|
||||
if (isPreprocessorGroup) {
|
||||
disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
return disabled;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export { ReferencesField } from './references-field';
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { useMemo } from 'react';
|
||||
|
||||
import { ViewVariableType } from '@coze-workflow/variable';
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
|
||||
import { ValueExpressionInputField } from '@/node-registries/common/fields';
|
||||
import { ImageModelSelectField } from '@/node-registries/common/components';
|
||||
import {
|
||||
withFieldArray,
|
||||
Section,
|
||||
FieldArrayList,
|
||||
FieldArrayItem,
|
||||
ColumnTitles,
|
||||
useFieldArray,
|
||||
InputNumberField,
|
||||
AddButton,
|
||||
} from '@/form';
|
||||
|
||||
import { type Reference } from '../../types';
|
||||
import { DEFAULT_REFERENCE } from '../../constants';
|
||||
import { createPreprocessorOptions } from './create-preprocessor-options';
|
||||
|
||||
export const ReferencesField = withFieldArray(() => {
|
||||
const { name, value, append, remove } = useFieldArray<Reference>();
|
||||
|
||||
const preprocessors = useMemo(
|
||||
() =>
|
||||
value
|
||||
?.map(item => item.preprocessor)
|
||||
.filter(item => item !== undefined) || [],
|
||||
[value],
|
||||
);
|
||||
|
||||
return (
|
||||
<Section
|
||||
title={I18n.t('Imageflow_reference_image')}
|
||||
actions={[
|
||||
<AddButton
|
||||
key="add"
|
||||
onClick={() => append(DEFAULT_REFERENCE)}
|
||||
disabled={value && value?.length >= 5}
|
||||
/>,
|
||||
]}
|
||||
>
|
||||
<ColumnTitles
|
||||
columns={[
|
||||
{
|
||||
label: I18n.t('Imageflow_reference_info1'),
|
||||
style: {
|
||||
width: 120,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: I18n.t('Imageflow_reference_info2'),
|
||||
style: {
|
||||
width: 150,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: I18n.t('Imageflow_reference_info3'),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<FieldArrayList>
|
||||
{value?.map((item, index) => {
|
||||
const preprocessorName = `${name}.${index}.preprocessor`;
|
||||
const urlName = `${name}.${index}.url`;
|
||||
const weightName = `${name}.${index}.weight`;
|
||||
|
||||
const options = createPreprocessorOptions({
|
||||
currentPreprocessor: item.preprocessor,
|
||||
allSelectedPreprocessor: preprocessors,
|
||||
});
|
||||
|
||||
return (
|
||||
<FieldArrayItem onRemove={() => remove(index)}>
|
||||
<div className="flex-[2_1_0%] min-w-[0px] max-w-[120px]">
|
||||
<ImageModelSelectField
|
||||
name={preprocessorName}
|
||||
options={options}
|
||||
showClear={true}
|
||||
placeholder={I18n.t('Imageflow_mode_choose')}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="w-[150px]">
|
||||
<ValueExpressionInputField
|
||||
name={urlName}
|
||||
inputType={ViewVariableType.Image}
|
||||
selectStyle={{
|
||||
width: 80,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="w-full">
|
||||
<InputNumberField
|
||||
name={weightName}
|
||||
min={0}
|
||||
max={1}
|
||||
step={0.1}
|
||||
/>
|
||||
</div>
|
||||
</FieldArrayItem>
|
||||
);
|
||||
})}
|
||||
</FieldArrayList>
|
||||
</Section>
|
||||
);
|
||||
});
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export const DEFAULT_REFERENCE = {
|
||||
weight: 0.7,
|
||||
};
|
||||
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { nanoid } from 'nanoid';
|
||||
import { get, set } from 'lodash-es';
|
||||
import {
|
||||
ValidateTrigger,
|
||||
type FormMetaV2,
|
||||
} from '@flowgram-adapter/free-layout-editor';
|
||||
import { ViewVariableType } from '@coze-workflow/base';
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
|
||||
import { ValueExpressionService } from '@/services';
|
||||
import { nodeMetaValidate } from '@/nodes-v2/materials/node-meta-validate';
|
||||
import {
|
||||
fireNodeTitleChange,
|
||||
provideNodeOutputVariablesEffect,
|
||||
} from '@/node-registries/common/effects';
|
||||
|
||||
import { type FormData } from './types';
|
||||
import { FormRender } from './form';
|
||||
|
||||
export const IMAGE_GENERATE_FORM_META: FormMetaV2<FormData> = {
|
||||
// 节点表单渲染
|
||||
render: () => <FormRender />,
|
||||
|
||||
// 验证触发时机
|
||||
validateTrigger: ValidateTrigger.onChange,
|
||||
|
||||
// 验证规则
|
||||
validate: {
|
||||
nodeMeta: nodeMetaValidate,
|
||||
['inputs.modelSetting.model']: ({ value, formValues }) => {
|
||||
const invalidPreprocessors = {
|
||||
1: [4, 5, 6],
|
||||
8: [1, 2, 3, 4, 5, 6, 7],
|
||||
3: [7],
|
||||
6: [6, 7],
|
||||
};
|
||||
|
||||
// 获取references字段
|
||||
const references = formValues?.inputs?.references || [];
|
||||
|
||||
// 获取value对应的无效preprocessor值数组
|
||||
const invalidValues = invalidPreprocessors[value] || [];
|
||||
|
||||
// 检查references中的preprocessor是否包含无效值
|
||||
for (const reference of references) {
|
||||
if (invalidValues.includes(reference?.preprocessor)) {
|
||||
return I18n.t('Imageflow_not_support');
|
||||
}
|
||||
}
|
||||
},
|
||||
['inputs.prompt.prompt']: ({ value }) => {
|
||||
if (!value) {
|
||||
return I18n.t('workflow_detail_node_error_empty');
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
// 副作用管理
|
||||
effect: {
|
||||
nodeMeta: fireNodeTitleChange,
|
||||
outputs: provideNodeOutputVariablesEffect,
|
||||
},
|
||||
|
||||
// 默认值
|
||||
defaultValues: () => ({
|
||||
inputs: {
|
||||
modelSetting: {
|
||||
model: 1,
|
||||
custom_ratio: {
|
||||
width: 1024,
|
||||
height: 1024,
|
||||
},
|
||||
ddim_steps: 25,
|
||||
},
|
||||
references: [],
|
||||
prompt: {
|
||||
prompt: '',
|
||||
negative_prompt: '',
|
||||
},
|
||||
inputParameters: [],
|
||||
},
|
||||
outputs: [
|
||||
{
|
||||
key: nanoid(),
|
||||
name: 'data',
|
||||
type: ViewVariableType.Image,
|
||||
},
|
||||
{
|
||||
key: nanoid(),
|
||||
name: 'msg',
|
||||
type: ViewVariableType.String,
|
||||
},
|
||||
],
|
||||
}),
|
||||
|
||||
formatOnInit(value, context) {
|
||||
const { node } = context;
|
||||
const valueExpressionService = node.getService<ValueExpressionService>(
|
||||
ValueExpressionService,
|
||||
);
|
||||
|
||||
const references = get(value, 'inputs.references') || [];
|
||||
set(
|
||||
value,
|
||||
'inputs.references',
|
||||
references.map(item => ({
|
||||
...item,
|
||||
url: valueExpressionService.toVO(item.url),
|
||||
})),
|
||||
);
|
||||
|
||||
return value;
|
||||
},
|
||||
|
||||
formatOnSubmit(value, context) {
|
||||
const { node } = context;
|
||||
const valueExpressionService = node.getService<ValueExpressionService>(
|
||||
ValueExpressionService,
|
||||
);
|
||||
|
||||
const references = get(value, 'inputs.references') || [];
|
||||
set(
|
||||
value,
|
||||
'inputs.references',
|
||||
references.map(item => ({
|
||||
...item,
|
||||
url: valueExpressionService.toDTO(item.url),
|
||||
})),
|
||||
);
|
||||
|
||||
return value;
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { useUpdateEffect, usePrevious } from 'ahooks';
|
||||
|
||||
import { withNodeConfigForm } from '@/node-registries/common/hocs';
|
||||
import {
|
||||
OutputsField,
|
||||
InputsParametersField,
|
||||
} from '@/node-registries/common/fields';
|
||||
import { useFieldValidate, useForm } from '@/form';
|
||||
|
||||
import { type FormData } from './types';
|
||||
import { ModelSettingField, ReferencesField, PromptField } from './components';
|
||||
|
||||
export const FormRender = withNodeConfigForm(() => {
|
||||
const validateModel = useFieldValidate('inputs.modelSetting.model');
|
||||
|
||||
useReferenceModelChangeEffect(validateModel);
|
||||
|
||||
return (
|
||||
<>
|
||||
<ModelSettingField name="inputs.modelSetting" />
|
||||
<ReferencesField name="inputs.references" />
|
||||
<InputsParametersField name="inputs.inputParameters" />
|
||||
<PromptField name="inputs.prompt" />
|
||||
<OutputsField name="outputs" readonly={true} />
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
// 监听引用参考的模型变化触发模型设置的模型校验
|
||||
// 用useWatch目前无法监听引用模型 先监听整个表单值
|
||||
function useReferenceModelChangeEffect(callback: () => void) {
|
||||
const form = useForm<FormData>();
|
||||
const { values } = form;
|
||||
const previousReferences = usePrevious(values?.inputs?.references);
|
||||
|
||||
useUpdateEffect(() => {
|
||||
const currentPreprocessors = values?.inputs?.references?.map(
|
||||
reference => reference.preprocessor,
|
||||
);
|
||||
const previousPreprocessors = previousReferences?.map(
|
||||
reference => reference.preprocessor,
|
||||
);
|
||||
|
||||
const isSamePreprocessors =
|
||||
currentPreprocessors?.length === previousPreprocessors?.length &&
|
||||
currentPreprocessors?.every(
|
||||
(preprocessor, index) =>
|
||||
preprocessor === previousPreprocessors?.[index],
|
||||
);
|
||||
|
||||
if (!isSamePreprocessors) {
|
||||
callback();
|
||||
}
|
||||
}, [values]);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export { IMAGE_GENERATE_NODE_REGISTRY } from './node-registry';
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
StandardNodeType,
|
||||
type WorkflowNodeRegistry,
|
||||
} from '@coze-workflow/base';
|
||||
|
||||
import { type NodeTestMeta } from '@/test-run-kit';
|
||||
|
||||
import { test } from './node-test';
|
||||
import { IMAGE_GENERATE_FORM_META } from './form-meta';
|
||||
|
||||
export const IMAGE_GENERATE_NODE_REGISTRY: WorkflowNodeRegistry<NodeTestMeta> =
|
||||
{
|
||||
type: StandardNodeType.ImageGenerate,
|
||||
width: 508,
|
||||
meta: {
|
||||
nodeDTOType: StandardNodeType.ImageGenerate,
|
||||
test,
|
||||
helpLink: '/open/docs/guides/image_generation_node',
|
||||
},
|
||||
formMeta: IMAGE_GENERATE_FORM_META,
|
||||
};
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { I18n, type I18nKeysNoOptionsType } from '@coze-arch/i18n';
|
||||
import { FlowNodeFormData } from '@flowgram-adapter/free-layout-editor';
|
||||
|
||||
import { generateParametersToProperties } from '@/test-run-kit';
|
||||
import { type NodeTestMeta } from '@/test-run-kit';
|
||||
|
||||
export const test: NodeTestMeta = {
|
||||
generateFormInputProperties(node) {
|
||||
const formData = node
|
||||
.getData(FlowNodeFormData)
|
||||
.formModel.getFormItemValueByPath('/');
|
||||
const inputParameters =
|
||||
formData?.inputParameters || formData?.inputs.inputParameters || [];
|
||||
const references = (
|
||||
formData?.references ||
|
||||
formData?.inputs?.references ||
|
||||
[]
|
||||
)
|
||||
.filter(item => item.preprocessor)
|
||||
.map(item => ({
|
||||
name: `__image_references_${item.preprocessor}`,
|
||||
title: I18n.t(
|
||||
`Imageflow_reference${item.preprocessor}` as I18nKeysNoOptionsType,
|
||||
),
|
||||
input: item.url,
|
||||
}));
|
||||
|
||||
return {
|
||||
...generateParametersToProperties(references, { node }),
|
||||
...generateParametersToProperties(inputParameters, { node }),
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { type ViewVariableType, type InputValueVO } from '@coze-workflow/base';
|
||||
|
||||
export interface FormData {
|
||||
inputs: {
|
||||
modelSetting: ModelSetting;
|
||||
references: Reference[];
|
||||
prompt: {
|
||||
prompt: string;
|
||||
negative_prompt: string;
|
||||
};
|
||||
inputParameters: InputValueVO[];
|
||||
};
|
||||
outputs: Output[] | (() => Output[]);
|
||||
}
|
||||
|
||||
export interface ModelSetting {
|
||||
model: number;
|
||||
custom_ratio: {
|
||||
width: number;
|
||||
height: number;
|
||||
};
|
||||
ddim_steps: number;
|
||||
}
|
||||
|
||||
export interface Reference {
|
||||
preprocessor?: number;
|
||||
url?: string;
|
||||
weight?: number;
|
||||
}
|
||||
|
||||
export interface Output {
|
||||
key: string;
|
||||
name: string;
|
||||
type: ViewVariableType;
|
||||
}
|
||||