From 847b3e96c81776c6c5462c22cbe34f0929172ef1 Mon Sep 17 00:00:00 2001 From: adrian Date: Thu, 1 May 2025 14:10:46 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0LLMNode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/app/workflow/components/LLMNode.tsx | 104 ++++++++++++ .../app/workflow/components/OutputNode.tsx | 27 +++ .../app/workflow/components/StartNode.tsx | 28 ++++ .../workflow/components/WorkflowSidebar.tsx | 44 +++++ frontend/app/workflow/components/types.ts | 34 ++++ frontend/app/workflow/page.tsx | 158 +++++++++--------- 6 files changed, 318 insertions(+), 77 deletions(-) create mode 100644 frontend/app/workflow/components/LLMNode.tsx create mode 100644 frontend/app/workflow/components/OutputNode.tsx create mode 100644 frontend/app/workflow/components/StartNode.tsx create mode 100644 frontend/app/workflow/components/WorkflowSidebar.tsx create mode 100644 frontend/app/workflow/components/types.ts diff --git a/frontend/app/workflow/components/LLMNode.tsx b/frontend/app/workflow/components/LLMNode.tsx new file mode 100644 index 0000000..d9bd6de --- /dev/null +++ b/frontend/app/workflow/components/LLMNode.tsx @@ -0,0 +1,104 @@ +// File: frontend/app/workflow/components/LLMNode.tsx +// Description: 自定义 LLM 节点组件 + +import React, { useState, useCallback, useEffect, memo, ChangeEvent } from 'react'; +import { Handle, Position, useUpdateNodeInternals, useReactFlow, Node } from 'reactflow'; +import { BrainCircuit } from 'lucide-react'; +import { Input } from "@/components/ui/input"; +import { Textarea } from "@/components/ui/textarea"; +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; +import { Slider } from "@/components/ui/slider"; +import { Label } from "@/components/ui/label"; +import { type LLMNodeData, type CustomNodeProps, availableModels } from './types'; // 导入类型和模型列表 + +const LLMNodeComponent = ({ id, data, isConnectable }: CustomNodeProps) => { +// const [currentData, setCurrentData] = useState(data); + const updateNodeInternals = useUpdateNodeInternals(); + const { setNodes } = useReactFlow(); // 获取 setNodes 方法 + + // 从 props 更新内部状态 (如果外部数据变化) +// useEffect(() => { +// setCurrentData(data); +// }, [data]); + + // 处理内部表单变化的通用回调 - 直接更新 React Flow 主状态 + const handleDataChange = useCallback((key: keyof LLMNodeData, value: any) => { + // 使用 setNodes 更新特定节点的数据 + setNodes((nds: Node[]) => // 显式指定类型 + nds.map((node) => { + if (node.id === id) { + // 创建一个新的 data 对象 + const updatedData = { ...node.data, [key]: value }; + return { ...node, data: updatedData }; + } + return node; + }) + ); + console.log(`(LLMNode) Node ${id} data updated:`, { [key]: value }); + }, [id, setNodes]); // 依赖 id 和 setNodes + + const handleSliderChange = useCallback((value: number[]) => { handleDataChange('temperature', value[0]); }, [handleDataChange]); + const handleSelectChange = useCallback((value: string) => { handleDataChange('model', value); }, [handleDataChange]); + const handleTextChange = useCallback((event: ChangeEvent) => { + const { name, value } = event.target; + handleDataChange(name as keyof LLMNodeData, value); + }, [handleDataChange]); + + // 检查 inputConnected 状态是否需要更新 (如果外部更新了) + // 注意:这个逻辑依赖于父组件正确更新了 data.inputConnected + useEffect(() => { + // 可以在这里添加逻辑,如果 props.data.inputConnected 和 UI 显示不一致时触发更新 + // 但通常连接状态由 onConnect/onEdgesChange 在父组件处理更佳 + // updateNodeInternals(id); // 如果 Handle 显示依赖 inputConnected,可能需要调用 + }, [data.inputConnected, id, updateNodeInternals]); + + return ( + // 调整宽度,例如 w-96 (24rem) +
+
+
+ + LLM 调用 +
+

使用大语言模型生成文本

+
+
+
+ + + {/* 直接使用 props.data.inputConnected */} + {!data.inputConnected &&

连接文本或提示

} +
+
+ + {/* 直接使用 props.data 和 onChange 回调 */} +