Replies: 7 comments 9 replies
-
Beta Was this translation helpful? Give feedback.
-
初始化流程sequenceDiagram
participant App as 调用方<br/>(如ModelRuntime)
participant LobeComfyUI as LobeComfyUI<br/>(入口类)
participant ClientService as ClientService<br/>(客户端服务)
participant ModelResolver as ModelResolver<br/>(模型服务)
participant WorkflowBuilder as WorkflowBuilder<br/>(工作流服务)
participant ImageService as ImageService<br/>(图像服务)
participant ErrorHandler as ErrorHandler<br/>(错误处理)
%% 阶段1: LobeComfyUI构造函数入口
rect rgb(240, 248, 255)
note over App,LobeComfyUI: 阶段1: LobeComfyUI构造函数 (index.ts:31-58)
App->>LobeComfyUI: new LobeComfyUI(options: ComfyUIKeyVault)
%% 构造函数开始
LobeComfyUI->>LobeComfyUI: log('🏗️ ComfyUI Constructor called', {<br/> authType, baseURL<br/>}) (L32-35)
%% 配置处理
LobeComfyUI->>LobeComfyUI: this.options = options (L37)
LobeComfyUI->>LobeComfyUI: this.baseURL = options.baseURL ||<br/> process.env.COMFYUI_DEFAULT_URL ||<br/> COMFYUI_DEFAULTS.BASE_URL (L38)
end
%% 阶段2: ClientService初始化
rect rgb(255, 248, 240)
note over LobeComfyUI,ClientService: 阶段2: 初始化客户端服务 (index.ts:41)
LobeComfyUI->>ClientService: new ComfyUIClientService(options)
%% ClientService构造函数 (comfyuiClient.ts:55-77)
ClientService->>ErrorHandler: new ErrorHandlerService() (L56)
ErrorHandler-->>ClientService: errorHandler实例
ClientService->>ClientService: validateOptions(options) (L60)
ClientService->>ClientService: this.baseURL = options.baseURL || ... (L63)
ClientService->>ClientService: createCredentials(options) (L66)
ClientService->>ClientService: this.client = new ComfyApi(baseURL, undefined, { credentials }) (L69)
ClientService->>ClientService: this.client.init() (L70)
ClientService->>ClientService: log('Client initialized with baseURL:', this.baseURL) (L72)
alt 初始化失败 (L74-76)
ClientService->>ErrorHandler: handleError(error)
ErrorHandler-->>LobeComfyUI: throw AgentRuntimeError
else 初始化成功
ClientService-->>LobeComfyUI: ClientService实例
end
end
%% 阶段3: ModelResolver初始化
rect rgb(240, 255, 240)
note over LobeComfyUI,ModelResolver: 阶段3: 初始化模型解析服务 (index.ts:42)
LobeComfyUI->>ModelResolver: new ModelResolverService(clientService)
%% ModelResolver构造函数 (modelResolver.ts:37-39)
ModelResolver->>ModelResolver: this.clientService = clientService (L38)
ModelResolver->>ModelResolver: 初始化缓存Maps:<br/>- modelCache: Map<string, string><br/>- vaeCache: string[]<br/>- componentCache: Map<string, string[]> (L32-34)
ModelResolver-->>LobeComfyUI: ModelResolver实例
end
%% 阶段4: 创建WorkflowContext
rect rgb(255, 240, 248)
note over LobeComfyUI,WorkflowBuilder: 阶段4: 创建工作流上下文 (index.ts:44-50)
LobeComfyUI->>LobeComfyUI: context: WorkflowContext = {<br/> clientService: this.clientService,<br/> modelResolverService: modelResolverService<br/>} (L45-48)
%% WorkflowBuilder初始化
LobeComfyUI->>WorkflowBuilder: new WorkflowBuilderService(context)
%% WorkflowBuilder构造函数 (workflowBuilder.ts:41-43)
WorkflowBuilder->>WorkflowBuilder: this.context = context (L42)
WorkflowBuilder-->>LobeComfyUI: WorkflowBuilder实例
end
%% 阶段5: ImageService初始化
rect rgb(240, 248, 255)
note over LobeComfyUI,ImageService: 阶段5: 初始化图像服务 (index.ts:52-57)
LobeComfyUI->>ImageService: new ImageService(<br/> clientService,<br/> modelResolverService,<br/> workflowBuilderService<br/>)
%% ImageService构造函数 (imageService.ts:27-33)
ImageService->>ImageService: 保存依赖引用:<br/>- this.clientService<br/>- this.modelResolverService<br/>- this.workflowBuilderService (L28-31)
ImageService->>ErrorHandler: new ErrorHandlerService() (L32)
ErrorHandler-->>ImageService: errorHandler实例
ImageService-->>LobeComfyUI: ImageService实例
end
%% 阶段6: 完成初始化
rect rgb(255, 248, 240)
note over LobeComfyUI,App: 阶段6: 初始化完成 (index.ts:58)
LobeComfyUI->>LobeComfyUI: 构造函数完成,实例就绪
LobeComfyUI-->>App: LobeComfyUI实例
note over App: Runtime实例可用,<br/>但尚未验证连接
end
%% 延迟初始化说明
note over LobeComfyUI,ClientService: 注意:连接验证延迟到首次createImage调用
服务器模型解析sequenceDiagram
participant Client as 调用者
participant MRS as ModelResolverService
participant CCS as ComfyUIClientService
participant SDK as ComfyUI SDK
participant Server as ComfyUI Server
participant Registry as ModelRegistry
participant SysComp as SystemComponents
Note over Client, SysComp: 模型解析完整流程 - 基于代码实现
%% 1. 模型文件名解析
Client->>+MRS: resolveModelFileName(modelId)
Note right of MRS: modelResolver.ts:49
%% 缓存检查
MRS->>MRS: 检查 modelCache
alt 缓存命中
MRS-->>Client: 返回缓存结果
else 缓存未命中
%% 清理模型ID
MRS->>MRS: 清理模型ID (去除 comfyui/ 前缀)
Note right of MRS: modelResolver.ts:60
%% 特殊处理 - 自定义SD模型
alt 自定义SD模型
MRS->>MRS: 检查 CUSTOM_SD_CONFIG.MODEL_FILENAME
Note right of MRS: constants.ts:216-218
MRS->>+CCS: getAvailableModelFiles()
CCS->>+SDK: getCheckpoints()
SDK->>+Server: GET /object_info
Server-->>-SDK: 服务器模型列表
SDK-->>-CCS: 模型文件列表
CCS-->>-MRS: 验证自定义模型存在
alt 自定义模型存在
MRS->>MRS: 缓存结果到 modelCache
MRS-->>Client: 返回固定文件名
else 自定义模型不存在
MRS-->>Client: ModelResolverError(MODEL_NOT_FOUND)
end
else 普通模型处理
%% 注册表查找
MRS->>+Registry: 查询 MODEL_REGISTRY
Note right of Registry: modelRegistry.ts:22-25
Registry-->>-MRS: 模型配置 (如果存在)
alt 在注册表中找到
MRS->>MRS: 缓存到 modelCache
MRS-->>Client: 返回模型文件名
else 注册表中未找到
%% 模型文件格式检查
MRS->>MRS: isModelFile() 检查
Note right of MRS: constants.ts:208-210
alt 是模型文件格式
MRS->>+CCS: getAvailableModelFiles()
CCS->>+SDK: getCheckpoints()
SDK->>+Server: GET /object_info
Server-->>-SDK: 服务器模型列表
SDK-->>-CCS: 模型文件列表
CCS-->>-MRS: 可用模型列表
alt 服务器中存在该文件
MRS->>MRS: 缓存到 modelCache
MRS-->>Client: 返回模型文件名
else 服务器中不存在
MRS-->>Client: ModelResolverError(MODEL_NOT_FOUND)
end
else 非模型文件格式
MRS-->>Client: ModelResolverError(MODEL_NOT_FOUND)
end
end
end
end
%% 2. 最优组件选择
Client->>+MRS: getOptimalComponent(type, modelFamily)
Note right of MRS: modelResolver.ts:184
%% 系统组件配置查询
MRS->>+SysComp: getAllComponentsWithNames(filters)
Note right of SysComp: systemComponents.ts:344
SysComp->>SysComp: 过滤匹配的组件
SysComp-->>-MRS: 按优先级排序的组件列表
%% 节点映射查询
MRS->>MRS: 查询 COMPONENT_NODE_MAPPINGS
Note right of MRS: constants.ts:225-231
alt 找到节点映射
%% 获取服务器可用文件
MRS->>+CCS: getAvailableComponentFiles(node, field)
Note right of CCS: comfyuiClient.ts:150
%% 检查缓存
CCS->>CCS: 检查 componentCache
alt 缓存命中
CCS-->>MRS: 返回缓存结果
else 缓存未命中
CCS->>+SDK: getNodeDefs(nodeName)
SDK->>+Server: GET /object_info
Server-->>-SDK: 节点定义信息
SDK-->>-CCS: 组件文件列表
CCS->>CCS: 缓存到 componentCache
CCS-->>-MRS: 可用组件文件列表
end
%% 匹配最优组件
MRS->>MRS: 按优先级匹配第一个可用组件
alt 找到匹配组件
MRS-->>Client: 返回最优组件名
else 未找到匹配组件
MRS-->>Client: ModelResolverError(COMPONENT_NOT_FOUND)
end
else 未找到节点映射
MRS-->>Client: ModelResolverError(COMPONENT_NOT_FOUND)
end
%% 3. VAE选择
Client->>+MRS: selectVAE(options)
Note right of MRS: modelResolver.ts:231
alt 指定了自定义VAE
MRS->>+CCS: getAvailableVAEFiles()
Note right of CCS: comfyuiClient.ts:119
%% VAE缓存检查
CCS->>CCS: 检查 vaeCache
alt 缓存命中
CCS-->>MRS: 返回缓存的VAE列表
else 缓存未命中
CCS->>+SDK: getNodeDefs('VAELoader')
SDK->>+Server: GET /object_info
Server-->>-SDK: VAE加载器节点定义
SDK-->>-CCS: 可用VAE列表
CCS->>CCS: 缓存到 vaeCache
CCS-->>-MRS: 可用VAE文件列表
end
alt 自定义VAE存在
MRS-->>Client: 返回自定义VAE
else 自定义VAE不存在
Note right of MRS: 继续后续VAE选择逻辑
end
end
alt 自定义SD模型
MRS->>MRS: 检查 CUSTOM_SD_CONFIG.VAE_FILENAME
MRS->>+CCS: getAvailableVAEFiles()
CCS-->>-MRS: 服务器VAE列表
alt 配置的VAE存在
MRS-->>Client: 返回配置的VAE
else 配置的VAE不存在
MRS-->>Client: undefined (无VAE)
end
else 基于模型家族选择VAE
MRS->>+Registry: getModelConfig(modelFileName)
Registry-->>-MRS: 模型配置信息
alt 找到模型配置
MRS->>MRS: getOptimalComponent('vae', modelFamily)
Note right of MRS: 重用组件选择逻辑
MRS-->>Client: 返回最优VAE
else 未找到模型配置
MRS-->>Client: undefined (无VAE)
end
end
%% 4. 模型验证
Client->>+MRS: validateModel(modelId)
Note right of MRS: modelResolver.ts:282
MRS->>MRS: resolveModelFileName(modelId)
alt 解析成功
MRS-->>Client: { exists: true, actualFileName }
else 解析失败 (ModelResolverError)
MRS-->>Client: 重新抛出错误
else 其他异常
MRS-->>Client: { exists: false }
end
%% 错误处理流程
Note over MRS, Server: 统一错误处理
alt API调用失败
CCS->>CCS: handleApiError()
Note right of CCS: comfyuiClient.ts:287
alt 网络错误
CCS-->>MRS: ModelResolverError(CONNECTION_ERROR)
else HTTP 401/403
CCS-->>MRS: ModelResolverError(PERMISSION_DENIED)
else HTTP 5xx
CCS-->>MRS: ModelResolverError(SERVICE_UNAVAILABLE)
else 其他错误
CCS-->>MRS: ServicesError(EXECUTION_FAILED)
end
end
Note over Client, SysComp: 主要组件及其职责
Note right of MRS: ModelResolverService: 业务逻辑层
Note right of CCS: ComfyUIClientService: 基础设施层
Note right of Registry: 配置驱动的模型注册表
Note right of SysComp: 系统组件配置管理
|
Beta Was this translation helpful? Give feedback.
-
文生图和图生图时序图sequenceDiagram
participant User as 用户
participant Entry as LobeComfyUI<br/>(入口)
participant ImageService as ImageService<br/>(业务服务)
participant ErrorHandler as ErrorHandler<br/>(错误处理)
participant ModelResolver as ModelResolver<br/>(模型解析)
participant WorkflowDetector as WorkflowDetector<br/>(工作流检测)
participant WorkflowBuilder as WorkflowBuilder<br/>(工作流构建)
participant WorkflowImpl as Workflow实现<br/>(如flux-dev.ts)
participant ClientService as ClientService<br/>(客户端)
participant ComfyAPI as ComfyUI Server<br/>(远程服务器)
%% 阶段1: 请求初始化
rect rgb(240, 248, 255)
note over User,Entry: 阶段1: 请求初始化 (index.ts:64-67)
User->>Entry: createImage({<br/> model: "comfyui/flux-dev",<br/> params: {<br/> prompt: "...",<br/> width: 1024,<br/> height: 1024<br/> }<br/>})
Entry->>ImageService: createImage(payload) <br/>[委托所有业务逻辑]
end
%% 阶段2: 连接验证
rect rgb(255, 248, 240)
note over ImageService,ComfyAPI: 阶段2: 连接验证 (imageService.ts:43)
ImageService->>ClientService: validateConnection()
alt 缓存有效 (comfyuiClient.ts:282-284)
ClientService-->>ImageService: 返回cached=true
else 需要验证连接
ClientService->>ClientService: getNodeDefs() <br/>[使用SDK方法验证]
ClientService->>ComfyAPI: SDK: getNodeDefs()
alt 连接成功 (comfyuiClient.ts:287-300)
ComfyAPI-->>ClientService: 返回NodeDefs对象
ClientService->>ClientService: 设置connectionValidated=true
ClientService-->>ImageService: 连接有效
else 连接失败 (comfyuiClient.ts:302-304)
ComfyAPI-->>ClientService: 网络错误/超时
ClientService->>ErrorHandler: handleApiError()
ErrorHandler->>ErrorHandler: 转换为ServicesError
ErrorHandler-->>ImageService: throw ServicesError
ImageService->>ErrorHandler: handleError()
ErrorHandler-->>Entry: throw AgentRuntimeError
Entry-->>User: 返回友好错误信息
end
end
end
%% 阶段3: 模型验证与解析
rect rgb(240, 255, 240)
note over ImageService,ModelResolver: 阶段3: 模型验证与解析 (imageService.ts:45-54)
ImageService->>ModelResolver: validateModel("comfyui/flux-dev")
ModelResolver->>ModelResolver: resolveModelFileName() <br/>[modelResolver.ts:49-104]
%% 模型解析子流程
ModelResolver->>ModelResolver: 1. 检查缓存 (L53-57)
ModelResolver->>ModelResolver: 2. 清理ID移除前缀 (L60)
alt 特殊处理自定义SD模型 (L63-79)
ModelResolver->>ClientService: getAvailableModelFiles()
ClientService->>ComfyAPI: SDK: getCheckpoints()
ComfyAPI-->>ClientService: 模型文件列表
ClientService-->>ModelResolver: string[]
ModelResolver->>ModelResolver: 验证CUSTOM_SD_CONFIG.MODEL_FILENAME
else 注册表查找 (L82-86)
ModelResolver->>ModelResolver: 查找MODEL_REGISTRY[cleanId]
else 服务器验证 (L89-96)
ModelResolver->>ClientService: getAvailableModelFiles()
ClientService-->>ModelResolver: 服务器模型列表
ModelResolver->>ModelResolver: 验证文件存在
end
alt 模型找到
ModelResolver->>ModelResolver: 更新缓存
ModelResolver-->>ImageService: {exists: true, actualFileName: "..."}
else 模型不存在 (L99-103)
ModelResolver-->>ImageService: throw ModelResolverError
ImageService->>ErrorHandler: handleError()
ErrorHandler-->>Entry: throw AgentRuntimeError
Entry-->>User: 模型不存在错误
end
end
%% 阶段3.5: 图片预处理 (关键遗漏步骤)
rect rgb(255, 255, 240)
note over ImageService,ComfyAPI: 阶段3.5: 图片预处理 (imageService.ts:58)
ImageService->>ImageService: processImageFetch(params) <br/>[处理img2img场景]
alt 存在imageUrl参数 (L102-106)
ImageService->>ImageService: 检查是否为URL (L113-117)
alt 是HTTP URL需要处理
ImageService->>ImageService: fetch(imageUrl) <br/>[获取图片数据]
ImageService->>ImageService: 验证图片数据和大小 (L137-153)
ImageService->>ClientService: uploadImage(buffer, fileName)
ClientService->>ComfyAPI: SDK: uploadImage()
ComfyAPI-->>ClientService: 上传成功,返回文件名
ClientService-->>ImageService: ComfyUI文件名
ImageService->>ImageService: 替换params中的URL为文件名 (L167-170)
else 已是ComfyUI文件名
ImageService->>ImageService: 跳过处理
end
else 无图片URL
ImageService->>ImageService: 跳过图片处理
end
end
%% 阶段4: 工作流构建
rect rgb(255, 240, 248)
note over ImageService,WorkflowImpl: 阶段4: 工作流构建 (imageService.ts:61)
ImageService->>ImageService: buildWorkflow(model, modelFileName, params) <br/>[L191-220]
%% 工作流检测 (实际代码中的步骤)
ImageService->>WorkflowDetector: detectModelType(modelFileName) <br/>[L199]
WorkflowDetector->>WorkflowDetector: 检查特殊模型 (workflowDetector.ts:27-33)
WorkflowDetector->>WorkflowDetector: resolveModel(cleanId) <br/>[查找模型注册表]
WorkflowDetector-->>ImageService: {architecture, variant, isSupported}
alt 不支持的模型 (imageService.ts:202-208)
ImageService-->>Entry: throw ServicesError(MODEL_NOT_FOUND)
end
%% 工作流构建路由
ImageService->>WorkflowBuilder: buildWorkflow(modelId, detectionResult, modelFileName, params) <br/>[L211-216]
WorkflowBuilder->>WorkflowBuilder: 路由判断 (workflowBuilder.ts:58-86)
alt FLUX架构 (L61-69)
alt modelFileName包含'schnell'
WorkflowBuilder->>WorkflowImpl: buildFluxSchnellWorkflow()
else variant === 'kontext'
WorkflowBuilder->>WorkflowImpl: buildFluxKontextWorkflow()
else 默认
WorkflowBuilder->>WorkflowImpl: buildFluxDevWorkflow()
end
else SD3架构 (L72-74)
WorkflowBuilder->>WorkflowImpl: buildSD35Workflow()
else SD1/SDXL架构 (L77-79)
WorkflowBuilder->>WorkflowImpl: buildSimpleSDWorkflow()
else 不支持 (L82-86)
WorkflowBuilder-->>ImageService: throw WorkflowError
end
%% 工作流内部构建 (以FLUX Dev为例)
WorkflowImpl->>ModelResolver: getOptimalComponent("t5", "FLUX") <br/>[通过context.modelResolverService]
ModelResolver->>ModelResolver: 查找SYSTEM_COMPONENTS配置
ModelResolver->>ClientService: getAvailableComponentFiles()
ClientService-->>ModelResolver: 服务器组件列表
ModelResolver-->>WorkflowImpl: "t5xxl_fp16.safetensors"
WorkflowImpl->>ModelResolver: getOptimalComponent("vae", "FLUX")
ModelResolver-->>WorkflowImpl: "ae.safetensors"
WorkflowImpl->>ModelResolver: getOptimalComponent("clip", "FLUX")
ModelResolver-->>WorkflowImpl: "clip_l.safetensors"
WorkflowImpl->>WorkflowImpl: 构建静态workflow对象 <br/>[参数注入和节点配置]
WorkflowImpl-->>WorkflowBuilder: PromptBuilder实例
WorkflowBuilder-->>ImageService: 完整工作流
end
%% 阶段5: 工作流执行
rect rgb(240, 248, 255)
note over ImageService,ComfyAPI: 阶段5: 工作流执行 (imageService.ts:70-73)
ImageService->>ClientService: executeWorkflow(workflow, progressCallback)
ClientService->>ClientService: new CallWrapper(client, workflow) <br/>[comfyuiClient.ts:124]
%% SDK执行流程
ClientService->>ComfyAPI: SDK: WebSocket连接 + POST /prompt
ComfyAPI->>ComfyAPI: 1. 解析工作流JSON<br/>2. 加载模型<br/>3. 执行节点链
loop 进度更新 (comfyuiClient.ts:150-153)
ComfyAPI-->>ClientService: WebSocket: progress事件
ClientService->>ImageService: onProgress回调
ImageService->>ImageService: log进度信息
end
alt 执行成功 (comfyuiClient.ts:125-128)
ComfyAPI->>ComfyAPI: 生成完成
ComfyAPI-->>ClientService: WebSocket: finished事件<br/>(包含图片信息)
ClientService-->>ImageService: WorkflowResult对象
else 执行失败 (comfyuiClient.ts:129-149)
ComfyAPI-->>ClientService: WebSocket: failed事件
ClientService->>ClientService: parseComfyUIErrorMessage()
ClientService-->>ImageService: throw ServicesError
end
end
%% 阶段6: 结果处理
rect rgb(255, 248, 240)
note over ImageService,User: 阶段6: 结果处理 (imageService.ts:75-90)
ImageService->>ImageService: 处理执行结果
ImageService->>ImageService: 验证图片数组非空 (L77-83)
alt 结果为空
ImageService->>ErrorHandler: throw ServicesError(EMPTY_RESULT)
end
ImageService->>ClientService: getPathImage(imageInfo) <br/>[L88]
ClientService->>ClientService: SDK: client.getPathImage() <br/>[构建完整图片URL]
ClientService-->>ImageService: 完整图片URL
ImageService-->>Entry: {<br/> imageUrl: "完整URL",<br/> width: params.width ?? 1024,<br/> height: params.height ?? 1024<br/>}
Entry-->>User: 返回图片结果
end
%% 统一错误处理
note over ImageService,ErrorHandler: 所有错误通过ErrorHandlerService统一处理 (imageService.ts:92-94)
alt 任何步骤发生错误
ImageService->>ErrorHandler: handleError(error)
ErrorHandler->>ErrorHandler: 映射内部错误到框架错误 <br/>[errorHandler.ts:24-52]
ErrorHandler-->>Entry: throw AgentRuntimeError
Entry-->>User: 友好的错误信息
end
sequenceDiagram
participant Caller as 调用方<br/>(如AsyncWorker)
participant ImageService as ImageService<br/>(业务逻辑)
participant ErrorHandler as ErrorHandler<br/>(错误处理)
participant ImageProcessor as processImageFetch<br/>(图片预处理)
participant ClientService as ClientService<br/>(客户端服务)
participant RemoteSource as 远程图片源<br/>(S3/静态服务器)
participant ComfyAPI as ComfyUI Server<br/>(远程服务器)
%% 阶段1: 图片处理入口
rect rgb(240, 248, 255)
note over Caller,ImageService: 阶段1: 图片处理请求 (imageService.ts:38)
Caller->>ImageService: createImage({<br/> model: "flux-dev",<br/> params: {<br/> imageUrl: "https://s3.../image.png",<br/> prompt: "...",<br/> strength: 0.8<br/> }<br/>})
end
%% 阶段2: 连接验证 (复用文生图流程)
rect rgb(255, 248, 240)
note over ImageService,ComfyAPI: 阶段2: 连接验证 (imageService.ts:43)
ImageService->>ClientService: validateConnection()
ClientService->>ComfyAPI: getNodeDefs()
ComfyAPI-->>ClientService: 返回NodeDefs
ClientService-->>ImageService: 连接验证成功
end
%% 阶段3: 模型验证 (复用文生图流程)
rect rgb(240, 255, 240)
note over ImageService,ComfyAPI: 阶段3: 模型验证 (imageService.ts:45-54)
ImageService->>ImageService: validateModel(model)
ImageService-->>ImageService: 模型验证成功
end
%% 阶段4: 图片预处理 (关键差异)
rect rgb(255, 255, 240)
note over ImageService,RemoteSource: 阶段4: 图片预处理 (imageService.ts:58)
ImageService->>ImageProcessor: processImageFetch(params) <br/>[L101-186]
%% 检测图片URL
ImageProcessor->>ImageProcessor: 提取imageUrl <br/>= params.imageUrl || params.imageUrls?.[0] (L102)
alt 无图片URL (L104-106)
ImageProcessor-->>ImageService: 跳过处理 (纯文生图)
else 已是ComfyUI文件名 (L113-117)
ImageProcessor->>ImageProcessor: 检查!imageUrl.includes('://')
ImageProcessor-->>ImageService: 跳过处理 (已处理过)
else 需要处理的远程URL
%% URL获取与验证
ImageProcessor->>RemoteSource: fetch(imageUrl) <br/>[HTTP/HTTPS请求] (L121)
alt 获取失败 (L123-129)
RemoteSource-->>ImageProcessor: HTTP错误 (404/500等)
ImageProcessor->>ErrorHandler: throw ServicesError<br/>(IMAGE_FETCH_FAILED)
ErrorHandler-->>ImageService: AgentRuntimeError
else 获取成功
RemoteSource-->>ImageProcessor: 返回图片数据 (Response)
ImageProcessor->>ImageProcessor: 转换为Buffer <br/>= Buffer.from(arrayBuffer) (L132-134)
%% 数据验证
ImageProcessor->>ImageProcessor: 验证数据完整性 (L137-143)
ImageProcessor->>ImageProcessor: 检查大小限制 30MB (L146-153)
alt 数据无效或过大
ImageProcessor->>ErrorHandler: throw ServicesError<br/>(IMAGE_TOO_LARGE)
ErrorHandler-->>ImageService: AgentRuntimeError
else 数据有效
%% 上传到ComfyUI
ImageProcessor->>ImageProcessor: 生成文件名 <br/>= LobeChat_img2img_${Date.now()}.png (L158)
ImageProcessor->>ClientService: uploadImage(buffer, fileName) <br/>[L159-162]
ClientService->>ComfyAPI: SDK: uploadImage()
alt 上传失败
ComfyAPI-->>ClientService: 上传错误
ClientService->>ErrorHandler: throw ServicesError<br/>(UPLOAD_FAILED)
ErrorHandler-->>ImageService: AgentRuntimeError
else 上传成功
ComfyAPI-->>ClientService: 返回ComfyUI文件名
ClientService-->>ImageProcessor: uploadedFileName
%% 参数替换
ImageProcessor->>ImageProcessor: 替换URL为文件名 (L167-170)
note right of ImageProcessor: params.imageUrl = uploadedFileName<br/>params.imageUrls[0] = uploadedFileName
ImageProcessor-->>ImageService: 处理完成
end
end
end
end
end
%% 阶段5: 工作流构建 (复用文生图,但包含图片参数)
rect rgb(255, 240, 248)
note over ImageService,ComfyAPI: 阶段5: 工作流构建 (imageService.ts:61)
ImageService->>ImageService: buildWorkflow(model, modelFileName, params)
note right of ImageService: params现在包含ComfyUI文件名<br/>而不是原始URL
ImageService->>ImageService: 工作流构建完成<br/>(包含图片输入节点)
end
%% 阶段6: 工作流执行 (复用文生图流程)
rect rgb(240, 248, 255)
note over ImageService,ComfyAPI: 阶段6: 工作流执行 (imageService.ts:70-73)
ImageService->>ClientService: executeWorkflow(workflow)
ClientService->>ComfyAPI: WebSocket + POST /prompt
ComfyAPI->>ComfyAPI: 加载基础图片<br/>(LobeChat_img2img_*.png)
ComfyAPI->>ComfyAPI: 执行img2img工作流
ComfyAPI-->>ClientService: 返回生成结果
ClientService-->>ImageService: WorkflowResult
end
%% 阶段7: 结果处理 (复用文生图流程)
rect rgb(255, 248, 240)
note over ImageService,Caller: 阶段7: 结果处理 (imageService.ts:86-90)
ImageService->>ClientService: getPathImage(imageInfo)
ClientService-->>ImageService: 完整图片URL
ImageService-->>Caller: {<br/> imageUrl: "ComfyUI结果URL",<br/> width: 1024,<br/> height: 1024<br/>}
end
%% 统一错误处理
note over ImageService,ErrorHandler: 所有错误通过ErrorHandlerService统一处理
alt 任何步骤发生错误
ImageService->>ErrorHandler: handleError(error)
ErrorHandler->>ErrorHandler: 映射到AgentRuntimeError
ErrorHandler-->>Caller: 友好错误信息
end
|
Beta Was this translation helpful? Give feedback.
-
|
基本要PR了,通过这次实际体验到了设想和做出来的不一样,到时候会有结项报告在PR
这是认知偏差,不是技术失误:
|
Beta Was this translation helpful? Give feedback.
-
工作流简易时序图sequenceDiagram
participant Client as 调用者
participant WBS as WorkflowBuilderService
participant WD as WorkflowDetector
participant MRS as ModelResolverService
participant FluxDev as buildFluxDevWorkflow
participant SimpleSD as buildSimpleSDWorkflow
participant SDK as PromptBuilder
participant Config as 配置系统
Note over Client, Config: 工作流构建完整流程 - 基于代码实现
%% 1. 工作流构建请求
Client->>+WBS: buildWorkflow(modelId, detectionResult, modelFileName, params)
Note right of WBS: workflowBuilder.ts:49
%% 2. 架构路由决策
WBS->>WBS: 解析 architecture & variant
Note right of WBS: 从 detectionResult 获取模型架构信息
alt FLUX 架构
%% FLUX Schnell 检测
alt modelFileName 包含 'schnell'
Note over WBS: FLUX Schnell 路由
WBS->>+FluxDev: buildFluxSchnellWorkflow(modelFileName, params, context)
Note right of FluxDev: workflows/flux-schnell.ts
%% 组件解析
FluxDev->>+MRS: getOptimalComponent('t5', 'FLUX')
MRS-->>-FluxDev: selectedT5Model
FluxDev->>+MRS: getOptimalComponent('vae', 'FLUX')
MRS-->>-FluxDev: selectedVAE
FluxDev->>+MRS: getOptimalComponent('clip', 'FLUX')
MRS-->>-FluxDev: selectedCLIP
%% 工作流构建
FluxDev->>FluxDev: 构建 FLUX Schnell 节点结构
Note right of FluxDev: KSampler + 简化节点,4步快速生成
FluxDev->>FluxDev: 注入参数到工作流节点
FluxDev->>+SDK: new PromptBuilder(workflow, inputs, outputs)
SDK-->>-FluxDev: builder 实例
FluxDev->>FluxDev: 设置输入输出节点映射
FluxDev-->>-WBS: 返回配置好的 PromptBuilder
else variant === 'kontext'
Note over WBS: FLUX Kontext 路由
WBS->>+FluxDev: buildFluxKontextWorkflow(modelFileName, params, context)
Note right of FluxDev: workflows/flux-kontext.ts
%% 图像编辑模型的特殊处理
FluxDev->>+MRS: getOptimalComponent('t5', 'FLUX')
MRS-->>-FluxDev: selectedT5Model
FluxDev->>+MRS: getOptimalComponent('vae', 'FLUX')
MRS-->>-FluxDev: selectedVAE
FluxDev->>+MRS: getOptimalComponent('clip', 'FLUX')
MRS-->>-FluxDev: selectedCLIP
FluxDev->>FluxDev: 构建 FLUX Kontext 节点结构
Note right of FluxDev: FluxGuidance + 图像编辑特化参数
FluxDev->>FluxDev: 应用 KONTEXT 专用配置 (28步, CFG 3.5)
FluxDev->>+SDK: new PromptBuilder(workflow, inputs, outputs)
SDK-->>-FluxDev: builder 实例
FluxDev-->>-WBS: 返回配置好的 PromptBuilder
else 默认 FLUX Dev
Note over WBS: FLUX Dev 路由
WBS->>+FluxDev: buildFluxDevWorkflow(modelFileName, params, context)
Note right of FluxDev: workflows/flux-dev.ts:18
%% 组件解析阶段
FluxDev->>+MRS: getOptimalComponent('t5', 'FLUX')
Note right of MRS: 查询 SYSTEM_COMPONENTS 获取最优T5编码器
MRS-->>-FluxDev: selectedT5Model
FluxDev->>+MRS: getOptimalComponent('vae', 'FLUX')
Note right of MRS: 查询 FLUX VAE 组件
MRS-->>-FluxDev: selectedVAE
FluxDev->>+MRS: getOptimalComponent('clip', 'FLUX')
Note right of MRS: 获取 CLIP-L 编码器
MRS-->>-FluxDev: selectedCLIP
%% Prompt 分离处理
FluxDev->>FluxDev: splitPromptForDualCLIP(params.prompt)
Note right of FluxDev: utils/promptSplitter.ts - 分离T5和CLIP提示词
%% 工作流结构构建
FluxDev->>FluxDev: 构建静态工作流节点
Note right of FluxDev: flux-dev.ts:32-183
rect rgb(240, 248, 255)
Note over FluxDev: FLUX Dev 工作流节点结构
Note right of FluxDev: 1: DualCLIPLoader (T5+CLIP)
Note right of FluxDev: 2: UNETLoader (FLUX模型)
Note right of FluxDev: 3: VAELoader (VAE解码器)
Note right of FluxDev: 4: ModelSamplingFlux (FLUX采样配置)
Note right of FluxDev: 5: CLIPTextEncodeFlux (FLUX文本编码)
Note right of FluxDev: 6: FluxGuidance (指导系统)
Note right of FluxDev: 7: EmptySD3LatentImage (潜在图像)
Note right of FluxDev: 8: KSamplerSelect (采样器选择)
Note right of FluxDev: 9: BasicScheduler (调度器)
Note right of FluxDev: 10: SamplerCustomAdvanced (高级采样)
Note right of FluxDev: 11: VAEDecode (VAE解码)
Note right of FluxDev: 12: SaveImage (保存图像)
Note right of FluxDev: 13: RandomNoise (随机噪声)
Note right of FluxDev: 14: BasicGuider (基础引导器)
end
%% 参数注入阶段
FluxDev->>FluxDev: 直接注入参数到工作流节点
Note right of FluxDev: flux-dev.ts:187-210
FluxDev->>FluxDev: workflow['5'].inputs.clip_l = clipLPrompt
FluxDev->>FluxDev: workflow['5'].inputs.t5xxl = t5xxlPrompt
FluxDev->>FluxDev: 设置width/height到多个节点
FluxDev->>FluxDev: 设置cfg到FluxGuidance节点
FluxDev->>FluxDev: 设置steps/scheduler到BasicScheduler
FluxDev->>FluxDev: 设置seed到RandomNoise节点
%% PromptBuilder 创建
FluxDev->>+SDK: new PromptBuilder(workflow, inputs, outputs)
Note right of SDK: flux-dev.ts:213-217
SDK-->>-FluxDev: builder 实例
%% 输入输出映射配置
FluxDev->>+SDK: setOutputNode('images', '12')
SDK-->>-FluxDev: 设置图像输出节点
FluxDev->>+SDK: setInputNode('seed', '13.inputs.noise_seed')
SDK-->>-FluxDev: 映射种子输入
FluxDev->>+SDK: setInputNode('width', '7.inputs.width')
SDK-->>-FluxDev: 映射宽度输入
FluxDev->>+SDK: setInputNode('height', '7.inputs.height')
SDK-->>-FluxDev: 映射高度输入
FluxDev->>+SDK: setInputNode('steps', '9.inputs.steps')
SDK-->>-FluxDev: 映射步数输入
FluxDev->>+SDK: setInputNode('cfg', '6.inputs.guidance')
SDK-->>-FluxDev: 映射CFG输入
%% 输入值设置
FluxDev->>+SDK: input('width', width).input('height', height)...
SDK-->>-FluxDev: 设置具体输入值
FluxDev-->>-WBS: 返回配置好的 PromptBuilder
end
else SD3 架构且包含 'sd35'
Note over WBS: SD3.5 路由
WBS->>+SimpleSD: buildSD35Workflow(modelFileName, params, context)
Note right of SimpleSD: workflows/sd35.ts
%% SD3.5 特殊处理
SimpleSD->>SimpleSD: 检测 SD3.5 模型类型
SimpleSD->>SimpleSD: 决定是否使用外部VAE
SimpleSD->>+MRS: selectVAE(options) - 可能不使用外部VAE
MRS-->>-SimpleSD: VAE配置或undefined
SimpleSD->>SimpleSD: 构建 SD3.5 节点结构
Note right of SimpleSD: CheckpointLoaderSimple + SD3特化
SimpleSD->>+SDK: new PromptBuilder(workflow, inputs, outputs)
SDK-->>-SimpleSD: builder 实例
SimpleSD-->>-WBS: 返回配置好的 PromptBuilder
else SD1 或 SDXL 架构
Note over WBS: Simple SD 路由
WBS->>+SimpleSD: buildSimpleSDWorkflow(modelFileName, params, context)
Note right of SimpleSD: workflows/simple-sd.ts:68
%% 模型配置查询
SimpleSD->>+Config: getModelConfig(modelFileName)
Config-->>-SimpleSD: modelConfig 或 null
%% VAE需求判断
SimpleSD->>SimpleSD: shouldAttachVAE(modelConfig)
Note right of SimpleSD: simple-sd.ts:57 - SD1/SDXL需要外部VAE
alt 需要外部VAE
SimpleSD->>+MRS: selectVAE(options)
MRS-->>-SimpleSD: 选择的VAE文件
else 不需要外部VAE
SimpleSD->>SimpleSD: 使用模型内建VAE
end
%% 模式检测
alt 存在 inputImage 或 imageUrl
Note over SimpleSD: 图生图模式 (i2i)
SimpleSD->>SimpleSD: 构建 i2i 工作流节点
Note right of SimpleSD: 包含 LoadImage + 强度参数
else 纯文本生成
Note over SimpleSD: 文生图模式 (t2i)
SimpleSD->>SimpleSD: 构建 t2i 工作流节点
Note right of SimpleSD: 标准 SD 生成流程
end
%% 调度器配置
SimpleSD->>SimpleSD: 根据模型类型选择调度器
Note right of SimpleSD: SD1:normal, SDXL:normal, SD3:sgm_uniform
SimpleSD->>SimpleSD: 应用参数到工作流节点
SimpleSD->>+SDK: new PromptBuilder(workflow, inputs, outputs)
SDK-->>-SimpleSD: builder 实例
SimpleSD-->>-WBS: 返回配置好的 PromptBuilder
else 不支持的架构
WBS-->>Client: WorkflowError(UNSUPPORTED_MODEL)
end
WBS-->>-Client: 返回构建好的 PromptBuilder
%% 错误处理
Note over WBS, Config: 统一错误处理
alt 组件解析失败
MRS-->>FluxDev: ModelResolverError(COMPONENT_NOT_FOUND)
FluxDev-->>WBS: 传播错误
WBS-->>Client: WorkflowError(MISSING_COMPONENT)
else 配置错误
Config-->>SimpleSD: ConfigError
SimpleSD-->>WBS: 传播错误
WBS-->>Client: WorkflowError(INVALID_CONFIG)
end
Note over Client, Config: 工作流构建核心特征
Note right of WBS: 协调器模式:路由到具体实现
Note right of FluxDev: 静态工作流 + 参数注入
Note right of SimpleSD: 动态模式切换 (t2i/i2i)
Note right of MRS: 组件解析与验证
|
Beta Was this translation helpful? Give feedback.
-
|
comfyui-error-analysis-complete-report.md 由于目前的 image 错误仍然还是工厂模式,所以我这边根据实际的 SDK 和一致性单独做了 errorHandeler 错误处理时序图sequenceDiagram
participant Client as 调用者
participant Service as 各种服务层
participant EHS as ErrorHandlerService
participant Parser as comfyuiErrorParser
participant Framework as Framework错误
Note over Client, Framework: ComfyUI 错误处理完整流程 - 基于代码实现
%% 1. 内部错误产生
alt 模型解析错误
Service->>Service: ModelResolverError
Note right of Service: modelResolverError.ts - MODEL_NOT_FOUND, COMPONENT_NOT_FOUND
Service->>+EHS: handleError(ModelResolverError)
else 服务层错误
Service->>Service: ServicesError
Note right of Service: servicesError.ts - CONNECTION_FAILED, EXECUTION_FAILED
Service->>+EHS: handleError(ServicesError)
else 工作流错误
Service->>Service: WorkflowError
Note right of Service: workflowError.ts - UNSUPPORTED_MODEL, INVALID_CONFIG
Service->>+EHS: handleError(WorkflowError)
else 配置错误
Service->>Service: ConfigError
Note right of Service: configError.ts - INVALID_CONFIG, MISSING_CONFIG
Service->>+EHS: handleError(ConfigError)
else 工具层错误
Service->>Service: UtilsError
Note right of Service: utilsError.ts - DETECTION_FAILED, ROUTING_FAILED
Service->>+EHS: handleError(UtilsError)
end
%% 2. 错误类型检查
EHS->>EHS: isComfyUIInternalError(error)
Note right of EHS: errorHandler.ts:26 & typeGuards.ts:10
alt ComfyUI 内部错误
EHS->>EHS: mapInternalErrorToRuntimeError(error)
Note right of EHS: errorHandler.ts:57
%% 映射不同错误类型
alt ModelResolverError
EHS->>EHS: 检查 error.reason
Note right of EHS: 映射到 ModelNotFound, ComfyUIServiceUnavailable 等
else ServicesError
EHS->>EHS: 检查 error.reason
Note right of EHS: 映射到 InvalidComfyUIArgs, ComfyUIBizError 等
else WorkflowError
EHS->>EHS: 检查 error.reason
Note right of EHS: 映射到 ComfyUIWorkflowError, ModelNotFound 等
else ConfigError
EHS->>EHS: 检查 error.reason
Note right of EHS: 映射到 ComfyUIBizError
else UtilsError
EHS->>EHS: 检查 error.reason
Note right of EHS: 映射到 ComfyUIServiceUnavailable, ComfyUIBizError 等
end
EHS->>+Framework: AgentRuntimeError.createImage()
Note right of Framework: 使用映射的错误类型创建框架错误
Framework->>-EHS: 结构化框架错误
EHS-->>-Client: 抛出 AgentRuntimeError
else 已格式化框架错误
EHS-->>-Client: 直接抛出错误
else 其他错误 (网络、SDK、未知)
EHS->>+Parser: parseComfyUIErrorMessage(error)
Note right of Parser: comfyuiErrorParser.ts:181
%% 错误信息提取
Parser->>Parser: extractComfyUIErrorInfo(error)
Note right of Parser: comfyuiErrorParser.ts:99
alt 字符串错误
Parser->>Parser: cleanComfyUIErrorMessage(error)
Note right of Parser: comfyuiErrorParser.ts:21 - 清理格式字符
else Error对象
Parser->>Parser: 提取message, code, status, type
Note right of Parser: 优先处理 Error 实例
else 结构化对象
Parser->>Parser: 多路径提取错误信息
Note right of Parser: message, status, details 等字段
else 其他类型
Parser->>Parser: String(error) 转换
end
%% 错误类型分类
Parser->>Parser: 错误优先级分类
Note right of Parser: HTTP状态码 > 网络错误 > 模型错误 > 工作流错误
alt HTTP状态码错误
alt status === 401
Parser-->>EHS: InvalidProviderAPIKey
else status === 403
Parser-->>EHS: PermissionDenied
else status === 404
Parser-->>EHS: ComfyUIServiceUnavailable
else status >= 500
Parser-->>EHS: ComfyUIServiceUnavailable
end
else 网络连接错误 (无HTTP状态)
Parser->>Parser: isNetworkError(error)
Note right of Parser: 检测 fetch failed, ECONNREFUSED 等
Parser-->>EHS: ComfyUIServiceUnavailable
else 消息中的HTTP状态码
Parser->>Parser: 检查消息中的HTTP状态码
Note right of Parser: "HTTP 401", "404" 等字符串
Parser-->>EHS: 相应的错误类型
else 模型相关错误
Parser->>Parser: isModelError(error)
Note right of Parser: 检测 "model not found", "safetensors" 等
Parser-->>EHS: ModelNotFound
else 工作流相关错误
Parser->>Parser: isWorkflowError(error)
Note right of Parser: 检测 "node", "workflow", "execution" 等
Parser-->>EHS: ComfyUIBizError
else 默认业务错误
Parser-->>EHS: ComfyUIBizError
end
Parser->>-EHS: { error: ComfyUIError, errorType }
EHS->>+Framework: AgentRuntimeError.createImage()
Framework->>-EHS: 结构化框架错误
EHS-->>-Client: 抛出 AgentRuntimeError
end
%% 3. 特定服务错误处理示例
Note over Service, Framework: 具体错误处理示例
%% ComfyUI客户端错误处理
rect rgb(240, 248, 255)
Note over Service: ComfyUIClientService 错误处理
Service->>Service: handleApiError(error)
Note right of Service: comfyuiClient.ts:287
alt 网络错误
Service->>Service: TypeError.includes('fetch')
Service-->>EHS: ModelResolverError(CONNECTION_ERROR)
else HTTP 401/403
Service->>Service: 解析状态码
Service-->>EHS: ModelResolverError(PERMISSION_DENIED)
else HTTP 5xx
Service-->>EHS: ModelResolverError(SERVICE_UNAVAILABLE)
else 其他错误
Service-->>EHS: ServicesError(EXECUTION_FAILED)
end
end
%% 工作流执行错误
rect rgb(248, 255, 240)
Note over Service: 工作流执行错误处理
Service->>Service: CallWrapper.onFailed(error)
Note right of Service: comfyuiClient.ts:129
alt 已结构化错误
Service-->>Client: 直接传播错误
else 原始ComfyUI错误
Service->>+Parser: parseComfyUIErrorMessage(error)
Parser-->>-Service: 解析结果
Service->>Service: new ServicesError(EXECUTION_FAILED)
Service-->>EHS: 传播给错误处理器
end
end
%% 错误传播链
Note over Client, Framework: 错误传播架构
Note right of Service: 各服务层产生内部错误
Note right of EHS: ErrorHandlerService 统一转换
Note right of Parser: comfyuiErrorParser 解析外部错误
Note right of Framework: AgentRuntimeError 框架标准化
|
Beta Was this translation helpful? Give feedback.
-
|
图源放 mdx的
|
Beta Was this translation helpful? Give feedback.



Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
ComfyUI 集成 LobeChat RFC
文档ID: LOBE-RFC-COMFYUI
状态: 技术方案确认
作者: @LobeTeam
Original Full RFC @deprecated
PRs
v1.0
#9043
v1.5
用户故事
核心问题:LobeChat 用户想用 FLUX、SD3.5 等最新模型,但配置 ComfyUI 太复杂
用户痛点:
产品理念
"零配置,全模型" - 让 ComfyUI 像 OpenAI 一样简单
用户体验流程:
交互设计
Before (原始 ComfyUI)
After (LobeChat 集成)
实现成果
产品层面
技术支撑
进度
市场验证:
相关调研文档
FLUX模型整体调研验证表格
SD模型整体调研验证表格
演进概述
RFC-128展现了一个经典的"从原型到企业级再到简化重构"的架构演进过程。这不是feature添加,而是纯粹的架构质量提升之旅。
Phase 1.0: 简单集成阶段
规模: 2,739行代码
特征: SDK封装,基础功能
初始架构
发现问题
Phase 1.5: 7组件系统重构
规模: 9,100+行代码 (233%增长)
特征: 企业级架构,组件化
架构重构决策
决策1: 组件分离策略
技术原理:
决策2: 配置驱动架构
技术优势:
决策3: 多层错误处理体系
技术效果:
决策4: 智能缓存策略
设计理念:
代码规模增长分析
233%增长的合理性:
这个增长体现的不是功能膨胀,而是质量提升:
架构演进里程碑 🏆
已完成里程碑
技术资产积累
架构优势
Beta Was this translation helpful? Give feedback.
All reactions