Skip to content

Commit 1135c11

Browse files
committed
feat: Tool workflow node execution
1 parent b90a1c9 commit 1135c11

File tree

21 files changed

+518
-41
lines changed

21 files changed

+518
-41
lines changed

apps/application/flow/i_step_node.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,19 @@ def __init__(self, chat_info, tool_id):
123123

124124
def handler(self, workflow):
125125
state = get_workflow_state(workflow)
126-
ToolRecord(tool_id=self.tool_id)
126+
record = ToolRecord(id=self.chat_info.tool_record_id, tool_id=self.tool_id,
127+
workspace_id=self.chat_info.workspace_id,
128+
source_type=self.chat_info.source_type,
129+
source_id=self.chat_info.source_id,
130+
state=state,
131+
meta={
132+
'output': workflow.out_context,
133+
'details': workflow.get_runtime_details(),
134+
'answer_text_list': workflow.get_answer_text_list()
135+
})
136+
self.chat_info.set_record(record)
137+
self.chat_info = None
138+
self.tool_id = None
127139

128140

129141
def get_loop_workflow_node(node_list):

apps/application/flow/knowledge_loop_workflow_manage.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,9 @@
1313
class KnowledgeLoopWorkflowManage(LoopWorkflowManage):
1414
def get_params_serializer_class(self):
1515
return KnowledgeFlowParamsSerializer
16+
17+
def get_source_type(self):
18+
return "KNOWLEDGE"
19+
20+
def get_source_id(self):
21+
return self.params.get('knowledge_id')

apps/application/flow/knowledge_workflow_manage.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,9 @@ def hand_node_result(self, current_node, node_result_future):
122122
current_node.node_chunk.end()
123123
QuerySet(KnowledgeAction).filter(id=self.params.get('knowledge_action_id')).update(
124124
details=self.get_runtime_details())
125+
126+
def get_source_type(self):
127+
return "KNOWLEDGE"
128+
129+
def get_source_id(self):
130+
return self.params.get('knowledge_id')

apps/application/flow/loop_workflow_manage.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,3 +191,9 @@ def generate_prompt(self, prompt: str):
191191
prompt_template = PromptTemplate.from_template(prompt, template_format='jinja2')
192192
value = prompt_template.format(context=context)
193193
return value
194+
195+
def get_source_type(self):
196+
return "APPLICATION"
197+
198+
def get_source_id(self):
199+
return self.params.get('application_id')

apps/application/flow/step_node/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
from .text_to_video_step_node.impl.base_text_to_video_node import BaseTextToVideoNode
3636
from .tool_lib_node import *
3737
from .tool_node import *
38+
from .tool_workflow_lib_node import BaseToolWorkflowLibNodeNode
3839
from .variable_aggregation_node.impl.base_variable_aggregation_node import BaseVariableAggregationNode
3940
from .variable_assign_node import BaseVariableAssignNode
4041
from .variable_splitting_node import BaseVariableSplittingNode
@@ -53,7 +54,7 @@
5354
BaseLoopContinueNode,
5455
BaseLoopBreakNode, BaseVariableSplittingNode, BaseParameterExtractionNode, BaseVariableAggregationNode,
5556
BaseDataSourceLocalNode, BaseDataSourceWebNode, BaseKnowledgeWriteNode, BaseDocumentSplitNode,
56-
BaseToolStartStepNode]
57+
BaseToolStartStepNode, BaseToolWorkflowLibNodeNode]
5758

5859
node_map = {n.type: {w: n for w in n.support} for n in node_list}
5960

apps/application/flow/step_node/form_node/impl/base_form_node.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,9 @@ def get_answer_list(self) -> List[Answer] | None:
144144
value = prompt_template.format(form=form, context=context, runtime_node_id=self.runtime_node_id,
145145
chat_record_id=self.flow_params_serializer.data.get("chat_record_id"),
146146
form_field_list=form_field_list)
147-
return [Answer(value, self.view_type, self.runtime_node_id, self.workflow_params['chat_record_id'], None,
148-
self.runtime_node_id, '')]
147+
return [
148+
Answer(value, self.view_type, self.runtime_node_id, self.workflow_params.get('chat_record_id') or '', None,
149+
self.runtime_node_id, '')]
149150

150151
def get_details(self, index: int, **kwargs):
151152
form_content_format = self.context.get('form_content_format')

