|
10 | 10 | from enum import Enum |
11 | 11 | from typing import List, Dict |
12 | 12 |
|
| 13 | +from django.utils.translation import gettext as _ |
| 14 | +from common.exception.app_exception import AppApiException |
13 | 15 | from common.utils.common import group_by |
14 | 16 |
|
15 | 17 |
|
@@ -106,6 +108,15 @@ def reset_variable(self, prompt: str): |
106 | 108 | return prompt |
107 | 109 |
|
108 | 110 |
|
| 111 | +class WorkflowType(Enum): |
| 112 | + # 应用 |
| 113 | + APPLICATION = "APPLICATION" |
| 114 | + # 知识库 |
| 115 | + KNOWLEDGE = "KNOWLEDGE" |
| 116 | + # 工具 |
| 117 | + TOOL = "TOOL" |
| 118 | + |
| 119 | + |
109 | 120 | class Workflow: |
110 | 121 | """ |
111 | 122 | 节点列表 |
@@ -194,17 +205,39 @@ def reset_prompt(self, prompt): |
194 | 205 | prompt = node_field.reset_variable(prompt) |
195 | 206 | return prompt |
196 | 207 |
|
197 | | - def is_valid(self): |
198 | | - pass |
199 | | - |
| 208 | + def is_valid(self, workflow_type: WorkflowType): |
| 209 | + """ |
| 210 | + 校验工作流数据:一趟遍历同时统计节点id出现次数、校验每个节点的参数 |
| 211 | + """ |
| 212 | + start_node_list = [] |
| 213 | + for node in self.nodes: |
| 214 | + if node.id == "start-node": |
| 215 | + start_node_list.append(node) |
| 216 | + self.is_valid_node(node, workflow_type) |
| 217 | + self.is_valid_start_node(start_node_list) |
| 218 | + |
| 219 | + def is_valid_start_node(self, start_node_list: List[Node]): |
| 220 | + """ |
| 221 | + 校验开始节点:有且只有一个 start-node |
| 222 | + """ |
| 223 | + if len(start_node_list) == 0: |
| 224 | + raise AppApiException(500, _("The starting node is required")) |
| 225 | + if len(start_node_list) > 1: |
| 226 | + raise AppApiException(500, _("There can only be one starting node")) |
200 | 227 |
|
201 | | -class WorkflowType(Enum): |
202 | | - # 应用 |
203 | | - APPLICATION = "APPLICATION" |
204 | | - # 知识库 |
205 | | - KNOWLEDGE = "KNOWLEDGE" |
206 | | - # 工具 |
207 | | - TOOL = "TOOL" |
| 228 | + def is_valid_node(self, node: Node, workflow_type: WorkflowType = WorkflowType.APPLICATION): |
| 229 | + """ |
| 230 | + 校验单个节点:交给该节点类型对应的序列化器 |
| 231 | + """ |
| 232 | + from application.workflow.nodes import node_map |
| 233 | + |
| 234 | + node_class = node_map.get(node.type, {}).get(workflow_type) |
| 235 | + if node_class is None or node_class.serializer_class is None: |
| 236 | + return |
| 237 | + try: |
| 238 | + node_class.serializer_class(data=get_node_parameters(node)).is_valid(raise_exception=True) |
| 239 | + except AppApiException as e: |
| 240 | + raise AppApiException(500, f"{node.properties.get('stepName')}:{e.message}") |
208 | 241 |
|
209 | 242 |
|
210 | 243 | def new_instance(flow_obj: Dict, workflow_type: WorkflowType = WorkflowType.APPLICATION): |
|
0 commit comments