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)
This commit is contained in:
balibabu
2025-10-09 19:03:29 +08:00
committed by GitHub
parent f04c9e2937
commit f4324e89d9
9 changed files with 90 additions and 41 deletions

View File

@ -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;
};

View File

@ -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',
}

View File

@ -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<string, any>;
avatar?: string;
canvas_category?: string;
}) => {

View File

@ -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);

View File

@ -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(

View File

@ -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<LLMFormFieldProps, 'options'>) {
return (
<LLMFormField
name={buildFieldNameWithPrefix('llm_id', prefix)}
options={options}
></LLMFormField>
);
}

View File

@ -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 */}
<LargeModelFormField prefix={prefix}></LargeModelFormField>
<LargeModelFormField
prefix={prefix}
options={modelOptions}
></LargeModelFormField>
</>
);
}

View File

@ -162,9 +162,9 @@ export default function DataFlow() {
onClick={handleRunAgent}
loading={running}
>
{running || (
<CirclePlay className={isParsing ? 'animate-spin' : ''} />
)}
<CirclePlay
className={isParsing || isLogEmpty ? 'animate-spin' : ''}
/>
{isParsing || running ? t('dataflow.running') : t('flow.run')}
</ButtonLoading>

View File

@ -61,24 +61,25 @@ export function LogSheet({
<SheetHeader>
<SheetTitle className="flex items-center gap-2.5">
<Logs className="size-4" /> {t('flow.log')}
<Button
variant={'ghost'}
disabled={!isCompleted}
onClick={navigateToDataflowResult({
id: messageId, // 'log_id',
[PipelineResultSearchParams.AgentId]: id, // 'agent_id',
[PipelineResultSearchParams.DocumentId]: uploadedFileData?.id, //'doc_id',
[PipelineResultSearchParams.AgentTitle]: agent.title, //'title',
[PipelineResultSearchParams.IsReadOnly]: 'true',
[PipelineResultSearchParams.Type]: 'dataflow',
[PipelineResultSearchParams.CreatedBy]:
uploadedFileData?.created_by,
[PipelineResultSearchParams.DocumentExtension]:
uploadedFileData?.extension,
})}
>
{t('dataflow.viewResult')} <ArrowUpRight />
</Button>
{isCompleted && (
<Button
variant={'ghost'}
onClick={navigateToDataflowResult({
id: messageId, // 'log_id',
[PipelineResultSearchParams.AgentId]: id, // 'agent_id',
[PipelineResultSearchParams.DocumentId]: uploadedFileData?.id, //'doc_id',
[PipelineResultSearchParams.AgentTitle]: agent.title, //'title',
[PipelineResultSearchParams.IsReadOnly]: 'true',
[PipelineResultSearchParams.Type]: 'dataflow',
[PipelineResultSearchParams.CreatedBy]:
uploadedFileData?.created_by,
[PipelineResultSearchParams.DocumentExtension]:
uploadedFileData?.extension,
})}
>
{t('dataflow.viewResult')} <ArrowUpRight />
</Button>
)}
</SheetTitle>
</SheetHeader>
<section className="max-h-[82vh] overflow-auto mt-6">