Skip to content

add canvas mode for deploy#919

Merged
helloyongyang merged 55 commits intoModelTC:mainfrom
xinyiqin:merge_website
Mar 5, 2026
Merged

add canvas mode for deploy#919
helloyongyang merged 55 commits intoModelTC:mainfrom
xinyiqin:merge_website

Conversation

@huochaitiantang
Copy link
Collaborator

服务化部署增加画布操作模式

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

此拉取请求为部署服务引入了全新的“画布模式”,旨在通过一个直观的拖放式界面,使用户能够轻松构建和执行复杂的 AI 工作流。它不仅增加了完整的 React/TypeScript 前端应用,还对后端进行了大量修改,以支持工作流的生命周期管理、数据存储和与多种 AI 模型的集成。

Highlights

  • 新增画布模式前端应用: 引入了一个全新的 React/TypeScript 前端应用,提供可视化、节点式的 AI 工作流编辑器。
  • 全面的工作流管理 API: 新增了一系列后端 API 端点,支持工作流的创建、列表查询、详情获取、更新、复制、删除,以及节点输出历史和聊天历史的管理。
  • 动态 AI 模型集成: 系统现在可以根据环境变量和 API 密钥动态加载和筛选可用的 AI 模型(包括 LightX2V、DeepSeek、Doubao、Gemini),实现了灵活的工具使用。
  • 增强的数据处理能力: 新增了处理工作流相关文件(本地和 S3)的工具,包括保存各种数据类型(字节、Base64、文本)以及清理孤立文件/任务的逻辑。
  • 交互式节点编辑: 节点配置面板现在支持节点名称编辑、模型选择、宽高比控制、TTS 设置和音色克隆配置等功能。
  • 高级输出管理: 连接的节点输出可以进行预览和手动编辑,修改后的内容会保存回上游节点。
  • AI 助手集成: 新增了一个 AI 聊天面板,通过自然语言协助用户构建和修改工作流。
  • 预设工作流库: 包含了多个预设工作流,展示了多机位唱歌视频、电影级一镜到底视频和数字人创建等多种 AI 能力。

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • dockerfiles/Dockerfile_deploy
    • 为新的 canvas_frontend 应用添加了构建步骤。
    • 更新了 Python 依赖,安装了 pyannote.audio==4.0.4pydub
  • lightx2v/deploy/common/utils.py
    • 扩展了 preload_data 函数以处理 workflow_output 类型。
    • 改进了 preload_data 中错误消息的格式,以处理非字符串值。
  • lightx2v/deploy/common/workflow_utils.py
    • 新增了一个 Python 模块,用于全面的工作流数据管理,包括 MIME 类型常量、文件/任务条目处理和输出处理。
  • lightx2v/deploy/data_manager/local_data_manager.py
    • 初始化了一个专门用于工作流文件的本地目录。
  • lightx2v/deploy/data_manager/s3_data_manager.py
    • 为 S3 存储的工作流文件定义了基础路径。
  • lightx2v/deploy/server/main.py
    • 导入了 aiohttpworkflow_utils 等新模块。
    • 配置了额外的 MIME 类型以支持静态文件服务。
    • 实现了 Volc Engine LLM 响应的代理端点。
    • 修改了 api_v1_task_submit 以集成工作流输出的转换处理。
    • 引入了一系列新的 API 端点,用于完整的工作流生命周期管理(创建、列表、获取、更新、复制、删除、历史记录、URL 生成、保存输出、聊天)。
    • 更新了 vue_fallback 路由,以正确处理画布前端的静态资源。
  • lightx2v/deploy/server/canvas_frontend/.gitignore
    • 为画布前端添加了新的 .gitignore 文件,排除了构建产物和 Node 模块。
  • lightx2v/deploy/server/canvas_frontend/App.tsx
    • 添加了 OmniFlow AI Canvas 的主 React 应用组件,协调所有 UI、状态和逻辑。
  • lightx2v/deploy/server/canvas_frontend/App.tsx.bak
    • 添加了 App.tsx 的备份文件,可能是旧版本或临时保存。
  • lightx2v/deploy/server/canvas_frontend/RAILWAY_DEPLOY.md
    • 添加了 Railway 部署指南。
  • lightx2v/deploy/server/canvas_frontend/README.md
    • 添加了 Omni-AI-Canvas 项目的综合 README,详细介绍了功能、快速入门、部署、支持的工具和预设工作流。
  • lightx2v/deploy/server/canvas_frontend/constants.tsx
    • 添加了工具定义常量和基于 API 响应的动态模型更新逻辑。
  • lightx2v/deploy/server/canvas_frontend/index.html
    • 添加了画布前端的主 HTML 入口文件。
  • lightx2v/deploy/server/canvas_frontend/index.tsx
    • 添加了 React 应用的主 TypeScript 入口文件,包括 Qiankun 生命周期钩子和独立运行逻辑。
  • lightx2v/deploy/server/canvas_frontend/metadata.json
    • 添加了画布应用的元数据,包括名称、描述和请求的帧权限。
  • lightx2v/deploy/server/canvas_frontend/nixpacks.toml
    • 添加了用于构建和部署画布前端的 Nixpacks 配置。
  • lightx2v/deploy/server/canvas_frontend/package.json
    • 添加了画布前端的包依赖和脚本。
  • lightx2v/deploy/server/canvas_frontend/preset_workflow.tsx
    • 添加了预设工作流的重新导出文件。
  • lightx2v/deploy/server/canvas_frontend/preset_workflows/9shotHealingVideo.ts
    • 添加了一个 9 分镜治愈动画的预设工作流。
  • lightx2v/deploy/server/canvas_frontend/preset_workflows/AiAnimation12.ts
    • 添加了一个 12 分镜 AI 动画的预设工作流。
  • lightx2v/deploy/server/canvas_frontend/preset_workflows/AvatarI2i.ts
    • 添加了一个使用图像到图像生成数字人视频的预设工作流。
  • lightx2v/deploy/server/canvas_frontend/preset_workflows/CinematicOner.ts
    • 添加了一个电影级一镜到底视频生成的预设工作流。
  • lightx2v/deploy/server/canvas_frontend/preset_workflows/EcommerceProductVideo.ts
    • 添加了一个电商多视角产品精修视频的预设工作流。
  • lightx2v/deploy/server/canvas_frontend/preset_workflows/KnowledgeIp.ts
    • 添加了一个知识 IP 口播工作流的预设。
  • lightx2v/deploy/server/canvas_frontend/preset_workflows/Morph.ts
    • 添加了一个文生首尾帧视频工作流的预设。
  • lightx2v/deploy/server/canvas_frontend/preset_workflows/MultiShotSinging.ts
    • 添加了一个多机位唱歌数字人视频的预设工作流。
  • lightx2v/deploy/server/canvas_frontend/preset_workflows/ProductWearing.ts
    • 添加了一个虚拟人结合电商产品工作流的预设。
  • lightx2v/deploy/server/canvas_frontend/preset_workflows/README.md
    • 添加了预设工作流目录的 README 文件。
  • lightx2v/deploy/server/canvas_frontend/preset_workflows/S2v.ts
    • 添加了一个文生数字人视频工作流的预设。
  • lightx2v/deploy/server/canvas_frontend/preset_workflows/Storyboard9.ts
    • 添加了一个 9 分镜故事板视频的预设工作流。
  • lightx2v/deploy/server/canvas_frontend/railway.json
    • 添加了 Railway 部署配置。
  • lightx2v/deploy/server/canvas_frontend/server.js
    • 添加了一个用于服务静态文件和代理的简单 Express 服务器。
  • lightx2v/deploy/server/canvas_frontend/services/geminiService.ts
    • 添加了 Gemini、DeepSeek、Doubao 和 LightX2V API 的服务集成,包括任务提交、状态轮询和语音列表检索。
  • lightx2v/deploy/server/canvas_frontend/services/watermarkRemover.ts
    • 添加了一个用于移除 Gemini 生成图像水印的工具。
  • lightx2v/deploy/server/canvas_frontend/src/components/canvas/Canvas.tsx
    • 添加了 Canvas 组件,用于渲染节点和连接,并处理交互。
  • lightx2v/deploy/server/canvas_frontend/src/components/canvas/Connection.tsx
    • 添加了 Connection 组件,用于绘制工作流连接。
  • lightx2v/deploy/server/canvas_frontend/src/components/common/Header.tsx
    • 添加了 Dashboard 的 Header 组件,包括语言切换和工作流创建按钮。
  • lightx2v/deploy/server/canvas_frontend/src/components/common/UserCard.tsx
    • 添加了 UserCard 组件,用于显示用户信息和登录/登出操作。
  • lightx2v/deploy/server/canvas_frontend/src/components/dashboard/Dashboard.tsx
    • 添加了 Dashboard 组件,用于显示和管理工作流。
  • lightx2v/deploy/server/canvas_frontend/src/components/dashboard/WorkflowCard.tsx
    • 添加了 WorkflowCard 组件,用于显示单个工作流的预览和操作。
  • lightx2v/deploy/server/canvas_frontend/src/components/editor/AIChatPanel.tsx
    • 添加了 AIChatPanel 组件,用于嵌入式 AI 助手聊天界面。
  • lightx2v/deploy/server/canvas_frontend/src/components/editor/ChatInput.tsx
    • 添加了 ChatInput 组件,用于 AI 聊天面板的输入。
  • lightx2v/deploy/server/canvas_frontend/src/components/editor/ChatMessage.tsx
    • 添加了 ChatMessage 组件,用于在 AI 聊天中显示单个消息。
  • lightx2v/deploy/server/canvas_frontend/src/components/editor/DraggableAIChatPanel.tsx
    • 添加了 DraggableAIChatPanel 组件,用于浮动、可调整大小的 AI 助手聊天窗口。
  • lightx2v/deploy/server/canvas_frontend/src/components/editor/Editor.tsx
    • 添加了主 Editor 组件,集成了画布、工具面板、配置面板和结果面板。
  • lightx2v/deploy/server/canvas_frontend/src/components/editor/EditorHeader.tsx
    • 添加了工作流编辑器的 EditorHeader 组件,包括缩放、撤销/重做、保存、运行和可见性控制。
  • lightx2v/deploy/server/canvas_frontend/src/components/editor/NodeConfigPanel.tsx
    • 添加了 NodeConfigPanel 组件,用于配置单个节点和全局输入。
  • lightx2v/deploy/server/canvas_frontend/src/components/editor/ResizableDivider.tsx
    • 添加了一个 ResizableDivider 组件,用于调整面板大小。
  • lightx2v/deploy/server/canvas_frontend/src/components/editor/ResultsPanel.tsx
    • 添加了 ResultsPanel 组件,用于显示执行结果和历史记录。
  • lightx2v/deploy/server/canvas_frontend/src/components/modals/AudioEditorModal.tsx
    • 添加了一个用于编辑音频输入的模态框。
  • lightx2v/deploy/server/canvas_frontend/src/components/modals/CloneVoiceModal.tsx
    • 添加了一个用于克隆语音的模态框。
  • lightx2v/deploy/server/canvas_frontend/src/components/modals/ErrorModal.tsx
    • 添加了一个用于显示通用错误的模态框。
  • lightx2v/deploy/server/canvas_frontend/src/components/modals/ExpandedOutputModal.tsx
    • 添加了一个用于显示扩展节点输出的模态框。
  • lightx2v/deploy/server/canvas_frontend/src/components/modals/ValidationModal.tsx
    • 添加了一个用于显示工作流验证错误的模态框。
  • lightx2v/deploy/server/canvas_frontend/src/components/modals/VideoEditorModal.tsx
    • 添加了一个用于编辑视频输入的模态框。
  • lightx2v/deploy/server/canvas_frontend/src/components/previews/AudioNodePreview.tsx
    • 添加了一个音频节点预览组件,包括波形显示和裁剪功能。
  • lightx2v/deploy/server/canvas_frontend/src/components/previews/ImageNodePreview.tsx
    • 添加了一个图像节点预览组件,包括裁剪功能。
  • lightx2v/deploy/server/canvas_frontend/src/components/previews/TextNodePreview.tsx
    • 添加了一个文本节点预览组件。
  • lightx2v/deploy/server/canvas_frontend/src/components/previews/VideoNodePreview.tsx
    • 添加了一个视频节点预览组件,包括裁剪功能。
  • lightx2v/deploy/server/canvas_frontend/src/config/runtimeMode.ts
    • 添加了一个实用工具,用于判断应用是否在独立模式下运行。
  • lightx2v/deploy/server/canvas_frontend/src/hooks/useAIGenerateWorkflow.ts
    • 添加了一个用于 AI 驱动工作流生成的 Hook。
  • lightx2v/deploy/server/canvas_frontend/src/hooks/useCanvas.ts
    • 添加了一个用于管理画布交互(如平移、缩放和节点拖动)的 Hook。
  • lightx2v/deploy/server/canvas_frontend/src/hooks/useConnectionManagement.ts
    • 添加了一个用于管理工作流连接的 Hook。
  • lightx2v/deploy/server/canvas_frontend/src/hooks/useModalState.ts
    • 添加了一个用于管理各种模态框和面板状态的 Hook。
  • lightx2v/deploy/server/canvas_frontend/src/hooks/useNodeManagement.ts
    • 添加了一个用于管理工作流节点(包括添加、删除、更新和替换节点)的 Hook。
  • lightx2v/deploy/server/canvas_frontend/src/hooks/useResultManagement.ts
    • 添加了一个用于管理和显示工作流执行结果的 Hook。
  • lightx2v/deploy/server/canvas_frontend/src/hooks/useShowIntermediateResults.ts
    • 添加了一个用于持久化显示中间结果状态的 Hook。
  • lightx2v/deploy/server/canvas_frontend/src/hooks/useUndoRedo.ts
    • 添加了一个用于工作流编辑器中撤销/重做功能的 Hook。
  • lightx2v/deploy/server/canvas_frontend/src/hooks/useVoiceList.ts
    • 添加了一个用于管理 TTS 和克隆语音列表的 Hook。
