# PLAN4 — 流编辑器深度重构:LLM→智能体→流节点→工作流 四层架构 ## 一、问题诊断 ### 当前架构痛点(逐一定位代码行级别) | # | 问题 | 根因位置 | 影响 | |---|------|----------|------| | 1 | **LLM/智能体与节点未打通** | [engine.py#L101-L118](file:///c:/Users/刘泽明/Documents/Git/hg-agents/backend/modules/flow_engine/engine.py#L101-L118) `LLMNodeAgent` 每次硬编码新建 `OpenAIChatModel`,忽略节点配置中 `model`/`temperature`/`system_prompt` | 节点的LLM配置表单完全无效 | | 2 | **节点只有壳,无法配置** | [FlowNode.vue](file:///c:/Users/刘泽明/Documents/Git/hg-agents/frontend/src/views/flow/FlowNode.vue) 固定 Top/Bottom Handle,条件节点只有一个出口 | 条件分支无法区分 true/false | | 3 | **连线位置漂移** | [FlowEdge.vue](file:///c:/Users/刘泽明/Documents/Git/hg-agents/frontend/src/views/flow/FlowEdge.vue) 自定义 SVG path + 没有绑定 vue-flow edge marker | 线条起点/终点不精准 | | 4 | **条件分支不可控** | [engine.py#L277-L293](file:///c:/Users/刘泽明/Documents/Git/hg-agents/backend/modules/flow_engine/engine.py#L277-L293) `ConditionNodeAgent` 只返回固定字符串 + 拓扑排序不支持跳过 | 即使 LLM 判断了真假,引擎也不会分支 | | 5 | **触发节点无实际参数** | FlowEditor 触发节点只有标签,无企微回调 URL / webhook 配置 | 无法真正接入企微触发 | | 6 | **AgentFactory 未集成** | [engine.py](file:///c:/Users/刘泽明/Documents/Git/hg-agents/backend/modules/flow_engine/engine.py) 从未调用 [factory.py](file:///c:/Users/刘泽明/Documents/Git/hg-agents/backend/agentscope_integration/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](file:///c:/Users/刘泽明/Documents/Git/hg-agents/frontend/src/views/flow/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) | 无出口 ``` **实施方案**: 1. 为条件节点增加两个 `Handle`:`Position.Right` (id="true") 和 `Position.Bottom` (id="false") 2. 为终节点(output/wecom_notify)移除 source Handle 3. FlowEditor.vue 中 `onConnect` 记录 `sourceHandle`,条件节点时记录含 `true`/`false` 分支信息 4. 保存时 edges 格式增加 `condition` 字段:`{source, target, condition: "true"|"false"}` #### P0-2: LLM节点集成 AgentFactory — 使用真实 Agent 配置 **文件**: [engine.py#L101-L160](file:///c:/Users/刘泽明/Documents/Git/hg-agents/backend/modules/flow_engine/engine.py#L101-L160) **现状**: `LLMNodeAgent.reply()` 每次新建模型,忽略节点 `config`。 **实施方案**: ```python 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](file:///c:/Users/刘泽明/Documents/Git/hg-agents/backend/modules/flow_engine/engine.py#L277-L340) + [engine.py#L45-L75](file:///c:/Users/刘泽明/Documents/Git/hg-agents/backend/modules/flow_engine/engine.py#L45-L75) **现状**: 拓扑排序线性执行,无法跳过分支。 **实施方案**: 将 `FlowEngine.execute()` 从纯拓扑排序改为 **DAG 条件遍历**: ```python 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](file:///c:/Users/刘泽明/Documents/Git/hg-agents/frontend/src/views/flow/FlowEditor.vue#L247-L268) **现状**: `elements` 用的是普通数组,节点自定义组件通过 `id` 查找,vue-flow 无法正确渲染 SVG 连线。 **实施方案**: 1. 使用 `useVueFlow` 的 `addNodes`/`addEdges` API 代替手动 `elements.value.push` 2. 注册 `@connect` 事件,让 vue-flow 原生处理连线渲染 3. 删除 [FlowEdge.vue](file:///c:/Users/刘泽明/Documents/Git/hg-agents/frontend/src/views/flow/FlowEdge.vue) 自定义 edge(vue-flow 内置 bezier 曲线更精准) 4. 条件节点的两条边使用不同颜色:true=绿, false=红 ```typescript 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](file:///c:/Users/刘泽明/Documents/Git/hg-agents/backend/schemas/__init__.py#L179-L181) `FlowNode.config` 目前是 `dict = {}`,改为结构化的各类型: ```python 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: ```python # 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) → 体验完善 [前端为主] ```