diff --git a/web/src/pages/agent/canvas/node/dropdown/next-step-dropdown.tsx b/web/src/pages/agent/canvas/node/dropdown/next-step-dropdown.tsx
index e741286f2..f8ffc4cb3 100644
--- a/web/src/pages/agent/canvas/node/dropdown/next-step-dropdown.tsx
+++ b/web/src/pages/agent/canvas/node/dropdown/next-step-dropdown.tsx
@@ -88,7 +88,7 @@ function AccordionOperators() {
Tools
-
+
diff --git a/web/src/pages/agent/constant.tsx b/web/src/pages/agent/constant.tsx
index 3f1d192e1..cebd46240 100644
--- a/web/src/pages/agent/constant.tsx
+++ b/web/src/pages/agent/constant.tsx
@@ -387,7 +387,7 @@ const initialQueryBaseValues = {
};
export const initialRetrievalValues = {
- query: '',
+ query: AgentGlobals.SysQuery,
top_n: 8,
top_k: 1024,
kb_ids: [],
@@ -686,6 +686,41 @@ export const initialAgentValues = {
},
};
+export enum TavilySearchDepth {
+ Basic = 'basic',
+ Advanced = 'advanced',
+}
+
+export enum TavilyTopic {
+ News = 'news',
+ General = 'general',
+}
+
+export const initialTavilyValues = {
+ api_key: '',
+ query: AgentGlobals.SysQuery,
+ search_depth: TavilySearchDepth.Basic,
+ topic: TavilyTopic.General,
+ max_results: 5,
+ days: 7,
+ include_answer: false,
+ include_raw_content: true,
+ include_images: false,
+ include_image_descriptions: false,
+ include_domains: [],
+ exclude_domains: [],
+ outputs: {
+ formalized_content: {
+ value: '',
+ type: 'string',
+ },
+ json: {
+ value: {},
+ type: 'Object',
+ },
+ },
+};
+
export const CategorizeAnchorPointPositions = [
{ top: 1, right: 34 },
{ top: 8, right: 18 },
@@ -813,6 +848,7 @@ export const NodeMap = {
[Operator.WaitingDialogue]: 'ragNode',
[Operator.Agent]: 'agentNode',
[Operator.Tool]: 'toolNode',
+ [Operator.Tavily]: 'ragNode',
};
export const LanguageOptions = [
diff --git a/web/src/pages/agent/form-sheet/use-form-config-map.tsx b/web/src/pages/agent/form-sheet/use-form-config-map.tsx
index d887bf58c..50b537a07 100644
--- a/web/src/pages/agent/form-sheet/use-form-config-map.tsx
+++ b/web/src/pages/agent/form-sheet/use-form-config-map.tsx
@@ -33,6 +33,7 @@ import RelevantForm from '../form/relevant-form';
import RetrievalForm from '../form/retrieval-form/next';
import RewriteQuestionForm from '../form/rewrite-question-form';
import SwitchForm from '../form/switch-form';
+import TavilyForm from '../form/tavily-form';
import TemplateForm from '../form/template-form';
import ToolForm from '../form/tool-form';
import TuShareForm from '../form/tushare-form';
@@ -375,6 +376,11 @@ export function useFormConfigMap() {
defaultValues: {},
schema: z.object({}),
},
+ [Operator.Tavily]: {
+ component: TavilyForm,
+ defaultValues: {},
+ schema: z.object({}),
+ },
};
return FormConfigMap;
diff --git a/web/src/pages/agent/form/agent-form/agent-tools.tsx b/web/src/pages/agent/form/agent-form/agent-tools.tsx
index 25bbead6d..5961c8e5a 100644
--- a/web/src/pages/agent/form/agent-form/agent-tools.tsx
+++ b/web/src/pages/agent/form/agent-form/agent-tools.tsx
@@ -36,7 +36,7 @@ export function AgentTools() {
{x}
-
+
{
name={`prompts`}
render={({ field }) => (
+ User Prompt
diff --git a/web/src/pages/agent/form/tavily-form/index.tsx b/web/src/pages/agent/form/tavily-form/index.tsx
index 3ff58b37f..461d00910 100644
--- a/web/src/pages/agent/form/tavily-form/index.tsx
+++ b/web/src/pages/agent/form/tavily-form/index.tsx
@@ -15,20 +15,26 @@ import { zodResolver } from '@hookform/resolvers/zod';
import { useMemo } from 'react';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
+import {
+ TavilySearchDepth,
+ TavilyTopic,
+ initialTavilyValues,
+} from '../../constant';
+import { INextOperatorForm } from '../../interface';
import { Output, OutputType } from '../components/output';
import { QueryVariable } from '../components/query-variable';
import { DynamicDomain } from './dynamic-domain';
-import { SearchDepth, Topic, defaultValues, useValues } from './use-values';
+import { useValues } from './use-values';
import { useWatchFormChange } from './use-watch-change';
-const TavilyForm = () => {
- const values = useValues();
+const TavilyForm = ({ node }: INextOperatorForm) => {
+ const values = useValues(node);
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]),
+ search_depth: z.enum([TavilySearchDepth.Advanced, TavilySearchDepth.Basic]),
+ topic: z.enum([TavilyTopic.News, TavilyTopic.General]),
max_results: z.coerce.number(),
days: z.coerce.number(),
include_answer: z.boolean(),
@@ -45,7 +51,7 @@ const TavilyForm = () => {
});
const outputList = useMemo(() => {
- return Object.entries(defaultValues.outputs).reduce(
+ return Object.entries(initialTavilyValues.outputs).reduce(
(pre, [key, val]) => {
pre.push({ title: key, type: val.type });
return pre;
@@ -54,7 +60,7 @@ const TavilyForm = () => {
);
}, []);
- useWatchFormChange(form);
+ useWatchFormChange(node?.id, form);
return (
@@ -104,12 +110,12 @@ const TavilyForm = () => {
name="topic"
render={({ field }) => (
- Topic
+ TavilyTopic
diff --git a/web/src/pages/agent/form/tavily-form/use-values.ts b/web/src/pages/agent/form/tavily-form/use-values.ts
index 486c06622..011e04005 100644
--- a/web/src/pages/agent/form/tavily-form/use-values.ts
+++ b/web/src/pages/agent/form/tavily-form/use-values.ts
@@ -1,59 +1,15 @@
-import { AgentGlobals } from '@/constants/agent';
+import { RAGFlowNodeType } from '@/interfaces/database/agent';
import { isEmpty } from 'lodash';
import { useMemo } from 'react';
-import useGraphStore from '../../store';
-import { convertToObjectArray, getAgentNodeTools } from '../../utils';
-
-export enum SearchDepth {
- Basic = 'basic',
- Advanced = 'advanced',
-}
-
-export enum Topic {
- News = 'news',
- General = 'general',
-}
-
-export const defaultValues = {
- api_key: '',
- query: AgentGlobals.SysQuery,
- search_depth: SearchDepth.Basic,
- topic: Topic.General,
- max_results: 5,
- days: 7,
- include_answer: false,
- include_raw_content: true,
- include_images: false,
- include_image_descriptions: false,
- include_domains: [],
- exclude_domains: [],
- outputs: {
- formalized_content: {
- value: '',
- type: 'string',
- },
- json: {
- value: {},
- type: 'Object',
- },
- },
-};
-
-export function useValues() {
- const { clickedToolId, clickedNodeId, findUpstreamNodeById } = useGraphStore(
- (state) => state,
- );
+import { initialTavilyValues } from '../../constant';
+import { convertToObjectArray } from '../../utils';
+export function useValues(node?: RAGFlowNodeType) {
const values = useMemo(() => {
- const agentNode = findUpstreamNodeById(clickedNodeId);
- const tools = getAgentNodeTools(agentNode);
-
- const formData = tools.find(
- (x) => x.component_name === clickedToolId,
- )?.params;
+ const formData = node?.data?.form;
if (isEmpty(formData)) {
- return defaultValues;
+ return initialTavilyValues;
}
return {
@@ -61,7 +17,7 @@ export function useValues() {
include_domains: convertToObjectArray(formData.include_domains),
exclude_domains: convertToObjectArray(formData.exclude_domains),
};
- }, [clickedNodeId, clickedToolId, findUpstreamNodeById]);
+ }, [node?.data?.form]);
return values;
}
diff --git a/web/src/pages/agent/form/tavily-form/use-watch-change.ts b/web/src/pages/agent/form/tavily-form/use-watch-change.ts
index 31927e9ed..8acaaa2f7 100644
--- a/web/src/pages/agent/form/tavily-form/use-watch-change.ts
+++ b/web/src/pages/agent/form/tavily-form/use-watch-change.ts
@@ -1,41 +1,23 @@
import { useEffect } from 'react';
import { UseFormReturn, useWatch } from 'react-hook-form';
import useGraphStore from '../../store';
-import { convertToStringArray, getAgentNodeTools } from '../../utils';
+import { convertToStringArray } from '../../utils';
-export function useWatchFormChange(form?: UseFormReturn) {
+export function useWatchFormChange(id?: string, form?: UseFormReturn) {
let values = useWatch({ control: form?.control });
- const { clickedToolId, clickedNodeId, findUpstreamNodeById, updateNodeForm } =
- useGraphStore((state) => state);
+ const updateNodeForm = useGraphStore((state) => state.updateNodeForm);
useEffect(() => {
- const agentNode = findUpstreamNodeById(clickedNodeId);
// Manually triggered form updates are synchronized to the canvas
- if (agentNode && form?.formState.isDirty) {
- const agentNodeId = agentNode?.id;
- const tools = getAgentNodeTools(agentNode);
-
+ if (id && form?.formState.isDirty) {
values = form?.getValues();
- const nextTools = tools.map((x) => {
- if (x.component_name === clickedToolId) {
- return {
- ...x,
- params: {
- ...values,
- include_domains: convertToStringArray(values.include_domains),
- exclude_domains: convertToStringArray(values.exclude_domains),
- },
- };
- }
- return x;
- });
-
- const nextValues = {
- ...(agentNode?.data?.form ?? {}),
- tools: nextTools,
+ let nextValues: any = {
+ ...values,
+ include_domains: convertToStringArray(values.include_domains),
+ exclude_domains: convertToStringArray(values.exclude_domains),
};
- updateNodeForm(agentNodeId, nextValues);
+ updateNodeForm(id, nextValues);
}
- }, [form?.formState.isDirty, updateNodeForm, values]);
+ }, [form?.formState.isDirty, id, updateNodeForm, values]);
}
diff --git a/web/src/pages/agent/form/tool-form/constant.ts b/web/src/pages/agent/form/tool-form/constant.ts
index a22aa8a2d..4954f51e1 100644
--- a/web/src/pages/agent/form/tool-form/constant.ts
+++ b/web/src/pages/agent/form/tool-form/constant.ts
@@ -13,9 +13,9 @@ import GoogleForm from '../google-form';
import GoogleScholarForm from '../google-scholar-form';
import PubMedForm from '../pubmed-form';
import RetrievalForm from '../retrieval-form/next';
-import TavilyForm from '../tavily-form';
import WikipediaForm from '../wikipedia-form';
import YahooFinanceForm from '../yahoo-finance-form';
+import TavilyForm from './tavily-form';
export const ToolFormConfigMap = {
[Operator.Retrieval]: RetrievalForm,
diff --git a/web/src/pages/agent/form/tool-form/tavily-form/index.tsx b/web/src/pages/agent/form/tool-form/tavily-form/index.tsx
new file mode 100644
index 000000000..3dde7fde9
--- /dev/null
+++ b/web/src/pages/agent/form/tool-form/tavily-form/index.tsx
@@ -0,0 +1,60 @@
+import { FormContainer } from '@/components/form-container';
+import {
+ Form,
+ FormControl,
+ FormField,
+ FormItem,
+ FormLabel,
+ FormMessage,
+} from '@/components/ui/form';
+import { Input } from '@/components/ui/input';
+import { zodResolver } from '@hookform/resolvers/zod';
+import { useForm } from 'react-hook-form';
+import { z } from 'zod';
+import { useValues } from '../use-values';
+import { useWatchFormChange } from '../use-watch-change';
+
+const TavilyForm = () => {
+ const values = useValues();
+
+ const FormSchema = z.object({
+ api_key: z.string(),
+ });
+
+ const form = useForm>({
+ defaultValues: values,
+ resolver: zodResolver(FormSchema),
+ });
+
+ useWatchFormChange(form);
+
+ return (
+
+
+ );
+};
+
+export default TavilyForm;
diff --git a/web/src/pages/agent/form/tool-form/use-values.ts b/web/src/pages/agent/form/tool-form/use-values.ts
new file mode 100644
index 000000000..f2745d279
--- /dev/null
+++ b/web/src/pages/agent/form/tool-form/use-values.ts
@@ -0,0 +1,43 @@
+import { isEmpty } from 'lodash';
+import { useMemo } from 'react';
+import useGraphStore from '../../store';
+import { getAgentNodeTools } from '../../utils';
+
+export enum SearchDepth {
+ Basic = 'basic',
+ Advanced = 'advanced',
+}
+
+export enum Topic {
+ News = 'news',
+ General = 'general',
+}
+
+export const defaultValues = {
+ api_key: '',
+};
+
+export function useValues() {
+ const { clickedToolId, clickedNodeId, findUpstreamNodeById } = useGraphStore(
+ (state) => state,
+ );
+
+ const values = useMemo(() => {
+ const agentNode = findUpstreamNodeById(clickedNodeId);
+ const tools = getAgentNodeTools(agentNode);
+
+ const formData = tools.find(
+ (x) => x.component_name === clickedToolId,
+ )?.params;
+
+ if (isEmpty(formData)) {
+ return defaultValues;
+ }
+
+ return {
+ ...formData,
+ };
+ }, [clickedNodeId, clickedToolId, findUpstreamNodeById]);
+
+ return values;
+}
diff --git a/web/src/pages/agent/form/tool-form/use-watch-change.ts b/web/src/pages/agent/form/tool-form/use-watch-change.ts
new file mode 100644
index 000000000..81a70a235
--- /dev/null
+++ b/web/src/pages/agent/form/tool-form/use-watch-change.ts
@@ -0,0 +1,39 @@
+import { useEffect } from 'react';
+import { UseFormReturn, useWatch } from 'react-hook-form';
+import useGraphStore from '../../store';
+import { getAgentNodeTools } from '../../utils';
+
+export function useWatchFormChange(form?: UseFormReturn) {
+ let values = useWatch({ control: form?.control });
+ const { clickedToolId, clickedNodeId, findUpstreamNodeById, updateNodeForm } =
+ useGraphStore((state) => state);
+
+ useEffect(() => {
+ const agentNode = findUpstreamNodeById(clickedNodeId);
+ // Manually triggered form updates are synchronized to the canvas
+ if (agentNode && form?.formState.isDirty) {
+ const agentNodeId = agentNode?.id;
+ const tools = getAgentNodeTools(agentNode);
+
+ values = form?.getValues();
+ const nextTools = tools.map((x) => {
+ if (x.component_name === clickedToolId) {
+ return {
+ ...x,
+ params: {
+ ...values,
+ },
+ };
+ }
+ return x;
+ });
+
+ const nextValues = {
+ ...(agentNode?.data?.form ?? {}),
+ tools: nextTools,
+ };
+
+ updateNodeForm(agentNodeId, nextValues);
+ }
+ }, [form?.formState.isDirty, updateNodeForm, values]);
+}
diff --git a/web/src/pages/agent/hooks.tsx b/web/src/pages/agent/hooks.tsx
index 7d194fef0..f10a72ecc 100644
--- a/web/src/pages/agent/hooks.tsx
+++ b/web/src/pages/agent/hooks.tsx
@@ -64,6 +64,7 @@ import {
initialRetrievalValues,
initialRewriteQuestionValues,
initialSwitchValues,
+ initialTavilyValues,
initialTemplateValues,
initialTuShareValues,
initialWaitingDialogueValues,
@@ -147,6 +148,7 @@ export const useInitializeOperatorParams = () => {
[Operator.Code]: initialCodeValues,
[Operator.WaitingDialogue]: initialWaitingDialogueValues,
[Operator.Agent]: { ...initialAgentValues, llm_id: llmId },
+ [Operator.Tavily]: initialTavilyValues,
};
}, [llmId]);
diff --git a/web/src/pages/agent/hooks/use-add-node.ts b/web/src/pages/agent/hooks/use-add-node.ts
index 074e1b201..0a74eac22 100644
--- a/web/src/pages/agent/hooks/use-add-node.ts
+++ b/web/src/pages/agent/hooks/use-add-node.ts
@@ -39,6 +39,7 @@ import {
initialRetrievalValues,
initialRewriteQuestionValues,
initialSwitchValues,
+ initialTavilyValues,
initialTemplateValues,
initialTuShareValues,
initialWaitingDialogueValues,
@@ -104,6 +105,7 @@ export const useInitializeOperatorParams = () => {
[Operator.WaitingDialogue]: initialWaitingDialogueValues,
[Operator.Agent]: { ...initialAgentValues, llm_id: llmId },
[Operator.Tool]: {},
+ [Operator.Tavily]: initialTavilyValues,
};
}, [llmId]);