Activity
  • 用户 huochaitiantang 创建了此拉取请求,旨在为服务化部署增加画布操作模式。
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

这个 PR 为服务化部署引入了一个新的画布(canvas)模式,包含了全新的前端应用和为工作流提供支持的大量后端 API。这些改动体量很大,但大部分结构良好。后端为工作流管理添加了许多新 API,前端则是一个功能完整的 React 应用。我的审查主要关注于提升代码的正确性、可维护性和健壮性。我提供了一些关于潜在 bug、类型提示不匹配以及重构机会的具体建议。另外,新的前端主组件 App.tsx 文件非常庞大,如果能将其拆分为更小的组件,将有助于提高可维护性。

Note: Security Review did not run due to the size of the PR.

body = await request.json()
except Exception as e:
raise HTTPException(status_code=400, detail=f"Invalid JSON body: {e}")
api_key = os.environ.get("VOLCENGINE_LLM_API_KEY").strip()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

如果环境变量 VOLCENGINE_LLM_API_KEY 未设置,os.environ.get(...) 会返回 None,此时调用 .strip() 会引发 AttributeError。在调用 .strip() 之前,应该检查该环境变量是否存在,以避免程序崩溃。

Suggested change
api_key = os.environ.get("VOLCENGINE_LLM_API_KEY").strip()
api_key = (os.environ.get("VOLCENGINE_LLM_API_KEY") or "").strip()

