comfyui 代码结构分析

comfyui的服务器端是用aiohtttp写的,webui是fastapi直接构建的,但是其实comfyui的这种设计思路是很好的,也许我们不需要在后端起一个复杂的前台,但是可以借助json结构化pipeline,然后利用node节点流把整个流程重新映射出来。有些串联的pipeline是比较复杂的,但是串联起来可以实现一些比较好的功能,而这些功能其实可以被放在一个框架中训练,这是很值得思考和算法化的地方。

1.启动

pip install -r requirements.txt

2.代码分析

main.py->
comfy->cli_args.py:server = server.PromptServer(loop)->- 
q = execution.PromptQueue(server)->init_custom_nodes()->nodes.py->load_custom_node()->load_custom_nodes()threading.Thread(target=prompt_worker,daemon=True,args=(q,server,)).start()- prompt_worker()->- queue_item = q.get() -> self.queue- item,item_id = queue_item   prompt_id = item[1]- e.execute(item[2],prompt_id,item[3],item[4]) ->-- with torch.inference_mode() ->-- for x in prompt: recursive_output_delete_if_changed(prompt,self.old_prompt,self.outputs,x)->--- inputs = prompt[unique_id]['inputs'] class_type = prompt[unique_id]['class_type'] class_def = nodes.NODE_CLASS_MAPPINGS[class_type] ->--- input_data_all = get_input_data(inputs,class_def,unique_id,outputs) ->--- is_changed = map_node_over_list(class_def,input_data_all,"IS_CHANGED") ->--- results.append(getattr(obj,func)(**slice_dict(input_data_all,i)))loop.run_until_complete(run(server,address,port,...))

comfyui中主要实现node节点的就是getattr(obj,func)方法,实现之后再存入节点中,下次取。

nodes.py 中存了大量的节点,是提前定义的,comfy_extras中也存了很多后来加入的节点,都放在NODE_CLASS_MAPPINGS中。

comfy中实现了具体的方法,当安装外部插件时,新增的后端代码放在custom_nodes中,前端代码放在web中,comfyui中的前端代码都在web/extension/core中,还算是一个前后分开的项目。

具体的节点调用方法,我这里有个简单的工作流,尝试着走完全流程来看下结果:

{"last_node_id": 9,"last_link_id": 9,"nodes": [{"id": 7,"type": "CLIPTextEncode","pos": [413,389],"size": {"0": 425.27801513671875,"1": 180.6060791015625},"flags": {},"order": 3,"mode": 0,"inputs": [{"name": "clip","type": "CLIP","link": 5}],"outputs": [{"name": "CONDITIONING","type": "CONDITIONING","links": [6],"slot_index": 0}],"properties": {"Node name for S&R": "CLIPTextEncode"},"widgets_values": ["text, watermark"]},{"id": 5,"type": "EmptyLatentImage","pos": [473,609],"size": {"0": 315,"1": 106},"flags": {},"order": 0,"mode": 0,"outputs": [{"name": "LATENT","type": "LATENT","links": [2],"slot_index": 0}],"properties": {"Node name for S&R": "EmptyLatentImage"},"widgets_values": [512,512,2]},{"id": 8,"type": "VAEDecode","pos": [1209,188],"size": {"0": 210,"1": 46},"flags": {},"order": 5,"mode": 0,"inputs": [{"name": "samples","type": "LATENT","link": 7},{"name": "vae","type": "VAE","link": 8}],"outputs": [{"name": "IMAGE","type": "IMAGE","links": [9],"slot_index": 0}],"properties": {"Node name for S&R": "VAEDecode"}},{"id": 3,"type": "KSampler","pos": [863,186],"size": {"0": 315,"1": 262},"flags": {},"order": 4,"mode": 0,"inputs": [{"name": "model","type": "MODEL","link": 1},{"name": "positive","type": "CONDITIONING","link": 4},{"name": "negative","type": "CONDITIONING","link": 6},{"name": "latent_image","type": "LATENT","link": 2}],"outputs": [{"name": "LATENT","type": "LATENT","links": [7],"slot_index": 0}],"properties": {"Node name for S&R": "KSampler"},"widgets_values": [710912628627374,"randomize",20,8,"dpmpp_3m_sde_gpu","normal",1]},{"id": 6,"type": "CLIPTextEncode","pos": [415,186],"size": {"0": 422.84503173828125,"1": 164.31304931640625},"flags": {},"order": 2,"mode": 0,"inputs": [{"name": "clip","type": "CLIP","link": 3}],"outputs": [{"name": "CONDITIONING","type": "CONDITIONING","links": [4],"slot_index": 0}],"properties": {"Node name for S&R": "CLIPTextEncode"},"widgets_values": ["beautiful scenery nature glass bottle landscape, , purple galaxy bottle,"]},{"id": 9,"type": "SaveImage","pos": [1451,189],"size": [210,270],"flags": {},"order": 6,"mode": 0,"inputs": [{"name": "images","type": "IMAGE","link": 9}],"properties": {},"widgets_values": ["ComfyUI"]},{"id": 4,"type": "CheckpointLoaderSimple","pos": [26,474],"size": {"0": 315,"1": 98},"flags": {},"order": 1,"mode": 0,"outputs": [{"name": "MODEL","type": "MODEL","links": [1],"slot_index": 0},{"name": "CLIP","type": "CLIP","links": [3,5],"slot_index": 1},{"name": "VAE","type": "VAE","links": [8],"slot_index": 2}],"properties": {"Node name for S&R": "CheckpointLoaderSimple"},"widgets_values": ["revAnimated_v122.safetensors"]}],"links": [[1,4,0,3,0,"MODEL"],[2,5,0,3,3,"LATENT"],[3,4,1,6,0,"CLIP"],[4,6,0,3,1,"CONDITIONING"],[5,4,1,7,0,"CLIP"],[6,7,0,3,2,"CONDITIONING"],[7,3,0,8,0,"LATENT"],[8,4,2,8,1,"VAE"],[9,8,0,9,0,"IMAGE"]],"groups": [],"config": {},"extra": {},"version": 0.4
}