apps/application/flow/step_node/loop_node/impl/base_loop_node.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -268,10 +268,16 @@ def get_loop_context(self):
268268
def execute(self, loop_type, array, number, loop_body, **kwargs) -> NodeResult:
269269
from application.flow.loop_workflow_manage import LoopWorkflowManage, Workflow
270270
from application.flow.knowledge_loop_workflow_manage import KnowledgeLoopWorkflowManage
271+
from application.flow.tool_loop_workflow_manage import ToolLoopWorkflowManage
271272
def workflow_manage_new_instance(loop_data, global_data, start_node_id=None,
272273
start_node_data=None, chat_record=None, child_node=None):
273-
workflow_mode = WorkflowMode.KNOWLEDGE_LOOP if WorkflowMode.KNOWLEDGE == self.workflow_manage.flow.workflow_mode else WorkflowMode.APPLICATION_LOOP
274-
c = KnowledgeLoopWorkflowManage if workflow_mode == WorkflowMode.KNOWLEDGE_LOOP else LoopWorkflowManage
274+
workflow_mode = {WorkflowMode.APPLICATION: WorkflowMode.APPLICATION_LOOP,
275+
WorkflowMode.KNOWLEDGE: WorkflowMode.KNOWLEDGE_LOOP,
276+
WorkflowMode.TOOL: WorkflowMode.TOOL_LOOP}.get(
277+
self.workflow_manage.flow.workflow_mode) or WorkflowMode.APPLICATION
278+
c = {WorkflowMode.APPLICATION_LOOP: LoopWorkflowManage,
279+
WorkflowMode.KNOWLEDGE_LOOP: KnowledgeLoopWorkflowManage,
280+
WorkflowMode.TOOL_LOOP: ToolLoopWorkflowManage}.get(workflow_mode) or LoopWorkflowManage
275281
workflow_manage = c(Workflow.new_instance(loop_body, workflow_mode),
276282
self.workflow_manage.params,
277283
LoopWorkFlowPostHandler(
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.py
6+
@date:2026/3/16 13:53
7+
@desc:
8+
"""
9+
from .impl import *
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# coding=utf-8
2+
"""
3+
@project: MaxKB
4+
@Author:虎
5+
@file: i_function_lib_node.py
6+
@date:2024/8/8 16:21
7+
@desc:
8+
"""
9+
from typing import Type
10+
11+
from django.db import connection
12+
from django.db.models import QuerySet
13+
from django.utils.translation import gettext_lazy as _
14+
from rest_framework import serializers
15+
16+
from application.flow.common import WorkflowMode
17+
from application.flow.i_step_node import INode, NodeResult
18+
from common.field.common import ObjectField
19+
from tools.models.tool import Tool, ToolType
20+
21+
22+
class InputField(serializers.Serializer):
23+
field = serializers.CharField(required=True, label=_('Variable Name'))
24+
label = serializers.CharField(required=True, label=_('Variable Label'))
25+
source = serializers.CharField(required=True, label=_('Variable Source'))
26+
type = serializers.CharField(required=True, label=_('Variable Type'))
27+
value = ObjectField(required=True, label=_("Variable Value"), model_type_list=[str, list, bool, dict, int, float])
28+
29+
30+
class FunctionLibNodeParamsSerializer(serializers.Serializer):
31+
tool_lib_id = serializers.UUIDField(required=True, label=_('Library ID'))
32+
input_field_list = InputField(required=True, many=True)
33+
is_result = serializers.BooleanField(required=False,
34+
label=_('Whether to return content'))
35+
36+
def is_valid(self, *, raise_exception=False):
37+
super().is_valid(raise_exception=True)
38+
f_lib = QuerySet(Tool).filter(id=self.data.get('tool_lib_id'), tool_type=ToolType.WORKFLOW).first()
39+
# 归还链接到连接池
40+
connection.close()
41+
if f_lib is None:
42+
raise Exception(_('The function has been deleted'))
43+
44+
45+
class IToolWorkflowLibNode(INode):
46+
type = 'tool-workflow-lib-node'
47+
support = [WorkflowMode.APPLICATION, WorkflowMode.APPLICATION_LOOP, WorkflowMode.KNOWLEDGE,
48+
WorkflowMode.KNOWLEDGE_LOOP, WorkflowMode.TOOL, WorkflowMode.TOOL_LOOP]
49+
50+
def get_node_params_serializer_class(self) -> Type[serializers.Serializer]:
51+
return FunctionLibNodeParamsSerializer
52+
53+
def _run(self):
54+
return self.execute(**self.node_params_serializer.data, **self.flow_params_serializer.data)
55+
56+
def execute(self, tool_lib_id, input_field_list, **kwargs) -> NodeResult:
57+
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.py
6+
@date:2026/3/16 13:53
7+
@desc:
8+
"""
9+
from .base_tool_workflow_lib_node import *

0 commit comments

Comments
 (0)