Skip to content

Commit f9887db

Browse files
committed
feat: IMG TTV node support reference model
1 parent 966a3a8 commit f9887db

File tree

9 files changed

+211
-66
lines changed

9 files changed

+211
-66
lines changed

apps/application/flow/step_node/image_generate_step_node/i_image_generate_node.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010

1111

1212
class ImageGenerateNodeSerializer(serializers.Serializer):
13-
model_id = serializers.CharField(required=True, label=_("Model id"))
14-
13+
model_id = serializers.CharField(required=False, allow_blank=True, allow_null=True, label=_("Model id"))
14+
model_id_type = serializers.CharField(required=False, default='custom', label=_("Model id type"))
15+
model_id_reference = serializers.ListField(required=False, child=serializers.CharField(), allow_empty=True,
16+
label=_("Reference Field"))
1517
prompt = serializers.CharField(required=True, label=_("Prompt word (positive)"))
1618

1719
negative_prompt = serializers.CharField(required=False, label=_("Prompt word (negative)"),
@@ -49,6 +51,6 @@ def _run(self):
4951

5052
def execute(self, model_id, prompt, negative_prompt, dialogue_number, dialogue_type, history_chat_record,
5153
model_params_setting,
52-
chat_record_id,
54+
chat_record_id, model_id_type=None, model_id_reference=None,
5355
**kwargs) -> NodeResult:
5456
pass

apps/application/flow/step_node/image_generate_step_node/impl/base_image_generate_node.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,21 @@ def save_context(self, details, workflow_manage):
2525
def execute(self, model_id, prompt, negative_prompt, dialogue_number, dialogue_type, history_chat_record,
2626
model_params_setting,
2727
chat_record_id,
28+
model_id_type=None, model_id_reference=None,
2829
**kwargs) -> NodeResult:
30+
# 处理引用类型
31+
if model_id_type == 'reference' and model_id_reference:
32+
reference_data = self.workflow_manage.get_reference_field(
33+
model_id_reference[0],
34+
model_id_reference[1:],
35+
)
36+
if reference_data and isinstance(reference_data, dict):
37+
model_id = reference_data.get('model_id', model_id)
38+
model_params_setting = reference_data.get('model_params_setting')
39+
2940
workspace_id = self.workflow_manage.get_body().get('workspace_id')
3041
tti_model = get_model_instance_by_model_workspace_id(model_id, workspace_id,
31-
**model_params_setting)
42+
**(model_params_setting or {}))
3243
history_message = self.get_history_message(history_chat_record, dialogue_number)
3344
self.context['history_message'] = history_message
3445
question = self.generate_prompt_question(prompt)

apps/application/flow/step_node/image_understand_step_node/i_image_understand_node.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@
1111

1212

1313
class ImageUnderstandNodeSerializer(serializers.Serializer):
14-
model_id = serializers.CharField(required=True, label=_("Model id"))
14+
model_id = serializers.CharField(required=False, allow_blank=True, allow_null=True, label=_("Model id"))
15+
model_id_type = serializers.CharField(required=False, default='custom', label=_("Model id type"))
16+
model_id_reference = serializers.ListField(required=False, child=serializers.CharField(), allow_empty=True,
17+
label=_("Reference Field"))
1518
system = serializers.CharField(required=False, allow_blank=True, allow_null=True,
1619
label=_("Role Setting"))
1720
prompt = serializers.CharField(required=True, label=_("Prompt word"))
@@ -52,5 +55,6 @@ def execute(self, model_id, system, prompt, dialogue_number, dialogue_type, hist
5255
model_params_setting,
5356
chat_record_id,
5457
image,
58+
model_id_type=None, model_id_reference=None,
5559
**kwargs) -> NodeResult:
5660
pass

