Skip to content

Commit 45c73c8

Browse files
Merge remote-tracking branch 'upstream/v2' into variable-assign-support-type-convert
2 parents 2d1449a + c255b25 commit 45c73c8

152 files changed

Lines changed: 5067 additions & 1906 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

apps/application/flow/common.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,8 @@ def is_valid_model_params(self):
249249
node_list = [node for node in self.nodes if (
250250
node.type == 'ai-chat-node' or node.type == 'question-node' or node.type == 'parameter-extraction-node')]
251251
for node in node_list:
252+
if (node.properties.get('node_data', {}).get('model_id_type') or 'custom') == 'reference':
253+
continue
252254
model = QuerySet(Model).filter(id=node.properties.get('node_data', {}).get('model_id')).first()
253255
if model is None:
254256
raise ValidationError(ErrorDetail(

apps/application/flow/i_step_node.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,7 @@ def __init__(self, node, workflow_params, workflow_manage, up_node_id_list=None,
298298
node.id]))),
299299
"utf-8")).hexdigest() + (
300300
"__" + str(salt) if salt is not None else '')
301+
self.extra = {}
301302

302303
def valid_args(self, node_params, flow_params):
303304
flow_params_serializer_class = self.get_flow_params_serializer_class()

apps/application/flow/step_node/ai_chat_step_node/impl/base_chat_node.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,8 @@ def execute(self, model_id, system, prompt, dialogue_number, history_chat_record
277277
if reference_data and isinstance(reference_data, dict):
278278
model_id = reference_data.get('model_id', model_id)
279279
model_params_setting = reference_data.get('model_params_setting')
280+
if model_id is None or model_id == '':
281+
raise Exception(_('Model is not allowed to be empty'))
280282

281283
if model_params_setting is None and model_id:
282284
model_params_setting = get_default_model_params_setting(model_id)
@@ -428,13 +430,19 @@ def _handle_mcp_request(self, mcp_source, mcp_servers, mcp_tool_id, mcp_tool_ids
428430
if len(mcp_servers_config) > 0 or len(tools) > 0:
429431
# 安全获取 application
430432
application_id = None
431-
if (self.workflow_manage and
432-
self.workflow_manage.work_flow_post_handler and
433-
self.workflow_manage.work_flow_post_handler.chat_info):
433+
tool_id = None
434+
knowledge_id = None
435+
if [WorkflowMode.KNOWLEDGE, WorkflowMode.KNOWLEDGE_LOOP].__contains__(
436+
self.workflow_manage.flow.workflow_mode):
437+
knowledge_id = self.workflow_params.get('knowledge_id')
438+
elif [WorkflowMode.APPLICATION, WorkflowMode.APPLICATION_LOOP].__contains__(
439+
self.workflow_manage.flow.workflow_mode):
434440
application_id = self.workflow_manage.work_flow_post_handler.chat_info.application.id
435-
knowledge_id = self.workflow_params.get('knowledge_id')
436-
source_id = application_id or knowledge_id
437-
source_type = 'APPLICATION' if application_id else 'KNOWLEDGE'
441+
elif [WorkflowMode.TOOL, WorkflowMode.TOOL_LOOP].__contains__(self.workflow_manage.flow.workflow_mode):
442+
tool_id = self.workflow_params.get('tool_id')
443+
444+
source_id = application_id or knowledge_id or tool_id
445+
source_type = 'APPLICATION' if application_id else 'KNOWLEDGE' if knowledge_id else 'TOOL'
438446
r = mcp_response_generator(chat_model, message_list, json.dumps(mcp_servers_config), mcp_output_enable,
439447
tool_init_params, source_id, source_type, chat_id, tools)
440448
return NodeResult(

apps/application/flow/step_node/document_extract_node/impl/base_document_extract_node.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import uuid_utils.compat as uuid
66
from django.db.models import QuerySet
77

8+
from application.flow.common import WorkflowMode
89
from application.flow.i_step_node import NodeResult
910
from application.flow.step_node.document_extract_node.i_document_extract_node import IDocumentExtractNode
1011
from knowledge.models import File, FileSourceType
@@ -28,30 +29,34 @@ def execute(self, document, chat_id=None, **kwargs):
2829

2930
# 安全获取 application
3031
application_id = None
31-
if (self.workflow_manage and
32-
self.workflow_manage.work_flow_post_handler and
33-
self.workflow_manage.work_flow_post_handler.chat_info):
32+
tool_id = None
33+
knowledge_id = None
34+
if [WorkflowMode.KNOWLEDGE, WorkflowMode.KNOWLEDGE_LOOP].__contains__(self.workflow_manage.flow.workflow_mode):
35+
knowledge_id = self.workflow_params.get('knowledge_id')
36+
elif [WorkflowMode.APPLICATION, WorkflowMode.APPLICATION_LOOP].__contains__(
37+
self.workflow_manage.flow.workflow_mode):
3438
application_id = self.workflow_manage.work_flow_post_handler.chat_info.application.id
35-
knowledge_id = self.workflow_params.get('knowledge_id')
39+
elif [WorkflowMode.TOOL, WorkflowMode.TOOL_LOOP].__contains__(self.workflow_manage.flow.workflow_mode):
40+
tool_id = self.workflow_params.get('tool_id')
3641

3742
# doc文件中的图片保存
3843
def save_image(image_list):
3944
for image in image_list:
4045
meta = {
41-
'debug': False if (application_id or knowledge_id) else True,
46+
'debug': False if (application_id or knowledge_id or tool_id) else True,
4247
'chat_id': chat_id,
4348
'application_id': str(application_id) if application_id else None,
4449
'knowledge_id': str(knowledge_id) if knowledge_id else None,
50+
'tool_id': str(tool_id) if tool_id else None,
4551
'file_id': str(image.id)
4652
}
4753
file_bytes = image.meta.pop('content')
4854
new_file = File(
4955
id=meta['file_id'],
5056
file_name=image.file_name,
5157
file_size=len(file_bytes),
52-
source_type=FileSourceType.APPLICATION.value if meta[
53-
'application_id'] else FileSourceType.KNOWLEDGE.value,
54-
source_id=meta['application_id'] if meta['application_id'] else meta['knowledge_id'],
58+
source_type=FileSourceType.APPLICATION.value if application_id else FileSourceType.KNOWLEDGE.value if knowledge_id else FileSourceType.APPLICATION.value,
59+
source_id=application_id or tool_id or knowledge_id,
5560
meta=meta
5661
)
5762
if not QuerySet(File).filter(id=new_file.id).exists():

apps/application/flow/step_node/document_split_node/i_document_split_node.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,13 @@ def get_node_params_serializer_class(self) -> Type[serializers.Serializer]:
8080
return DocumentSplitNodeSerializer
8181

8282
def _run(self):
83-
return self.execute(**self.node_params_serializer.data, **self.flow_params_serializer.data)
83+
if [WorkflowMode.APPLICATION, WorkflowMode.APPLICATION_LOOP, WorkflowMode.TOOL,
84+
WorkflowMode.TOOL_LOOP].__contains__(
85+
self.workflow_manage.flow.workflow_mode):
86+
return self.execute(**self.node_params_serializer.data, **self.flow_params_serializer.data,
87+
**{'knowledge_id': None})
88+
else:
89+
return self.execute(**self.node_params_serializer.data, **self.flow_params_serializer.data)
8490

8591
def execute(self, document_list, knowledge_id, split_strategy, paragraph_title_relate_problem_type,
8692
paragraph_title_relate_problem, paragraph_title_relate_problem_reference,

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import requests
66
from langchain_core.messages import BaseMessage, HumanMessage, AIMessage
7-
7+
from django.utils.translation import gettext_lazy as _
88
from application.flow.common import WorkflowMode
99
from application.flow.i_step_node import NodeResult
1010
from application.flow.step_node.image_generate_step_node.i_image_generate_node import IImageGenerateNode
@@ -37,6 +37,9 @@ def execute(self, model_id, prompt, negative_prompt, dialogue_number, dialogue_t
3737
model_id = reference_data.get('model_id', model_id)
3838
model_params_setting = reference_data.get('model_params_setting')
3939

40+
if model_id is None or model_id == '':
41+
raise Exception(_('Model is not allowed to be empty'))
42+
4043
workspace_id = self.workflow_manage.get_body().get('workspace_id')
4144
tti_model = get_model_instance_by_model_workspace_id(model_id, workspace_id,
4245
**(model_params_setting or {}))

apps/application/flow/step_node/image_to_video_step_node/i_image_to_video_node.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ def _run(self):
5959
self.node_params_serializer.data.get('last_frame_url')[1:])
6060
node_params_data = {k: v for k, v in self.node_params_serializer.data.items()
6161
if k not in ['first_frame_url', 'last_frame_url']}
62-
if [WorkflowMode.KNOWLEDGE, WorkflowMode.KNOWLEDGE_LOOP].__contains__(
62+
if [WorkflowMode.KNOWLEDGE, WorkflowMode.KNOWLEDGE_LOOP, WorkflowMode.TOOL,
63+
WorkflowMode.TOOL_LOOP].__contains__(
6364
self.workflow_manage.flow.workflow_mode):
6465
return self.execute(first_frame_url=first_frame_url, last_frame_url=last_frame_url, **node_params_data,
6566
**self.flow_params_serializer.data,

apps/application/flow/step_node/image_to_video_step_node/impl/base_image_to_video_node.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import requests
77
from django.db.models import QuerySet
88
from langchain_core.messages import BaseMessage, HumanMessage, AIMessage
9-
9+
from django.utils.translation import gettext_lazy as _
1010
from application.flow.common import WorkflowMode
1111
from application.flow.i_step_node import NodeResult
1212
from application.flow.step_node.image_to_video_step_node.i_image_to_video_node import IImageToVideoNode
@@ -40,7 +40,8 @@ def execute(self, model_id, prompt, negative_prompt, dialogue_number, dialogue_t
4040
if reference_data and isinstance(reference_data, dict):
4141
model_id = reference_data.get('model_id', model_id)
4242
model_params_setting = reference_data.get('model_params_setting')
43-
43+
if model_id is None or model_id == '':
44+
raise Exception(_('Model is not allowed to be empty'))
4445
workspace_id = self.workflow_manage.get_body().get('workspace_id')
4546
ttv_model = get_model_instance_by_model_workspace_id(model_id, workspace_id,
4647
**(model_params_setting or {}))

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
from django.db.models import QuerySet
99
from langchain_core.messages import BaseMessage, HumanMessage, SystemMessage, AIMessage
10-
10+
from django.utils.translation import gettext_lazy as _
1111
from application.flow.i_step_node import NodeResult, INode
1212
from application.flow.step_node.image_understand_step_node.i_image_understand_node import IImageUnderstandNode
1313
from application.flow.tools import Reasoning
@@ -153,6 +153,8 @@ def execute(self, model_id, system, prompt, dialogue_number, dialogue_type, hist
153153
model_id = reference_data.get('model_id', model_id)
154154
model_params_setting = reference_data.get('model_params_setting')
155155

156+
if model_id is None or model_id == '':
157+
raise Exception(_('Model is not allowed to be empty'))
156158
# 处理不正确的参数
157159
workspace_id = self.workflow_manage.get_body().get('workspace_id')
158160
image_model = get_model_instance_by_model_workspace_id(model_id, workspace_id,
@@ -205,7 +207,7 @@ def generate_history_ai_message(self, chat_record):
205207
def generate_history_human_message_for_details(self, chat_record):
206208
for data in chat_record.details.values():
207209
if self.node.id == data['node_id'] and 'image_list' in data:
208-
image_list = data['image_list']
210+
image_list = data['image_list'] or []
209211
if len(image_list) == 0 or data['dialogue_type'] == 'WORKFLOW':
210212
return HumanMessage(content=chat_record.problem_text)
211213

@@ -236,7 +238,7 @@ def generate_history_human_message(self, chat_record):
236238

237239
for data in chat_record.details.values():
238240
if self.node.id == data['node_id'] and 'image_list' in data:
239-
image_list = data['image_list']
241+
image_list = data['image_list'] or []
240242
if len(image_list) == 0 or data['dialogue_type'] == 'WORKFLOW':
241243
return HumanMessage(content=chat_record.problem_text)
242244
file_id_list = []

apps/application/flow/step_node/mcp_node/impl/base_mcp_node.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,13 @@ def execute(self, mcp_servers, mcp_server, mcp_tool, mcp_tool_id, mcp_source, to
2929
if not tool.is_active:
3030
raise ValueError(f"Tool with ID {mcp_tool_id} is inactive.")
3131
servers = json.loads(tool.code)
32-
servers = self.handle_variables(servers) # 处理servers中的变量
33-
params = json.loads(json.dumps(tool_params))
34-
params = self.handle_variables(params)
3532
else:
3633
servers = json.loads(mcp_servers)
37-
servers = self.handle_variables(servers) # 处理servers中的变量
38-
ToolExecutor().validate_mcp_transport(json.dumps(servers))
39-
params = json.loads(json.dumps(tool_params))
40-
params = self.handle_variables(params)
34+
35+
servers = self.handle_variables(servers) # 处理servers中的变量
36+
ToolExecutor().validate_mcp_transport(json.dumps(servers))
37+
params = json.loads(json.dumps(tool_params))
38+
params = self.handle_variables(params)
4139

4240
async def call_tool(t, a):
4341
client = MultiServerMCPClient(servers)

0 commit comments

Comments
 (0)