From f4324e89d96fd2249f40a288b3db2a2bd52ad16f Mon Sep 17 00:00:00 2001 From: balibabu Date: Thu, 9 Oct 2025 19:03:29 +0800 Subject: [PATCH] Feat: Importing data flow files from the list page #9869 (#10446) ### What problem does this PR solve? Feat: Importing data flow files from the list page #9869 ### Type of change - [x] New Feature (non-breaking change which adds functionality) --- .../llm-setting-items/llm-form-field.tsx | 2 +- web/src/constants/agent.ts | 10 +++++ web/src/hooks/use-agent-request.ts | 3 +- web/src/pages/agents/use-import-json.ts | 33 +++++++++++++++-- web/src/pages/data-flow/constant.tsx | 16 +++----- .../form/parser-form/common-form-fields.tsx | 11 +++++- .../form/parser-form/video-form-fields.tsx | 13 ++++++- web/src/pages/data-flow/index.tsx | 6 +-- web/src/pages/data-flow/log-sheet/index.tsx | 37 ++++++++++--------- 9 files changed, 90 insertions(+), 41 deletions(-) diff --git a/web/src/components/llm-setting-items/llm-form-field.tsx b/web/src/components/llm-setting-items/llm-form-field.tsx index 52aceb4a3..79809f3e8 100644 --- a/web/src/components/llm-setting-items/llm-form-field.tsx +++ b/web/src/components/llm-setting-items/llm-form-field.tsx @@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next'; import { SelectWithSearch } from '../originui/select-with-search'; import { RAGFlowFormItem } from '../ragflow-form'; -type LLMFormFieldProps = { +export type LLMFormFieldProps = { options?: any[]; name?: string; }; diff --git a/web/src/constants/agent.ts b/web/src/constants/agent.ts index 7e9340885..6e388d7a0 100644 --- a/web/src/constants/agent.ts +++ b/web/src/constants/agent.ts @@ -52,3 +52,13 @@ export enum AgentCategory { AgentCanvas = 'agent_canvas', DataflowCanvas = 'dataflow_canvas', } + +export enum DataflowOperator { + Begin = 'File', + Note = 'Note', + Parser = 'Parser', + Tokenizer = 'Tokenizer', + Splitter = 'Splitter', + HierarchicalMerger = 'HierarchicalMerger', + Extractor = 'Extractor', +} diff --git a/web/src/hooks/use-agent-request.ts b/web/src/hooks/use-agent-request.ts index ba6ce5d95..6b9673b44 100644 --- a/web/src/hooks/use-agent-request.ts +++ b/web/src/hooks/use-agent-request.ts @@ -3,7 +3,6 @@ import { useHandleFilterSubmit } from '@/components/list-filter-bar/use-handle-f import message from '@/components/ui/message'; import { AgentGlobals } from '@/constants/agent'; import { - DSL, IAgentLogsRequest, IAgentLogsResponse, IFlow, @@ -295,7 +294,7 @@ export const useSetAgent = (showMessage: boolean = true) => { mutationFn: async (params: { id?: string; title?: string; - dsl?: DSL; + dsl?: Record; avatar?: string; canvas_category?: string; }) => { diff --git a/web/src/pages/agents/use-import-json.ts b/web/src/pages/agents/use-import-json.ts index 54c0f89a3..e40247595 100644 --- a/web/src/pages/agents/use-import-json.ts +++ b/web/src/pages/agents/use-import-json.ts @@ -1,13 +1,20 @@ import { useToast } from '@/components/hooks/use-toast'; +import message from '@/components/ui/message'; +import { AgentCategory, DataflowOperator } from '@/constants/agent'; import { FileMimeType } from '@/constants/common'; import { useSetModalState } from '@/hooks/common-hooks'; import { EmptyDsl, useSetAgent } from '@/hooks/use-agent-request'; -import { message } from 'antd'; +import { Node } from '@xyflow/react'; import isEmpty from 'lodash/isEmpty'; import { useCallback } from 'react'; import { useTranslation } from 'react-i18next'; +import { DataflowEmptyDsl } from './hooks/use-create-agent'; import { FormSchemaType } from './upload-agent-dialog/upload-agent-form'; +function hasNode(nodes: Node[], operator: DataflowOperator) { + return nodes.some((x) => x.data.label === operator); +} + export const useHandleImportJsonFile = () => { const { visible: fileUploadVisible, @@ -32,8 +39,28 @@ export const useHandleImportJsonFile = () => { try { const graph = JSON.parse(graphStr); if (graphStr && !isEmpty(graph) && Array.isArray(graph?.nodes)) { - const dsl = { ...EmptyDsl, graph }; - setAgent({ title: name, dsl }); + const nodes: Node[] = graph.nodes; + + let isAgent = true; + + if ( + hasNode(nodes, DataflowOperator.Begin) && + hasNode(nodes, DataflowOperator.Parser) + ) { + isAgent = false; + } + + const dsl = isAgent + ? { ...EmptyDsl, graph } + : { ...DataflowEmptyDsl, graph }; + + setAgent({ + title: name, + dsl, + canvas_category: isAgent + ? AgentCategory.AgentCanvas + : AgentCategory.DataflowCanvas, + }); hideFileUploadModal(); } else { message.error(errorMessage); diff --git a/web/src/pages/data-flow/constant.tsx b/web/src/pages/data-flow/constant.tsx index 950227e60..600febef9 100644 --- a/web/src/pages/data-flow/constant.tsx +++ b/web/src/pages/data-flow/constant.tsx @@ -1,10 +1,14 @@ import { ParseDocumentType } from '@/components/layout-recognize-form-field'; -import { initialLlmBaseValues } from '@/constants/agent'; +import { + initialLlmBaseValues, + DataflowOperator as Operator, +} from '@/constants/agent'; import { ChatVariableEnabledField, variableEnabledFieldMap, } from '@/constants/chat'; import { setInitialChatVariableEnabledFieldValue } from '@/utils/chat'; +export { DataflowOperator as Operator } from '@/constants/agent'; import { Circle, @@ -112,16 +116,6 @@ export enum AgentDialogueMode { export const BeginId = 'File'; -export enum Operator { - Begin = 'File', - Note = 'Note', - Parser = 'Parser', - Tokenizer = 'Tokenizer', - Splitter = 'Splitter', - HierarchicalMerger = 'HierarchicalMerger', - Extractor = 'Extractor', -} - export const SwitchLogicOperatorOptions = ['and', 'or']; export const CommonOperatorList = Object.values(Operator).filter( diff --git a/web/src/pages/data-flow/form/parser-form/common-form-fields.tsx b/web/src/pages/data-flow/form/parser-form/common-form-fields.tsx index dc7039781..cd3fe0497 100644 --- a/web/src/pages/data-flow/form/parser-form/common-form-fields.tsx +++ b/web/src/pages/data-flow/form/parser-form/common-form-fields.tsx @@ -1,6 +1,9 @@ import { crossLanguageOptions } from '@/components/cross-language-form-field'; import { LayoutRecognizeFormField } from '@/components/layout-recognize-form-field'; -import { LLMFormField } from '@/components/llm-setting-items/llm-form-field'; +import { + LLMFormField, + LLMFormFieldProps, +} from '@/components/llm-setting-items/llm-form-field'; import { SelectWithSearch, SelectWithSearchFlagOptionType, @@ -60,10 +63,14 @@ export function ParserMethodFormField({ ); } -export function LargeModelFormField({ prefix }: CommonProps) { +export function LargeModelFormField({ + prefix, + options, +}: CommonProps & Pick) { return ( ); } diff --git a/web/src/pages/data-flow/form/parser-form/video-form-fields.tsx b/web/src/pages/data-flow/form/parser-form/video-form-fields.tsx index 79f64d6fd..d1ca8c68d 100644 --- a/web/src/pages/data-flow/form/parser-form/video-form-fields.tsx +++ b/web/src/pages/data-flow/form/parser-form/video-form-fields.tsx @@ -1,13 +1,24 @@ +import { LlmModelType } from '@/constants/knowledge'; +import { useComposeLlmOptionsByModelTypes } from '@/hooks/llm-hooks'; import { LargeModelFormField, OutputFormatFormFieldProps, } from './common-form-fields'; export function VideoFormFields({ prefix }: OutputFormatFormFieldProps) { + const modelOptions = useComposeLlmOptionsByModelTypes([ + LlmModelType.Chat, + LlmModelType.Image2text, + LlmModelType.Speech2text, + ]); + return ( <> {/* Multimodal Model */} - + ); } diff --git a/web/src/pages/data-flow/index.tsx b/web/src/pages/data-flow/index.tsx index f536f8580..5291ab834 100644 --- a/web/src/pages/data-flow/index.tsx +++ b/web/src/pages/data-flow/index.tsx @@ -162,9 +162,9 @@ export default function DataFlow() { onClick={handleRunAgent} loading={running} > - {running || ( - - )} + {isParsing || running ? t('dataflow.running') : t('flow.run')} diff --git a/web/src/pages/data-flow/log-sheet/index.tsx b/web/src/pages/data-flow/log-sheet/index.tsx index f66bada1b..a5bcb2787 100644 --- a/web/src/pages/data-flow/log-sheet/index.tsx +++ b/web/src/pages/data-flow/log-sheet/index.tsx @@ -61,24 +61,25 @@ export function LogSheet({ {t('flow.log')} - + {isCompleted && ( + + )}