Comment on lines +1891 to +1892
page = int(request.query_params.get("page", 1))
page_size = int(request.query_params.get("page_size", 10))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

如果查询参数 pagepage_size 的值不是有效的整数(例如 "abc"),int() 转换会引发 ValueError,导致未处理的异常和 500 错误。建议将这些转换放在 try-except 块中,以优雅地处理无效输入。

Suggested change
page = int(request.query_params.get("page", 1))
page_size = int(request.query_params.get("page_size", 10))
try:
page = int(request.query_params.get("page", 1))
page_size = int(request.query_params.get("page_size", 10))
except ValueError:
return error_response("Invalid 'page' or 'page_size' parameter. Must be an integer.", 400)

task_id = request.query_params.get("task_id", "")
try:
entries = await query_output_entries(user["user_id"], workflow_id, node_id, port_id, file_id, task_id, task_manager)
assert len(entries) == 1, f"should be one entry, but got {len(entries)}, {entries}"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

assert 语句在 Python 以 -O(优化)标志运行时会被移除,而这在生产环境中很常见。如果这个检查对于保证代码正确性很重要,最好使用显式的 if 判断并抛出适当的异常,例如 ValueError

Suggested change
assert len(entries) == 1, f"should be one entry, but got {len(entries)}, {entries}"
if len(entries) != 1:
raise ValueError(f"should be one entry, but got {len(entries)}, {entries}")

