From 3c859a6b7b844bf0e189d20d1ad40d8fbdc13e97 Mon Sep 17 00:00:00 2001 From: shaohuzhang1 <80892890+shaohuzhang1@users.noreply.github.com> Date: Wed, 22 Jan 2025 14:54:57 +0800 Subject: [PATCH] fix: New workflow application, node name not internationalized (#2066) --- .gitignore | 1 + .../application/flow/default_workflow_en.json | 451 ++++++++++++++++++ .../application/flow/default_workflow_zh.json | 451 ++++++++++++++++++ .../flow/default_workflow_zh_Hant.json | 451 ++++++++++++++++++ apps/application/flow/workflow_manage.py | 56 ++- .../serializers/application_serializers.py | 11 +- 6 files changed, 1396 insertions(+), 25 deletions(-) create mode 100644 apps/application/flow/default_workflow_en.json create mode 100644 apps/application/flow/default_workflow_zh.json create mode 100644 apps/application/flow/default_workflow_zh_Hant.json diff --git a/.gitignore b/.gitignore index af87ce403..0aad90be7 100644 --- a/.gitignore +++ b/.gitignore @@ -178,6 +178,7 @@ ui/node_modules ui/dist apps/static models/ +apps/xpack !apps/**/models/ data .dev diff --git a/apps/application/flow/default_workflow_en.json b/apps/application/flow/default_workflow_en.json new file mode 100644 index 000000000..7c0194be6 --- /dev/null +++ b/apps/application/flow/default_workflow_en.json @@ -0,0 +1,451 @@ +{ + "nodes": [ + { + "id": "base-node", + "type": "base-node", + "x": 360, + "y": 2810, + "properties": { + "config": { + + }, + "height": 825.6, + "stepName": "Base", + "node_data": { + "desc": "", + "name": "maxkbapplication", + "prologue": "Hello, I am the MaxKB assistant. You can ask me about MaxKB usage issues.\n-What are the main functions of MaxKB?\n-What major language models does MaxKB support?\n-What document types does MaxKB support?" + }, + "input_field_list": [ + + ] + } + }, + { + "id": "start-node", + "type": "start-node", + "x": 430, + "y": 3660, + "properties": { + "config": { + "fields": [ + { + "label": "用户问题", + "value": "question" + } + ], + "globalFields": [ + { + "label": "当前时间", + "value": "time" + } + ] + }, + "fields": [ + { + "label": "用户问题", + "value": "question" + } + ], + "height": 276, + "stepName": "Start", + "globalFields": [ + { + "label": "当前时间", + "value": "time" + } + ] + } + }, + { + "id": "b931efe5-5b66-46e0-ae3b-0160cb18eeb5", + "type": "search-dataset-node", + "x": 840, + "y": 3210, + "properties": { + "config": { + "fields": [ + { + "label": "检索结果的分段列表", + "value": "paragraph_list" + }, + { + "label": "满足直接回答的分段列表", + "value": "is_hit_handling_method_list" + }, + { + "label": "检索结果", + "value": "data" + }, + { + "label": "满足直接回答的分段内容", + "value": "directly_return" + } + ] + }, + "height": 794, + "stepName": "Knowledge Search", + "node_data": { + "dataset_id_list": [ + + ], + "dataset_setting": { + "top_n": 3, + "similarity": 0.6, + "search_mode": "embedding", + "max_paragraph_char_number": 5000 + }, + "question_reference_address": [ + "start-node", + "question" + ], + "source_dataset_id_list": [ + + ] + } + } + }, + { + "id": "fc60863a-dec2-4854-9e5a-7a44b7187a2b", + "type": "condition-node", + "x": 1490, + "y": 3210, + "properties": { + "width": 600, + "config": { + "fields": [ + { + "label": "分支名称", + "value": "branch_name" + } + ] + }, + "height": 543.675, + "stepName": "Conditional Branch", + "node_data": { + "branch": [ + { + "id": "1009", + "type": "IF", + "condition": "and", + "conditions": [ + { + "field": [ + "b931efe5-5b66-46e0-ae3b-0160cb18eeb5", + "is_hit_handling_method_list" + ], + "value": "1", + "compare": "len_ge" + } + ] + }, + { + "id": "4908", + "type": "ELSE IF 1", + "condition": "and", + "conditions": [ + { + "field": [ + "b931efe5-5b66-46e0-ae3b-0160cb18eeb5", + "paragraph_list" + ], + "value": "1", + "compare": "len_ge" + } + ] + }, + { + "id": "161", + "type": "ELSE", + "condition": "and", + "conditions": [ + + ] + } + ] + }, + "branch_condition_list": [ + { + "index": 0, + "height": 121.225, + "id": "1009" + }, + { + "index": 1, + "height": 121.225, + "id": "4908" + }, + { + "index": 2, + "height": 44, + "id": "161" + } + ] + } + }, + { + "id": "4ffe1086-25df-4c85-b168-979b5bbf0a26", + "type": "reply-node", + "x": 2170, + "y": 2480, + "properties": { + "config": { + "fields": [ + { + "label": "内容", + "value": "answer" + } + ] + }, + "height": 378, + "stepName": "Specified Reply", + "node_data": { + "fields": [ + "b931efe5-5b66-46e0-ae3b-0160cb18eeb5", + "directly_return" + ], + "content": "", + "reply_type": "referencing", + "is_result": true + } + } + }, + { + "id": "f1f1ee18-5a02-46f6-b4e6-226253cdffbb", + "type": "ai-chat-node", + "x": 2160, + "y": 3200, + "properties": { + "config": { + "fields": [ + { + "label": "AI 回答内容", + "value": "answer" + } + ] + }, + "height": 763, + "stepName": "AI Chat", + "node_data": { + "prompt": "Known information:\n{{Knowledge Search.data}}\nQuestion:\n{{Start.question}}", + "system": "", + "model_id": "", + "dialogue_number": 0, + "is_result": true + } + } + }, + { + "id": "309d0eef-c597-46b5-8d51-b9a28aaef4c7", + "type": "ai-chat-node", + "x": 2160, + "y": 3970, + "properties": { + "config": { + "fields": [ + { + "label": "AI 回答内容", + "value": "answer" + } + ] + }, + "height": 763, + "stepName": "AI Chat1", + "node_data": { + "prompt": "{{Start.question}}", + "system": "", + "model_id": "", + "dialogue_number": 0, + "is_result": true + } + } + } + ], + "edges": [ + { + "id": "7d0f166f-c472-41b2-b9a2-c294f4c83d73", + "type": "app-edge", + "sourceNodeId": "start-node", + "targetNodeId": "b931efe5-5b66-46e0-ae3b-0160cb18eeb5", + "startPoint": { + "x": 590, + "y": 3660 + }, + "endPoint": { + "x": 680, + "y": 3210 + }, + "properties": { + + }, + "pointsList": [ + { + "x": 590, + "y": 3660 + }, + { + "x": 700, + "y": 3660 + }, + { + "x": 570, + "y": 3210 + }, + { + "x": 680, + "y": 3210 + } + ], + "sourceAnchorId": "start-node_right", + "targetAnchorId": "b931efe5-5b66-46e0-ae3b-0160cb18eeb5_left" + }, + { + "id": "35cb86dd-f328-429e-a973-12fd7218b696", + "type": "app-edge", + "sourceNodeId": "b931efe5-5b66-46e0-ae3b-0160cb18eeb5", + "targetNodeId": "fc60863a-dec2-4854-9e5a-7a44b7187a2b", + "startPoint": { + "x": 1000, + "y": 3210 + }, + "endPoint": { + "x": 1200, + "y": 3210 + }, + "properties": { + + }, + "pointsList": [ + { + "x": 1000, + "y": 3210 + }, + { + "x": 1110, + "y": 3210 + }, + { + "x": 1090, + "y": 3210 + }, + { + "x": 1200, + "y": 3210 + } + ], + "sourceAnchorId": "b931efe5-5b66-46e0-ae3b-0160cb18eeb5_right", + "targetAnchorId": "fc60863a-dec2-4854-9e5a-7a44b7187a2b_left" + }, + { + "id": "e8f6cfe6-7e48-41cd-abd3-abfb5304d0d8", + "type": "app-edge", + "sourceNodeId": "fc60863a-dec2-4854-9e5a-7a44b7187a2b", + "targetNodeId": "4ffe1086-25df-4c85-b168-979b5bbf0a26", + "startPoint": { + "x": 1780, + "y": 3073.775 + }, + "endPoint": { + "x": 2010, + "y": 2480 + }, + "properties": { + + }, + "pointsList": [ + { + "x": 1780, + "y": 3073.775 + }, + { + "x": 1890, + "y": 3073.775 + }, + { + "x": 1900, + "y": 2480 + }, + { + "x": 2010, + "y": 2480 + } + ], + "sourceAnchorId": "fc60863a-dec2-4854-9e5a-7a44b7187a2b_1009_right", + "targetAnchorId": "4ffe1086-25df-4c85-b168-979b5bbf0a26_left" + }, + { + "id": "994ff325-6f7a-4ebc-b61b-10e15519d6d2", + "type": "app-edge", + "sourceNodeId": "fc60863a-dec2-4854-9e5a-7a44b7187a2b", + "targetNodeId": "f1f1ee18-5a02-46f6-b4e6-226253cdffbb", + "startPoint": { + "x": 1780, + "y": 3203 + }, + "endPoint": { + "x": 2000, + "y": 3200 + }, + "properties": { + + }, + "pointsList": [ + { + "x": 1780, + "y": 3203 + }, + { + "x": 1890, + "y": 3203 + }, + { + "x": 1890, + "y": 3200 + }, + { + "x": 2000, + "y": 3200 + } + ], + "sourceAnchorId": "fc60863a-dec2-4854-9e5a-7a44b7187a2b_4908_right", + "targetAnchorId": "f1f1ee18-5a02-46f6-b4e6-226253cdffbb_left" + }, + { + "id": "19270caf-bb9f-4ba7-9bf8-200aa70fecd5", + "type": "app-edge", + "sourceNodeId": "fc60863a-dec2-4854-9e5a-7a44b7187a2b", + "targetNodeId": "309d0eef-c597-46b5-8d51-b9a28aaef4c7", + "startPoint": { + "x": 1780, + "y": 3293.6124999999997 + }, + "endPoint": { + "x": 2000, + "y": 3970 + }, + "properties": { + + }, + "pointsList": [ + { + "x": 1780, + "y": 3293.6124999999997 + }, + { + "x": 1890, + "y": 3293.6124999999997 + }, + { + "x": 1890, + "y": 3970 + }, + { + "x": 2000, + "y": 3970 + } + ], + "sourceAnchorId": "fc60863a-dec2-4854-9e5a-7a44b7187a2b_161_right", + "targetAnchorId": "309d0eef-c597-46b5-8d51-b9a28aaef4c7_left" + } + ] +} \ No newline at end of file diff --git a/apps/application/flow/default_workflow_zh.json b/apps/application/flow/default_workflow_zh.json new file mode 100644 index 000000000..48ac23c4d --- /dev/null +++ b/apps/application/flow/default_workflow_zh.json @@ -0,0 +1,451 @@ +{ + "nodes": [ + { + "id": "base-node", + "type": "base-node", + "x": 360, + "y": 2810, + "properties": { + "config": { + + }, + "height": 825.6, + "stepName": "基本信息", + "node_data": { + "desc": "", + "name": "maxkbapplication", + "prologue": "您好,我是 MaxKB 小助手,您可以向我提出 MaxKB 使用问题。\n- MaxKB 主要功能有什么?\n- MaxKB 支持哪些大语言模型?\n- MaxKB 支持哪些文档类型?" + }, + "input_field_list": [ + + ] + } + }, + { + "id": "start-node", + "type": "start-node", + "x": 430, + "y": 3660, + "properties": { + "config": { + "fields": [ + { + "label": "用户问题", + "value": "question" + } + ], + "globalFields": [ + { + "label": "当前时间", + "value": "time" + } + ] + }, + "fields": [ + { + "label": "用户问题", + "value": "question" + } + ], + "height": 276, + "stepName": "开始", + "globalFields": [ + { + "label": "当前时间", + "value": "time" + } + ] + } + }, + { + "id": "b931efe5-5b66-46e0-ae3b-0160cb18eeb5", + "type": "search-dataset-node", + "x": 840, + "y": 3210, + "properties": { + "config": { + "fields": [ + { + "label": "检索结果的分段列表", + "value": "paragraph_list" + }, + { + "label": "满足直接回答的分段列表", + "value": "is_hit_handling_method_list" + }, + { + "label": "检索结果", + "value": "data" + }, + { + "label": "满足直接回答的分段内容", + "value": "directly_return" + } + ] + }, + "height": 794, + "stepName": "知识库检索", + "node_data": { + "dataset_id_list": [ + + ], + "dataset_setting": { + "top_n": 3, + "similarity": 0.6, + "search_mode": "embedding", + "max_paragraph_char_number": 5000 + }, + "question_reference_address": [ + "start-node", + "question" + ], + "source_dataset_id_list": [ + + ] + } + } + }, + { + "id": "fc60863a-dec2-4854-9e5a-7a44b7187a2b", + "type": "condition-node", + "x": 1490, + "y": 3210, + "properties": { + "width": 600, + "config": { + "fields": [ + { + "label": "分支名称", + "value": "branch_name" + } + ] + }, + "height": 543.675, + "stepName": "判断器", + "node_data": { + "branch": [ + { + "id": "1009", + "type": "IF", + "condition": "and", + "conditions": [ + { + "field": [ + "b931efe5-5b66-46e0-ae3b-0160cb18eeb5", + "is_hit_handling_method_list" + ], + "value": "1", + "compare": "len_ge" + } + ] + }, + { + "id": "4908", + "type": "ELSE IF 1", + "condition": "and", + "conditions": [ + { + "field": [ + "b931efe5-5b66-46e0-ae3b-0160cb18eeb5", + "paragraph_list" + ], + "value": "1", + "compare": "len_ge" + } + ] + }, + { + "id": "161", + "type": "ELSE", + "condition": "and", + "conditions": [ + + ] + } + ] + }, + "branch_condition_list": [ + { + "index": 0, + "height": 121.225, + "id": "1009" + }, + { + "index": 1, + "height": 121.225, + "id": "4908" + }, + { + "index": 2, + "height": 44, + "id": "161" + } + ] + } + }, + { + "id": "4ffe1086-25df-4c85-b168-979b5bbf0a26", + "type": "reply-node", + "x": 2170, + "y": 2480, + "properties": { + "config": { + "fields": [ + { + "label": "内容", + "value": "answer" + } + ] + }, + "height": 378, + "stepName": "指定回复", + "node_data": { + "fields": [ + "b931efe5-5b66-46e0-ae3b-0160cb18eeb5", + "directly_return" + ], + "content": "", + "reply_type": "referencing", + "is_result": true + } + } + }, + { + "id": "f1f1ee18-5a02-46f6-b4e6-226253cdffbb", + "type": "ai-chat-node", + "x": 2160, + "y": 3200, + "properties": { + "config": { + "fields": [ + { + "label": "AI 回答内容", + "value": "answer" + } + ] + }, + "height": 763, + "stepName": "AI 对话", + "node_data": { + "prompt": "已知信息:\n{{知识库检索.data}}\n问题:\n{{开始.question}}", + "system": "", + "model_id": "", + "dialogue_number": 0, + "is_result": true + } + } + }, + { + "id": "309d0eef-c597-46b5-8d51-b9a28aaef4c7", + "type": "ai-chat-node", + "x": 2160, + "y": 3970, + "properties": { + "config": { + "fields": [ + { + "label": "AI 回答内容", + "value": "answer" + } + ] + }, + "height": 763, + "stepName": "AI 对话1", + "node_data": { + "prompt": "{{开始.question}}", + "system": "", + "model_id": "", + "dialogue_number": 0, + "is_result": true + } + } + } + ], + "edges": [ + { + "id": "7d0f166f-c472-41b2-b9a2-c294f4c83d73", + "type": "app-edge", + "sourceNodeId": "start-node", + "targetNodeId": "b931efe5-5b66-46e0-ae3b-0160cb18eeb5", + "startPoint": { + "x": 590, + "y": 3660 + }, + "endPoint": { + "x": 680, + "y": 3210 + }, + "properties": { + + }, + "pointsList": [ + { + "x": 590, + "y": 3660 + }, + { + "x": 700, + "y": 3660 + }, + { + "x": 570, + "y": 3210 + }, + { + "x": 680, + "y": 3210 + } + ], + "sourceAnchorId": "start-node_right", + "targetAnchorId": "b931efe5-5b66-46e0-ae3b-0160cb18eeb5_left" + }, + { + "id": "35cb86dd-f328-429e-a973-12fd7218b696", + "type": "app-edge", + "sourceNodeId": "b931efe5-5b66-46e0-ae3b-0160cb18eeb5", + "targetNodeId": "fc60863a-dec2-4854-9e5a-7a44b7187a2b", + "startPoint": { + "x": 1000, + "y": 3210 + }, + "endPoint": { + "x": 1200, + "y": 3210 + }, + "properties": { + + }, + "pointsList": [ + { + "x": 1000, + "y": 3210 + }, + { + "x": 1110, + "y": 3210 + }, + { + "x": 1090, + "y": 3210 + }, + { + "x": 1200, + "y": 3210 + } + ], + "sourceAnchorId": "b931efe5-5b66-46e0-ae3b-0160cb18eeb5_right", + "targetAnchorId": "fc60863a-dec2-4854-9e5a-7a44b7187a2b_left" + }, + { + "id": "e8f6cfe6-7e48-41cd-abd3-abfb5304d0d8", + "type": "app-edge", + "sourceNodeId": "fc60863a-dec2-4854-9e5a-7a44b7187a2b", + "targetNodeId": "4ffe1086-25df-4c85-b168-979b5bbf0a26", + "startPoint": { + "x": 1780, + "y": 3073.775 + }, + "endPoint": { + "x": 2010, + "y": 2480 + }, + "properties": { + + }, + "pointsList": [ + { + "x": 1780, + "y": 3073.775 + }, + { + "x": 1890, + "y": 3073.775 + }, + { + "x": 1900, + "y": 2480 + }, + { + "x": 2010, + "y": 2480 + } + ], + "sourceAnchorId": "fc60863a-dec2-4854-9e5a-7a44b7187a2b_1009_right", + "targetAnchorId": "4ffe1086-25df-4c85-b168-979b5bbf0a26_left" + }, + { + "id": "994ff325-6f7a-4ebc-b61b-10e15519d6d2", + "type": "app-edge", + "sourceNodeId": "fc60863a-dec2-4854-9e5a-7a44b7187a2b", + "targetNodeId": "f1f1ee18-5a02-46f6-b4e6-226253cdffbb", + "startPoint": { + "x": 1780, + "y": 3203 + }, + "endPoint": { + "x": 2000, + "y": 3200 + }, + "properties": { + + }, + "pointsList": [ + { + "x": 1780, + "y": 3203 + }, + { + "x": 1890, + "y": 3203 + }, + { + "x": 1890, + "y": 3200 + }, + { + "x": 2000, + "y": 3200 + } + ], + "sourceAnchorId": "fc60863a-dec2-4854-9e5a-7a44b7187a2b_4908_right", + "targetAnchorId": "f1f1ee18-5a02-46f6-b4e6-226253cdffbb_left" + }, + { + "id": "19270caf-bb9f-4ba7-9bf8-200aa70fecd5", + "type": "app-edge", + "sourceNodeId": "fc60863a-dec2-4854-9e5a-7a44b7187a2b", + "targetNodeId": "309d0eef-c597-46b5-8d51-b9a28aaef4c7", + "startPoint": { + "x": 1780, + "y": 3293.6124999999997 + }, + "endPoint": { + "x": 2000, + "y": 3970 + }, + "properties": { + + }, + "pointsList": [ + { + "x": 1780, + "y": 3293.6124999999997 + }, + { + "x": 1890, + "y": 3293.6124999999997 + }, + { + "x": 1890, + "y": 3970 + }, + { + "x": 2000, + "y": 3970 + } + ], + "sourceAnchorId": "fc60863a-dec2-4854-9e5a-7a44b7187a2b_161_right", + "targetAnchorId": "309d0eef-c597-46b5-8d51-b9a28aaef4c7_left" + } + ] +} \ No newline at end of file diff --git a/apps/application/flow/default_workflow_zh_Hant.json b/apps/application/flow/default_workflow_zh_Hant.json new file mode 100644 index 000000000..b06301533 --- /dev/null +++ b/apps/application/flow/default_workflow_zh_Hant.json @@ -0,0 +1,451 @@ +{ + "nodes": [ + { + "id": "base-node", + "type": "base-node", + "x": 360, + "y": 2810, + "properties": { + "config": { + + }, + "height": 825.6, + "stepName": "基本資訊", + "node_data": { + "desc": "", + "name": "maxkbapplication", + "prologue": "您好,我是MaxKB小助手,您可以向我提出MaxKB使用問題。\n- MaxKB主要功能有什麼?\n- MaxKB支持哪些大語言模型?\n- MaxKB支持哪些文檔類型?" + }, + "input_field_list": [ + + ] + } + }, + { + "id": "start-node", + "type": "start-node", + "x": 430, + "y": 3660, + "properties": { + "config": { + "fields": [ + { + "label": "用户问题", + "value": "question" + } + ], + "globalFields": [ + { + "label": "当前时间", + "value": "time" + } + ] + }, + "fields": [ + { + "label": "用户问题", + "value": "question" + } + ], + "height": 276, + "stepName": "開始", + "globalFields": [ + { + "label": "当前时间", + "value": "time" + } + ] + } + }, + { + "id": "b931efe5-5b66-46e0-ae3b-0160cb18eeb5", + "type": "search-dataset-node", + "x": 840, + "y": 3210, + "properties": { + "config": { + "fields": [ + { + "label": "检索结果的分段列表", + "value": "paragraph_list" + }, + { + "label": "满足直接回答的分段列表", + "value": "is_hit_handling_method_list" + }, + { + "label": "检索结果", + "value": "data" + }, + { + "label": "满足直接回答的分段内容", + "value": "directly_return" + } + ] + }, + "height": 794, + "stepName": "知識庫檢索", + "node_data": { + "dataset_id_list": [ + + ], + "dataset_setting": { + "top_n": 3, + "similarity": 0.6, + "search_mode": "embedding", + "max_paragraph_char_number": 5000 + }, + "question_reference_address": [ + "start-node", + "question" + ], + "source_dataset_id_list": [ + + ] + } + } + }, + { + "id": "fc60863a-dec2-4854-9e5a-7a44b7187a2b", + "type": "condition-node", + "x": 1490, + "y": 3210, + "properties": { + "width": 600, + "config": { + "fields": [ + { + "label": "分支名称", + "value": "branch_name" + } + ] + }, + "height": 543.675, + "stepName": "判斷器", + "node_data": { + "branch": [ + { + "id": "1009", + "type": "IF", + "condition": "and", + "conditions": [ + { + "field": [ + "b931efe5-5b66-46e0-ae3b-0160cb18eeb5", + "is_hit_handling_method_list" + ], + "value": "1", + "compare": "len_ge" + } + ] + }, + { + "id": "4908", + "type": "ELSE IF 1", + "condition": "and", + "conditions": [ + { + "field": [ + "b931efe5-5b66-46e0-ae3b-0160cb18eeb5", + "paragraph_list" + ], + "value": "1", + "compare": "len_ge" + } + ] + }, + { + "id": "161", + "type": "ELSE", + "condition": "and", + "conditions": [ + + ] + } + ] + }, + "branch_condition_list": [ + { + "index": 0, + "height": 121.225, + "id": "1009" + }, + { + "index": 1, + "height": 121.225, + "id": "4908" + }, + { + "index": 2, + "height": 44, + "id": "161" + } + ] + } + }, + { + "id": "4ffe1086-25df-4c85-b168-979b5bbf0a26", + "type": "reply-node", + "x": 2170, + "y": 2480, + "properties": { + "config": { + "fields": [ + { + "label": "内容", + "value": "answer" + } + ] + }, + "height": 378, + "stepName": "指定回覆", + "node_data": { + "fields": [ + "b931efe5-5b66-46e0-ae3b-0160cb18eeb5", + "directly_return" + ], + "content": "", + "reply_type": "referencing", + "is_result": true + } + } + }, + { + "id": "f1f1ee18-5a02-46f6-b4e6-226253cdffbb", + "type": "ai-chat-node", + "x": 2160, + "y": 3200, + "properties": { + "config": { + "fields": [ + { + "label": "AI 回答内容", + "value": "answer" + } + ] + }, + "height": 763, + "stepName": "AI 對話", + "node_data": { + "prompt": "已知資訊:\n{{知識庫檢索.data}}\n問題:\n{{開始.question}}", + "system": "", + "model_id": "", + "dialogue_number": 0, + "is_result": true + } + } + }, + { + "id": "309d0eef-c597-46b5-8d51-b9a28aaef4c7", + "type": "ai-chat-node", + "x": 2160, + "y": 3970, + "properties": { + "config": { + "fields": [ + { + "label": "AI 回答内容", + "value": "answer" + } + ] + }, + "height": 763, + "stepName": "AI 對話1", + "node_data": { + "prompt": "{{開始.question}}", + "system": "", + "model_id": "", + "dialogue_number": 0, + "is_result": true + } + } + } + ], + "edges": [ + { + "id": "7d0f166f-c472-41b2-b9a2-c294f4c83d73", + "type": "app-edge", + "sourceNodeId": "start-node", + "targetNodeId": "b931efe5-5b66-46e0-ae3b-0160cb18eeb5", + "startPoint": { + "x": 590, + "y": 3660 + }, + "endPoint": { + "x": 680, + "y": 3210 + }, + "properties": { + + }, + "pointsList": [ + { + "x": 590, + "y": 3660 + }, + { + "x": 700, + "y": 3660 + }, + { + "x": 570, + "y": 3210 + }, + { + "x": 680, + "y": 3210 + } + ], + "sourceAnchorId": "start-node_right", + "targetAnchorId": "b931efe5-5b66-46e0-ae3b-0160cb18eeb5_left" + }, + { + "id": "35cb86dd-f328-429e-a973-12fd7218b696", + "type": "app-edge", + "sourceNodeId": "b931efe5-5b66-46e0-ae3b-0160cb18eeb5", + "targetNodeId": "fc60863a-dec2-4854-9e5a-7a44b7187a2b", + "startPoint": { + "x": 1000, + "y": 3210 + }, + "endPoint": { + "x": 1200, + "y": 3210 + }, + "properties": { + + }, + "pointsList": [ + { + "x": 1000, + "y": 3210 + }, + { + "x": 1110, + "y": 3210 + }, + { + "x": 1090, + "y": 3210 + }, + { + "x": 1200, + "y": 3210 + } + ], + "sourceAnchorId": "b931efe5-5b66-46e0-ae3b-0160cb18eeb5_right", + "targetAnchorId": "fc60863a-dec2-4854-9e5a-7a44b7187a2b_left" + }, + { + "id": "e8f6cfe6-7e48-41cd-abd3-abfb5304d0d8", + "type": "app-edge", + "sourceNodeId": "fc60863a-dec2-4854-9e5a-7a44b7187a2b", + "targetNodeId": "4ffe1086-25df-4c85-b168-979b5bbf0a26", + "startPoint": { + "x": 1780, + "y": 3073.775 + }, + "endPoint": { + "x": 2010, + "y": 2480 + }, + "properties": { + + }, + "pointsList": [ + { + "x": 1780, + "y": 3073.775 + }, + { + "x": 1890, + "y": 3073.775 + }, + { + "x": 1900, + "y": 2480 + }, + { + "x": 2010, + "y": 2480 + } + ], + "sourceAnchorId": "fc60863a-dec2-4854-9e5a-7a44b7187a2b_1009_right", + "targetAnchorId": "4ffe1086-25df-4c85-b168-979b5bbf0a26_left" + }, + { + "id": "994ff325-6f7a-4ebc-b61b-10e15519d6d2", + "type": "app-edge", + "sourceNodeId": "fc60863a-dec2-4854-9e5a-7a44b7187a2b", + "targetNodeId": "f1f1ee18-5a02-46f6-b4e6-226253cdffbb", + "startPoint": { + "x": 1780, + "y": 3203 + }, + "endPoint": { + "x": 2000, + "y": 3200 + }, + "properties": { + + }, + "pointsList": [ + { + "x": 1780, + "y": 3203 + }, + { + "x": 1890, + "y": 3203 + }, + { + "x": 1890, + "y": 3200 + }, + { + "x": 2000, + "y": 3200 + } + ], + "sourceAnchorId": "fc60863a-dec2-4854-9e5a-7a44b7187a2b_4908_right", + "targetAnchorId": "f1f1ee18-5a02-46f6-b4e6-226253cdffbb_left" + }, + { + "id": "19270caf-bb9f-4ba7-9bf8-200aa70fecd5", + "type": "app-edge", + "sourceNodeId": "fc60863a-dec2-4854-9e5a-7a44b7187a2b", + "targetNodeId": "309d0eef-c597-46b5-8d51-b9a28aaef4c7", + "startPoint": { + "x": 1780, + "y": 3293.6124999999997 + }, + "endPoint": { + "x": 2000, + "y": 3970 + }, + "properties": { + + }, + "pointsList": [ + { + "x": 1780, + "y": 3293.6124999999997 + }, + { + "x": 1890, + "y": 3293.6124999999997 + }, + { + "x": 1890, + "y": 3970 + }, + { + "x": 2000, + "y": 3970 + } + ], + "sourceAnchorId": "fc60863a-dec2-4854-9e5a-7a44b7187a2b_161_right", + "targetAnchorId": "309d0eef-c597-46b5-8d51-b9a28aaef4c7_left" + } + ] +} \ No newline at end of file diff --git a/apps/application/flow/workflow_manage.py b/apps/application/flow/workflow_manage.py index 5bc31b418..d4a7e69d1 100644 --- a/apps/application/flow/workflow_manage.py +++ b/apps/application/flow/workflow_manage.py @@ -17,6 +17,9 @@ from typing import List, Dict from django.db import close_old_connections from django.db.models import QuerySet +from django.utils import translation +from django.utils.translation import get_language +from django.utils.translation import gettext as _ from langchain_core.prompts import PromptTemplate from rest_framework import status from rest_framework.exceptions import ErrorDetail, ValidationError @@ -103,12 +106,14 @@ class Flow: edge_list = [edge for edge in self.edges if edge.sourceAnchorId == source_anchor_id] if len(edge_list) == 0: raise AppApiException(500, - f'{node.properties.get("stepName")} 节点的{branch.get("type")}分支需要连接') + _('The branch {branch} of the {node} node needs to be connected').format( + node=node.properties.get("stepName"), branch=branch.get("type"))) else: edge_list = [edge for edge in self.edges if edge.sourceNodeId == node.id] if len(edge_list) == 0 and not end_nodes.__contains__(node.type): - raise AppApiException(500, f'{node.properties.get("stepName")} 节点不能当做结束节点') + raise AppApiException(500, _("{node} Nodes cannot be considered as end nodes").format( + node=node.properties.get("stepName"))) def get_next_nodes(self, node: Node): edge_list = [edge for edge in self.edges if edge.sourceNodeId == node.id] @@ -117,7 +122,7 @@ class Flow: []) if len(node_list) == 0 and not end_nodes.__contains__(node.type): raise AppApiException(500, - f'不存在的下一个节点') + _("The next node that does not exist")) return node_list def is_valid_work_flow(self, up_node=None): @@ -131,16 +136,17 @@ class Flow: def is_valid_start_node(self): start_node_list = [node for node in self.nodes if node.id == 'start-node'] if len(start_node_list) == 0: - raise AppApiException(500, '开始节点必填') + raise AppApiException(500, _('The starting node is required')) if len(start_node_list) > 1: - raise AppApiException(500, '开始节点只能有一个') + raise AppApiException(500, _('There can only be one starting node')) def is_valid_model_params(self): node_list = [node for node in self.nodes if (node.type == 'ai-chat-node' or node.type == 'question-node')] for node in node_list: model = QuerySet(Model).filter(id=node.properties.get('node_data', {}).get('model_id')).first() if model is None: - raise ValidationError(ErrorDetail(f'节点{node.properties.get("stepName")} 模型不存在')) + raise ValidationError(ErrorDetail( + _('The node {node} model does not exist').format(node=node.properties.get("stepName")))) credential = get_model_credential(model.provider, model.model_type, model.model_name) model_params_setting = node.properties.get('node_data', {}).get('model_params_setting') model_params_setting_form = credential.get_model_params_setting_form( @@ -149,22 +155,25 @@ class Flow: model_params_setting = model_params_setting_form.get_default_form_data() node.properties.get('node_data', {})['model_params_setting'] = model_params_setting if node.properties.get('status', 200) != 200: - raise ValidationError(ErrorDetail(f'节点{node.properties.get("stepName")} 不可用')) + raise ValidationError( + ErrorDetail(_("Node {node} is unavailable").format(node.properties.get("stepName")))) node_list = [node for node in self.nodes if (node.type == 'function-lib-node')] for node in node_list: function_lib_id = node.properties.get('node_data', {}).get('function_lib_id') if function_lib_id is None: - raise ValidationError(ErrorDetail(f'节点{node.properties.get("stepName")} 函数库id不能为空')) + raise ValidationError(ErrorDetail( + _('The library ID of node {node} cannot be empty').format(node=node.properties.get("stepName")))) f_lib = QuerySet(FunctionLib).filter(id=function_lib_id).first() if f_lib is None: - raise ValidationError(ErrorDetail(f'节点{node.properties.get("stepName")} 函数库不可用')) + raise ValidationError(ErrorDetail(_("The function library for node {node} is not available").format( + node=node.properties.get("stepName")))) def is_valid_base_node(self): base_node_list = [node for node in self.nodes if node.id == 'base-node'] if len(base_node_list) == 0: - raise AppApiException(500, '基本信息节点必填') + raise AppApiException(500, _('Basic information node is required')) if len(base_node_list) > 1: - raise AppApiException(500, '基本信息节点只能有一个') + raise AppApiException(500, _('There can only be one basic information node')) class NodeResultFuture: @@ -307,16 +316,17 @@ class WorkflowManage: def run(self): close_old_connections() + language = get_language() if self.params.get('stream'): - return self.run_stream(self.start_node, None) - return self.run_block() + return self.run_stream(self.start_node, None, language) + return self.run_block(language) - def run_block(self): + def run_block(self, language='zh'): """ 非流式响应 @return: 结果 """ - self.run_chain_async(None, None) + self.run_chain_async(None, None, language) while self.is_run(): pass details = self.get_runtime_details() @@ -334,12 +344,12 @@ class WorkflowManage: , message_tokens, answer_tokens, _status=status.HTTP_200_OK if self.status == 200 else status.HTTP_500_INTERNAL_SERVER_ERROR) - def run_stream(self, current_node, node_result_future): + def run_stream(self, current_node, node_result_future, language='zh'): """ 流式响应 @return: """ - self.run_chain_async(current_node, node_result_future) + self.run_chain_async(current_node, node_result_future, language) return tools.to_stream_response_simple(self.await_result()) def is_run(self, timeout=0.5): @@ -385,11 +395,12 @@ class WorkflowManage: [], '', True, message_tokens, answer_tokens, {}) - def run_chain_async(self, current_node, node_result_future): - future = executor.submit(self.run_chain_manage, current_node, node_result_future) + def run_chain_async(self, current_node, node_result_future, language='zh'): + future = executor.submit(self.run_chain_manage, current_node, node_result_future, language) self.future_list.append(future) - def run_chain_manage(self, current_node, node_result_future): + def run_chain_manage(self, current_node, node_result_future, language='zh'): + translation.activate(language) if current_node is None: start_node = self.get_start_node() current_node = get_node(start_node.type)(start_node, self.params, self) @@ -401,11 +412,12 @@ class WorkflowManage: return node_list = self.get_next_node_list(current_node, result) if len(node_list) == 1: - self.run_chain_manage(node_list[0], None) + self.run_chain_manage(node_list[0], None, language) elif len(node_list) > 1: sorted_node_run_list = sorted(node_list, key=lambda n: n.node.y) # 获取到可执行的子节点 - result_list = [{'node': node, 'future': executor.submit(self.run_chain_manage, node, None)} for node in + result_list = [{'node': node, 'future': executor.submit(self.run_chain_manage, node, None, language)} for + node in sorted_node_run_list] for r in result_list: self.future_list.append(r.get('future')) diff --git a/apps/application/serializers/application_serializers.py b/apps/application/serializers/application_serializers.py index d714eb8d7..d199a4eab 100644 --- a/apps/application/serializers/application_serializers.py +++ b/apps/application/serializers/application_serializers.py @@ -54,7 +54,7 @@ from setting.models_provider.tools import get_model_instance_by_model_user_id from setting.serializers.provider_serializers import ModelSerializer from smartdoc.conf import PROJECT_DIR from users.models import User -from django.utils.translation import gettext_lazy as _ +from django.utils.translation import gettext_lazy as _, get_language, to_locale chat_cache = cache.caches['chat_cache'] @@ -154,11 +154,16 @@ class ApplicationWorkflowSerializer(serializers.Serializer): @staticmethod def to_application_model(user_id: str, application: Dict): + language = get_language() if application.get('work_flow') is not None: default_workflow = application.get('work_flow') else: - default_workflow_json = get_file_content( - os.path.join(PROJECT_DIR, "apps", "application", 'flow', 'default_workflow.json')) + workflow_file_path = os.path.join(PROJECT_DIR, "apps", "application", 'flow', + f'default_workflow_{to_locale(language)}.json') + if not os.path.exists(workflow_file_path): + workflow_file_path = os.path.join(PROJECT_DIR, "apps", "application", 'flow', + f'default_workflow_zh.json') + default_workflow_json = get_file_content(workflow_file_path) default_workflow = json.loads(default_workflow_json) for node in default_workflow.get('nodes'): if node.get('id') == 'base-node':