Load Checkpoint->CheckpointLoaderSimple
input_data_all:{'ckpt_name': ['revAnimated_v122.safetensors']}
obj:<nodes.CheckpointLoaderSimple object at 0x7f3f9b3af640>
func:load_checkpoint
nodes.py->CheckpointLoaderSimple.load_checkpoint()
- RETURN_TYPES=("MODEL","CLIP","VAE")=右边的节点;FUNCTION="load_checkpoint"节点中的方法
- INPUT_TYPES=要输入的节点
- out = comfy.sd.load_checkpoint_guess_config(ckpt_path,...)->
-- sd = comfy.utils.load_torch_file(ckpt_path)
-- model = model_config.get_model(sd,"model.diffusion_model.")
-- model.load_model_weights()
-- vae = VAE(sd=vae_sd)
-- clip = CLIP(clip_target, embedding_directory=embedding_directory)
-- m, u = clip.load_sd(clip_sd, full_model=True)
-- model_patcher = comfy.model_patcher.ModelPatcher()
[(<comfy.model_patcher.ModelPatcher object at 0x7f35fc07dab0>, <comfy.sd.CLIP object at 0x7f35fc1937f0>, <comfy.sd.VAE object at 0x7f35ffd36320>)]CLIP Text Encode(Prompt)->CLIPTextEncode
input_data_all:{'text': ['beautiful scenery nature glass bottle landscape, , purple galaxy bottle,'], 'clip': [<comfy.sd.CLIP object at 0x7f35fc1937f0>]}
obj:<nodes.CLIPTextEncode object at 0x7f35fc193760>
func:"encode"
nodes.py->CLIPTextEncode.encode()
- RETURN_TYPES=("CONDITIONING") FUNCTION="encode"  INPUT_TYPES {"required":{"text":("STRING",{"multiline":True}),"clip":("CLIP",)}}
- tokens = clip.tokenize(text)
-- comfyui.comfy.sd.CLIP.tokenize->
-- self.tokenizer.tokenize_with_weights(text,return_word_ids)
--- comfyui.comfy.sd1_clip.SD1Tokenizer.tokenize_with_weights(text,..)
- cond,pooled = clip.encode_from_tokens(tokens,return_pooled=True)
cond:1x77x768 pooled:1x768Empty Latent Image->EmptyLatentImage
input_data_all:{'width': [512], 'height': [512], 'batch_size': [2]}
obj:<nodes.EmptyLatentImage object at 0x7f36006d7640>
func:"generat"
nodes.py->EmptyLatentImage.generate
- latent = torch.zeros([batch_size, 4, height // 8, width // 8], device=self.device)
({"samples":latent})KSampler->Ksampler
input_data_all:'seed': [50385774161222], 'steps': [20], 'cfg': [8.0], 'sampler_name': ['dpmpp_3m_sde_gpu'], 'scheduler': ['normal'], 'denoise': [1.0], 'model': [<comfy.model_patcher.ModelPatcher object at 0x7f35fc07dab0>], 'positive':....
obj:<nodes.KSampler object at 0x7f35fc193b20>
func:sample
nodes.py->Ksampler.sample
- common_ksampler(...)->
-- latent_image = latent['sample']
-- noise = comfy.sample.prepare_noise(latent_image, seed, batch_inds)
-- samples = comfy.sample.sample(model, noise, steps, cfg, sampler_name, scheduler, positive, negative, ....)
--- real_model, positive_copy, negative_copy, noise_mask, models = prepare_sampling(model, noise.shape, positive, negative, noise_mask)
--- sampler = comfy.samplers.KSampler(real_model, steps=steps, device=model.load_device, sampler=sampler_name, scheduler=scheduler, denoise=denoise, model_options=model.model_options)
--- samples = sampler.sample(noise, ....)....

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/572569.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

pytorch实战-2张量类型处理

1 图像类型 有多种库可加载图像&#xff0c;如imageio&#xff0c; torchvision等。张量对图像维度排序一般为通道数x图像长x图像宽 1.1 imageio import imageioimg_t imageio.imread(img_path) 1.2 改变布局 可对tensor调用permute方法改变张量某个维度元素排序 和转置类…

单链表的基本操作

链表 文章目录 链表创建链表单链表实现一&#xff1a;实现二&#xff1a;错例 循环链表单独创建逐节点创建约瑟夫环问题 删除节点实现方式一&#xff1a;实现方式二&#xff1a;删除节点并建立新链表 逆置链表实现&#xff1a; 链表排序实现一&#xff1a;实现二&#xff1a;实…

Linux 系统 docker搭建LNMP环境

1、安装nginx docker pull nginx (默认安装的是最新版本) 2、运行nginx docker run --name nginx -p 80:80 -d nginx:latest 备注&#xff1a;--name nginx 表示容器名为 nginx -d 表示后台运行 -p 80:80 表示把本地80端口绑定到Nginx服务端的 80端口 nginx:lates…

mac-git上传至github(ssh版本,个人tokens总出错)

第一步 git clone https://github.com/用户名/项目名.git 第二步 cd 项目名 第三步 将本地的文件移动到项目下 第四步 git add . 第五步 git commit -m "添加****文件夹" 第六步 git push origin main 报错&#xff1a; 采用ssh验证 本地文件链接公钥 …

【办公类-21-11】 20240327三级育婴师 多个二级文件夹的docx合并成docx有页码,转PDF

背景展示&#xff1a;有页码的操作题 背景需求&#xff1a; 实操课终于全部结束了&#xff0c;把考试内容&#xff08;docx&#xff09;都写好了 【办公类-21-10】三级育婴师 视频转文字docx&#xff08;等线小五单倍行距&#xff09;&#xff0c;批量改成“宋体小四、1.5倍行…

【力扣hot100】1. 两数之和 49.字母异位词分组 128. 最长连续序列

目录 1. 两数之和题目描述做题思路参考代码 49.字母异位词分组题目描述做题思路参考代码 128. 最长连续序列题目描述做题思路参考代码 1. 两数之和 题目描述 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数…

深度学习编译工具链中的核心——图优化。

图优化 图优化的概念&#xff1a; 深度神经网络模型可以看做由多个算子连接而成的有向无环图&#xff0c;图中每个算子代表一类操作&#xff08;如乘法、卷积&#xff09;&#xff0c;连接各个算子的边表示数据流动。在部署深度神经网络的过程中&#xff0c;为了适应硬件平台…

[AIGC] 对比MySQL全文索引,RedisSearch,和Elasticsearch的详细区别

全文搜索是数据库和搜索引擎的重要功能。这个功能能在一个或多个列中查找用户查询的文本&#xff0c;这对诸如电子商务网站和检索大量文本数据的应用是必需的。在这篇文章中&#xff0c;我们将详细对比三种主流全文搜索技术&#xff1a; MySQL全文索引&#xff0c;Redis的Redis…

2024年 导出环境依赖requirements.txt

2024年 导出环境依赖 一、前言 有时候需要导出环境依赖&#xff0c;遂记录一下这个短短的步骤 二、具体步骤 1、使用pip进行安装和管理环境 安装导出依赖的库pipreqs pip install pipreqs将环境依赖项导出到当前目录的requirements.txt文件&#xff0c;编码格式用utf-8 …

YoloV5改进策略:BackBone改进|ECA-Net:用于深度卷积神经网络的高效通道注意力

摘要 本文使用ECA-Net注意力机制加入到YoloV5中。我尝试了多种改进方法&#xff0c;并附上改进结果&#xff0c;方便大家了解改进后的效果&#xff0c;为论文改进提供思路。&#xff08;更新中。。。。&#xff09; 论文&#xff1a;《ECA-Net&#xff1a;用于深度卷积神经网…

解决方案:如何安装neo4j软件

文章目录 一、安装JDK二、安装neo4j 一、安装JDK 第一步先安装JDK&#xff0c;因为neo4j环境需要JDK&#xff0c;过程比较多&#xff0c;截图如下&#xff1a; 安装JDK网址 https://www.oracle.com/java/technologies/downloads winR&#xff0c;输入cmd&#xff0c;再输入j…

【计算机考研】408到底有多难?

你真以为大家是学不会408吗&#xff1f; 不是&#xff01;单纯是因为时间不够&#xff01;&#xff01;&#xff01; 再准确一些就是不会分配时间 408的知识其实并不难&#xff0c;要说想上130那确实有难度&#xff0c;但是100在时间充裕的情况下还是可以做到的 我本人是双…