apps/application/flow/step_node/image_understand_step_node/impl/base_image_understand_node.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,22 @@ def execute(self, model_id, system, prompt, dialogue_number, dialogue_type, hist
8383
model_params_setting,
8484
chat_record_id,
8585
image,
86+
model_id_type=None, model_id_reference=None,
8687
**kwargs) -> NodeResult:
88+
# 处理引用类型
89+
if model_id_type == 'reference' and model_id_reference:
90+
reference_data = self.workflow_manage.get_reference_field(
91+
model_id_reference[0],
92+
model_id_reference[1:],
93+
)
94+
if reference_data and isinstance(reference_data, dict):
95+
model_id = reference_data.get('model_id', model_id)
96+
model_params_setting = reference_data.get('model_params_setting')
97+
8798
# 处理不正确的参数
8899
workspace_id = self.workflow_manage.get_body().get('workspace_id')
89100
image_model = get_model_instance_by_model_workspace_id(model_id, workspace_id,
90-
**model_params_setting)
101+
**(model_params_setting or {}))
91102
# 执行详情中的历史消息不需要图片内容
92103
history_message = self.get_history_message_for_details(history_chat_record, dialogue_number)
93104
self.context['history_message'] = history_message

apps/application/flow/step_node/text_to_video_step_node/i_text_to_video_node.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010

1111

1212
class TextToVideoNodeSerializer(serializers.Serializer):
13-
model_id = serializers.CharField(required=True, label=_("Model id"))
14-
13+
model_id = serializers.CharField(required=False, allow_blank=True, allow_null=True, label=_("Model id"))
14+
model_id_type = serializers.CharField(required=False, default='custom', label=_("Model id type"))
15+
model_id_reference = serializers.ListField(required=False, child=serializers.CharField(), allow_empty=True,
16+
label=_("Reference Field"))
1517
prompt = serializers.CharField(required=True, label=_("Prompt word (positive)"))
1618

1719
negative_prompt = serializers.CharField(required=False, label=_("Prompt word (negative)"),
@@ -50,5 +52,6 @@ def _run(self):
5052
def execute(self, model_id, prompt, negative_prompt, dialogue_number, dialogue_type, history_chat_record,
5153
model_params_setting,
5254
chat_record_id,
55+
model_id_type=None, model_id_reference=None,
5356
**kwargs) -> NodeResult:
5457
pass

apps/application/flow/step_node/text_to_video_step_node/impl/base_text_to_video_node.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,21 @@ def save_context(self, details, workflow_manage):
2626
def execute(self, model_id, prompt, negative_prompt, dialogue_number, dialogue_type, history_chat_record,
2727
model_params_setting,
2828
chat_record_id,
29+
model_id_type=None, model_id_reference=None,
2930
**kwargs) -> NodeResult:
31+
# 处理引用类型
32+
if model_id_type == 'reference' and model_id_reference:
33+
reference_data = self.workflow_manage.get_reference_field(
34+
model_id_reference[0],
35+
model_id_reference[1:],
36+
)
37+
if reference_data and isinstance(reference_data, dict):
38+
model_id = reference_data.get('model_id', model_id)
39+
model_params_setting = reference_data.get('model_params_setting')
40+
3041
workspace_id = self.workflow_manage.get_body().get('workspace_id')
3142
ttv_model = get_model_instance_by_model_workspace_id(model_id, workspace_id,
32-
**model_params_setting)
43+
**(model_params_setting or {}))
3344
history_message = self.get_history_message(history_chat_record, dialogue_number)
3445
self.context['history_message'] = history_message
3546
question = self.generate_prompt_question(prompt)

ui/src/workflow/nodes/image-generate/index.vue

