Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ def loop(workflow_manage_new_instance, node: INode, generate_loop):
node.context['loop_answer_data'] = loop_answer_data
node.context["index"] = current_index
node.context["item"] = current_index
node.context['run_time'] = time.time() - node.context.get("start_time")


def get_write_context(loop_type, array, number, loop_body):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code is generally well-written, but there are a few points that could be improved:

  1. Initialization of index and current_index:

    • The line node.context["index"] = current_index; node.context['item'] = current_index; appears to be identical. It should either use one or remove both occurrences.
  2. Check if loop_answer_data exists:

    • Ensure that loop.answer_data is available when setting it in the context. This might raise an error if the data does not exist.
  3. Useless operation:

    • The line node.context['run_time'] = time.time() - node.context.get("start_time"); initializes node.context['run_time']. If you want to update this value during each iteration, consider using another variable or modifying run_time.
  4. Readability:

    • Consider improving readability by adding comments explaining why certain operations are performed.

Overall, the code functions correctly with these changes applied.

Expand Down
102 changes: 95 additions & 7 deletions ui/src/workflow/common/validate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ const end_nodes_dict = {
[WorkflowMode.Application]: end_nodes,
[WorkflowMode.Knowledge]: [WorkflowType.KnowledgeWriteNode],
[WorkflowMode.ApplicationLoop]: loop_end_nodes,
[WorkflowMode.KnowledgeLoop]: loop_end_nodes,
[WorkflowMode.KnowledgeLoop]: [...loop_end_nodes, WorkflowType.KnowledgeWriteNode],
}

