mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-06-26 22:19:57 +00:00
### What problem does this PR solve? Feat: Improve the tavily form #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
parent
936a91c5fe
commit
8695d60055
@ -1,4 +1,4 @@
|
||||
type OutputType = {
|
||||
export type OutputType = {
|
||||
title: string;
|
||||
type: string;
|
||||
};
|
||||
|
57
web/src/pages/agent/form/tavily-form/dynamic-domain.tsx
Normal file
57
web/src/pages/agent/form/tavily-form/dynamic-domain.tsx
Normal file
@ -0,0 +1,57 @@
|
||||
import { BlockButton, Button } from '@/components/ui/button';
|
||||
import {
|
||||
FormControl,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from '@/components/ui/form';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { X } from 'lucide-react';
|
||||
import { ReactNode } from 'react';
|
||||
import { useFieldArray, useFormContext } from 'react-hook-form';
|
||||
|
||||
type DynamicDomainProps = { name: string; label: ReactNode };
|
||||
|
||||
export const DynamicDomain = ({ name, label }: DynamicDomainProps) => {
|
||||
const form = useFormContext();
|
||||
|
||||
const { fields, append, remove } = useFieldArray({
|
||||
name: name,
|
||||
control: form.control,
|
||||
});
|
||||
|
||||
return (
|
||||
<FormItem>
|
||||
<FormLabel>{label}</FormLabel>
|
||||
<div className="space-y-4">
|
||||
{fields.map((field, index) => (
|
||||
<div key={field.id} className="flex">
|
||||
<div className="space-y-2 flex-1">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name={`${name}.${index}.value`}
|
||||
render={({ field }) => (
|
||||
<FormItem className="flex-1">
|
||||
<FormControl>
|
||||
<Input {...field}></Input>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<Button
|
||||
type="button"
|
||||
variant={'ghost'}
|
||||
onClick={() => remove(index)}
|
||||
>
|
||||
<X />
|
||||
</Button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<FormMessage />
|
||||
<BlockButton onClick={() => append({ value: '' })}>Add</BlockButton>
|
||||
</FormItem>
|
||||
);
|
||||
};
|
@ -9,18 +9,23 @@ import {
|
||||
} from '@/components/ui/form';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { RAGFlowSelect } from '@/components/ui/select';
|
||||
import { Switch } from '@/components/ui/switch';
|
||||
import { buildOptions } from '@/utils/form';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { useMemo } from 'react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { z } from 'zod';
|
||||
import { Output, OutputType } from '../components/output';
|
||||
import { QueryVariable } from '../components/query-variable';
|
||||
import { SearchDepth, Topic, useValues } from './use-values';
|
||||
import { DynamicDomain } from './dynamic-domain';
|
||||
import { SearchDepth, Topic, defaultValues, useValues } from './use-values';
|
||||
import { useWatchFormChange } from './use-watch-change';
|
||||
|
||||
const TavilyForm = () => {
|
||||
const values = useValues();
|
||||
|
||||
const FormSchema = z.object({
|
||||
api_key: z.string(),
|
||||
query: z.string(),
|
||||
search_depth: z.enum([SearchDepth.Advanced, SearchDepth.Basic]),
|
||||
topic: z.enum([Topic.News, Topic.General]),
|
||||
@ -30,15 +35,25 @@ const TavilyForm = () => {
|
||||
include_raw_content: z.boolean(),
|
||||
include_images: z.boolean(),
|
||||
include_image_descriptions: z.boolean(),
|
||||
include_domains: z.array(z.string()),
|
||||
exclude_domains: z.array(z.string()),
|
||||
include_domains: z.array(z.object({ value: z.any() })), // TODO: z.string should be used, but an error will be reported
|
||||
exclude_domains: z.array(z.object({ value: z.any() })),
|
||||
});
|
||||
|
||||
const form = useForm({
|
||||
const form = useForm<z.infer<typeof FormSchema>>({
|
||||
defaultValues: values,
|
||||
resolver: zodResolver(FormSchema),
|
||||
});
|
||||
|
||||
const outputList = useMemo(() => {
|
||||
return Object.entries(defaultValues.outputs).reduce<OutputType[]>(
|
||||
(pre, [key, val]) => {
|
||||
pre.push({ title: key, type: val.type });
|
||||
return pre;
|
||||
},
|
||||
[],
|
||||
);
|
||||
}, []);
|
||||
|
||||
useWatchFormChange(form);
|
||||
|
||||
return (
|
||||
@ -50,9 +65,23 @@ const TavilyForm = () => {
|
||||
e.preventDefault();
|
||||
}}
|
||||
>
|
||||
<FormContainer>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="api_key"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Api Key</FormLabel>
|
||||
<FormControl>
|
||||
<Input type="password" {...field}></Input>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</FormContainer>
|
||||
<FormContainer>
|
||||
<QueryVariable></QueryVariable>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="search_depth"
|
||||
@ -100,8 +129,96 @@ const TavilyForm = () => {
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="days"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Days</FormLabel>
|
||||
<FormControl>
|
||||
<Input type={'number'} {...field}></Input>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="include_answer"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Include Answer</FormLabel>
|
||||
<FormControl>
|
||||
<Switch
|
||||
checked={field.value}
|
||||
onCheckedChange={field.onChange}
|
||||
></Switch>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="include_raw_content"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Include Raw Content</FormLabel>
|
||||
<FormControl>
|
||||
<Switch
|
||||
checked={field.value}
|
||||
onCheckedChange={field.onChange}
|
||||
></Switch>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="include_images"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Include Images</FormLabel>
|
||||
<FormControl>
|
||||
<Switch
|
||||
checked={field.value}
|
||||
onCheckedChange={field.onChange}
|
||||
></Switch>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="include_image_descriptions"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Include Image Descriptions</FormLabel>
|
||||
<FormControl>
|
||||
<Switch
|
||||
checked={field.value}
|
||||
onCheckedChange={field.onChange}
|
||||
></Switch>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<DynamicDomain
|
||||
name="include_domains"
|
||||
label={'Include Domains'}
|
||||
></DynamicDomain>
|
||||
<DynamicDomain
|
||||
name="exclude_domains"
|
||||
label={'Exclude Domains'}
|
||||
></DynamicDomain>
|
||||
</FormContainer>
|
||||
</form>
|
||||
<div className="p-5">
|
||||
<Output list={outputList}></Output>
|
||||
</div>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { AgentGlobals } from '@/constants/agent';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { useMemo } from 'react';
|
||||
import useGraphStore from '../../store';
|
||||
import { getAgentNodeTools } from '../../utils';
|
||||
import { convertToObjectArray, getAgentNodeTools } from '../../utils';
|
||||
|
||||
export enum SearchDepth {
|
||||
Basic = 'basic',
|
||||
@ -13,8 +14,9 @@ export enum Topic {
|
||||
General = 'general',
|
||||
}
|
||||
|
||||
const defaultValues = {
|
||||
query: '',
|
||||
export const defaultValues = {
|
||||
api_key: '',
|
||||
query: AgentGlobals.SysQuery,
|
||||
search_depth: SearchDepth.Basic,
|
||||
topic: Topic.General,
|
||||
max_results: 5,
|
||||
@ -25,6 +27,16 @@ const defaultValues = {
|
||||
include_image_descriptions: false,
|
||||
include_domains: [],
|
||||
exclude_domains: [],
|
||||
outputs: {
|
||||
formalized_content: {
|
||||
value: '',
|
||||
type: 'string',
|
||||
},
|
||||
json: {
|
||||
value: {},
|
||||
type: 'Object',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export function useValues() {
|
||||
@ -46,6 +58,8 @@ export function useValues() {
|
||||
|
||||
return {
|
||||
...formData,
|
||||
include_domains: convertToObjectArray(formData.include_domains),
|
||||
exclude_domains: convertToObjectArray(formData.exclude_domains),
|
||||
};
|
||||
}, [clickedNodeId, clickedToolId, findUpstreamNodeById]);
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { useEffect } from 'react';
|
||||
import { UseFormReturn, useWatch } from 'react-hook-form';
|
||||
import useGraphStore from '../../store';
|
||||
import { getAgentNodeTools } from '../../utils';
|
||||
import { convertToStringArray, getAgentNodeTools } from '../../utils';
|
||||
|
||||
export function useWatchFormChange(form?: UseFormReturn<any>) {
|
||||
let values = useWatch({ control: form?.control });
|
||||
@ -18,7 +18,14 @@ export function useWatchFormChange(form?: UseFormReturn<any>) {
|
||||
values = form?.getValues();
|
||||
const nextTools = tools.map((x) => {
|
||||
if (x.component_name === clickedToolId) {
|
||||
return { ...x, params: { ...values } };
|
||||
return {
|
||||
...x,
|
||||
params: {
|
||||
...values,
|
||||
include_domains: convertToStringArray(values.include_domains),
|
||||
exclude_domains: convertToStringArray(values.exclude_domains),
|
||||
},
|
||||
};
|
||||
}
|
||||
return x;
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user