Skip to content

Commit df94068

Browse files
Variable assign (#2346)
* feat: Support variable assign * feat: Workfloat support variable assign(#2114) * feat: Support variable assign save input output value * feat: Execution detail support variable assign(#2114) * feat: Support variable assign dict array value config * chore: rename package --------- Co-authored-by: wangdan-fit2cloud <[email protected]>
1 parent bb557fd commit df94068

File tree

18 files changed

+420
-32
lines changed

18 files changed

+420
-32
lines changed

apps/application/flow/step_node/__init__.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,14 @@
2424
from .speech_to_text_step_node import BaseSpeechToTextNode
2525
from .start_node import *
2626
from .text_to_speech_step_node.impl.base_text_to_speech_node import BaseTextToSpeechNode
27+
from .variable_assign_node import BaseVariableAssignNode
2728

28-
node_list = [BaseStartStepNode, BaseChatNode, BaseSearchDatasetNode, BaseQuestionNode, BaseConditionNode, BaseReplyNode,
29+
node_list = [BaseStartStepNode, BaseChatNode, BaseSearchDatasetNode, BaseQuestionNode,
30+
BaseConditionNode, BaseReplyNode,
2931
BaseFunctionNodeNode, BaseFunctionLibNodeNode, BaseRerankerNode, BaseApplicationNode,
3032
BaseDocumentExtractNode,
31-
BaseImageUnderstandNode, BaseFormNode, BaseSpeechToTextNode, BaseTextToSpeechNode,BaseImageGenerateNode]
33+
BaseImageUnderstandNode, BaseFormNode, BaseSpeechToTextNode, BaseTextToSpeechNode,
34+
BaseImageGenerateNode, BaseVariableAssignNode]
3235

3336

3437
def get_node(node_type):
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# coding=utf-8
2+
3+
from .impl import *
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# coding=utf-8
2+
3+
from typing import Type
4+
5+
from django.utils.translation import gettext_lazy as _
6+
from rest_framework import serializers
7+
8+
from application.flow.i_step_node import INode, NodeResult
9+
from common.util.field_message import ErrMessage
10+
11+
12+
class VariableAssignNodeParamsSerializer(serializers.Serializer):
13+
variable_list = serializers.ListField(required=True,
14+
error_messages=ErrMessage.list(_("Reference Field")))
15+
16+
17+
class IVariableAssignNode(INode):
18+
type = 'variable-assign-node'
19+
20+
def get_node_params_serializer_class(self) -> Type[serializers.Serializer]:
21+
return VariableAssignNodeParamsSerializer
22+
23+
def _run(self):
24+
return self.execute(**self.node_params_serializer.data, **self.flow_params_serializer.data)
25+
26+
def execute(self, variable_list, stream, **kwargs) -> NodeResult:
27+
pass
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# coding=utf-8
2+
"""
3+
@project: maxkb
4+
@Author:虎
5+
@file: __init__.py
6+
@date:2024/6/11 17:49
7+
@desc:
8+
"""
9+
from .base_variable_assign_node import *
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# coding=utf-8
2+
import json
3+
from typing import List
4+
5+
from application.flow.i_step_node import NodeResult
6+
from application.flow.step_node.variable_assign_node.i_variable_assign_node import IVariableAssignNode
7+
8+
9+
class BaseVariableAssignNode(IVariableAssignNode):
10+
def save_context(self, details, workflow_manage):
11+
self.context['variable_list'] = details.get('variable_list')
12+
self.context['result_list'] = details.get('result_list')
13+
14+
def execute(self, variable_list, stream, **kwargs) -> NodeResult:
15+
#
16+
result_list = []
17+
for variable in variable_list:
18+
if 'fields' not in variable:
19+
continue
20+
if 'global' == variable['fields'][0]:
21+
result = {
22+
'name': variable['name'],
23+
'input_value': self.get_reference_content(variable['fields']),
24+
}
25+
if variable['source'] == 'custom':
26+
if variable['type'] in ['dict', 'array']:
27+
if isinstance(variable['value'], dict) or isinstance(variable['value'], list):
28+
val = variable['value']
29+
else:
30+
val = json.loads(variable['value'])
31+
self.workflow_manage.context[variable['fields'][1]] = val
32+
result['output_value'] = variable['value'] = val
33+
else:
34+
self.workflow_manage.context[variable['fields'][1]] = variable['value']
35+
result['output_value'] = variable['value']
36+
else:
37+
reference = self.get_reference_content(variable['reference'])
38+
self.workflow_manage.context[variable['fields'][1]] = reference
39+
result['output_value'] = reference
40+
result_list.append(result)
41+
42+
return NodeResult({'variable_list': variable_list, 'result_list': result_list}, {})
43+
44+
def get_reference_content(self, fields: List[str]):
45+
return str(self.workflow_manage.get_reference_field(
46+
fields[0],
47+
fields[1:]))
48+
49+
def get_details(self, index: int, **kwargs):
50+
return {
51+
'name': self.node.properties.get('stepName'),
52+
"index": index,
53+
'run_time': self.context.get('run_time'),
54+
'type': self.node.type,
55+
'variable_list': self.context.get('variable_list'),
56+
'result_list': self.context.get('result_list'),
57+
'status': self.status,
58+
'err_message': self.err_message
59+
}

ui/src/assets/icon_assigner.svg

Lines changed: 5 additions & 0 deletions
Loading

ui/src/components/ai-chat/ExecutionDetailDialog.vue

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,16 @@
5959
<h5 class="p-8-12">
6060
{{ $t('common.param.inputParam') }}
6161
</h5>
62+
6263
<div class="p-8-12 border-t-dashed lighter">
6364
<div class="mb-8">
6465
<span class="color-secondary">
6566
{{ $t('chat.paragraphSource.question') }}:</span
6667
>
68+
6769
{{ item.question || '-' }}
6870
</div>
71+
6972
<div v-for="(f, i) in item.global_fields" :key="i" class="mb-8">
7073
<span class="color-secondary">{{ f.label }}:</span> {{ f.value }}
7174
</div>
@@ -604,6 +607,30 @@
604607
</div>
605608
</div>
606609
</template>
610+
611+
<!-- 变量赋值 -->
612+
<template v-if="item.type === WorkflowType.VariableAssignNode">
613+
<div class="card-never border-r-4">
614+
<h5 class="p-8-12">
615+
{{ $t('common.param.inputParam') }}
616+
</h5>
617+
<div class="p-8-12 border-t-dashed lighter">
618+
<div v-for="(f, i) in item.result_list" :key="i" class="mb-8">
619+
<span class="color-secondary">{{ f.name }}:</span> {{ f.input_value }}
620+
</div>
621+
</div>
622+
</div>
623+
<div class="card-never border-r-4">
624+
<h5 class="p-8-12">
625+
{{ $t('common.param.outputParam') }}
626+
</h5>
627+
<div class="p-8-12 border-t-dashed lighter">
628+
<div v-for="(f, i) in item.result_list" :key="i" class="mb-8">
629+
<span class="color-secondary">{{ f.name }}:</span> {{ f.output_value }}
630+
</div>
631+
</div>
632+
</div>
633+
</template>
607634
</template>
608635
<template v-else>
609636
<div class="card-never border-r-4">

ui/src/enums/workflow.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ export enum WorkflowType {
1212
Application = 'application-node',
1313
DocumentExtractNode = 'document-extract-node',
1414
ImageUnderstandNode = 'image-understand-node',
15+
VariableAssignNode = 'variable-assign-node',
1516
FormNode = 'form-node',
1617
TextToSpeechNode = 'text-to-speech-node',
1718
SpeechToTextNode = 'speech-to-text-node',
18-
ImageGenerateNode = 'image-generate-node'
19+
ImageGenerateNode = 'image-generate-node'
1920
}

ui/src/locales/lang/en-US/views/application-workflow.ts

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export default {
1919
autoSave: 'Auto Save',
2020
latestRelease: 'Latest Release',
2121
copyParam: 'Copy Parameters',
22-
debug: 'Run',
22+
debug: 'Run'
2323
},
2424
tip: {
2525
publicSuccess: 'Published successfully',
@@ -48,12 +48,13 @@ export default {
4848
beautify: 'Auto-Arrange'
4949
},
5050
variable: {
51+
label: 'Variable',
5152
global: 'Global Variable',
5253
Referencing: 'Referenced Variable',
5354
ReferencingRequired: 'Referenced variable is required',
5455
ReferencingError: 'Invalid referenced variable',
5556
NoReferencing: 'Referenced variable does not exist',
56-
fieldMessage: 'Please select a variable'
57+
placeholder: 'Please select a variable'
5758
},
5859
condition: {
5960
title: 'Execution Condition',
@@ -82,12 +83,11 @@ export default {
8283
baseNode: {
8384
label: 'Base Information',
8485
appName: {
85-
label: 'App Name',
86-
86+
label: 'App Name'
8787
},
8888
appDescription: {
89-
label: 'App Description',
90-
},
89+
label: 'App Description'
90+
},
9191
fileUpload: {
9292
label: 'File Upload',
9393
tooltip: 'When enabled, the Q&A page will display a file upload button.'
@@ -114,7 +114,7 @@ export default {
114114
If you want the user to see the output of this node, please turn on the switch.`
115115
},
116116
defaultPrompt: 'Known Information',
117-
think: 'Thinking Process',
117+
think: 'Thinking Process'
118118
},
119119
searchDatasetNode: {
120120
label: 'Knowledge Retrieval',
@@ -188,8 +188,7 @@ export default {
188188
label: 'Form Output Content',
189189
requiredMessage:
190190
'Please set the output content of this node, { form } is a placeholder for the form.',
191-
tooltip:
192-
'Define the output content of this node. { form } is a placeholder for the form'
191+
tooltip: 'Define the output content of this node. { form } is a placeholder for the form'
193192
},
194193
formAllContent: 'All Form Content',
195194
formSetting: 'Form Configuration'
@@ -212,6 +211,11 @@ export default {
212211
requiredMessage: 'Please select an image'
213212
}
214213
},
214+
variableAssignNode: {
215+
label: 'Variable Assign',
216+
text: 'Update the value of the global variable',
217+
assign: 'Set Value'
218+
},
215219
imageGenerateNode: {
216220
label: 'Image Generation',
217221
text: 'Generate images based on provided text content',
@@ -222,13 +226,11 @@ export default {
222226
},
223227
prompt: {
224228
label: 'Positive Prompt',
225-
tooltip:
226-
'Describe elements and visual features you want in the generated image'
229+
tooltip: 'Describe elements and visual features you want in the generated image'
227230
},
228231
negative_prompt: {
229232
label: 'Negative Prompt',
230-
tooltip:
231-
'Describe elements you want to exclude from the generated image',
233+
tooltip: 'Describe elements you want to exclude from the generated image',
232234
placeholder:
233235
'Please describe content you do not want to generate, such as color, bloody content'
234236
}

ui/src/locales/lang/zh-CN/views/application-workflow.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export default {
1919
autoSave: '自动保存',
2020
latestRelease: '最近发布',
2121
copyParam: '复制参数',
22-
debug: '调试',
22+
debug: '调试'
2323
},
2424
tip: {
2525
publicSuccess: '发布成功',
@@ -48,12 +48,13 @@ export default {
4848
beautify: '一键美化'
4949
},
5050
variable: {
51+
label: '变量',
5152
global: '全局变量',
5253
Referencing: '引用变量',
5354
ReferencingRequired: '引用变量必填',
5455
ReferencingError: '引用变量错误',
5556
NoReferencing: '不存在的引用变量',
56-
fieldMessage: '请选择变量'
57+
placeholder: '请选择变量'
5758
},
5859
condition: {
5960
title: '执行条件',
@@ -83,12 +84,11 @@ export default {
8384
baseNode: {
8485
label: '基本信息',
8586
appName: {
86-
label: '应用名称',
87-
87+
label: '应用名称'
8888
},
8989
appDescription: {
90-
label: '应用描述',
91-
},
90+
label: '应用描述'
91+
},
9292
fileUpload: {
9393
label: '文件上传',
9494
tooltip: '开启后,问答页面会显示上传文件的按钮。'
@@ -115,7 +115,7 @@ export default {
115115
如果你想让用户看到该节点的输出内容,请打开开关。`
116116
},
117117
defaultPrompt: '已知信息',
118-
think: '思考过程',
118+
think: '思考过程'
119119
},
120120
searchDatasetNode: {
121121
label: '知识库检索',
@@ -211,6 +211,11 @@ export default {
211211
requiredMessage: '请选择图片'
212212
}
213213
},
214+
variableAssignNode: {
215+
label: '变量赋值',
216+
text: '更新全局变量的值',
217+
assign: '赋值'
218+
},
214219
imageGenerateNode: {
215220
label: '图片生成',
216221
text: '根据提供的文本内容生成图片',

0 commit comments

Comments
 (0)