export class WorkFlowInstance {
Expand Down Expand Up @@ -218,9 +218,11 @@ export class WorkFlowInstance {

export class KnowledgeWorkFlowInstance extends WorkFlowInstance {
is_valid_start_node() {
const start_node_list = this.nodes.filter(
(item) => item.properties.kind === WorkflowKind.DataSource,
)
const start_node_list =
this.workflowModel == WorkflowMode.Knowledge
? this.nodes.filter((item) => item.properties.kind === WorkflowKind.DataSource)
: this.nodes.filter((item) => item.type === WorkflowType.LoopStartNode)

if (start_node_list.length == 0) {
throw t('workflow.validate.startNodeRequired')
}
Expand All @@ -239,9 +241,7 @@ export class KnowledgeWorkFlowInstance extends WorkFlowInstance {

is_valid_work_flow() {
this.workFlowNodes = []
const start_node_list = this.nodes.filter(
(item) => item.properties.kind === WorkflowKind.DataSource,
)
const start_node_list = this.get_start_nodes()
start_node_list.forEach((n) => {
this._is_valid_work_flow(n)
})
Expand All @@ -250,10 +250,12 @@ export class KnowledgeWorkFlowInstance extends WorkFlowInstance {
.filter(
(node: any) =>
node.id !== WorkflowType.KnowledgeBase &&
node.type !== WorkflowType.LoopStartNode &&
node.properties.kind !== WorkflowKind.DataSource,
)
.filter((node) => !this.workFlowNodes.includes(node))
if (notInWorkFlowNodes.length > 0) {
console.log('ss')
throw `${t('workflow.validate.notInWorkFlowNode')}:${notInWorkFlowNodes.map((node) => node.properties.stepName).join(',')}`
}
this.workFlowNodes = []
Expand All @@ -263,6 +265,7 @@ export class KnowledgeWorkFlowInstance extends WorkFlowInstance {
for (const node of this.nodes) {
if (
node.type !== WorkflowType.KnowledgeBase &&
node.type !== WorkflowType.LoopStartNode &&
node.properties.kind !== WorkflowKind.DataSource
) {
if (!this.edges.some((edge) => edge.targetNodeId === node.id)) {
Expand All @@ -271,4 +274,89 @@ export class KnowledgeWorkFlowInstance extends WorkFlowInstance {
}
}
}
get_start_nodes() {
if (this.workflowModel == WorkflowMode.Knowledge) {
return this.nodes.filter((item) => item.properties.kind === WorkflowKind.DataSource)
} else {
return this.nodes.filter((item) => item.type === WorkflowType.LoopStartNode)
}
}
get_end_nodes() {
const start_node_list = this.get_start_nodes()
return start_node_list.flatMap((n) => {
return this._get_end_nodes(n, [])
})
}
_get_end_nodes(startNode: any, value: Array<any>) {
const next = this.get_next_nodes(startNode)
if (next.length == 0) {
value.push(startNode)
} else {
next.forEach((n) => {
this._get_end_nodes(n, value)
})
}
return value
}

/**
* 获取流程下一个节点列表
* @param node 节点
* @returns 节点列表
*/
get_next_nodes(node: any) {
const edge_list = this.edges.filter((edge) => edge.sourceNodeId == node.id)
const node_list = edge_list
.map((edge) => this.nodes.filter((node) => node.id == edge.targetNodeId))
.reduce((x, y) => [...x, ...y], [])

return node_list
}

/**
* 校验节点
* @param node 节点
*/
is_valid_node(node: any) {
if (node.properties.status && node.properties.status === 500) {
throw `${node.properties.stepName} ${t('workflow.validate.nodeUnavailable')}`
}
if (node.type === WorkflowType.Condition) {
const branch_list = node.properties.node_data.branch
for (const branch of branch_list) {
const source_anchor_id = `${node.id}_${branch.id}_right`
const edge_list = this.edges.filter((edge) => edge.sourceAnchorId == source_anchor_id)
if (edge_list.length == 0) {
throw `${node.properties.stepName} ${t('workflow.validate.needConnect1')}${branch.type}${t('workflow.validate.needConnect2')}`
}
}
} else {
const edge_list = this.edges.filter((edge) => edge.sourceNodeId == node.id)
const end = end_nodes_dict[this.workflowModel]
if (this.workflowModel == WorkflowMode.KnowledgeLoop) {
if (edge_list.length == 0 && !end.includes(node.type)) {
throw `${node.properties.stepName} ${t('workflow.validate.cannotEndNode')}`
}
return
}
if (edge_list.length == 0 && !end.includes(node.type)) {
if (node.type == WorkflowType.LoopNode) {
if (node.properties.node_data.loop_body) {
const end_nodes = new KnowledgeWorkFlowInstance(
node.properties.node_data.loop_body,
WorkflowMode.KnowledgeLoop,
).get_end_nodes()
if (!end_nodes.every((n) => end.includes(n.type))) {
throw `${node.properties.stepName} ${t('workflow.validate.cannotEndNode')}`
}
}
} else {
throw `${node.properties.stepName} ${t('workflow.validate.cannotEndNode')}`
}
}
}
if (node.properties.status && node.properties.status !== 200) {
throw `${node.properties.stepName} ${t('workflow.validate.nodeUnavailable')}`
}
}
}
7 changes: 5 additions & 2 deletions ui/src/workflow/nodes/loop-body-node/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import Dagre from '@/workflow/plugins/dagre'
import { initDefaultShortcut } from '@/workflow/common/shortcut'
import LoopBodyContainer from '@/workflow/nodes/loop-body-node/LoopBodyContainer.vue'
import { WorkflowMode } from '@/enums/application'
import { WorkFlowInstance } from '@/workflow/common/validate'
import { WorkFlowInstance, KnowledgeWorkFlowInstance } from '@/workflow/common/validate'
import { t } from '@/locales'
import { disconnectByFlow } from '@/workflow/common/teleport'
const loop_workflow_mode = inject('loopWorkflowMode') || WorkflowMode.ApplicationLoop
Expand All @@ -21,7 +21,10 @@ const props = defineProps<{ nodeModel: any }>()
const containerRef = ref()
const LoopBodyContainerRef = ref<InstanceType<typeof LoopBodyContainer>>()
const validate = () => {
const workflow = new WorkFlowInstance(lf.value.getGraphData(), WorkflowMode.ApplicationLoop)
const workflow =
loop_workflow_mode == WorkflowMode.ApplicationLoop
? new WorkFlowInstance(lf.value.getGraphData(), WorkflowMode.ApplicationLoop)
: new KnowledgeWorkFlowInstance(lf.value.getGraphData(), WorkflowMode.KnowledgeLoop)
return Promise.all(lf.value.graphModel.nodes.map((element: any) => element?.validate?.()))
.then(() => {
const loop_node_id = props.nodeModel.properties.loop_node_id
Expand Down
Loading