Comment on lines +30 to +31
RUN pip uninstall pyannote.audio -y \
&& pip install pyannote.audio==4.0.4 pydub
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

为了更好地利用Docker的层缓存机制,建议将pip install命令分为两步:首先安装pyannote.audio,然后再安装pydub。这样,如果只有pydub发生变化,pyannote.audio的安装层仍然可以被缓存。

RUN pip uninstall pyannote.audio -y \
    && pip install pyannote.audio==4.0.4
RUN pip install pydub

port_id: str,
files_tasks: dict,
data_manager: BaseDataManager,
) -> list[dict]:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

此处的返回类型提示为 list[dict],但函数 save_task_entrysave_b64_entry 等实际上返回的是单个 dict。为了保持类型提示的准确性,应将其更正为 -> dict

Suggested change
) -> list[dict]:
) -> dict:

entry: dict,
task_manager: BaseTaskManager,
data_manager: BaseDataManager,
) -> bytes | None:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

函数 load_bytes_from_entry 的返回类型提示为 bytes | None,但函数实际返回的是一个元组 (data, filename, mime_type)。返回类型提示应更新以匹配实际的返回值,例如 -> tuple[bytes, str, str] | None

Suggested change
) -> bytes | None:
) -> tuple[bytes, str, str] | None:

}
proxy = os.environ.get("HTTPS_PROXY") or None

