本文为《React Agent:从零开始构建 AI 智能体》专栏系列文章。 专栏地址:https://blog.csdn.net/suiyingy/category_12933485.html。项目地址:https://gitee.com/fgai/react-agent(含完整代码示例与实战源)。完整介绍:数据分析智能体构建实战:LLM 工具调用 + 记忆管理模块代码实现全解析(附 Qwen-Turbo 代码实现)-CSDN博客。
在大模型浪潮奔涌向前的当下,智能体技术的应用愈发广泛且深入,而高效搭建智能体组件成为开发者亟待解决的关键问题。React Flow 作为一款强大的可视化流程编辑库,凭借其灵活的布局与交互能力,为智能体组件的构建提供了新的思路与方法。本章将围绕基于 React Flow 搭建的智能体基本组件示例展开,从输入节点、输出节点等多个核心节点切入,逐步探索智能体组件搭建的奥秘。
本节主要介绍环境搭建,从下一节开始逐一介绍节点组件创建:输入节点、输出节点、网络节点、代码节点、工具节点以及大模型智能对话节点等。
1 创建 React Flow 项目
我们首先按照下面步骤创建一个 agent-nodes 项目:
# 创建项目
npx create-react-app agent-nodes
cd agent-nodes
# 考虑兼容性,安装18版本
npm install react@18 react-dom@18
npm install reactflow react-flow-renderer
# 安装 tailwindcss
npm install -D [email protected]
npx tailwindcss init
# 安装 Font Awesome 图标库
npm install @fortawesome/react-fontawesome @fortawesome/free-solid-svg-icons
修改 agent-nodes/tailwind.config.js文件,添加 tailwindcss 样式。
module.exports = {
content: [
"./src/**/*.{js,jsx,ts,tsx}",
// 包含所有组件文件路径
],
theme: { extend: {} },
plugins: [
// require('@tailwindcss/forms'), // 如果使用表单插件
],
}
进一步在agent-nodes/src/index.css文件中引入样式。
@tailwind base;
@tailwind components;
@tailwind utilities;
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}
创建成功后 agent-nodes/packge.json 中内容如下:
{
"name": "agent-nodes",
"version": "0.1.0",
"private": true,
"dependencies": {
"@fortawesome/free-solid-svg-icons": "^6.7.2",
"@fortawesome/react-fontawesome": "^0.2.2",
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.3.0",
"@testing-library/user-event": "^13.5.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-flow-renderer": "^10.3.17",
"react-scripts": "5.0.1",
"reactflow": "^11.11.4",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"tailwindcss": "^3.4.17"
}
}
此时,我们可通过 npm start 启动项目,并且在浏览器看到 React 默认页面。
2 主页搭建
我们设计在 App.js 主页面用于展示后续不同类型的节点,程序如下所示。
// src/App.js
import React, { useState, useCallback, useEffect } from 'react';
import ReactFlow, {
applyNodeChanges,
applyEdgeChanges,
addEdge,
Background,
useReactFlow,
ReactFlowProvider
} from 'reactflow';
import 'reactflow/dist/style.css';
const nodeTypes = {
};
function App() {
const { screenToFlowPosition } = useReactFlow();
const [nodes, setNodes] = useState([]);
const [edges, setEdges] = useState([]);
const [contextMenu, setContextMenu] = useState(null);
// 双击节点处理
const onNodeDoubleClick = useCallback((_, node) => {
}, []);
// 右键菜单
const handlePaneContextMenu = (event) => {
event.preventDefault();
const position = screenToFlowPosition({
x: event.clientX,
y: event.clientY,
});
setContextMenu({
flowPosition: position,
screenPosition: { x: event.clientX, y: event.clientY }
});
};
// 关闭菜单
const closeContextMenu = useCallback(() => {
setContextMenu(null);
}, []);
useEffect(() => {
if (contextMenu) {
document.addEventListener('click', closeContextMenu);
return () => document.removeEventListener('click', closeContextMenu);
}
}, [contextMenu, closeContextMenu]);
// 运行按钮
const handleRun = async () => {
};
const onNodesChange = useCallback(
(changes) => setNodes((nds) => applyNodeChanges(changes, nds)),
[]
);
const onEdgesChange = useCallback(
(changes) => setEdges((eds) => applyEdgeChanges(changes, eds)),
[]
);
const onConnect = useCallback(
(params) => setEdges((eds) => addEdge(
{
...params,
animated: true,
style: { stroke: '#666' },
},
eds
)),
[]
);
return (
<div style={{ height: '100vh', position: 'relative' }}>
<button
onClick={handleRun}
style={{
position: 'absolute',
top: 20,
left: '50%',
transform: 'translateX(-50%)',
zIndex: 10,
padding: '8px 20px',
background: '#4CAF50',
color: 'white',
border: 'none',
borderRadius: 20,
cursor: 'pointer',
boxShadow: '0 2px 4px rgba(0,0,0,0.2)',
fontSize: 14,
fontWeight: 'bold',
}}
>
▶ 运行处理
</button>
<ReactFlow
nodes={nodes}
edges={edges}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
onConnect={onConnect}
onPaneContextMenu={handlePaneContextMenu}
onNodeDoubleClick={onNodeDoubleClick}
nodeTypes={nodeTypes}
fitView
connectionRadius={20}
snapToGrid={true}
snapGrid={[15, 15]}
defaultEdgeOptions={{
type: 'smoothstep',
style: {
strokeWidth: 2,
},
}}
>
<Background
color="#ddd"
gap={25}
style={{ backgroundColor: '#f8f9fa' }}
/>
</ReactFlow>
{contextMenu && (
<div
style={{
position: 'fixed',
top: contextMenu.screenPosition.y,
left: contextMenu.screenPosition.x,
background: 'white',
boxShadow: '0 2px 4px rgba(0,0,0,0.2)',
borderRadius: 4,
zIndex: 10,
}}
onClick={(e) => e.stopPropagation()}
>
<div
style={{
padding: '8px 16px',
cursor: 'pointer',
transition: 'background 0.2s',
':hover': {
background: '#f5f5f5',
},
}}
// onClick={createInputNode}
>
添加节点
</div>
</div>
)}
</div>
);
}
export default function FlowWrapper() {
return (
<ReactFlowProvider>
<App />
</ReactFlowProvider>
);
}
将以上程序复制到 src/app.js 文件,npm start 运行程序后页面如下图所示。页面上方居中位置有一个"运行处理"按钮。此按钮样式为绿色背景、白色文字,有圆角和阴影效果,视觉上比较突出。

图1 主页基本页面
在初始化时,节点和边的数据为空,后续可以通过交互进行添加和修改。流程图具有一些实用的配置,如支持网格吸附,这使得节点移动时会自动对齐到网格,方便布局;边默认采用平滑曲线样式,线条宽度为 2px,并且连接时会有动画效果。此外,还添加了带有网格的背景,增强了视觉辨识度。
当在流程图空白处点击右键时,会弹出一个右键菜单,菜单中有"添加节点"的选项,可用于后续添加节点。如果在菜单以外的区域点击,菜单会自动关闭。同时,程序预留了节点双击处理和运行按钮点击处理的逻辑,可根据实际需求进一步完善。
立即关注获取最新动态
点击订阅《React Agent 开发专栏》,每周获取智能体开发深度教程。项目代码持续更新至React Agent 开源仓库,欢迎 Star 获取实时更新通知!FGAI 人工智能平台:FGAI 人工智能平台 https://www.botaigc.cn/