-
用户输入
-
diff --git a/ui/src/workflow-canvas/nodes/base-node/constant.ts b/ui/src/workflow-canvas/nodes/base-node/constant.ts
new file mode 100644
index 00000000000..c74d58e7a18
--- /dev/null
+++ b/ui/src/workflow-canvas/nodes/base-node/constant.ts
@@ -0,0 +1,14 @@
+import type { FileUploadSetting } from './types'
+
+export const defaultFileUploadSetting: FileUploadSetting = {
+ audio: false,
+ document: true,
+ fileLimit: 50,
+ image: false,
+ local_upload: true,
+ maxFiles: 3,
+ other: false,
+ otherExtensions: ['PPT', 'DOC'],
+ url_upload: false,
+ video: false,
+}
diff --git a/ui/src/workflow-canvas/nodes/base-node/index.vue b/ui/src/workflow-canvas/nodes/base-node/index.vue
index 24dfb821c82..a653c5c8f6d 100644
--- a/ui/src/workflow-canvas/nodes/base-node/index.vue
+++ b/ui/src/workflow-canvas/nodes/base-node/index.vue
@@ -3,26 +3,26 @@ import { computed, inject, onMounted, ref, useTemplateRef } from 'vue'
import { cloneDeep } from 'lodash'
import type { FormInstance } from 'element-plus'
import type { ModelItem, ModelProviderItem } from '@/api/types'
+import type { FormField } from '@/components/mk-dynamics-form'
import NodeContainer from '@/workflow-canvas/core/node-container/index.vue'
import type { WorkflowNodeModel } from '@/workflow-canvas/core/workflow-node'
import { useWorkflowStore } from '@/workflow-canvas/store'
import ApiParameter from './component/api-parameter/index.vue'
import ConversationVariable from './component/conversation-variable/index.vue'
-import FileUploadSetting from './component/file-upload/index.vue'
-import LongTermMemorySetting from './component/long-term-memory/index.vue'
+import FileUpload from './component/file-upload/index.vue'
+import LongTermMemory from './component/long-term-memory/index.vue'
import SpeechInput from './component/speech-input/index.vue'
import SpeechPlayback from './component/speech-playback/index.vue'
import UserInput from './component/user-input/index.vue'
+import { defaultFileUploadSetting } from './constant'
import {
- defaultFileUploadSetting,
type ApiInputField,
type BaseNodeForm,
type ChatInputField,
- type FileUploadSetting as FileUploadSettingValue,
+ type FileUploadSetting,
type LongTermSetting,
type SpeechInputSetting,
type SpeechPlaybackSetting,
- type UserInputField,
type UserInputSetting,
} from './types'
@@ -92,7 +92,7 @@ function handleEditorWheel(event: WheelEvent) {
}
// 子模块数据映射
-const userInputFields = computed(() => (model.properties.user_input_field_list ?? []) as UserInputField[])
+const userInputFields = computed(() => (model.properties.user_input_field_list ?? []) as FormField[])
const apiInputFields = computed(() => (model.properties.api_input_field_list ?? []) as ApiInputField[])
const conversationVariables = computed(() => (model.properties.chat_input_field_list ?? []) as ChatInputField[])
const userInputSetting = computed
(() =>
@@ -165,12 +165,12 @@ function updateFileUploadEnabled(enabled: boolean) {
model.graphModel.eventCenter.emit('refreshFileUploadConfig', undefined)
}
-function updateFileUploadSetting(setting: FileUploadSettingValue) {
+function updateFileUploadSetting(setting: FileUploadSetting) {
formData.value.file_upload_setting = setting
model.graphModel.eventCenter.emit('refreshFileUploadConfig', undefined)
}
-function updateUserInputFields(fields: UserInputField[]) {
+function updateUserInputFields(fields: FormField[]) {
model.properties.user_input_field_list = fields
model.graphModel.eventCenter.emit('refreshFieldList', undefined)
}
@@ -229,10 +229,11 @@ onMounted(() => {
-
+
-
+ {
@update:setting="updateLongTermSetting"
/>
-
+
+
(() => {
]
})
+// 节点初始化时补齐默认值和兼容旧数据,computed 只读取表单。
+if (!model.properties.node_data) {
+ model.properties.node_data = { is_result: true, form_content_format: '', form_field_list: [] }
+}
+
const form_data = computed<{ is_result: boolean; form_field_list: FormField[]; form_content_format: string }>({
- get: () => {
- if (!model.properties.node_data) {
- model.properties.node_data = { is_result: true, form_content_format: '', form_field_list: [] }
- }
- return model.properties.node_data as { is_result: boolean; form_field_list: FormField[]; form_content_format: string }
- },
+ get: () => model.properties.node_data as { is_result: boolean; form_field_list: FormField[]; form_content_format: string },
set: (value) => {
model.properties.node_data = value
},
diff --git a/ui/src/workflow-canvas/nodes/image-generate-node/index.vue b/ui/src/workflow-canvas/nodes/image-generate-node/index.vue
index d9995fe9fba..6eb8bdc8eab 100644
--- a/ui/src/workflow-canvas/nodes/image-generate-node/index.vue
+++ b/ui/src/workflow-canvas/nodes/image-generate-node/index.vue
@@ -31,26 +31,26 @@ const store = useWorkflowStore(apiType)
const modelList = ref>([])
const providerOptions = ref>([])
+// 节点初始化时补齐默认值和兼容旧数据,computed 只读取表单。
+if (!model.properties.node_data) {
+ model.properties.node_data = {
+ model_id: '',
+ model_id_type: 'custom',
+ model_id_reference: [],
+ prompt: '{{开始.question}}',
+ negative_prompt: '',
+ model_params_setting: {},
+ }
+}
+const initialNodeData = model.properties.node_data as ImageGenerateNodeForm
+if (initialNodeData.model_id_type === undefined) initialNodeData.model_id_type = 'custom'
+if (!Array.isArray(initialNodeData.model_id_reference)) initialNodeData.model_id_reference = []
+if (initialNodeData.prompt === undefined) initialNodeData.prompt = '{{开始.question}}'
+if (initialNodeData.negative_prompt === undefined) initialNodeData.negative_prompt = ''
+if (!initialNodeData.model_params_setting) initialNodeData.model_params_setting = {}
+
const formData = computed({
- get: () => {
- if (!model.properties.node_data) {
- model.properties.node_data = {
- model_id: '',
- model_id_type: 'custom',
- model_id_reference: [],
- prompt: '{{开始.question}}',
- negative_prompt: '',
- model_params_setting: {},
- }
- }
- const data = model.properties.node_data as ImageGenerateNodeForm
- if (data.model_id_type === undefined) data.model_id_type = 'custom'
- if (!Array.isArray(data.model_id_reference)) data.model_id_reference = []
- if (data.prompt === undefined) data.prompt = '{{开始.question}}'
- if (data.negative_prompt === undefined) data.negative_prompt = ''
- if (!data.model_params_setting) data.model_params_setting = {}
- return data
- },
+ get: () => model.properties.node_data as ImageGenerateNodeForm,
set: (value) => (model.properties.node_data = value),
})
diff --git a/ui/src/workflow-canvas/nodes/image-understand-node/index.vue b/ui/src/workflow-canvas/nodes/image-understand-node/index.vue
index 61f3fe40395..7b099db4976 100644
--- a/ui/src/workflow-canvas/nodes/image-understand-node/index.vue
+++ b/ui/src/workflow-canvas/nodes/image-understand-node/index.vue
@@ -35,34 +35,34 @@ const store = useWorkflowStore(apiType)
const modelList = ref>([])
const providerOptions = ref>([])
+// 节点初始化时补齐默认值和兼容旧数据,computed 只读取表单。
+if (!model.properties.node_data) {
+ model.properties.node_data = {
+ model_id: '',
+ model_id_type: 'custom',
+ model_id_reference: [],
+ model_setting: { reasoning_content_enable: false },
+ prompt: '{{开始.question}}',
+ system: '',
+ dialogue_type: 'WORKFLOW',
+ dialogue_number: 1,
+ image_list: [],
+ }
+}
+const initialNodeData = model.properties.node_data as ImageUnderstandNodeForm
+if (initialNodeData.model_id_type === undefined) initialNodeData.model_id_type = 'custom'
+if (!Array.isArray(initialNodeData.model_id_reference)) initialNodeData.model_id_reference = []
+if (!initialNodeData.model_setting) initialNodeData.model_setting = { reasoning_content_enable: false }
+if (initialNodeData.prompt === undefined) initialNodeData.prompt = '{{开始.question}}'
+if (initialNodeData.system === undefined) initialNodeData.system = ''
+if (initialNodeData.dialogue_type === undefined) initialNodeData.dialogue_type = 'WORKFLOW'
+if (initialNodeData.dialogue_number === undefined || initialNodeData.dialogue_number === null) {
+ initialNodeData.dialogue_number = 1
+}
+if (!Array.isArray(initialNodeData.image_list)) initialNodeData.image_list = []
+
const formData = computed({
- get: () => {
- if (!model.properties.node_data) {
- model.properties.node_data = {
- model_id: '',
- model_id_type: 'custom',
- model_id_reference: [],
- model_setting: { reasoning_content_enable: false },
- prompt: '{{开始.question}}',
- system: '',
- dialogue_type: 'WORKFLOW',
- dialogue_number: 1,
- image_list: [],
- }
- }
- const data = model.properties.node_data as ImageUnderstandNodeForm
- if (data.model_id_type === undefined) data.model_id_type = 'custom'
- if (!Array.isArray(data.model_id_reference)) data.model_id_reference = []
- if (!data.model_setting) data.model_setting = { reasoning_content_enable: false }
- if (data.prompt === undefined) data.prompt = '{{开始.question}}'
- if (data.system === undefined) data.system = ''
- if (data.dialogue_type === undefined) data.dialogue_type = 'WORKFLOW'
- if (data.dialogue_number === undefined || data.dialogue_number === null) {
- data.dialogue_number = 1
- }
- if (!Array.isArray(data.image_list)) data.image_list = []
- return data
- },
+ get: () => model.properties.node_data as ImageUnderstandNodeForm,
set: (value) => (model.properties.node_data = value),
})
diff --git a/ui/src/workflow-canvas/nodes/intent-node/index.vue b/ui/src/workflow-canvas/nodes/intent-node/index.vue
index 19acf32ea11..e5813c00d14 100644
--- a/ui/src/workflow-canvas/nodes/intent-node/index.vue
+++ b/ui/src/workflow-canvas/nodes/intent-node/index.vue
@@ -48,34 +48,34 @@ function defaultBranch(): IntentNodeBranch[] {
]
}
+// 节点初始化时补齐默认值和兼容旧数据,computed 只读取表单。
+if (!model.properties.node_data) {
+ model.properties.node_data = {
+ model_id: '',
+ model_id_type: 'custom',
+ model_id_reference: [],
+ model_params_setting: {},
+ content_list: [],
+ dialogue_type: 'WORKFLOW',
+ dialogue_number: 1,
+ branch: defaultBranch(),
+ }
+}
+const initialNodeData = model.properties.node_data as IntentNodeForm
+if (initialNodeData.model_id_type === undefined) initialNodeData.model_id_type = 'custom'
+if (!Array.isArray(initialNodeData.model_id_reference)) initialNodeData.model_id_reference = []
+if (!initialNodeData.model_params_setting) initialNodeData.model_params_setting = {}
+if (!Array.isArray(initialNodeData.content_list)) initialNodeData.content_list = []
+if (initialNodeData.dialogue_type === undefined) initialNodeData.dialogue_type = 'WORKFLOW'
+if (initialNodeData.dialogue_number === undefined || initialNodeData.dialogue_number === null) {
+ initialNodeData.dialogue_number = 1
+}
+if (!Array.isArray(initialNodeData.branch) || initialNodeData.branch.length === 0) {
+ initialNodeData.branch = defaultBranch()
+}
+
const formData = computed({
- get: () => {
- if (!model.properties.node_data) {
- model.properties.node_data = {
- model_id: '',
- model_id_type: 'custom',
- model_id_reference: [],
- model_params_setting: {},
- content_list: [],
- dialogue_type: 'WORKFLOW',
- dialogue_number: 1,
- branch: defaultBranch(),
- }
- }
- const data = model.properties.node_data as IntentNodeForm
- if (data.model_id_type === undefined) data.model_id_type = 'custom'
- if (!Array.isArray(data.model_id_reference)) data.model_id_reference = []
- if (!data.model_params_setting) data.model_params_setting = {}
- if (!Array.isArray(data.content_list)) data.content_list = []
- if (data.dialogue_type === undefined) data.dialogue_type = 'WORKFLOW'
- if (data.dialogue_number === undefined || data.dialogue_number === null) {
- data.dialogue_number = 1
- }
- if (!Array.isArray(data.branch) || data.branch.length === 0) {
- data.branch = defaultBranch()
- }
- return data
- },
+ get: () => model.properties.node_data as IntentNodeForm,
set: (value) => (model.properties.node_data = value),
})
diff --git a/ui/src/workflow-canvas/nodes/parameter-extraction-node/component/ParametersFieldTable.vue b/ui/src/workflow-canvas/nodes/parameter-extraction-node/component/ParametersFieldTable.vue
index c40fb318385..d4c928cbcda 100644
--- a/ui/src/workflow-canvas/nodes/parameter-extraction-node/component/ParametersFieldTable.vue
+++ b/ui/src/workflow-canvas/nodes/parameter-extraction-node/component/ParametersFieldTable.vue
@@ -61,16 +61,16 @@ const nodeProps = props.nodeModel.properties as unknown as {
node_data: Record
}
+// 节点初始化时补齐默认值和兼容旧数据,computed 只读取表单。
+if (!nodeProps.node_data) {
+ nodeProps.node_data = {}
+}
+if (!Array.isArray(nodeProps.node_data.variable_list)) {
+ nodeProps.node_data.variable_list = []
+}
+
const inputFieldList = computed>>({
- get: () => {
- if (!nodeProps.node_data) {
- nodeProps.node_data = {}
- }
- if (!Array.isArray(nodeProps.node_data.variable_list)) {
- nodeProps.node_data.variable_list = []
- }
- return nodeProps.node_data.variable_list as Array>
- },
+ get: () => nodeProps.node_data.variable_list as Array>,
set: (value) => {
nodeProps.node_data.variable_list = value
},
diff --git a/ui/src/workflow-canvas/nodes/parameter-extraction-node/index.vue b/ui/src/workflow-canvas/nodes/parameter-extraction-node/index.vue
index 607c1199950..354680085d6 100644
--- a/ui/src/workflow-canvas/nodes/parameter-extraction-node/index.vue
+++ b/ui/src/workflow-canvas/nodes/parameter-extraction-node/index.vue
@@ -91,29 +91,29 @@ const store = useWorkflowStore(apiType)
const modelList = ref>([])
const providerOptions = ref>([])
+// 节点初始化时补齐默认值和兼容旧数据,computed 只读取表单。
+if (!model.properties.node_data) {
+ model.properties.node_data = {
+ input_variable: [],
+ model_params_setting: {},
+ model_id: '',
+ model_id_type: 'custom',
+ model_id_reference: [],
+ variable_list: [],
+ }
+}
+const initialNodeData = model.properties.node_data as ParameterExtractionForm
+if (initialNodeData.model_id_type === undefined) initialNodeData.model_id_type = 'custom'
+if (!Array.isArray(initialNodeData.model_id_reference)) initialNodeData.model_id_reference = []
+if (!initialNodeData.model_params_setting) initialNodeData.model_params_setting = {}
+const shouldInit = initialNodeData.input_variable !== undefined || initialNodeData.variable_list !== undefined
+if (shouldInit) {
+ if (!Array.isArray(initialNodeData.input_variable)) initialNodeData.input_variable = []
+ if (!Array.isArray(initialNodeData.variable_list)) initialNodeData.variable_list = []
+}
+
const formData = computed({
- get: () => {
- if (!model.properties.node_data) {
- model.properties.node_data = {
- input_variable: [],
- model_params_setting: {},
- model_id: '',
- model_id_type: 'custom',
- model_id_reference: [],
- variable_list: [],
- }
- }
- const data = model.properties.node_data as ParameterExtractionForm
- if (data.model_id_type === undefined) data.model_id_type = 'custom'
- if (!Array.isArray(data.model_id_reference)) data.model_id_reference = []
- if (!data.model_params_setting) data.model_params_setting = {}
- const shouldInit = data.input_variable !== undefined || data.variable_list !== undefined
- if (shouldInit) {
- if (!Array.isArray(data.input_variable)) data.input_variable = []
- if (!Array.isArray(data.variable_list)) data.variable_list = []
- }
- return data
- },
+ get: () => model.properties.node_data as ParameterExtractionForm,
set: (value) => (model.properties.node_data = value),
})
diff --git a/ui/src/workflow-canvas/nodes/question-node/index.vue b/ui/src/workflow-canvas/nodes/question-node/index.vue
index 10d60806f2c..b84e7a9d8d2 100644
--- a/ui/src/workflow-canvas/nodes/question-node/index.vue
+++ b/ui/src/workflow-canvas/nodes/question-node/index.vue
@@ -33,35 +33,35 @@ const store = useWorkflowStore(apiType)
const modelList = ref>([])
const providerOptions = ref>([])
+// 节点初始化时补齐默认值和兼容旧数据,computed 只读取表单。
+if (!model.properties.node_data) {
+ model.properties.node_data = {
+ model_id: '',
+ model_id_type: 'custom',
+ model_id_reference: [],
+ system:
+ '# 角色\n你是一位问题优化大师,擅长根据上下文精准揣测用户意图,并对用户提出的问题进行优化。\n\n' +
+ '## 技能\n### 技能 1: 优化问题\n2. 接收用户输入的问题。\n3. 依据上下文仔细分析问题含义。\n4. 输出优化后的问题。\n\n' +
+ '## 限制:\n - 仅返回优化后的问题,不进行额外解释或说明。\n - 确保优化后的问题准确反映原始问题意图,不得改变原意。',
+ prompt: '{{开始.question}}',
+ dialogue_type: 'WORKFLOW',
+ dialogue_number: 1,
+ model_params_setting: {},
+ }
+}
+const initialNodeData = model.properties.node_data as QuestionNodeForm
+if (initialNodeData.model_id_type === undefined) initialNodeData.model_id_type = 'custom'
+if (!Array.isArray(initialNodeData.model_id_reference)) initialNodeData.model_id_reference = []
+if (initialNodeData.system === undefined) initialNodeData.system = ''
+if (initialNodeData.prompt === undefined) initialNodeData.prompt = '{{开始.question}}'
+if (initialNodeData.dialogue_type === undefined) initialNodeData.dialogue_type = 'WORKFLOW'
+if (initialNodeData.dialogue_number === undefined || initialNodeData.dialogue_number === null) {
+ initialNodeData.dialogue_number = 1
+}
+if (!initialNodeData.model_params_setting) initialNodeData.model_params_setting = {}
+
const formData = computed({
- get: () => {
- if (!model.properties.node_data) {
- model.properties.node_data = {
- model_id: '',
- model_id_type: 'custom',
- model_id_reference: [],
- system:
- '# 角色\n你是一位问题优化大师,擅长根据上下文精准揣测用户意图,并对用户提出的问题进行优化。\n\n' +
- '## 技能\n### 技能 1: 优化问题\n2. 接收用户输入的问题。\n3. 依据上下文仔细分析问题含义。\n4. 输出优化后的问题。\n\n' +
- '## 限制:\n - 仅返回优化后的问题,不进行额外解释或说明。\n - 确保优化后的问题准确反映原始问题意图,不得改变原意。',
- prompt: '{{开始.question}}',
- dialogue_type: 'WORKFLOW',
- dialogue_number: 1,
- model_params_setting: {},
- }
- }
- const data = model.properties.node_data as QuestionNodeForm
- if (data.model_id_type === undefined) data.model_id_type = 'custom'
- if (!Array.isArray(data.model_id_reference)) data.model_id_reference = []
- if (data.system === undefined) data.system = ''
- if (data.prompt === undefined) data.prompt = '{{开始.question}}'
- if (data.dialogue_type === undefined) data.dialogue_type = 'WORKFLOW'
- if (data.dialogue_number === undefined || data.dialogue_number === null) {
- data.dialogue_number = 1
- }
- if (!data.model_params_setting) data.model_params_setting = {}
- return data
- },
+ get: () => model.properties.node_data as QuestionNodeForm,
set: (value) => (model.properties.node_data = value),
})
diff --git a/ui/src/workflow-canvas/nodes/reply-node/index.vue b/ui/src/workflow-canvas/nodes/reply-node/index.vue
index 717e281d616..bca83193ffe 100644
--- a/ui/src/workflow-canvas/nodes/reply-node/index.vue
+++ b/ui/src/workflow-canvas/nodes/reply-node/index.vue
@@ -2,7 +2,7 @@
import { computed, inject, onMounted, useTemplateRef } from 'vue'
import type { FormInstance } from 'element-plus'
-import type { WorkflowNodeModel } from '@/workflow-canvas/core/workflow-node'
+import { handleNodeWheel } from '@/workflow-canvas/core/utils'
import NodeCascader from '@/workflow-canvas/core/NodeCascader.vue'
import NodeContainer from '@/workflow-canvas/core/node-container/index.vue'
import { isLastNode } from '@/workflow-canvas/core/utils'
@@ -21,13 +21,13 @@ interface ReplyNodeForm {
const formRef = useTemplateRef('formRef')
const nodeCascaderRef = useTemplateRef>('nodeCascaderRef')
+// 节点初始化时补齐默认值和兼容旧数据,computed 只读取表单。
+if (!model.properties.node_data) {
+ model.properties.node_data = { content: '', fields: [], is_result: true, reply_type: 'content' }
+}
+
const formData = computed({
- get: () => {
- if (!model.properties.node_data) {
- model.properties.node_data = { content: '', fields: [], is_result: true, reply_type: 'content' }
- }
- return model.properties.node_data as ReplyNodeForm
- },
+ get: () => model.properties.node_data as ReplyNodeForm,
set: (value) => (model.properties.node_data = value),
})
@@ -48,25 +48,43 @@ onMounted(() => {
-
-
-
-
- 回复内容
-
-
-
-
-
-
+
+
+
+
+
+ 回复内容
+
+
+
+
+
+
+
+
-
-
-
+
+
-
-
-
-
+
+
+ 返回内容
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/src/workflow-canvas/nodes/search-knowledge-node/component/search-scope/index.vue b/ui/src/workflow-canvas/nodes/search-knowledge-node/component/search-scope/index.vue
new file mode 100644
index 00000000000..183970a951d
--- /dev/null
+++ b/ui/src/workflow-canvas/nodes/search-knowledge-node/component/search-scope/index.vue
@@ -0,0 +1,132 @@
+
+
+
+
+
+
+
检索范围
+
+
+
+
+
+
+
+
+
+
+
+
+
请选择关联知识库
+
+
+
+
+ {{ resource.name || resource.id }}
+
+
+
+
+
+
+
+
+
+ 选择变量
+
+ {{
+ '["019d8ac3-e2c6-7ff2-8956-c9c98f0e11f4", "019d8ac3-e2c6-7ff2-8956-c9c98f0e11f3"]'
+ }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/src/workflow-canvas/nodes/search-knowledge-node/component/search-setting/SearchSettingDialog.vue b/ui/src/workflow-canvas/nodes/search-knowledge-node/component/search-setting/SearchSettingDialog.vue
new file mode 100644
index 00000000000..3515fb54be6
--- /dev/null
+++ b/ui/src/workflow-canvas/nodes/search-knowledge-node/component/search-setting/SearchSettingDialog.vue
@@ -0,0 +1,103 @@
+
+
+
+
+
+
+
+
+ {{ option.label }}
+ {{ option.description }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 取消
+ 保存
+
+
+
diff --git a/ui/src/workflow-canvas/nodes/search-knowledge-node/component/search-setting/index.vue b/ui/src/workflow-canvas/nodes/search-knowledge-node/component/search-setting/index.vue
new file mode 100644
index 00000000000..0bb973a239c
--- /dev/null
+++ b/ui/src/workflow-canvas/nodes/search-knowledge-node/component/search-setting/index.vue
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+ 检索参数
+
+
+
+
+
+ - {{ row.label }}
+ - {{ row.value }}
+
+
+
+
+
diff --git a/ui/src/workflow-canvas/nodes/search-knowledge-node/config.ts b/ui/src/workflow-canvas/nodes/search-knowledge-node/config.ts
new file mode 100644
index 00000000000..12f41178695
--- /dev/null
+++ b/ui/src/workflow-canvas/nodes/search-knowledge-node/config.ts
@@ -0,0 +1,15 @@
+import { KNOWLEDGE_SEARCH_MODE } from '@/api/enums'
+import type { KnowledgeSearchSetting } from './types'
+
+export const defaultSearchSetting: KnowledgeSearchSetting = {
+ top_n: 3,
+ similarity: 0.6,
+ max_paragraph_char_number: 5000,
+ search_mode: KNOWLEDGE_SEARCH_MODE.EMBEDDING,
+}
+
+export const searchModeOptions = [
+ { value: KNOWLEDGE_SEARCH_MODE.EMBEDDING, label: '向量检索', description: '基于向量相似度检索,适用于知识库中的大数据量场景。' },
+ { value: KNOWLEDGE_SEARCH_MODE.KEYWORDS, label: '全文检索', description: '基于文本相似度检索,适用于知识库中的小数据量场景。' },
+ { value: KNOWLEDGE_SEARCH_MODE.BLEND, label: '混合检索', description: '结合向量和文本相似度检索,适用于知识库中的中等数据量场景。' },
+]
diff --git a/ui/src/workflow-canvas/nodes/search-knowledge-node/index.ts b/ui/src/workflow-canvas/nodes/search-knowledge-node/index.ts
new file mode 100644
index 00000000000..d3abb64472f
--- /dev/null
+++ b/ui/src/workflow-canvas/nodes/search-knowledge-node/index.ts
@@ -0,0 +1,15 @@
+import SearchKnowledgeNodeVue from './index.vue'
+import { WorkflowNodeModel, WorkflowNodeView } from '@/workflow-canvas/core/workflow-node'
+import { WorkflowNodeType } from '@/workflow-canvas/types'
+
+class SearchKnowledgeNodeView extends WorkflowNodeView {
+ constructor(props: ConstructorParameters[0]) {
+ super(props, SearchKnowledgeNodeVue)
+ }
+}
+
+export default {
+ type: WorkflowNodeType.SearchKnowledge,
+ model: WorkflowNodeModel,
+ view: SearchKnowledgeNodeView,
+}
diff --git a/ui/src/workflow-canvas/nodes/search-knowledge-node/index.vue b/ui/src/workflow-canvas/nodes/search-knowledge-node/index.vue
new file mode 100644
index 00000000000..f8ea018ecf0
--- /dev/null
+++ b/ui/src/workflow-canvas/nodes/search-knowledge-node/index.vue
@@ -0,0 +1,102 @@
+
+
+
+
+ 节点设置
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/src/workflow-canvas/nodes/search-knowledge-node/types.ts b/ui/src/workflow-canvas/nodes/search-knowledge-node/types.ts
new file mode 100644
index 00000000000..7356a7be26d
--- /dev/null
+++ b/ui/src/workflow-canvas/nodes/search-knowledge-node/types.ts
@@ -0,0 +1,21 @@
+import type { KNOWLEDGE_SEARCH_MODE } from '@/api/enums'
+import type { KnowledgeSelection } from '@/components/business/knowledge-selection-dialog/types'
+
+export interface KnowledgeSearchSetting {
+ top_n: number
+ similarity: number
+ max_paragraph_char_number: number
+ search_mode: (typeof KNOWLEDGE_SEARCH_MODE)[keyof typeof KNOWLEDGE_SEARCH_MODE]
+}
+
+export interface SearchKnowledgeNodeForm {
+ knowledge_id_list: string[]
+ knowledge_list: KnowledgeSelection[]
+ all_knowledge_id_list?: string[]
+ knowledge_setting: KnowledgeSearchSetting
+ question_reference_address: string[]
+ show_knowledge: boolean
+ search_scope_type: 'custom' | 'referencing'
+ search_scope_source: 'knowledge' | 'document'
+ search_scope_reference: string[]
+}
diff --git a/ui/src/workflow-canvas/nodes/speech-to-text-node/index.vue b/ui/src/workflow-canvas/nodes/speech-to-text-node/index.vue
index 386655654cf..d7ac3f38e4b 100644
--- a/ui/src/workflow-canvas/nodes/speech-to-text-node/index.vue
+++ b/ui/src/workflow-canvas/nodes/speech-to-text-node/index.vue
@@ -30,24 +30,24 @@ const store = useWorkflowStore(apiType)
const modelList = ref>([])
const providerOptions = ref>([])
+// 节点初始化时补齐默认值和兼容旧数据,computed 只读取表单。
+if (!model.properties.node_data) {
+ model.properties.node_data = {
+ stt_model_id: '',
+ stt_model_id_type: 'custom',
+ stt_model_id_reference: [],
+ audio_list: [],
+ model_params_setting: {},
+ }
+}
+const initialNodeData = model.properties.node_data as SpeechToTextNodeForm
+if (initialNodeData.stt_model_id_type === undefined) initialNodeData.stt_model_id_type = 'custom'
+if (!Array.isArray(initialNodeData.stt_model_id_reference)) initialNodeData.stt_model_id_reference = []
+if (!Array.isArray(initialNodeData.audio_list)) initialNodeData.audio_list = []
+if (!initialNodeData.model_params_setting) initialNodeData.model_params_setting = {}
+
const formData = computed({
- get: () => {
- if (!model.properties.node_data) {
- model.properties.node_data = {
- stt_model_id: '',
- stt_model_id_type: 'custom',
- stt_model_id_reference: [],
- audio_list: [],
- model_params_setting: {},
- }
- }
- const data = model.properties.node_data as SpeechToTextNodeForm
- if (data.stt_model_id_type === undefined) data.stt_model_id_type = 'custom'
- if (!Array.isArray(data.stt_model_id_reference)) data.stt_model_id_reference = []
- if (!Array.isArray(data.audio_list)) data.audio_list = []
- if (!data.model_params_setting) data.model_params_setting = {}
- return data
- },
+ get: () => model.properties.node_data as SpeechToTextNodeForm,
set: (value) => (model.properties.node_data = value),
})
diff --git a/ui/src/workflow-canvas/nodes/text-to-speech-node/index.vue b/ui/src/workflow-canvas/nodes/text-to-speech-node/index.vue
index 966e161fdd5..567629bc508 100644
--- a/ui/src/workflow-canvas/nodes/text-to-speech-node/index.vue
+++ b/ui/src/workflow-canvas/nodes/text-to-speech-node/index.vue
@@ -30,24 +30,24 @@ const store = useWorkflowStore(apiType)
const modelList = ref>([])
const providerOptions = ref>([])
+// 节点初始化时补齐默认值和兼容旧数据,computed 只读取表单。
+if (!model.properties.node_data) {
+ model.properties.node_data = {
+ tts_model_id: '',
+ tts_model_id_type: 'custom',
+ tts_model_id_reference: [],
+ content_list: [],
+ model_params_setting: {},
+ }
+}
+const initialNodeData = model.properties.node_data as TextToSpeechNodeForm
+if (initialNodeData.tts_model_id_type === undefined) initialNodeData.tts_model_id_type = 'custom'
+if (!Array.isArray(initialNodeData.tts_model_id_reference)) initialNodeData.tts_model_id_reference = []
+if (!Array.isArray(initialNodeData.content_list)) initialNodeData.content_list = []
+if (!initialNodeData.model_params_setting) initialNodeData.model_params_setting = {}
+
const formData = computed({
- get: () => {
- if (!model.properties.node_data) {
- model.properties.node_data = {
- tts_model_id: '',
- tts_model_id_type: 'custom',
- tts_model_id_reference: [],
- content_list: [],
- model_params_setting: {},
- }
- }
- const data = model.properties.node_data as TextToSpeechNodeForm
- if (data.tts_model_id_type === undefined) data.tts_model_id_type = 'custom'
- if (!Array.isArray(data.tts_model_id_reference)) data.tts_model_id_reference = []
- if (!Array.isArray(data.content_list)) data.content_list = []
- if (!data.model_params_setting) data.model_params_setting = {}
- return data
- },
+ get: () => model.properties.node_data as TextToSpeechNodeForm,
set: (value) => (model.properties.node_data = value),
})
diff --git a/ui/src/workflow-canvas/nodes/text-to-video-node/index.vue b/ui/src/workflow-canvas/nodes/text-to-video-node/index.vue
index ad7d73d2287..7d278a4b4b0 100644
--- a/ui/src/workflow-canvas/nodes/text-to-video-node/index.vue
+++ b/ui/src/workflow-canvas/nodes/text-to-video-node/index.vue
@@ -31,26 +31,26 @@ const store = useWorkflowStore(apiType)
const modelList = ref>([])
const providerOptions = ref>([])
+// 节点初始化时补齐默认值和兼容旧数据,computed 只读取表单。
+if (!model.properties.node_data) {
+ model.properties.node_data = {
+ model_id: '',
+ model_id_type: 'custom',
+ model_id_reference: [],
+ prompt: '{{开始.question}}',
+ negative_prompt: '',
+ model_params_setting: {},
+ }
+}
+const initialNodeData = model.properties.node_data as TextToVideoNodeForm
+if (initialNodeData.model_id_type === undefined) initialNodeData.model_id_type = 'custom'
+if (!Array.isArray(initialNodeData.model_id_reference)) initialNodeData.model_id_reference = []
+if (initialNodeData.prompt === undefined) initialNodeData.prompt = '{{开始.question}}'
+if (initialNodeData.negative_prompt === undefined) initialNodeData.negative_prompt = ''
+if (!initialNodeData.model_params_setting) initialNodeData.model_params_setting = {}
+
const formData = computed({
- get: () => {
- if (!model.properties.node_data) {
- model.properties.node_data = {
- model_id: '',
- model_id_type: 'custom',
- model_id_reference: [],
- prompt: '{{开始.question}}',
- negative_prompt: '',
- model_params_setting: {},
- }
- }
- const data = model.properties.node_data as TextToVideoNodeForm
- if (data.model_id_type === undefined) data.model_id_type = 'custom'
- if (!Array.isArray(data.model_id_reference)) data.model_id_reference = []
- if (data.prompt === undefined) data.prompt = '{{开始.question}}'
- if (data.negative_prompt === undefined) data.negative_prompt = ''
- if (!data.model_params_setting) data.model_params_setting = {}
- return data
- },
+ get: () => model.properties.node_data as TextToVideoNodeForm,
set: (value) => (model.properties.node_data = value),
})