12 KiB
PLAN4 — 流编辑器深度重构:LLM→智能体→流节点→工作流 四层架构
一、问题诊断
当前架构痛点(逐一定位代码行级别)
| # | 问题 | 根因位置 | 影响 |
|---|---|---|---|
| 1 | LLM/智能体与节点未打通 | engine.py#L101-L118 LLMNodeAgent 每次硬编码新建 OpenAIChatModel,忽略节点配置中 model/temperature/system_prompt |
节点的LLM配置表单完全无效 |
| 2 | 节点只有壳,无法配置 | FlowNode.vue 固定 Top/Bottom Handle,条件节点只有一个出口 | 条件分支无法区分 true/false |
| 3 | 连线位置漂移 | FlowEdge.vue 自定义 SVG path + 没有绑定 vue-flow edge marker | 线条起点/终点不精准 |
| 4 | 条件分支不可控 | engine.py#L277-L293 ConditionNodeAgent 只返回固定字符串 + 拓扑排序不支持跳过 |
即使 LLM 判断了真假,引擎也不会分支 |
| 5 | 触发节点无实际参数 | FlowEditor 触发节点只有标签,无企微回调 URL / webhook 配置 | 无法真正接入企微触发 |
| 6 | AgentFactory 未集成 | engine.py 从未调用 factory.py | 智能体复用、缓存管理能力全部浪费 |
二、目标架构:四层递进模型
┌──────────────────────────────────────────────┐
│ 第四层: 工作流 (Workflow) │
│ 多个节点串联的执行拓扑图,含条件分支、循环 │
│ → FlowEngine.execute() │
├──────────────────────────────────────────────┤
│ 第三层: 流节点 (Flow Node) │
│ 每个节点是可配置的 Agent 实例 │
│ → LLMNodeAgent / ToolNodeAgent / ... │
├──────────────────────────────────────────────┤
│ 第二层: 智能体 (Agent) │
│ 封装了 LLM + 工具 + 系统提示词的 agent │
│ → AgentFactory.get_agent(agent_type, config) │
├──────────────────────────────────────────────┤
│ 第一层: LLM 模型 (Model) │
│ 底层大语言模型配置 (api_key, model, base_url) │
│ → config.py Settings / 模型配置面板 │
└──────────────────────────────────────────────┘
用户操作流程:新建 Agent(选定模型+提示词+工具)→ 拖入流编辑器作为节点 → 连线组装工作流 → 发布到企微
三、实施方案
P0 — 核心打通(必须完成)
P0-1: 节点 Handle 重构 — 按节点类型动态分配输入/输出端口
文件: FlowNode.vue
现状: 所有节点固定 Top=target, Bottom=source,条件节点无法双出口。
目标:
trigger: Top(target) ←可有可无 | Bottom(source)
llm: Left(target) | Right(source)
tool: Left(target) | Right(source)
mcp: Left(target) | Right(source)
wecom_notify: Left(target) | 无出口(终节点) OR Bottom(source)
condition: Left(target) | Right(source=true) + Bottom(source=false)
rag: Left(target) | Right(source)
output: Left(target) | 无出口
实施方案:
- 为条件节点增加两个
Handle:Position.Right(id="true") 和Position.Bottom(id="false") - 为终节点(output/wecom_notify)移除 source Handle
- FlowEditor.vue 中
onConnect记录sourceHandle,条件节点时记录含true/false分支信息 - 保存时 edges 格式增加
condition字段:{source, target, condition: "true"|"false"}
P0-2: LLM节点集成 AgentFactory — 使用真实 Agent 配置
文件: engine.py#L101-L160
现状: LLMNodeAgent.reply() 每次新建模型,忽略节点 config。
实施方案:
class LLMNodeAgent(AgentBase):
async def reply(self, msg: Msg, **kwargs) -> Msg:
# 从节点 config 读取参数,而非硬编码
system_prompt = self.config.get("system_prompt", "")
model_name = self.config.get("model", settings.LLM_MODEL)
temperature = float(self.config.get("temperature", 0.7))
agent_id = self.config.get("agent_id", "") # 可选:关联已有 Agent
# 优先使用 AgentFactory 获取或创建 agent
if agent_id:
agent = await Agents.get_or_create(agent_id, model_name, system_prompt)
else:
agent = await self._create_agent(model_name, system_prompt, temperature)
result = await agent(msg)
return self._to_msg(result)
P0-3: 条件分支引擎 — 支持 true/false 两条路径
文件: engine.py#L277-L340 + engine.py#L45-L75
现状: 拓扑排序线性执行,无法跳过分支。
实施方案:
将 FlowEngine.execute() 从纯拓扑排序改为 DAG 条件遍历:
async def execute(self, input_msg, context):
nodes = self.definition["nodes"]
edges = self.definition["edges"]
# 构建邻接表: node_id -> [(target_id, condition)]
graph = self._build_graph(nodes, edges)
# 找到起始节点(入度为0的节点)
start_nodes = self._find_start_nodes(graph)
# BFS/DFS 带条件遍历
result = await self._traverse(start_nodes[0], input_msg, context, graph)
return result
async def _traverse(self, node_id, msg, context, graph):
agent = self._get_agent(node_id)
result = await agent.reply(msg)
context["_node_results"][node_id] = str(result)
# 如果是条件节点,根据判断结果选择分支
next_nodes = graph.get(node_id, [])
for target_id, cond in next_nodes:
if cond is None or cond == "true":
await self._traverse(target_id, result, context, graph)
return result
关键: 条件节点执行后解析 condition:true|xxx 或 condition:false|xxx,只沿对应分支继续。
P0-4: 连线位置修复 — 使用 vue-flow 原生 Handle 机制
文件: FlowEditor.vue
现状: elements 用的是普通数组,节点自定义组件通过 id 查找,vue-flow 无法正确渲染 SVG 连线。
实施方案:
- 使用
useVueFlow的addNodes/addEdgesAPI 代替手动elements.value.push - 注册
@connect事件,让 vue-flow 原生处理连线渲染 - 删除 FlowEdge.vue 自定义 edge(vue-flow 内置 bezier 曲线更精准)
- 条件节点的两条边使用不同颜色:true=绿, false=红
const { addNodes, addEdges, onConnect: onVueConnect } = useVueFlow()
function onConnect(connection: Edge) {
const newEdge = {
...connection,
id: `edge_${connection.source}_${connection.target}`,
type: connection.sourceHandle === 'false' ? 'smoothstep-red' : 'default',
animated: true,
style: connection.sourceHandle === 'false'
? { stroke: '#F56C6C' }
: { stroke: '#409EFF' },
}
addEdges([newEdge])
}
P1 — 节点配置增强(提升灵活性)
P1-1: LLM节点 — 支持选择已有 Agent
文件: FlowEditor.vue LLM 配置区域
- 新增
agent_id下拉框:从后端GET /api/agents加载已有智能体列表 - 选择 Agent 后自动填入
system_prompt、model、temperature - 不选 Agent 则手动填写(当前行为保留)
P1-2: 触发节点 — 企微 Webhook URL 配置
文件: FlowEditor.vue trigger 配置区域
- 触发节点增加
wecom_webhook_url和event_type字段 event_type支持:text_message/button_click/enter_chat- 发布流时自动注册企微回调(如果配置了 webhook)
P1-3: 节点配置持久化增强 — 支持 JSON Schema
后端 schema 变更: schemas/init.py
FlowNode.config 目前是 dict = {},改为结构化的各类型:
class LLMNodeConfig(BaseModel):
system_prompt: str = ""
model: str = "gpt-4o-mini"
temperature: float = 0.7
agent_id: str = ""
class ToolNodeConfig(BaseModel):
tool_name: str = ""
class ConditionNodeConfig(BaseModel):
condition: str = ""
class WeComNotifyNodeConfig(BaseModel):
message_template: str = ""
target: str = "@all"
class FlowNode(BaseModel):
id: str | None = None
type: str # trigger/llm/tool/mcp/wecom_notify/condition/rag/output
label: str
config: LLMNodeConfig | ToolNodeConfig | ... = {}
P1-4: 新增 Agent 管理 API(后端)
新文件: backend/modules/agent/router.py
提供 GET/POST/PUT/DELETE /api/agents,管理可复用的 Agent:
# Agent 模型
class Agent(Base):
__tablename__ = "agents"
name, system_prompt, model, temperature, tools: list[str], status
这样 FlowEditor 的 LLM 节点可以通过 API 获取已有 Agent 列表。
P2 — 体验完善
P2-1: 撤销/重做 (Ctrl+Z / Ctrl+Y)
使用 vue-flow 内置的 useUndoRedo composable。
P2-2: 节点缩略图 MiniMap 增强
当前 MiniMap 已导入但不可用,改为真正的 Pane 节点缩略图。
P2-3: 流模板市场
预置 3-5 个常用工作流模板(文档处理流、企微通知流、数据分析流)。
四、文件变更清单
| 文件 | 变更类型 | 说明 |
|---|---|---|
frontend/src/views/flow/FlowNode.vue |
重写 | 按节点类型动态 Handle |
frontend/src/views/flow/FlowEdge.vue |
删除 | 用 vue-flow 内置 edge |
frontend/src/views/flow/FlowEditor.vue |
重大重构 | useVueFlow API、Agent选择、条件边 |
backend/modules/flow_engine/engine.py |
重大重构 | AgentFactory集成、条件DAG遍历 |
backend/modules/flow_engine/router.py |
修改 | 新增agent列表查询端点 |
backend/modules/agent/router.py |
新建 | Agent CRUD API |
backend/models/__init__.py |
修改 | 新增Agent模型 |
backend/schemas/__init__.py |
修改 | 新增Agent schema + FlowNode结构化config |
frontend/src/api/index.ts |
修改 | 新增agentApi |
frontend/src/router/index.ts |
修改 | 新增agent管理路由 |
五、实施顺序
Phase 1 (P0-1, P0-4) → Handle重构 + 连线修复 [前端为主]
Phase 2 (P0-3) → 条件分支引擎 [后端为主]
Phase 3 (P0-2, P1-1) → LLM节点集成AgentFactory [前后端联动]
Phase 4 (P1-2 ~ P1-4) → 节点配置增强 + Agent管理API [前后端联动]
Phase 5 (P2-1 ~ P2-3) → 体验完善 [前端为主]