mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-08 20:42:30 +08:00
### What problem does this PR solve? Feat: Add HierarchicalMergerForm #9869 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
@ -380,7 +380,7 @@ export const initialParserValues = { outputs: {}, parser: [] };
|
|||||||
|
|
||||||
export const initialSplitterValues = { outputs: {}, chunk_token_size: 512 };
|
export const initialSplitterValues = { outputs: {}, chunk_token_size: 512 };
|
||||||
|
|
||||||
export const initialHierarchicalMergerValues = {};
|
export const initialHierarchicalMergerValues = { outputs: {} };
|
||||||
|
|
||||||
export const CategorizeAnchorPointPositions = [
|
export const CategorizeAnchorPointPositions = [
|
||||||
{ top: 1, right: 34 },
|
{ top: 1, right: 34 },
|
||||||
|
|||||||
@ -1,134 +1,152 @@
|
|||||||
import { FormContainer } from '@/components/form-container';
|
|
||||||
import NumberInput from '@/components/originui/number-input';
|
|
||||||
import { SelectWithSearch } from '@/components/originui/select-with-search';
|
import { SelectWithSearch } from '@/components/originui/select-with-search';
|
||||||
import {
|
import { RAGFlowFormItem } from '@/components/ragflow-form';
|
||||||
Form,
|
import { BlockButton, Button } from '@/components/ui/button';
|
||||||
FormControl,
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||||
FormField,
|
import { Form } from '@/components/ui/form';
|
||||||
FormItem,
|
import { Input } from '@/components/ui/input';
|
||||||
FormLabel,
|
|
||||||
FormMessage,
|
|
||||||
} from '@/components/ui/form';
|
|
||||||
import { useTranslate } from '@/hooks/common-hooks';
|
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
|
import { X } from 'lucide-react';
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import { useForm, useFormContext } from 'react-hook-form';
|
import { useFieldArray, useForm, useFormContext } from 'react-hook-form';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { initialChunkerValues } from '../../constant';
|
import { initialHierarchicalMergerValues } from '../../constant';
|
||||||
import { useFormValues } from '../../hooks/use-form-values';
|
import { useFormValues } from '../../hooks/use-form-values';
|
||||||
import { useWatchFormChange } from '../../hooks/use-watch-form-change';
|
import { useWatchFormChange } from '../../hooks/use-watch-form-change';
|
||||||
import { INextOperatorForm } from '../../interface';
|
import { INextOperatorForm } from '../../interface';
|
||||||
import { GoogleCountryOptions, GoogleLanguageOptions } from '../../options';
|
|
||||||
import { buildOutputList } from '../../utils/build-output-list';
|
import { buildOutputList } from '../../utils/build-output-list';
|
||||||
import { ApiKeyField } from '../components/api-key-field';
|
|
||||||
import { FormWrapper } from '../components/form-wrapper';
|
import { FormWrapper } from '../components/form-wrapper';
|
||||||
import { Output } from '../components/output';
|
import { Output } from '../components/output';
|
||||||
import { QueryVariable } from '../components/query-variable';
|
|
||||||
|
|
||||||
const outputList = buildOutputList(initialChunkerValues.outputs);
|
const outputList = buildOutputList(initialHierarchicalMergerValues.outputs);
|
||||||
|
|
||||||
export const GoogleFormPartialSchema = {
|
enum Hierarchy {
|
||||||
api_key: z.string(),
|
H1 = '1',
|
||||||
country: z.string(),
|
H2 = '2',
|
||||||
language: z.string(),
|
H3 = '3',
|
||||||
};
|
H4 = '4',
|
||||||
|
H5 = '5',
|
||||||
|
}
|
||||||
|
|
||||||
|
const HierarchyOptions = [
|
||||||
|
{ label: 'H1', value: Hierarchy.H1 },
|
||||||
|
{ label: 'H2', value: Hierarchy.H2 },
|
||||||
|
{ label: 'H3', value: Hierarchy.H3 },
|
||||||
|
{ label: 'H4', value: Hierarchy.H4 },
|
||||||
|
{ label: 'H5', value: Hierarchy.H5 },
|
||||||
|
];
|
||||||
|
|
||||||
export const FormSchema = z.object({
|
export const FormSchema = z.object({
|
||||||
...GoogleFormPartialSchema,
|
hierarchy: z.number(),
|
||||||
q: z.string(),
|
levels: z.array(
|
||||||
start: z.number(),
|
z.object({
|
||||||
num: z.number(),
|
expressions: z.array(z.object({ expression: z.string() })),
|
||||||
|
}),
|
||||||
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
export function GoogleFormWidgets() {
|
type RegularExpressionsProps = {
|
||||||
|
index: number;
|
||||||
|
parentName: string;
|
||||||
|
removeParent: (index: number) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function RegularExpressions({
|
||||||
|
index,
|
||||||
|
parentName,
|
||||||
|
removeParent,
|
||||||
|
}: RegularExpressionsProps) {
|
||||||
const form = useFormContext();
|
const form = useFormContext();
|
||||||
const { t } = useTranslate('flow');
|
|
||||||
|
const name = `${parentName}.${index}.expressions`;
|
||||||
|
|
||||||
|
const { fields, append, remove } = useFieldArray({
|
||||||
|
name: name,
|
||||||
|
control: form.control,
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Card>
|
||||||
<FormField
|
<CardHeader className="flex-row justify-between items-center">
|
||||||
control={form.control}
|
<CardTitle>H{index}</CardTitle>
|
||||||
name={`country`}
|
<Button
|
||||||
render={({ field }) => (
|
type="button"
|
||||||
<FormItem className="flex-1">
|
variant={'ghost'}
|
||||||
<FormLabel>{t('country')}</FormLabel>
|
onClick={() => removeParent(index)}
|
||||||
<FormControl>
|
>
|
||||||
<SelectWithSearch
|
<X />
|
||||||
{...field}
|
</Button>
|
||||||
options={GoogleCountryOptions}
|
</CardHeader>
|
||||||
></SelectWithSearch>
|
<CardContent>
|
||||||
</FormControl>
|
<section className="space-y-4">
|
||||||
<FormMessage />
|
{fields.map((field, index) => (
|
||||||
</FormItem>
|
<div key={field.id} className="flex items-center gap-2">
|
||||||
)}
|
<div className="space-y-2 flex-1">
|
||||||
/>
|
<RAGFlowFormItem
|
||||||
<FormField
|
name={`${name}.${index}.expression`}
|
||||||
control={form.control}
|
label={'expression'}
|
||||||
name={`language`}
|
labelClassName="!hidden"
|
||||||
render={({ field }) => (
|
>
|
||||||
<FormItem className="flex-1">
|
<Input className="!m-0"></Input>
|
||||||
<FormLabel>{t('language')}</FormLabel>
|
</RAGFlowFormItem>
|
||||||
<FormControl>
|
</div>
|
||||||
<SelectWithSearch
|
<Button
|
||||||
{...field}
|
type="button"
|
||||||
options={GoogleLanguageOptions}
|
variant={'ghost'}
|
||||||
></SelectWithSearch>
|
onClick={() => remove(index)}
|
||||||
</FormControl>
|
>
|
||||||
<FormMessage />
|
<X />
|
||||||
</FormItem>
|
</Button>
|
||||||
)}
|
</div>
|
||||||
/>
|
))}
|
||||||
</>
|
</section>
|
||||||
|
<BlockButton
|
||||||
|
onClick={() => append({ expression: '' })}
|
||||||
|
className="mt-6"
|
||||||
|
>
|
||||||
|
Add
|
||||||
|
</BlockButton>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const HierarchicalMergerForm = ({ node }: INextOperatorForm) => {
|
const HierarchicalMergerForm = ({ node }: INextOperatorForm) => {
|
||||||
const { t } = useTranslate('flow');
|
const defaultValues = useFormValues(initialHierarchicalMergerValues, node);
|
||||||
const defaultValues = useFormValues(initialChunkerValues, node);
|
|
||||||
|
|
||||||
const form = useForm<z.infer<typeof FormSchema>>({
|
const form = useForm<z.infer<typeof FormSchema>>({
|
||||||
defaultValues,
|
defaultValues,
|
||||||
resolver: zodResolver(FormSchema),
|
resolver: zodResolver(FormSchema),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const name = 'levels';
|
||||||
|
|
||||||
|
const { fields, append, remove } = useFieldArray({
|
||||||
|
name: name,
|
||||||
|
control: form.control,
|
||||||
|
});
|
||||||
|
|
||||||
useWatchFormChange(node?.id, form);
|
useWatchFormChange(node?.id, form);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form {...form}>
|
<Form {...form}>
|
||||||
<FormWrapper>
|
<FormWrapper>
|
||||||
<FormContainer>
|
<RAGFlowFormItem name={'hierarchy'} label={'hierarchy'}>
|
||||||
<QueryVariable name="q"></QueryVariable>
|
<SelectWithSearch options={HierarchyOptions}></SelectWithSearch>
|
||||||
</FormContainer>
|
</RAGFlowFormItem>
|
||||||
<FormContainer>
|
{fields.map((field, index) => (
|
||||||
<ApiKeyField placeholder={t('apiKeyPlaceholder')}></ApiKeyField>
|
<div key={field.id} className="flex items-center gap-2">
|
||||||
<FormField
|
<div className="space-y-2 flex-1">
|
||||||
control={form.control}
|
<RegularExpressions
|
||||||
name={`start`}
|
parentName={name}
|
||||||
render={({ field }) => (
|
index={index}
|
||||||
<FormItem>
|
removeParent={remove}
|
||||||
<FormLabel>{t('flowStart')}</FormLabel>
|
></RegularExpressions>
|
||||||
<FormControl>
|
</div>
|
||||||
<NumberInput {...field} className="w-full"></NumberInput>
|
</div>
|
||||||
</FormControl>
|
))}
|
||||||
<FormMessage />
|
<BlockButton onClick={() => append({ expressions: [] })}>
|
||||||
</FormItem>
|
Add
|
||||||
)}
|
</BlockButton>
|
||||||
/>
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name={`num`}
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>{t('flowNum')}</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<NumberInput {...field} className="w-full"></NumberInput>
|
|
||||||
</FormControl>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<GoogleFormWidgets></GoogleFormWidgets>
|
|
||||||
</FormContainer>
|
|
||||||
</FormWrapper>
|
</FormWrapper>
|
||||||
<div className="p-5">
|
<div className="p-5">
|
||||||
<Output list={outputList}></Output>
|
<Output list={outputList}></Output>
|
||||||
|
|||||||
@ -35,7 +35,9 @@ export function buildOptions(
|
|||||||
) {
|
) {
|
||||||
if (t) {
|
if (t) {
|
||||||
return Object.values(data).map((val) => ({
|
return Object.values(data).map((val) => ({
|
||||||
label: t(`${prefix ? prefix + '.' : ''}${val.toLowerCase()}`),
|
label: t(
|
||||||
|
`${prefix ? prefix + '.' : ''}${typeof val === 'string' ? val.toLowerCase() : val}`,
|
||||||
|
),
|
||||||
value: val,
|
value: val,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user