From 3404469e2a74c21360b04574013b20ae4a5d1c58 Mon Sep 17 00:00:00 2001 From: balibabu Date: Fri, 12 Sep 2025 10:14:26 +0800 Subject: [PATCH] Feat: Dynamically increase the configuration of the parser operator #9869 (#10060) ### What problem does this PR solve? Feat: Dynamically increase the configuration of the parser operator #9869 ### Type of change - [x] New Feature (non-breaking change which adds functionality) --- .../llm-setting-items/llm-form-field.tsx | 25 +++ web/src/components/llm-setting-items/next.tsx | 27 +-- web/src/pages/data-flow/constant.tsx | 12 ++ .../form/parser-form/common-form-fields.tsx | 46 +++++ .../form/parser-form/email-form-fields.tsx | 31 ++++ .../form/parser-form/image-form-fields.tsx | 17 ++ .../data-flow/form/parser-form/index.tsx | 172 +++++++----------- .../data-flow/form/parser-form/interface.ts | 3 + .../form/parser-form/pdf-form-fields.tsx | 19 ++ .../pages/data-flow/form/parser-form/utils.ts | 3 + .../form/parser-form/video-form-fields.tsx | 15 ++ 11 files changed, 243 insertions(+), 127 deletions(-) create mode 100644 web/src/components/llm-setting-items/llm-form-field.tsx create mode 100644 web/src/pages/data-flow/form/parser-form/common-form-fields.tsx create mode 100644 web/src/pages/data-flow/form/parser-form/email-form-fields.tsx create mode 100644 web/src/pages/data-flow/form/parser-form/image-form-fields.tsx create mode 100644 web/src/pages/data-flow/form/parser-form/interface.ts create mode 100644 web/src/pages/data-flow/form/parser-form/pdf-form-fields.tsx create mode 100644 web/src/pages/data-flow/form/parser-form/utils.ts create mode 100644 web/src/pages/data-flow/form/parser-form/video-form-fields.tsx diff --git a/web/src/components/llm-setting-items/llm-form-field.tsx b/web/src/components/llm-setting-items/llm-form-field.tsx new file mode 100644 index 000000000..f91119996 --- /dev/null +++ b/web/src/components/llm-setting-items/llm-form-field.tsx @@ -0,0 +1,25 @@ +import { LlmModelType } from '@/constants/knowledge'; +import { useComposeLlmOptionsByModelTypes } from '@/hooks/llm-hooks'; +import { useTranslation } from 'react-i18next'; +import { SelectWithSearch } from '../originui/select-with-search'; +import { RAGFlowFormItem } from '../ragflow-form'; + +type LLMFormFieldProps = { + options?: any[]; + name?: string; +}; + +export function LLMFormField({ options, name }: LLMFormFieldProps) { + const { t } = useTranslation(); + + const modelOptions = useComposeLlmOptionsByModelTypes([ + LlmModelType.Chat, + LlmModelType.Image2text, + ]); + + return ( + + + + ); +} diff --git a/web/src/components/llm-setting-items/next.tsx b/web/src/components/llm-setting-items/next.tsx index 14e6e532c..8d21bf9a8 100644 --- a/web/src/components/llm-setting-items/next.tsx +++ b/web/src/components/llm-setting-items/next.tsx @@ -1,11 +1,9 @@ -import { LlmModelType, ModelVariableType } from '@/constants/knowledge'; +import { ModelVariableType } from '@/constants/knowledge'; import { useTranslate } from '@/hooks/common-hooks'; -import { useComposeLlmOptionsByModelTypes } from '@/hooks/llm-hooks'; import { camelCase } from 'lodash'; import { useCallback } from 'react'; import { useFormContext } from 'react-hook-form'; import { z } from 'zod'; -import { SelectWithSearch } from '../originui/select-with-search'; import { FormControl, FormField, @@ -20,6 +18,7 @@ import { SelectTrigger, SelectValue, } from '../ui/select'; +import { LLMFormField } from './llm-form-field'; import { SliderInputSwitchFormField } from './slider'; import { useHandleFreedomChange } from './use-watch-change'; @@ -61,11 +60,6 @@ export function LlmSettingFieldItems({ const form = useFormContext(); const { t } = useTranslate('chat'); - const modelOptions = useComposeLlmOptionsByModelTypes([ - LlmModelType.Chat, - LlmModelType.Image2text, - ]); - const getFieldWithPrefix = useCallback( (name: string) => { return prefix ? `${prefix}.${name}` : name; @@ -82,22 +76,7 @@ export function LlmSettingFieldItems({ return (
- ( - - {t('model')} - - - - - - )} - /> + + + + ); +} + +export function OutputFormatFormField({ prefix }: CommonProps) { + return ( + + + + ); +} + +export function ParserMethodFormField({ prefix }: CommonProps) { + return ( + + + + ); +} + +export function LargeModelFormField({ prefix }: CommonProps) { + return ( + + ); +} diff --git a/web/src/pages/data-flow/form/parser-form/email-form-fields.tsx b/web/src/pages/data-flow/form/parser-form/email-form-fields.tsx new file mode 100644 index 000000000..1fbd82c54 --- /dev/null +++ b/web/src/pages/data-flow/form/parser-form/email-form-fields.tsx @@ -0,0 +1,31 @@ +import { SelectWithSearch } from '@/components/originui/select-with-search'; +import { RAGFlowFormItem } from '@/components/ragflow-form'; +import { buildOptions } from '@/utils/form'; +import { OutputFormatFormField } from './common-form-fields'; +import { CommonProps } from './interface'; +import { buildFieldNameWithPrefix } from './utils'; + +const options = buildOptions([ + 'from', + 'to', + 'cc', + 'bcc', + 'date', + 'subject', + 'body', + 'attachments', +]); + +export function EmailFormFields({ prefix }: CommonProps) { + return ( + <> + + + + + + ); +} diff --git a/web/src/pages/data-flow/form/parser-form/image-form-fields.tsx b/web/src/pages/data-flow/form/parser-form/image-form-fields.tsx new file mode 100644 index 000000000..6c8479269 --- /dev/null +++ b/web/src/pages/data-flow/form/parser-form/image-form-fields.tsx @@ -0,0 +1,17 @@ +import { + LargeModelFormField, + OutputFormatFormField, + ParserMethodFormField, +} from './common-form-fields'; +import { CommonProps } from './interface'; + +export function ImageFormFields({ prefix }: CommonProps) { + return ( + <> + + {/* Multimodal Model */} + + + + ); +} diff --git a/web/src/pages/data-flow/form/parser-form/index.tsx b/web/src/pages/data-flow/form/parser-form/index.tsx index 1a84c304a..732564936 100644 --- a/web/src/pages/data-flow/form/parser-form/index.tsx +++ b/web/src/pages/data-flow/form/parser-form/index.tsx @@ -1,135 +1,101 @@ import { FormContainer } from '@/components/form-container'; -import NumberInput from '@/components/originui/number-input'; import { SelectWithSearch } from '@/components/originui/select-with-search'; -import { - Form, - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, -} from '@/components/ui/form'; -import { useTranslate } from '@/hooks/common-hooks'; +import { RAGFlowFormItem } from '@/components/ragflow-form'; +import { BlockButton, Button } from '@/components/ui/button'; +import { Form } from '@/components/ui/form'; +import { buildOptions } from '@/utils/form'; import { zodResolver } from '@hookform/resolvers/zod'; -import { memo } from 'react'; -import { useForm, useFormContext } from 'react-hook-form'; +import { Trash2 } from 'lucide-react'; +import { memo, useCallback } from 'react'; +import { useFieldArray, useForm } from 'react-hook-form'; import { z } from 'zod'; -import { initialParserValues } from '../../constant'; +import { FileType, initialParserValues } from '../../constant'; import { useFormValues } from '../../hooks/use-form-values'; import { useWatchFormChange } from '../../hooks/use-watch-form-change'; import { INextOperatorForm } from '../../interface'; -import { GoogleCountryOptions, GoogleLanguageOptions } from '../../options'; import { buildOutputList } from '../../utils/build-output-list'; -import { ApiKeyField } from '../components/api-key-field'; -import { FormWrapper } from '../components/form-wrapper'; import { Output } from '../components/output'; -import { QueryVariable } from '../components/query-variable'; +import { OutputFormatFormField } from './common-form-fields'; +import { EmailFormFields } from './email-form-fields'; +import { ImageFormFields } from './image-form-fields'; +import { PdfFormFields } from './pdf-form-fields'; +import { buildFieldNameWithPrefix } from './utils'; +import { VideoFormFields } from './video-form-fields'; const outputList = buildOutputList(initialParserValues.outputs); -export const GoogleFormPartialSchema = { - api_key: z.string(), - country: z.string(), - language: z.string(), +const FileFormatOptions = buildOptions(FileType); + +const FileFormatWidgetMap = { + [FileType.PDF]: PdfFormFields, + [FileType.Video]: VideoFormFields, + [FileType.Audio]: VideoFormFields, + [FileType.Email]: EmailFormFields, + [FileType.Image]: ImageFormFields, }; export const FormSchema = z.object({ - ...GoogleFormPartialSchema, - q: z.string(), - start: z.number(), - num: z.number(), + parser: z.array( + z.object({ + fileFormat: z.string().optional(), + }), + ), }); -export function GoogleFormWidgets() { - const form = useFormContext(); - const { t } = useTranslate('flow'); - - return ( - <> - ( - - {t('country')} - - - - - - )} - /> - ( - - {t('language')} - - - - - - )} - /> - - ); -} - const ParserForm = ({ node }: INextOperatorForm) => { - const { t } = useTranslate('flow'); const defaultValues = useFormValues(initialParserValues, node); const form = useForm>({ defaultValues, resolver: zodResolver(FormSchema), + shouldUnregister: true, }); + const name = 'parser'; + const { fields, remove, append } = useFieldArray({ + name, + control: form.control, + }); + + const add = useCallback(() => { + append({ + fileFormat: undefined, + }); + }, [append]); + useWatchFormChange(node?.id, form); return (
- - - - - - - ( - - {t('flowStart')} - - - - - - )} - /> - ( - - {t('flowNum')} - - - - - - )} - /> - - - + {fields.map((field, index) => { + const prefix = `${name}.${index}`; + const fileFormat = form.getValues(`${name}.${index}.fileFormat`); + + const Widget = + fileFormat && fileFormat in FileFormatWidgetMap + ? FileFormatWidgetMap[ + fileFormat as keyof typeof FileFormatWidgetMap + ] + : OutputFormatFormField; + return ( + +
+ Parser {index} + +
+ + + + +
+ ); + })} + Add Parser
diff --git a/web/src/pages/data-flow/form/parser-form/interface.ts b/web/src/pages/data-flow/form/parser-form/interface.ts new file mode 100644 index 000000000..698ba8e64 --- /dev/null +++ b/web/src/pages/data-flow/form/parser-form/interface.ts @@ -0,0 +1,3 @@ +export type CommonProps = { + prefix: string; +}; diff --git a/web/src/pages/data-flow/form/parser-form/pdf-form-fields.tsx b/web/src/pages/data-flow/form/parser-form/pdf-form-fields.tsx new file mode 100644 index 000000000..0b67ed7a7 --- /dev/null +++ b/web/src/pages/data-flow/form/parser-form/pdf-form-fields.tsx @@ -0,0 +1,19 @@ +import { + LanguageFormField, + LargeModelFormField, + OutputFormatFormField, + ParserMethodFormField, +} from './common-form-fields'; +import { CommonProps } from './interface'; + +export function PdfFormFields({ prefix }: CommonProps) { + return ( + <> + + {/* Multimodal Model */} + + + + + ); +} diff --git a/web/src/pages/data-flow/form/parser-form/utils.ts b/web/src/pages/data-flow/form/parser-form/utils.ts new file mode 100644 index 000000000..851429f77 --- /dev/null +++ b/web/src/pages/data-flow/form/parser-form/utils.ts @@ -0,0 +1,3 @@ +export function buildFieldNameWithPrefix(name: string, prefix: string) { + return `${prefix}.${name}`; +} 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 new file mode 100644 index 000000000..619336143 --- /dev/null +++ b/web/src/pages/data-flow/form/parser-form/video-form-fields.tsx @@ -0,0 +1,15 @@ +import { + LargeModelFormField, + OutputFormatFormField, +} from './common-form-fields'; +import { CommonProps } from './interface'; + +export function VideoFormFields({ prefix }: CommonProps) { + return ( + <> + {/* Multimodal Model */} + + + + ); +}