diff --git a/web/src/interfaces/database/agent.ts b/web/src/interfaces/database/agent.ts index 74d254d15..8fd95d83d 100644 --- a/web/src/interfaces/database/agent.ts +++ b/web/src/interfaces/database/agent.ts @@ -139,6 +139,29 @@ export interface ICodeForm { script?: string; } +export interface IAgentForm { + sys_prompt: string; + prompts: Array<{ + role: string; + content: string; + }>; + max_retries: number; + delay_after_error: number; + visual_files_var: string; + max_rounds: number; + exception_method: Nullable<'comment' | 'go'>; + exception_comment: any; + exception_goto: any; + tools: Array<{ + component_name: string; + params: Record; + }>; + outputs: { + structured_output: Record>; + content: Record; + }; +} + export type BaseNodeData = { label: string; // operator type name: string; // operator name @@ -167,7 +190,7 @@ export type IIterationStartNode = BaseNode; export type IKeywordNode = BaseNode; export type ICodeNode = BaseNode; export type IAgentNode = BaseNode; -export type IToolNode = BaseNode; +export type IToolNode = BaseNode; export type RAGFlowNodeType = | IBeginNode diff --git a/web/src/pages/agent/canvas/node/tool-node.tsx b/web/src/pages/agent/canvas/node/tool-node.tsx index bc45460f7..0305d15e9 100644 --- a/web/src/pages/agent/canvas/node/tool-node.tsx +++ b/web/src/pages/agent/canvas/node/tool-node.tsx @@ -1,7 +1,9 @@ -import { IToolNode } from '@/interfaces/database/agent'; +import { IAgentForm, IToolNode } from '@/interfaces/database/agent'; import { Handle, NodeProps, Position } from '@xyflow/react'; +import { get } from 'lodash'; import { memo } from 'react'; import { NodeHandleId } from '../../constant'; +import useGraphStore from '../../store'; import { NodeWrapper } from './node-wrapper'; function InnerToolNode({ @@ -10,6 +12,16 @@ function InnerToolNode({ isConnectable = true, selected, }: NodeProps) { + const { edges, getNode } = useGraphStore((state) => state); + const upstreamAgentNodeId = edges.find((x) => x.target === id)?.source; + const upstreamAgentNode = getNode(upstreamAgentNodeId); + + const tools: IAgentForm['tools'] = get( + upstreamAgentNode, + 'data.form.tools', + [], + ); + return ( +
    + {tools.map((x) => ( +
  • {x.component_name}
  • + ))} +
); } 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 2530d4ed9..d887bf58c 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 @@ -34,6 +34,7 @@ import RetrievalForm from '../form/retrieval-form/next'; import RewriteQuestionForm from '../form/rewrite-question-form'; import SwitchForm from '../form/switch-form'; import TemplateForm from '../form/template-form'; +import ToolForm from '../form/tool-form'; import TuShareForm from '../form/tushare-form'; import WenCaiForm from '../form/wencai-form'; import WikipediaForm from '../form/wikipedia-form'; @@ -369,6 +370,11 @@ export function useFormConfigMap() { defaultValues: {}, schema: z.object({}), }, + [Operator.Tool]: { + component: ToolForm, + defaultValues: {}, + schema: z.object({}), + }, }; return FormConfigMap; diff --git a/web/src/pages/agent/form/agent-form/tool-popover/index.tsx b/web/src/pages/agent/form/agent-form/tool-popover/index.tsx index fcb53d69a..d903c3168 100644 --- a/web/src/pages/agent/form/agent-form/tool-popover/index.tsx +++ b/web/src/pages/agent/form/agent-form/tool-popover/index.tsx @@ -3,33 +3,43 @@ import { PopoverContent, PopoverTrigger, } from '@/components/ui/popover'; +import { IAgentForm } from '@/interfaces/database/agent'; import { Operator } from '@/pages/agent/constant'; import { AgentFormContext, AgentInstanceContext } from '@/pages/agent/context'; import { Position } from '@xyflow/react'; -import { PropsWithChildren, useCallback, useContext } from 'react'; +import { get } from 'lodash'; +import { PropsWithChildren, useCallback, useContext, useMemo } from 'react'; import { ToolCommand } from './tool-command'; +import { useUpdateAgentNodeTools } from './use-update-tools'; export function ToolPopover({ children }: PropsWithChildren) { const { addCanvasNode } = useContext(AgentInstanceContext); const node = useContext(AgentFormContext); + const { updateNodeTools } = useUpdateAgentNodeTools(); + + const toolNames = useMemo(() => { + const tools: IAgentForm['tools'] = get(node, 'data.form.tools', []); + return tools.map((x) => x.component_name); + }, [node]); const handleChange = useCallback( (value: string[]) => { - if (Array.isArray(value) && value.length > 0) { + if (Array.isArray(value) && value.length > 0 && node?.id) { + updateNodeTools(value); addCanvasNode(Operator.Tool, { position: Position.Bottom, nodeId: node?.id, })(); } }, - [addCanvasNode, node?.id], + [addCanvasNode, node?.id, updateNodeTools], ); return ( {children} - + ); diff --git a/web/src/pages/agent/form/agent-form/tool-popover/tool-command.tsx b/web/src/pages/agent/form/agent-form/tool-popover/tool-command.tsx index 6ee3c5f12..507444098 100644 --- a/web/src/pages/agent/form/agent-form/tool-popover/tool-command.tsx +++ b/web/src/pages/agent/form/agent-form/tool-popover/tool-command.tsx @@ -45,11 +45,6 @@ const Menus = [ }, ]; -const Options = Menus.reduce((pre, cur) => { - pre.push(...cur.list); - return pre; -}, []); - type ToolCommandProps = { value?: string[]; onChange?(values: string[]): void; @@ -57,7 +52,6 @@ type ToolCommandProps = { export function ToolCommand({ value, onChange }: ToolCommandProps) { const [currentValue, setCurrentValue] = useState([]); - console.log('🚀 ~ ToolCommand ~ currentValue:', currentValue); const toggleOption = useCallback( (option: string) => { diff --git a/web/src/pages/agent/form/agent-form/tool-popover/use-update-tools.ts b/web/src/pages/agent/form/agent-form/tool-popover/use-update-tools.ts new file mode 100644 index 000000000..2c55ce1ac --- /dev/null +++ b/web/src/pages/agent/form/agent-form/tool-popover/use-update-tools.ts @@ -0,0 +1,29 @@ +import { IAgentForm } from '@/interfaces/database/agent'; +import { AgentFormContext } from '@/pages/agent/context'; +import useGraphStore from '@/pages/agent/store'; +import { get } from 'lodash'; +import { useCallback, useContext } from 'react'; + +export function useUpdateAgentNodeTools() { + const { updateNodeForm } = useGraphStore((state) => state); + const node = useContext(AgentFormContext); + + const updateNodeTools = useCallback( + (value: string[]) => { + if (node?.id) { + const tools: IAgentForm['tools'] = get(node, 'data.form.tools'); + + const nextValue = value.reduce((pre, cur) => { + const tool = tools.find((x) => x.component_name === cur); + pre.push(tool ? tool : { component_name: cur, params: {} }); + return pre; + }, []); + + updateNodeForm(node?.id, nextValue, ['tools']); + } + }, + [node, updateNodeForm], + ); + + return { updateNodeTools }; +}