### What problem does this PR solve? Feat: Construct RetrievalForm with original fields #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)tags/v0.19.1
| FormLabel, | FormLabel, | ||||
| FormMessage, | FormMessage, | ||||
| } from './ui/form'; | } from './ui/form'; | ||||
| import { | |||||
| Select, | |||||
| SelectContent, | |||||
| SelectGroup, | |||||
| SelectItem, | |||||
| SelectLabel, | |||||
| SelectTrigger, | |||||
| SelectValue, | |||||
| } from './ui/select'; | |||||
| import { RAGFlowSelect } from './ui/select'; | |||||
| type FieldType = { | type FieldType = { | ||||
| rerank_id?: string; | rerank_id?: string; | ||||
| <FormItem> | <FormItem> | ||||
| <FormLabel tooltip={t('rerankTip')}>{t('rerankModel')}</FormLabel> | <FormLabel tooltip={t('rerankTip')}>{t('rerankModel')}</FormLabel> | ||||
| <FormControl> | <FormControl> | ||||
| <Select onValueChange={field.onChange} {...field}> | |||||
| <SelectTrigger | |||||
| value={field.value} | |||||
| onReset={() => { | |||||
| form.resetField(RerankId); | |||||
| }} | |||||
| > | |||||
| <SelectValue placeholder={t('rerankPlaceholder')} /> | |||||
| </SelectTrigger> | |||||
| <SelectContent> | |||||
| {options.map((x) => ( | |||||
| <SelectGroup key={x.label}> | |||||
| <SelectLabel>{x.label}</SelectLabel> | |||||
| {x.options.map((y) => ( | |||||
| <SelectItem | |||||
| value={y.value} | |||||
| key={y.value} | |||||
| disabled={y.disabled} | |||||
| > | |||||
| {y.label} | |||||
| </SelectItem> | |||||
| ))} | |||||
| </SelectGroup> | |||||
| ))} | |||||
| </SelectContent> | |||||
| </Select> | |||||
| <RAGFlowSelect | |||||
| allowClear | |||||
| {...field} | |||||
| options={options} | |||||
| ></RAGFlowSelect> | |||||
| </FormControl> | </FormControl> | ||||
| <FormMessage /> | <FormMessage /> | ||||
| </FormItem> | </FormItem> |
| modeTip: 'The mode defines how the workflow is initiated.', | modeTip: 'The mode defines how the workflow is initiated.', | ||||
| beginInputTip: | beginInputTip: | ||||
| 'By defining input parameters, this content can be accessed by other components in subsequent processes.', | 'By defining input parameters, this content can be accessed by other components in subsequent processes.', | ||||
| query: 'Query variables', | |||||
| }, | }, | ||||
| llmTools: { | llmTools: { | ||||
| bad_calculator: { | bad_calculator: { |
| openingSwitchTip: '您的用户将在开始时看到此欢迎消息。', | openingSwitchTip: '您的用户将在开始时看到此欢迎消息。', | ||||
| modeTip: '模式定义了工作流的启动方式。', | modeTip: '模式定义了工作流的启动方式。', | ||||
| beginInputTip: '通过定义输入参数,此内容可以被后续流程中的其他组件访问。', | beginInputTip: '通过定义输入参数,此内容可以被后续流程中的其他组件访问。', | ||||
| query: '查询变量', | |||||
| }, | }, | ||||
| footer: { | footer: { | ||||
| profile: 'All rights reserved @ React', | profile: 'All rights reserved @ React', |
| import { BlockButton, Button } from '@/components/ui/button'; | |||||
| import { Button } from '@/components/ui/button'; | |||||
| import { | import { | ||||
| FormControl, | FormControl, | ||||
| FormField, | FormField, | ||||
| )} | )} | ||||
| </div> | </div> | ||||
| ))} | ))} | ||||
| <BlockButton | |||||
| type="button" | |||||
| onClick={() => append({ value: '' })} // "" will cause the inability to add, refer to: https://github.com/orgs/react-hook-form/discussions/8485#discussioncomment-2961861 | |||||
| > | |||||
| {t('flow.addMessage')} | |||||
| </BlockButton> | |||||
| </div> | </div> | ||||
| <FormMessage /> | <FormMessage /> | ||||
| </FormItem> | </FormItem> |
| import { LargeModelFormField } from '@/components/large-model-form-field'; | import { LargeModelFormField } from '@/components/large-model-form-field'; | ||||
| import { LlmSettingSchema } from '@/components/llm-setting-items/next'; | import { LlmSettingSchema } from '@/components/llm-setting-items/next'; | ||||
| import { MessageHistoryWindowSizeFormField } from '@/components/message-history-window-size-item'; | import { MessageHistoryWindowSizeFormField } from '@/components/message-history-window-size-item'; | ||||
| import { SelectWithSearch } from '@/components/originui/select-with-search'; | |||||
| import { | |||||
| Form, | |||||
| FormControl, | |||||
| FormField, | |||||
| FormItem, | |||||
| FormLabel, | |||||
| FormMessage, | |||||
| } from '@/components/ui/form'; | |||||
| import { Form } from '@/components/ui/form'; | |||||
| import { zodResolver } from '@hookform/resolvers/zod'; | import { zodResolver } from '@hookform/resolvers/zod'; | ||||
| import { useForm } from 'react-hook-form'; | import { useForm } from 'react-hook-form'; | ||||
| import { useTranslation } from 'react-i18next'; | import { useTranslation } from 'react-i18next'; | ||||
| import { z } from 'zod'; | import { z } from 'zod'; | ||||
| import { INextOperatorForm } from '../../interface'; | import { INextOperatorForm } from '../../interface'; | ||||
| import { QueryVariable } from '../components/query-variable'; | |||||
| import DynamicCategorize from './dynamic-categorize'; | import DynamicCategorize from './dynamic-categorize'; | ||||
| import { useValues } from './use-values'; | import { useValues } from './use-values'; | ||||
| import { useWatchFormChange } from './use-watch-change'; | import { useWatchFormChange } from './use-watch-change'; | ||||
| const values = useValues(node); | const values = useValues(node); | ||||
| const FormSchema = z.object({ | const FormSchema = z.object({ | ||||
| input: z.string().optional(), | |||||
| query: z.string().optional(), | |||||
| parameter: z.string().optional(), | parameter: z.string().optional(), | ||||
| ...LlmSettingSchema, | ...LlmSettingSchema, | ||||
| message_history_window_size: z.coerce.number(), | message_history_window_size: z.coerce.number(), | ||||
| }} | }} | ||||
| > | > | ||||
| <FormContainer> | <FormContainer> | ||||
| <FormField | |||||
| control={form.control} | |||||
| name="input" | |||||
| render={({ field }) => ( | |||||
| <FormItem> | |||||
| <FormLabel tooltip={t('chat.modelTip')}> | |||||
| {t('chat.input')} | |||||
| </FormLabel> | |||||
| <FormControl> | |||||
| <SelectWithSearch {...field}></SelectWithSearch> | |||||
| </FormControl> | |||||
| <FormMessage /> | |||||
| </FormItem> | |||||
| )} | |||||
| /> | |||||
| <QueryVariable></QueryVariable> | |||||
| <LargeModelFormField></LargeModelFormField> | <LargeModelFormField></LargeModelFormField> | ||||
| </FormContainer> | </FormContainer> | ||||
| <MessageHistoryWindowSizeFormField | <MessageHistoryWindowSizeFormField |
| import { SelectWithSearch } from '@/components/originui/select-with-search'; | |||||
| import { | |||||
| FormControl, | |||||
| FormField, | |||||
| FormItem, | |||||
| FormLabel, | |||||
| FormMessage, | |||||
| } from '@/components/ui/form'; | |||||
| import { useFormContext } from 'react-hook-form'; | |||||
| import { useTranslation } from 'react-i18next'; | |||||
| export function QueryVariable() { | |||||
| const { t } = useTranslation(); | |||||
| const form = useFormContext(); | |||||
| return ( | |||||
| <FormField | |||||
| control={form.control} | |||||
| name="query" | |||||
| render={({ field }) => ( | |||||
| <FormItem> | |||||
| <FormLabel tooltip={t('chat.modelTip')}>{t('flow.query')}</FormLabel> | |||||
| <FormControl> | |||||
| <SelectWithSearch {...field}></SelectWithSearch> | |||||
| </FormControl> | |||||
| <FormMessage /> | |||||
| </FormItem> | |||||
| )} | |||||
| /> | |||||
| ); | |||||
| } |
| import { FormContainer } from '@/components/form-container'; | |||||
| import { KnowledgeBaseFormField } from '@/components/knowledge-base-item'; | import { KnowledgeBaseFormField } from '@/components/knowledge-base-item'; | ||||
| import { LargeModelFormField } from '@/components/large-model-form-field'; | |||||
| import { RerankFormFields } from '@/components/rerank'; | import { RerankFormFields } from '@/components/rerank'; | ||||
| import { SimilaritySliderFormField } from '@/components/similarity-slider'; | |||||
| import { | |||||
| initialKeywordsSimilarityWeightValue, | |||||
| initialSimilarityThresholdValue, | |||||
| SimilaritySliderFormField, | |||||
| } from '@/components/similarity-slider'; | |||||
| import { TopNFormField } from '@/components/top-n-item'; | import { TopNFormField } from '@/components/top-n-item'; | ||||
| import { | import { | ||||
| Form, | Form, | ||||
| FormMessage, | FormMessage, | ||||
| } from '@/components/ui/form'; | } from '@/components/ui/form'; | ||||
| import { Textarea } from '@/components/ui/textarea'; | import { Textarea } from '@/components/ui/textarea'; | ||||
| import { zodResolver } from '@hookform/resolvers/zod'; | |||||
| import { useForm } from 'react-hook-form'; | |||||
| import { useTranslation } from 'react-i18next'; | import { useTranslation } from 'react-i18next'; | ||||
| import { z } from 'zod'; | |||||
| import { INextOperatorForm } from '../../interface'; | import { INextOperatorForm } from '../../interface'; | ||||
| import { DynamicInputVariable } from '../components/next-dynamic-input-variable'; | |||||
| import { QueryVariable } from '../components/query-variable'; | |||||
| const FormSchema = z.object({ | |||||
| query: z.string().optional(), | |||||
| similarity_threshold: z.coerce.number(), | |||||
| keywords_similarity_weight: z.coerce.number(), | |||||
| top_n: z.coerce.number(), | |||||
| top_k: z.coerce.number(), | |||||
| kb_ids: z.array(z.string()), | |||||
| rerank_id: z.string(), | |||||
| empty_response: z.string(), | |||||
| }); | |||||
| const defaultValues = { | |||||
| query: '', | |||||
| top_n: 0.2, | |||||
| top_k: 1024, | |||||
| kb_ids: [], | |||||
| rerank_id: '', | |||||
| empty_response: '', | |||||
| ...initialSimilarityThresholdValue, | |||||
| ...initialKeywordsSimilarityWeightValue, | |||||
| }; | |||||
| const RetrievalForm = ({ form, node }: INextOperatorForm) => { | |||||
| const RetrievalForm = ({ node }: INextOperatorForm) => { | |||||
| const { t } = useTranslation(); | const { t } = useTranslation(); | ||||
| const form = useForm({ | |||||
| defaultValues: defaultValues, | |||||
| resolver: zodResolver(FormSchema), | |||||
| }); | |||||
| return ( | return ( | ||||
| <Form {...form}> | <Form {...form}> | ||||
| <form | <form | ||||
| className="space-y-6" | |||||
| className="space-y-6 p-4" | |||||
| onSubmit={(e) => { | onSubmit={(e) => { | ||||
| e.preventDefault(); | e.preventDefault(); | ||||
| }} | }} | ||||
| > | > | ||||
| <DynamicInputVariable node={node}></DynamicInputVariable> | |||||
| <SimilaritySliderFormField | |||||
| vectorSimilarityWeightName="keywords_similarity_weight" | |||||
| isTooltipShown | |||||
| ></SimilaritySliderFormField> | |||||
| <TopNFormField></TopNFormField> | |||||
| <RerankFormFields></RerankFormFields> | |||||
| <KnowledgeBaseFormField></KnowledgeBaseFormField> | |||||
| <FormField | |||||
| control={form.control} | |||||
| name="empty_response" | |||||
| render={({ field }) => ( | |||||
| <FormItem> | |||||
| <FormLabel>{t('chat.emptyResponse')}</FormLabel> | |||||
| <FormControl> | |||||
| <Textarea | |||||
| placeholder={t('common.namePlaceholder')} | |||||
| {...field} | |||||
| autoComplete="off" | |||||
| rows={4} | |||||
| /> | |||||
| </FormControl> | |||||
| <FormMessage /> | |||||
| </FormItem> | |||||
| )} | |||||
| /> | |||||
| <FormContainer> | |||||
| <QueryVariable></QueryVariable> | |||||
| <LargeModelFormField></LargeModelFormField> | |||||
| </FormContainer> | |||||
| <FormContainer> | |||||
| <SimilaritySliderFormField | |||||
| vectorSimilarityWeightName="keywords_similarity_weight" | |||||
| isTooltipShown | |||||
| ></SimilaritySliderFormField> | |||||
| <TopNFormField></TopNFormField> | |||||
| <RerankFormFields></RerankFormFields> | |||||
| <KnowledgeBaseFormField></KnowledgeBaseFormField> | |||||
| <FormField | |||||
| control={form.control} | |||||
| name="empty_response" | |||||
| render={({ field }) => ( | |||||
| <FormItem> | |||||
| <FormLabel>{t('chat.emptyResponse')}</FormLabel> | |||||
| <FormControl> | |||||
| <Textarea | |||||
| placeholder={t('common.namePlaceholder')} | |||||
| {...field} | |||||
| autoComplete="off" | |||||
| rows={4} | |||||
| /> | |||||
| </FormControl> | |||||
| <FormMessage /> | |||||
| </FormItem> | |||||
| )} | |||||
| /> | |||||
| </FormContainer> | |||||
| </form> | </form> | ||||
| </Form> | </Form> | ||||
| ); | ); |