You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

12 KiB

PLAN6 — 对标 Dify 无代码发布架构:差距分析与升级路线

一、核心结论

我们的流发布逻辑与 Dify 的底层思路高度一致(配置即数据 + 动态引擎),但在 7 个关键维度存在显著差距,需要补齐才能真正实现"无代码秒级发布,即刻可用"。

已对齐的架构思路

Dify 核心思路 我们的实现 对齐度
配置即数据:前端生成 JSON,存入数据库 FlowEditor 生成 nodes+edges JSON,存入 FlowDefinition.definition_json 完全对齐
零部署:发布 = 数据库状态变更,不启动新服务 publish 仅修改 status 字段,执行时动态加载 JSON 完全对齐
动态编排引擎:解析 JSON → 执行 FlowEngine 解析 JSON → 构建图 → traverse 执行 基本对齐
DAG 拓扑排序执行 _build_graph() + traverse() 支持条件分支和循环 基本对齐
多种节点类型 9 种节点:trigger/llm/tool/mcp/condition/rag/output/loop/code 基本对齐
双渠道发布 企微 + Web 双渠道发布状态管理 额外优势

存在差距的关键维度

# 维度 差距等级 影响
1 版本快照 / 发布不可变 🔴 严重 发布后编辑直接影响线上服务
2 流式输出 (SSE) 🔴 严重 长流程用户体验极差,无法实时看到结果
3 统一 API 网关 + App API Key 🟠 无法被外部系统调用,无法做 API 市场
4 工具 Schema 标准化 🟠 无法运行时扩展工具,无参数校验
5 Flow 节点 Memory 🟠 LLM 节点无上下文记忆,无法多轮对话
6 变量类型系统 🟡 复杂业务逻辑难以表达
7 执行监控与可观测性 🟡 无法追溯执行版本,缺少 token/延迟指标

二、逐维度详细对比

1. 版本快照 / 发布不可变(🔴 严重)

Dify 的做法:

  • 点击"发布"时,将当前草稿 JSON 创建一份版本快照(snapshot),存入独立的 workflow_versions
  • FlowDefinitionpublished_version 字段,指向当前生效的版本
  • 执行引擎加载的是 published_version 对应的 JSON,而非草稿
  • 编辑草稿不影响已发布版本,回滚只需切换 published_version 指针

我们的现状:

  • FlowDefinition 只有 version 计数器(int),没有 published_version 字段
  • 发布仅修改 status="published",不创建快照
  • 编辑草稿直接修改 definition_json,已发布的服务立即受影响
  • FlowExecution 不记录执行时的版本号,无法追溯

需要补齐:

新增模型:FlowVersion
  - id: UUID
  - flow_id: FK → FlowDefinition
  - version: int
  - definition_json: JSON(快照)
  - created_by: UUID
  - created_at: datetime

修改模型:FlowDefinition
  - 新增 published_version_id: FK → FlowVersion(nullable)
  - 新增 draft_version: int(草稿版本号)

发布逻辑改造:
  - publish → 创建 FlowVersion 快照 → 设置 published_version_id
  - execute → 加载 published_version.definition_json(而非草稿)
  - 编辑 → 只修改草稿,不影响 published_version
  - 回滚 → 切换 published_version_id 指针

2. 流式输出 SSE(🔴 严重)

Dify 的做法:

  • 统一 API 支持 response_mode: "streaming",返回 SSE 事件流
  • 事件类型:workflow_startednode_startednode_finishedworkflow_finished
  • LLM 节点支持 token-by-token 实时推送(text_chunk 事件)
  • 前端通过 EventSource 实时渲染

我们的现状:

  • FlowEngine.execute() 返回最终 Msg,无中间状态
  • LLMNodeAgent 虽然配置了 stream=True,但 model(prompt) 等待完整响应
  • WebSocket 端点仅 echo,未与 Flow 引擎集成
  • 没有 SSE 端点

需要补齐:

新增 SSE 端点:GET /api/chat/stream/{flow_id}
  - 接收 query 参数:message, session_id
  - 返回 text/event-stream
  - 事件格式:
    event: node_started
    data: {"node_id": "xxx", "node_type": "llm", "label": "生成摘要"}

    event: text_chunk
    data: {"node_id": "xxx", "content": "根据"}

    event: node_finished
    data: {"node_id": "xxx", "output": "..."}

    event: workflow_finished
    data: {"output": "最终结果"}