Lines changed: 56 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,13 @@
1313
>
1414
<el-form-item
1515
:label="$t('workflow.nodes.imageGenerateNode.model.label')"
16-
prop="model_id"
16+
:prop="form_data.model_id_type === 'reference' ? 'model_id_reference' : 'model_id'"
1717
:rules="{
1818
required: true,
19-
message: $t('workflow.nodes.imageGenerateNode.model.requiredMessage'),
19+
message:
20+
form_data.model_id_type === 'reference'
21+
? $t('workflow.variable.placeholder')
22+
: $t('workflow.nodes.imageGenerateNode.model.requiredMessage'),
2023
trigger: 'change',
2124
}"
2225
>
@@ -28,31 +31,51 @@
2831
}}<span class="color-danger">*</span></span
2932
>
3033
</div>
34+
<el-select
35+
v-model="form_data.model_id_type"
36+
:teleported="false"
37+
size="small"
38+
style="width: 85px"
39+
@change="form_data.model_id_reference = []"
40+
>
41+
<el-option :label="$t('workflow.variable.Referencing')" value="reference" />
42+
<el-option :label="$t('common.custom')" value="custom" />
43+
</el-select>
44+
</div>
45+
</template>
46+
<div class="flex-between w-full" v-if="form_data.model_id_type !== 'reference'">
47+
<ModelSelect
48+
@change="model_change"
49+
@wheel="wheel"
50+
:teleported="false"
51+
v-model="form_data.model_id"
52+
:placeholder="$t('workflow.nodes.imageGenerateNode.model.requiredMessage')"
53+
:options="modelOptions"
54+
showFooter
55+
@focus="getSelectModel"
56+
:model-type="'TTI'"
57+
></ModelSelect>
58+
<div class="ml-8">
3159
<el-button
3260
:disabled="!form_data.model_id"
33-
type="primary"
34-
link
3561
@click="openAIParamSettingDialog(form_data.model_id)"
3662
@refreshForm="refreshParam"
3763
>
38-
<AppIcon iconName="app-setting"></AppIcon>
64+
<el-icon>
65+
<Operation />
66+
</el-icon>
3967
</el-button>
4068
</div>
41-
</template>
42-
43-
<ModelSelect
44-
@change="model_change"
45-
@wheel="wheel"
46-
:teleported="false"
47-
v-model="form_data.model_id"
48-
:placeholder="$t('workflow.nodes.imageGenerateNode.model.requiredMessage')"
49-
:options="modelOptions"
50-
showFooter
51-
@focus="getSelectModel"
52-
:model-type="'TTI'"
53-
></ModelSelect>
69+
</div>
70+
<NodeCascader
71+
v-else
72+
ref="nodeCascaderRef"
73+
:nodeModel="nodeModel"
74+
class="w-full"
75+
:placeholder="$t('workflow.variable.placeholder')"
76+
v-model="form_data.model_id_reference"
77+
/>
5478
</el-form-item>
55-
5679
<el-form-item
5780
:label="$t('workflow.nodes.imageGenerateNode.prompt.label')"
5881
prop="prompt"
@@ -158,6 +181,7 @@ import type { FormInstance } from 'element-plus'
158181
import AIModeParamSettingDialog from '@/views/application/component/AIModeParamSettingDialog.vue'
159182
import { t } from '@/locales'
160183
import { useRoute } from 'vue-router'
184+
import NodeCascader from '@/workflow/common/NodeCascader.vue'
161185
import { loadSharedApi } from '@/utils/dynamics-api/shared-api'
162186
import { WorkflowMode } from '@/enums/application'
163187
const workflowMode = (inject('workflowMode') as WorkflowMode) || WorkflowMode.Application
@@ -184,10 +208,14 @@ const AIModeParamSettingDialogRef = ref<InstanceType<typeof AIModeParamSettingDi
184208
185209
const aiChatNodeFormRef = ref<FormInstance>()
186210
const validate = () => {
187-
return aiChatNodeFormRef.value?.validate().catch((err) => {
211+
return Promise.all([
212+
nodeCascaderRef.value ? nodeCascaderRef.value.validate() : Promise.resolve(''),
213+
aiChatNodeFormRef.value?.validate(),
214+
]).catch((err: any) => {
188215
return Promise.reject({ node: props.nodeModel, errMessage: err })
189216
})
190217
}
218+
const nodeCascaderRef = ref()
191219
192220
const wheel = (e: any) => {
193221
if (e.ctrlKey === true) {
@@ -203,6 +231,8 @@ const defaultPrompt = `{{${t('workflow.nodes.startNode.label')}.question}}`
203231
204232
const form = {
205233
model_id: '',
234+
model_id_type: 'custom',
235+
model_id_reference: [],
206236
system: '',
207237
prompt: defaultPrompt,
208238
negative_prompt: '',
@@ -217,6 +247,12 @@ const form = {
217247
const form_data = computed({
218248
get: () => {
219249
if (props.nodeModel.properties.node_data) {
250+
if (!props.nodeModel.properties.node_data.model_id_type) {
251+
set(props.nodeModel.properties.node_data, 'model_id_type', 'custom')
252+
}
253+
if (!props.nodeModel.properties.node_data.model_id_reference) {
254+
set(props.nodeModel.properties.node_data, 'model_id_reference', [])
255+
}
220256
return props.nodeModel.properties.node_data
221257
} else {
222258
set(props.nodeModel.properties, 'node_data', form)

ui/src/workflow/nodes/image-understand/index.vue

Lines changed: 48 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,13 @@
1313
>
1414
<el-form-item
1515
:label="$t('workflow.nodes.imageUnderstandNode.model.label')"
16-
prop="model_id"
16+
:prop="form_data.model_id_type === 'reference' ? 'model_id_reference' : 'model_id'"
1717
:rules="{
1818
required: true,
19-
message: $t('workflow.nodes.imageUnderstandNode.model.requiredMessage'),
19+
message:
20+
form_data.model_id_type === 'reference'
21+
? $t('workflow.variable.placeholder')
22+
: $t('workflow.nodes.imageUnderstandNode.model.requiredMessage'),
2023
trigger: 'change',
2124
}"
2225
>
@@ -28,29 +31,49 @@
2831
}}<span class="color-danger">*</span></span
2932
>
3033
</div>
34+
<el-select
35+
v-model="form_data.model_id_type"
36+
:teleported="false"
37+
size="small"
38+
style="width: 85px"
39+
@change="form_data.model_id_reference = []"
40+
>
41+
<el-option :label="$t('workflow.variable.Referencing')" value="reference" />
42+
<el-option :label="$t('common.custom')" value="custom" />
43+
</el-select>
44+
</div>
45+
</template>
46+
<div class="flex-between w-full" v-if="form_data.model_id_type !== 'reference'">
47+
<ModelSelect
48+
@wheel="wheel"
49+
:teleported="false"
50+
v-model="form_data.model_id"
51+
:placeholder="$t('workflow.nodes.imageUnderstandNode.model.requiredMessage')"
52+
:options="modelOptions"
53+
showFooter
54+
:model-type="'IMAGE'"
55+
></ModelSelect>
56+
<div class="ml-8">
3157
<el-button
3258
:disabled="!form_data.model_id"
33-
type="primary"
34-
link
3559
@click="openAIParamSettingDialog(form_data.model_id)"
3660
@refreshForm="refreshParam"
3761
>
38-
<AppIcon iconName="app-setting"></AppIcon>
62+
<el-icon>
63+
<Operation />
64+
</el-icon>
3965
</el-button>
4066
</div>
41-
</template>
42-
43-
<ModelSelect
44-
@wheel="wheel"
45-
:teleported="false"
46-
v-model="form_data.model_id"
47-
:placeholder="$t('workflow.nodes.imageUnderstandNode.model.requiredMessage')"
48-
:options="modelOptions"
49-
showFooter
50-
:model-type="'IMAGE'"
51-
></ModelSelect>
67+
</div>
68+
<NodeCascader
69+
v-else
70+
ref="nodeCascaderRef"
71+
:nodeModel="nodeModel"
72+
class="w-full"
73+
:placeholder="$t('workflow.variable.placeholder')"
74+
v-model="form_data.model_id_reference"
75+
/>
5276
</el-form-item>
53-
5477
<el-form-item>
5578
<template #label>
5679
<div class="flex-between">
@@ -262,6 +285,8 @@ const defaultPrompt = `{{${t('workflow.nodes.startNode.label')}.question}}`
262285
263286
const form = {
264287
model_id: '',
288+
model_id_type: 'custom',
289+
model_id_reference: [],
265290
system: '',
266291
prompt: defaultPrompt,
267292
dialogue_number: 0,
@@ -275,6 +300,12 @@ const form = {
275300
const form_data = computed({
276301
get: () => {
277302
if (props.nodeModel.properties.node_data) {
303+
if (!props.nodeModel.properties.node_data.model_id_type) {
304+
set(props.nodeModel.properties.node_data, 'model_id_type', 'custom')
305+
}
306+
if (!props.nodeModel.properties.node_data.model_id_reference) {
307+
set(props.nodeModel.properties.node_data, 'model_id_reference', [])
308+
}
278309
return props.nodeModel.properties.node_data
279310
} else {
280311
set(props.nodeModel.properties, 'node_data', form)

0 commit comments

Comments
 (0)