session = aiohttp.ClientSession()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

建议使用 async with aiohttp.ClientSession() as session: 的方式来管理 ClientSession,以确保即使发生异常,会话也能被正确关闭。虽然您在 finally 块中手动关闭了会话,但使用 async with 语句是更简洁、更不容易出错的做法。

Comment on lines +1877 to +1879
except Exception:
traceback.print_exc()
return error_response("Failed to create workflow", 500)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

在生产环境中使用 traceback.print_exc() 会将堆栈跟踪打印到标准错误流,这不利于日志管理。建议改用 logger.exception(),它能更好地与日志系统集成,并提供更丰富的上下文信息。此建议适用于该文件中所有类似的 except Exception 块。

Suggested change
except Exception:
traceback.print_exc()
return error_response("Failed to create workflow", 500)
except Exception as e:
logger.exception(f"Failed to create workflow: {e}")
return error_response("Failed to create workflow", 500)


// --- Main App ---

const App: React.FC = () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

App 组件非常庞大(超过1700行),包含了大量的逻辑、状态管理和副作用。这使得代码难以阅读、维护和测试。建议进行重构,将逻辑提取到更多的自定义 Hook 中,并将 UI 拆分为更小、更专注的组件。例如,仪表板视图和编辑器视图的逻辑可以分别放在独立的组件中。

@helloyongyang helloyongyang merged commit 03e5d2c into ModelTC:main Mar 5, 2026
1 check passed
helloyongyang pushed a commit that referenced this pull request Mar 6, 2026
服务化部署增加画布操作模式

---------

Co-authored-by: qinxinyi <qxy118045534@163.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants