ComfyUI - 客户端、服务端



概览

概览

Comfy服务器运行在aiohttp框架之上,后者又使用asyncio

从服务器到客户端的消息由套接字消息通过服务器的send_sync方法发送,该方法是PromptServer(在server.py中定义)的一个实例,它们由在api.js中注册的套接字事件侦听器处理参见消息

客户端到服务器的消息由api. js中定义的api.fetchApi()方法api.js,由服务器定义的http路由处理参见路由

当您对请求进行排队时,客户端会提交整个工作流(小部件值和所有值)。在您向队列发送请求后,服务器不会收到您所做的任何更改。如果您想在执行期间修改服务器行为,您需要路由。


Messages

Messages

在执行期间(或队列状态发生变化时),PromptExecutor通过PromptServersend_sync方法将消息发送回客户端。

这些消息由api.js中定义的套接字事件侦听器接收(在撰写第90行时,或搜索this.socket.addEventListener),它为任何已知的消息类型创建一个CustomEvent对象,并将其分派给任何注册的侦听器。

扩展可以按照标准Javascript习惯用法注册以接收事件(通常在setup()函数中完成):

api.addEventListener(message_type, messageHandler);

如果message_type不是内置的,它将自动添加到已知消息类型列表中。将使用CustomEvent对象调用消息messageHandler,该对象扩展套接字引发的事件以添加.detail属性,这是服务器发送的数据的字典。因此,用法通常如下:

function messageHandler(event) {
    if (event.detail.node == aNodeIdThatIsInteresting) {
        // do something with event.detail.other_things
    }
}

内置消息类型

在执行期间(或队列状态发生变化时),PromptExecutor通过PromptServersend_sync方法将以下消息发送回客户端。扩展可以注册为其中任何一个的侦听器。

事件数据
execution_start当提示即将运行时prompt_id
execution_error当执行过程中发生错误时prompt_id,加上附加信息
execution_interrupted当执行被节点停止时InterruptProcessingExceptionprompt_idnode_idnode_typeexecuted(被执行节点的列表)
execution_cached在执行开始时prompt_idnodes(因为可以使用缓存的输出而被跳过的节点列表)
executing当一个新节点即将被执行时node(节点ID或None表示完成),prompt_id
executed当一个节点返回一个用户界面元素node``prompt_id, output
progressDuring execution of a node that implements the required hooknode (node id), prompt_id, value, max
statusWhen the state of the queue changesexec_info, a dictionary holding queue_remaining, the number of entries in the queue

使用已执行

尽管有这个名称,但executed消息不会在节点完成执行时发送(与executing不同),而是仅在节点返回用户界面更新时发送。

为此,main函数需要返回字典而不是元组:

# at the end of my main method
        return { "ui":a_new_dictionary, "result": the_tuple_of_output_values }

a_new_dictionary然后将作为executed消息中的output值发送。如果节点没有输出,则可以省略result键(例如,参见nodes.pySaveImage的代码)


自定义消息类型

如上所述,在客户端,只需注册为唯一消息类型名称的侦听器即可添加自定义消息类型。

api.addEventListener("my.custom.message", messageHandler);

在服务器上,代码同样简单:

from server import PromptServer
# then, in your main execution function (normally)
        PromptServer.instance.send_sync("my.custom.message", a_dictionary)

获取 node_id

大多数内置消息都在node的值中包含当前nodeid。您可能也想这样做。

node_id通过隐藏输入在服务器端可用,该输入是通过INPUT_TYPES字典中的hidden键获得的:

    @classmethod    
    def INPUT_TYPES(s):
        return {"required" : { }, # whatever your required inputs are 
                "hidden": { "node_id": "UNIQUE_ID" } } # Add the hidden key

    def my_main_function(self, required_inputs, node_id):
        # do some things
        PromptServer.instance.send_sync("my.custom.message", {"node": node_id, "other_things": etc})

路由

路由

getpost方法,可以通过在server.py中搜索@routes找到。当您在Web客户端中提交工作流时,它会被发布到/prompt,该prompt_idnumber(队列中的位置),或者如果验证失败则返回errornode_errors。提示队列在execution.py中定义,它还定义了PromptExecutor类。

内置路由

server.py定义以下路由:

路径获取/发布目的
/get加载舒适的网页
/embeddingsget检索可用嵌入名称的列表
/extensionsget检索注册WEB_DIRECTORY
/upload/imagepost上传图像的扩展列表
/upload/maskpost上传蒙版
/viewget@routes.get("/view") in server.py
/view_metadata/getretrieve metadata for a model
/system_statsgetretrieve information about the system (python version, devices, vram etc)
/promptgetretrieve current status
/promptpostsubmit a prompt to the queue
/object_infogetretrieve details of all node types
/object_info/{node_class}getretrieve details of one node type
/historygetretrieve the queue history
/history/{prompt_id}getretrieve the queue history for a specific prompt
/historypostclear history or delete history item
/queuegetretrieve the state of the queue
/interruptpoststop the current workflow
/freepostfree memory by unloading specified models

自定义路由

如果您想在执行期间从客户端向服务器发送消息,您将需要添加到服务器的自定义路由。对于任何复杂的事情,您都需要深入了解aiohttp框架文档,但大多数情况下可以处理如下:

from server import PromptServer
from aiohttp import web
routes = PromptServer.instance.routes
@routes.post('/my_new_path')
async def my_function(request):
    the_data = await request.post()
    # the_data now holds a dictionary of the values sent
    MyClass.handle_my_message(the_data)
    return web.json_response({})

除非你知道你在做什么,否则不要试图在类中定义my_function@routes.post装饰器做了很多工作!相反,定义上面的函数,然后调用类方法。

如果不更改任何内容,也可以定义@routes.get

客户端可以通过发送带有类似代码的FormData对象来使用这个新路由,这将导致the_data,在上面的代码中,包含messagenode_id键:

import { api } from "../../scripts/api.js";
function send_message(node_id, message) {
    const body = new FormData();
    body.append('message',message);
    body.append('node_id', node_id);
    api.fetchApi("/my_new_path", { method: "POST", body, });
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值