在Dify调用EAS部署的ComfyUI服务

更新时间:
复制 MD 格式

PAI-EAS部署的万相(ComfyUI)服务集成到Dify,可实现从文本到多媒体内容的端到端自动化生成。本文介绍从部署ComfyUI服务到配置Dify工作流的完整操作步骤。

方案概述

本方案以Dify为应用编排器,调用PAI-EAS上的ComfyUI推理服务。ComfyUI推理任务异步执行,整个调用链路如下:

  1. 提交任务:DifyEAS服务发送一个POST请求,请求体中包含ComfyUI工作流的JSON描述。EAS接收任务后,会立即返回一个唯一的prompt_id

  2. 轮询状态:Dify使用上一步获取的prompt_id,通过GET请求循环查询(轮询)任务的执行状态。EAS会返回任务是否完成、成功或失败等信息。

  3. 获取结果:判断任务成功后,再次发起GET请求获取最终结果,结果包含生成文件在OSS上的文件名。Dify将文件名与OSS访问地址拼接,向用户展示完整的图片或视频链接。

工作流开始节点接收 positive_promptnegative_prompt 两个必填参数。所有 HTTP 请求节点均配置为失败时重试 3 次。轮询阶段通过等待十分钟代码节点控制每次轮询间隔。获取结果后依次经过筛选结果模板转换节点处理,最终以 Markdown 图片链接格式直接回复用户。

步骤一:(可选)部署Dify

说明

若已有Dify环境,可跳过本节。本文以计算巢部署Dify社区单机版为例。

  1. 进入计算巢Dify社区版服务详情页,单击开始部署

  2. 根据需求选择配置。基础演示可选单机版模板,实例类型选择ecs.u1-c1m2.xlarge,设置实例密码,选择可用区。

  3. 单击下一步:确认订单,在跳转页面单击立即创建

  4. 服务部署完成后,单击详情,在概览页签的立即使用区域,找到dify访问链接。注册账号后登录就能创建dify应用。

