From 0b6b9793c12810326f78ce8a75740f4612335e46 Mon Sep 17 00:00:00 2001 From: Li Xin Date: Tue, 29 Apr 2025 14:13:39 +0800 Subject: [PATCH] feat: add MultiAgentVisualization --- .../_components/multi-agent-visualization.tsx | 288 ++++++++++++++++++ web/src/app/page.tsx | 8 +- 2 files changed, 295 insertions(+), 1 deletion(-) create mode 100644 web/src/app/_components/multi-agent-visualization.tsx diff --git a/web/src/app/_components/multi-agent-visualization.tsx b/web/src/app/_components/multi-agent-visualization.tsx new file mode 100644 index 0000000..80a4db3 --- /dev/null +++ b/web/src/app/_components/multi-agent-visualization.tsx @@ -0,0 +1,288 @@ +// Copyright (c) 2025 Bytedance Ltd. and/or its affiliates +// SPDX-License-Identifier: MIT + +"use client"; + +import { + ReactFlow, + Background, + useNodesState, + useEdgesState, + Handle, + Position, +} from "@xyflow/react"; + +import "@xyflow/react/dist/style.css"; + +const ROW_HEIGHT = 75; +const ROW_1 = 0; +const ROW_2 = ROW_HEIGHT; +const ROW_3 = ROW_HEIGHT * 2; +const ROW_4 = ROW_HEIGHT * 2; +const ROW_5 = ROW_HEIGHT * 3; +const ROW_6 = ROW_HEIGHT * 4; +const initialNodes = [ + { + id: "Start", + type: "circle", + data: { label: "Start" }, + position: { x: 80, y: ROW_1 }, + }, + { + id: "Coordinator", + data: { label: "Coordinator" }, + position: { x: 150, y: ROW_1 }, + }, + { + id: "Planner", + data: { label: "Planner" }, + position: { x: 150, y: ROW_2 }, + }, + { + id: "Reporter", + data: { label: "Reporter" }, + position: { x: 25, y: ROW_3 }, + }, + { + id: "Human Feedback", + data: { label: "Human Feedback" }, + position: { x: 275, y: ROW_4 }, + }, + { + id: "Research Team", + data: { label: "Research Team" }, + position: { x: 275, y: ROW_5 }, + }, + { + id: "Researcher", + data: { label: "Researcher" }, + position: { x: 175, y: ROW_6 }, + }, + { + id: "Coder", + data: { label: "Coder" }, + position: { x: 375, y: ROW_6 }, + }, + { + id: "End", + type: "circle", + data: { label: "End" }, + position: { x: 80, y: ROW_6 }, + }, +]; + +const initialEdges = [ + { + id: "Start->Coordinator", + source: "Start", + target: "Coordinator", + sourceHandle: "right", + targetHandle: "left", + animated: true, + }, + { + id: "Coordinator->Planner", + source: "Coordinator", + target: "Planner", + sourceHandle: "bottom", + targetHandle: "top", + animated: true, + }, + { + id: "Planner->Reporter", + source: "Planner", + target: "Reporter", + sourceHandle: "left", + targetHandle: "top", + animated: true, + }, + { + id: "Planner->Human Feedback", + source: "Planner", + target: "Human Feedback", + sourceHandle: "bottom", + targetHandle: "left", + animated: true, + }, + { + id: "Human Feedback->Planner", + source: "Human Feedback", + target: "Planner", + sourceHandle: "top", + targetHandle: "right", + animated: true, + }, + { + id: "Human Feedback->Research Team", + source: "Human Feedback", + target: "Research Team", + sourceHandle: "bottom", + targetHandle: "top", + animated: true, + }, + { + id: "Reporter->End", + source: "Reporter", + target: "End", + sourceHandle: "bottom", + targetHandle: "top", + animated: true, + }, + { + id: "Research Team->Researcher", + source: "Research Team", + target: "Researcher", + sourceHandle: "left", + targetHandle: "top", + animated: true, + }, + { + id: "Research Team->Coder", + source: "Research Team", + target: "Coder", + sourceHandle: "bottom", + targetHandle: "left", + animated: true, + }, + { + id: "Research Team->Planner", + source: "Research Team", + target: "Planner", + sourceHandle: "left", + targetHandle: "bottom", + animated: true, + }, + { + id: "Researcher->Research Team", + source: "Researcher", + target: "Research Team", + sourceHandle: "right", + targetHandle: "bottom", + animated: true, + }, + { + id: "Coder->Research Team", + source: "Coder", + target: "Research Team", + sourceHandle: "top", + targetHandle: "right", + animated: true, + }, +]; + +const nodeTypes = { + circle: CircleNode, + agent: AgentNode, + default: AgentNode, +}; + +export function MultiAgentVisualization() { + const [nodes, , onNodesChange] = useNodesState(initialNodes); + const [edges, , onEdgesChange] = useEdgesState(initialEdges); + + return ( + + + + ); +} + +function CircleNode({ data }: { data: { label: string } }) { + return ( + <> +
+

{data.label}

+
+ {data.label === "Start" && ( + + )} + {data.label === "End" && ( + + )} + + ); +} + +function AgentNode({ data }: { data: { label: string } }) { + return ( + <> +
{data.label}
+ + + + + + + + + + ); +} diff --git a/web/src/app/page.tsx b/web/src/app/page.tsx index bfc652e..3613d0c 100644 --- a/web/src/app/page.tsx +++ b/web/src/app/page.tsx @@ -26,6 +26,7 @@ import { BentoGrid } from "~/components/magicui/bento-grid"; import { FlickeringGrid } from "~/components/magicui/flickering-grid"; import { Button } from "~/components/ui/button"; +import { MultiAgentVisualization } from "./_components/multi-agent-visualization"; import { Ray } from "./_components/ray"; export default function HomePage() { @@ -237,11 +238,16 @@ function CaseStudySection() { function MultiAgentSection() { return ( -
+
+
+
+ +
+
); }