FlowEngine 改造:
  - execute() 接受可选的 callback: Callable[[str, dict], None]
  - 每个节点执行前后调用 callback("node_started"/"node_finished", data)
  - LLMNodeAgent.reply() 改为 async generator,yield token

3. 统一 API 网关 + App API Key(🟠 高)

Dify 的做法:

  • 每个 App 有独立的 API Key(app-xxxxxxxx
  • 统一入口:POST /v1/chat-messages(对话型)、POST /v1/workflows/run(工作流型)
  • 请求格式标准化:{inputs: {}, query: "", response_mode: "blocking|streaming", user: "user-id"}
  • 无需用户登录,API Key 即认证

我们的现状:

  • 所有 API 依赖 JWT 用户认证,无 App-level API Key
  • 执行分散在 /api/flow/definitions/{id}/execute/api/chat/message/{id}
  • 无法被外部系统(如企微回调、第三方应用)直接调用

需要补齐:

新增模型:FlowApiKey
  - id: UUID
  - flow_id: FK → FlowDefinition
  - key_hash: str(sha256)
  - key_prefix: str(前8位,用于展示)
  - name: str
  - created_by: UUID
  - created_at: datetime
  - last_used_at: datetime(nullable)

新增统一网关端点:
  POST /v1/chat-messages    → 对话型 Flow(自动找 trigger → llm → output 路径)
  POST /v1/workflows/run    → 工作流型 Flow(完整 DAG 执行)

认证方式:
  Header: Authorization: Bearer app-xxxxxxxx
  → 查 FlowApiKey 表 → 获取 flow_id → 加载 published_version → 执行

4. 工具 Schema 标准化(🟠 高)

Dify 的做法:

  • 所有工具(内置/自定义 API/MCP)统一转换为 OpenAI Function Calling 的 JSON Schema
  • Schema 包含:name, description, parameters(JSON Schema 格式,含 type/enum/description)
  • 注入 LLM 时,工具 Schema 作为 tools 参数传入
  • 用户可在前端自定义 API 工具(填 URL、Method、参数结构)

我们的现状:

  • ToolNodeAgent._TOOL_REGISTRY 硬编码 12 个工具函数
  • 工具函数只有 Python 签名,无结构化 Schema 描述
  • tool_params: dict = {} 无校验
  • 无法运行时扩展工具

需要补齐:

工具 Schema 标准化格式:
{
  "name": "send_notification",
  "description": "发送企业微信通知给指定用户",
  "parameters": {
    "type": "object",
    "properties": {
      "to_user": {"type": "string", "description": "接收人用户ID"},
      "message": {"type": "string", "description": "消息内容"}
    },
    "required": ["to_user", "message"]
  }
}

改造 ToolNodeAgent:
  - _TOOL_REGISTRY 改为 _TOOL_SCHEMA_REGISTRY: dict[str, dict]
  - 每个工具注册时同时注册 Schema
  - 调用前基于 Schema 校验 tool_params
  - LLM 调用时将 Schema 作为 tools 参数传入

新增自定义 API 工具:
  - 用户可填入 OpenAPI/Swagger URL
  - 系统自动解析为标准 Schema 并注册
  - 执行时通过 httpx 调用

5. Flow 节点 Memory(🟠 高)

Dify 的做法:

  • 每个 App 有独立的对话记忆(窗口记忆/摘要记忆)
  • 记忆在多次调用间持久化(Redis/数据库)
  • LLM 节点自动注入历史对话上下文

我们的现状:

  • UserIsolatedMemory 存在但未在 Flow 节点中使用
  • Flow 中的 LLM 节点每次调用都是无状态的
  • ChatMessage 表存储了历史消息,但 Flow 执行时不读取

需要补齐:

FlowEngine 改造:
  - execute() 接受 session_id 参数
  - 创建 FlowSessionMemory(session_id, user_id)
  - LLM 节点执行前注入历史消息

新增 FlowSessionMemory:
  - 基于 ChatMessage 表持久化
  - 按session_id + user_id 隔离
  - 支持窗口大小配置(最近 N 条)
  - 支持摘要模式(超过窗口时调用 LLM 生成摘要)

6. 变量类型系统(🟡 中)

Dify 的做法:

  • 完整的变量面板:输入变量、环境变量、会话变量、上游节点变量
  • 变量类型:string/number/array/object/file
  • 支持 Jinja2 模板、类型转换、默认值
  • "变量聚合"节点:汇聚并行分支输出
  • "迭代"节点:对列表逐项处理

我们的现状:

  • 仅有 {{node_id.output}}{{trigger.field}} 模板
  • 所有值都是 str,无类型系统
  • 无并行汇聚、无迭代节点

需要补齐:

变量系统升级:
  - 节点输出增加类型标注(string/number/array/object)
  - 模板解析支持类型转换和默认值
  - 新增"变量聚合"节点(ParallelMergeNode)
  - Loop 节点支持迭代数组模式
  - 输入变量面板(Flow 级别的入参定义)

7. 执行监控与可观测性(🟡 中)

Dify 的做法:

  • FlowExecution 记录执行时的版本号
  • 统计 token 用量、延迟、费用
  • 执行日志可按 App/时间/状态筛选
  • 失败重试机制

我们的现状:

  • FlowExecution 不记录版本号
  • 无 token/延迟统计
  • 无失败重试

需要补齐:

FlowExecution 增加字段:
  - version: int(执行时的版本号)
  - token_usage: JSON(prompt_tokens, completion_tokens, total_tokens)
  - latency_ms: int
  - error_message: str(nullable)

执行引擎改造:
  - 记录每个节点的 token 用量和耗时
  - 汇总到 FlowExecution
  - 失败节点支持重试配置

三、升级路线图

Phase 1 — 发布安全基础(P0,1-2周)

任务 改动范围
新增 FlowVersion 模型 + 迁移 models, database
FlowDefinition 增加 published_version_id models, schemas
发布逻辑改造:创建快照 flow_engine/router.py
执行逻辑改造:加载 published_version flow_engine/engine.py, chat/router.py
FlowExecution 记录版本号 models, flow_engine/router.py

Phase 2 — 用户体验核心(P0,2-3周)

任务 改动范围
SSE 流式输出端点 chat/router.py(新增)
FlowEngine callback 机制 flow_engine/engine.py
LLMNodeAgent async generator 改造 flow_engine/engine.py
前端 EventSource 集成 FlowChat.vue(新增)
Flow 节点 Memory 集成 flow_engine/engine.py, 新增 FlowSessionMemory

Phase 3 — 服务化能力(P1,2-3周)

任务 改动范围
FlowApiKey 模型 + CRUD models, schemas, 新增 router
统一 API 网关 /v1/chat-messages, /v1/workflows/run 新增 gateway router
API Key 认证中间件 middleware
工具 Schema 标准化 tools/*.py, ToolNodeAgent
自定义 API 工具(OpenAPI 导入) 新增 custom_tool 模块

Phase 4 — 高级能力(P2,2-3周)

任务 改动范围
变量类型系统 schemas, engine.py
变量聚合节点 新增 ParallelMergeNodeAgent
Loop 迭代数组模式 LoopNodeAgent
执行监控指标 FlowExecution, engine.py
工具认证改造(去掉硬编码) tools/*.py

四、架构哲学对齐度总结

Dify 架构哲学 我们的现状 对齐度
数据驱动:复杂 AI 逻辑抽象为可配置参数 已实现。9 种节点类型,每种有独立 config 90%
统一 Runner:一套引擎解析千种 JSON 组合 ⚠️ 部分实现。引擎存在但缺少流式/Memory/版本快照 60%
插件化架构:Tool/Model 实现高度抽象接口 未实现。工具硬编码,无标准 Schema,无自动发现 20%

核心差距一句话总结:我们的"配置即数据"和"零部署"思路与 Dify 完全一致,但缺少"发布不可变"(版本快照)、"实时反馈"(SSE 流式)、"开放接入"(统一网关+API Key)和"插件化工具"(标准 Schema)四大关键能力,导致无法真正实现"无代码秒级发布,即刻可用"的完整体验。

补齐 Phase 1 + Phase 2 后,即可达到 Dify 约 80% 的核心能力。