步骤二:部署万相ComfyUI

  1. 进入ModelGallery,在搜索框中输入万相2.1-文生视频-1.3B,单击卡片进入模型详情页。

  2. 单击右上角部署,在配置页面进行以下设置,其余保持默认。

    • 部署方式:选择ComfyUI > 标准部署

    • 服务配置:在JSON编辑器中,配置storage.oss.path参数,将其值修改为实际的OSS路径(例如:oss://examplebucket/wan)。此路径为ComfyUI工作目录,用于存放生成内容。关于OSS操作,请参见OSS控制台快速入门

  3. 单击部署。等待约3分钟,当服务状态变为运行中,表示部署成功。

  4. 服务详情页单击查看调用信息。获取EAS服务的公网调用地址和Token,用于在Dify中调用服务。

步骤三:创建Dify应用

Dify导入示例DSL文件wan-comfyui-dify.yml,本文以此说明调用ComfyUI的关键节点设置。

工作室页面,单击创建应用 > 导入 DSL 文件,在弹出的导入 DSL对话框中选择文件标签页,上传 DSL 文件后单击创建

1. 设置环境变量

  • OSS_URL:生成文件的访问路径。本文ComfyUI工作目录为oss://examplebucket/wan,因此设为https://examplebucket.oss-cn-hangzhou.aliyuncs.com/wan/output。其中oss-cn-hangzhou.aliyuncs.comOSS杭州的外网Endpoint,其他地域请参见地域和Endpoint

  • EAS_Token:步骤二中获取的服务Token。

  • EAS_URL:步骤二中获取的服务公网调用地址。

单击工作流编辑器顶部导航栏中的 ENV 图标打开环境变量配置面板,单击 + 添加环境变量 分别添加上述三个环境变量及其对应值。

2. 开始节点设置输入变量

将正反向提示词等动态参数设为变量,供每次调用时输入。

开始节点的输入字段中分别添加 positive_promptnegative_prompt 两个变量,字段类型均选择段落,最大长度设为 10000,并勾选必填

3. 配置POST请求(获取Prompt ID)

3.1 设置请求地址

EAS_URL后追加/prompt构成POST请求地址。

PromptID_url 节点的设置页签中,添加输入变量 eas_prompt_url 并引用环境变量 EAS_URL,代码区域(Jinja2)输入 {{ eas_prompt_url }}prompt

3.2 构造并发起POST请求

配置URL、HEADERSBODY。其中BODY为导出的ComfyUI工作流JSON(创建及导出参见通过WebUI使用),并将需要动态修改的参数(如提示词、种子数等)替换为Dify中的变量。

请求方法选择 POSTURL 中引用 PromptI 节点的 output 变量。HEADERSContent-Type 设为 application/jsonAuthorization 引用环境变量 EAS_TokenBODY 选择 JSON 类型,在 CLIPTextEncode 节点的 inputs.text 字段中,分别引用开始节点的 positive_promptnegative_prompt 变量。

3.3 获取Prompt ID

从返回结果中提取prompt_id,用于后续轮询结果。

def main(arg: str) -> dict:
    data = json.loads(arg)
    return {"result": data["prompt_id"]}

4. 配置轮询逻辑(获取推理结果)

使用prompt_id循环发起GET请求,检查任务状态。

4.1 设置请求地址

EAS_URL后追加history/<prompt_id>构成GET请求地址。其中<prompt_id>为上一步的结果。

Filename_URL 模板节点中,设置输入变量 eas_filename_url(来源为环境变量 EAS_URL)和 result(来源为上一步输出),并在代码区域输入 Jinja2 表达式 {{ eas_filename_url }}history/{{ result }}

4.2 根据prompt_id发起GET请求

配置HTTP节点获取prompt_id执行内容:请求方法选择GET,在URL栏中通过数据引用拼接动态请求地址。在HEADERS中添加一行,键为Authorization,值引用环境变量EAS_TokenBODY选择none,开启验证 SSL 证书开关。

4.3 延时等待

在每次轮询之间插入代码节点,执行time.sleep(12),避免请求过于频繁。

import time
def main()-> dict:
    time.sleep(12)
    return {
        "result": ""
    }

4.4 判断执行结束

返回结果中有prompt_id表示推理已完成。

循环终止条件中配置规则:引用上游 HTTP 请求节点的 {x} body,条件选择包含,值填写 prompt_id。将最大循环次数设置为 50

5. 拼接文件地址并展示结果

任务完成后,从轮询结果中提取文件名,与OSS_URL拼接形成可公开访问的链接,在Dify”结束”节点中展示。

5.1 获取推理结果

该节点配置与4.2的节点配置相同。

5.2 提取文件名

代码执行节点中,添加输入变量 input_str(映射到获取推理结果节点的 body),代码如下:

import json
def main(input_str: str) -> dict:
    data = json.loads(input_str)
    images = []
    image_names = []
    first_key = next(iter(data))
    status = data[first_key]["status"]
    if status["completed"] and status["status_str"] == "success":
        images = data[first_key]["outputs"]["28"]["images"]
    for img in images:
        image_names.append(img["filename"])
    # 将列表转换为字符串
    image_names_str = ",".join(image_names)
    return {
        "result": image_names_str,
    }

5.3 拼接文件访问地址

将文件名与OSS_URL拼接,形成可访问的公网链接,在Dify应用中展示。

重要

需确保OSS bucket已设置为公共读权限,详情见Bucket ACL

在 OSS 控制台对应 Bucket 的管理页面,选择左侧导航栏权限控制 > 读写权限,在 Bucket ACL 区域选择公共读,然后单击设置

模板转换节点中,添加输入变量 arg1(映射到筛选结果的 result)和 OSS_URL(映射到环境变量),Jinja2 模板设为 {{ OSS_URL }}{{ arg1 }}。在直接回复节点中,使用 Markdown 图片语法 ![这是图片](模板转换/output) 引用拼接后的公网链接进行展示。

步骤四:测试应用

Dify单击右上角预览,输入正反向提示词。对话框中输入任意文字(工作流未使用该字段),发送后等待生成结果。

例如,positive_prompt 输入 一个小狗在草地上奔跑negative_prompt 输入画面质量排除项(如过曝、细节模糊、低质量等)。Bot 返回工作流执行结果及生成的图片,表示流程执行成功。

生产应用建议

  • 安全性:在生产环境中,将OSS Bucket设置为公共读存在数据安全风险。建议限制只允许特定IPVPC访问,详情见Bucket Policy

  • 稳定性与成本:合理设置轮询等待时间。间隔过短会增加API调用次数和服务器负载,可能产生不必要费用;间隔过长则增加用户等待时间。建议根据任务平均耗时调整。

常见问题

  1. 为什么无法访问生成的图片或视频链接?

    请检查以下几点:

    • OSS Bucket是否已设置为公共读权限。

    • Dify中配置的OSS_URL环境变量是否正确,特别是OSS访问域名是否与Bucket所在地域匹配。

  2. 工作流一直卡在轮询步骤怎么办?

    通常是EAS服务端任务未能成功完成。请登录PAI控制台,查看对应EAS服务的实时日志,排查运行时错误。