20250830算法题解析-偏爱的字符串

废话

最近博客突然打不开了,看了一眼是PHP开始报莫名奇妙的错误。这个博客主题是当年随便从网上找的一个,历经多个PHP和wordpress大版本变化还凑合能正常展示已经非常不易了,中途历经多次魔改和打补丁。原计划是在10周年之前把所有文章彻底重写一次换掉wordpress,但以我这个鸽子的风格看了一眼还有1个月时间显然不现实,所以这次我直接放弃了,直接用官方的模板改了改css就成了现在这个样子。

看了一眼历史记录,我的第一篇博客还是在大学时候联系ubuntu linux搭建wodpress后写的,当时正好是大一的期末即将C语言考试,写了一系列的C语言教程当作期末复习。众所周知我的算法比较弱(相比于栋神或然妞),并且从未在算法上怎么努力过,就这么得过且过了10年,做深度算法的分析屈指可数。印象中比较清晰的只有KMP算法、Levenshtein距离、上班时为了优化聊天室pin消息new红点的算法、为了模仿outlook日程布局设计的排版算法。

前段时间在群里看到有人在讨论一个算法题,我简单分享了思路,但懒得动手。这次正好做个深度解析。顺带一提虽然现在ai编程非常的火,工作的话因为讲究效率优先有时候无需考虑原理,只要结果对就行。但长期来看我的态度还是要磨练下基本功,不然AI错了你根本纠正不回来,所以本次不会使用任何AI补全,完全一步步手动实现再逐步优化。

原题目

https://www.nowcoder.com/practice/294da7ea5f184655a31bf659035fc874?tab=note

视频版

https://www.bilibili.com/video/BV1cChqzqEh8

描述

小李天生偏爱一些字符,对于一个字符串,他总是想把字符串中的字符变成他偏爱的那些字符。如果字符串中某个字符不是他所偏爱的字符,称为非偏爱字符,那么他会将该非偏爱字符替换为字符串中距离该字符最近的一个偏爱的字符。这里的距离定义即为字符在字符串中的对应下标之差的绝对值。如果有不止一个偏爱的字符距离非偏爱字符最近,那么小李会选择最左边的那个偏爱字符来替换该非偏爱字符,这样就保证了替换后的字符串是唯一的。小李的所有替换操作是同时进行的。
假定小李有 m 个偏爱的字符,依次为c1,c2…cm,当小李看到一个长度为 n 的字符串 s 时,请你输出小李在进行全部替换操作后形成的字符串。

输入描述:

第一行输入两个正整数n,m。
接下来一行输入m个字符c1,c2…cm,每两个字符之间用空格隔开,表示小李偏爱的字符。

接下来一行输入一个字符串s。

1≤n≤1e5,1≤m≤26,保证题目中所有的字符均为大写字符,小李偏爱的字符互不相同,且偏爱字符至少出现一次。

输出描述:

输出一行字符串,表示小李将给定的字符串s替换后形成的字符串。

输入:

输出:

说明:

题目分析

我做算法题因为没有限时,所以一般来说我都是先用暴力手段写正确结果,再逐步优化

题目里废话实在太多,翻译成人话就是把后续所有输入都改成指定的几个字母,以最近的为准,如果距离一样用左边的。

暴力版本

加一点优化

根据刚才的运行结果,如果尝试打印寻找过程

注意到每次左侧寻找的距离都是递增的,so优化思路就是不要每次都从头开始搜,如果还没出现新的偏爱字符,那上一次寻找的结果直接+1就是本次搜索的结果,如果距离右侧最新的偏爱字符过半了,那就是右侧的结果。因此之前循环的状态需要记录下左侧和右侧的距离或索引。

TODO 待编写代码

再加一点优化

按上面的思路,如果能提前知道哪些位置是偏爱字符,那么根本不需要逐个字符判断、搜索、替换,可以直接按偏爱字符的位置就能计算最终的结果。你会发现最终结果只和偏爱字符的位置有关,和其他输入的字符无关,你甚至都不需要读入其他字符也能计算出最终结果

TODO 待编写代码

另类思路

按上面所说既然结果和其他字符无关,只需要特殊字符和对应的位置+总字符串长度就能计算的话。实时处理也是可能的,这也是目前AI输入输出常见的表现形式,打字机效果。当输入一个字符后,实时输出最终结果,当发现前几个字符结果不对了,删除前n个字符后纠正回正确的字符。这种算法不需要预处理,但因为无法预知后续输入所以必须有纠正的过程出现。实际实现逻辑只需记录最后一次输入的偏爱字符和当前字符和最后一次输入的偏爱字符距离,即可知道是应该打印最后一次的偏爱字符,还是应该删除前n个距离当前输入的偏爱字符更近的字符。

TODO 待编写代码

20250503jupyter-mcp-server自动化

背景

20250131jupyter自动修改IDEA项目SDK、获取GIT信息

20230429 IaC之IDE,也许是下一个ChatIDE?

在我尝试将jupyter kotlin kernel 内嵌到IDEA的JVM后,用jupyter控制IDEA用了很长时间,但除了utils工具类之外IDEA的openapi和公开的方法基本都是为了UI而编写的异步代码,这在自动化过程中获取返回值非常不方便。我预期的是直接复制粘贴官方源码稍微改改就能用,不想对官方代码做大的结构修改。

继IDEA官方编写MCP后,我发现二月份的时候jupyter也有MCP server了。

datalayer在尝试用ai把jupyter自动化,使用自然语言描述数据处理的请求然后生成notebook并执行python代码,我一看这不正好是我想要的么。

如果我人工能操作jupyterlab完成结果,相比调整kotlin脚本的控制流,我只需要糊一点python代码就能代替我手工操作的部分

原理

jupyter mcp server的代码非常的少,我想要的其实是排除mcp的部分,去掉注解改一改直接就能用

本质上是直接调用了jupyter lab的接口获取websocket,通过jupyter lab的collaboration扩展通道操作notebook

过程记录

安装jupyter lab,注意这里新增了jupyter-collaboration

实测发现之前的安装命令不好使了,日志报错如下

很明显kernel接到了jupyterlab的请求但反序列化失败了,注意到jupyterlab没指定版本

根据上一次安装记录对比版本号可发现,是最近jupyterlab的更新4.4.0时header新增了一个字段,而kotlin kernel反序列化不接受未定义的字段导致,因此降级到4.3的最后一个版本4.3.6

还是记录下版本号方便后续对比

降级后测试原来的功能正常

第一次先使用再建一个独立virtualenv防止破坏环境

按官方文档安装依赖,修改官方的源码作为测试脚本。因为官方是使用独立进程的python kernel运行脚本,而我是要让一个已经运行了的内嵌kernel执行,所以需要指定下当前的kernel_id复用。否则代码会启动一个新的python kernel执行kotlin脚本就和我的预期不符了

既然python文件单独执行是能成功的,也就意味着python kernel也能执行相同的代码,而一个jupyterlab可以同时开启notebook分配不同的kernel。既然如此已经有一个现成的python环境了为什么不直接用呢?因此续尝试合并这个独立的python环境到jupyterlab的python环境

为了防止安装新的依赖破坏现有版本,pip list记录下当前的依赖版本后再安装新的依赖,通过对比安装前后差异可以发现都是datalayer实现的库,这些库用于和jupyterserver交互并且除了websocket没有什么额外的垃圾依赖进来

合并后的安装命令

 

然后就可以尝试将脚本放入另一个notebook中了,kernel如下

执行效果如下

到此为止用python半自动的控制IDEA的目标达成,python代码可以控制IDEA并且能调用IDEA JVM的所有代码,同时执行过程全部可见、可追溯、可重放。这样后续就可以看实际情况逐渐把这个过程的控制权交给AI。
但我没想好的是:当一个程序有能力对自身进行修正的时候,让AI有这么强大的行动能力会不会带来额外的安全问题

后续计划

jupyterlab的启动内置到idea插件中,全自动化整个初始化流程
升级embedded kotlin jupyter core兼容最新的jupyterlab的header字段

参考

https://github.com/dev-assistant/skykoma-plugin-idea

https://github.com/datalayer/jupyter-mcp-server/tree/main/jupyter_mcp_server 

 

20250323postwoman/hoppscotch私有化部署

背景

尝试搭建个私有化的postman玩

视频版见B站 https://www.bilibili.com/video/BV1SDoBYrEjC

准备

一台虚拟机

一个域名

一个SMTP服务器:我用的是qq的,需要一个额外授权码当密码用

安装docker和docker-compose

准备环境配置

注:安全起见SMTP密码在视频发布后会失效

准备compose文件

首次启动

注意首次需要初始化一下数据库

进入后台并试玩

从http://postwoman.hylstudio.local/admin登录完成首次设置后可用

todo

TODO 扩展一种本地的密码登录或CAS登录?

参考

https://docs.hoppscotch.io/documentation/self-host/getting-started

https://docs.hoppscotch.io/documentation/self-host/community-edition/install-and-build

20250201AI应用相关技术调研

背景

20230515LLM笔记

继上次调研后,很久没更新AI相关技术了,这次一并更新。

应用

全本地部署的ai https://github.com/mudler/LocalAI

应用框架

数据索引框架 data index framework

llamaindex

https://docs.llamaindex.ai/en/stable/ https://github.com/run-llama/llama_index

https://docs.llamaindex.ai/en/stable/use_cases/agents/ Property Graph Index可以用neo4j

https://docs.llamaindex.ai/en/stable/module_guides/storing

Vector Stores:Elasticsearch、Lantern、OpenSearch、Postgres、Qdrant

Document Stores:Mongo、Redis

Index Stores:Mongo、Redis

Chat Stores:Redis

Key-Value Stores:Mongo

Note: At the moment, these storage abstractions are not externally facing. https://docs.llamaindex.ai/en/stable/module_guides/storing/customization/

ai agents framework

自动化框架 restack

https://www.restack.io/

agents框架 eko

https://github.com/FellouAI/eko

pydantic

https://github.com/pydantic/pydantic-ai

composio

https://composio.dev/swe-kit/

https://github.com/ComposioHQ/composio/tree/master/python/swe?utm_source=website

https://docs.composio.dev/framework/llamaindex

https://docs.composio.dev/framework/langchain

比langchain底层的工作流agent编排框架 LangGraph

prompt框架

https://docs.langchain4j.dev/

https://github.com/langchain4j/langchain4j

https://docs.spring.io/spring-ai/reference/index.html

https://github.com/spring-projects/spring-ai

xinference

AI上下文协议框架MCP

https://modelcontextprotocol.io/introduction

https://modelcontextprotocol.io/quickstart

https://github.com/modelcontextprotocol

https://github.com/modelcontextprotocol/servers

知识库

上层

https://github.com/getzep/graphiti

向量数据库

https://lancedb.github.io/lancedb/concepts/storage/ embeddedable|localfile|s3

https://www.trychroma.com/ embeddedable|localfile

https://milvus.io/ need etcd、Pulsar embeddedable|s3

es dense_vector

20250131jupyter自动修改IDEA项目SDK、获取GIT信息

背景

20230429 IaC之IDE,也许是下一个ChatIDE?

在2023年4月的时候从phodal的项目中知道了jupyter core是可以embedded之后,我就尝试将它embedd进了IDEA自身以获取全量IDE的自动化能力

源码:https://github.com/dev-assistant/skykoma-plugin-idea

示例:https://github.com/dev-assistant/skykoma-plugin-idea/blob/main/demo/demo.ipynb

因部分java项目的sdk总是没法正确识别,IDEA多年以来的bug都需要手动选下无法完成全量的自动化,所以在官方处理之前想尝试解决下。部分kotlin简写本次一并更新,同时替换掉了基于命令行的git信息获取,改成git4idea接口和官方保持一致

20250201更新:

今天发现官方有了mcp-server的实现,以及已经有了基于MCP的客户端来集成但功能有限,我的插件甚至比MCP的出现(2024年11月25日)和IDEA官方MCP实现(2024年12月9日)要早得多(2023年4月)

自动设置SDK

注意到源码com.intellij.openapi.roots.ui.configuration.ProjectConfigurableUi就是project structure的实现

myProjectJdkConfigurable内容修改时候会触发


而当myLanguageLevelCombo变动时会触发


所以最终实际修改的是LanguageLevelProjectExtensionImpl.getInstanceImpl(myProject).currentLevel

也不难发现是SDK选择后生效的代码

而从ProjectJdkTable.getInstance().findJdk()等一系列方法可以快速获取想要的Sdk对象

官方初始化过程可参考

自动操作GIT

相关操作都在GitRepositoryManager里,UI操作参考GitLogBranchOperationsActionGroup即可

分支UI的操作见plugins/git4idea/resources/META-INF/plugin.xml

可以看到右键菜单是固定的一个分组+两个固定操作,分组操作里会根据选中项是否有分支和tag决定是否显示相关操作

git4idea.ui.branch.GitBranchPopupActions.RemoteBranchActions.CheckoutRemoteBranchAction

TODO

git4idea.ui.branch.GitBranchPopupActions.CheckoutAsNewBranch

TODO

com.intellij.vcs.log.ui.actions.RefreshLogAction

git4idea.actions.GitFetch

com.intellij.openapi.vcs.changes.actions.RefreshAction

 

其他自动化

可以参考官方MCP实现

https://github.com/JetBrains/mcp-server-plugin/tree/master/src/main/kotlin/org/jetbrains/mcpserverplugin

或直接翻官方的IDEA源码https://github.com/JetBrains/intellij-community照抄即可

END

20250127comfyui使用笔记

参考https://github.com/cubiq/ComfyUI_Workflows进行的demo实验,部分内容可能会过时,但只是为了玩下所以无所谓

第一个demo

  • 加载了v1-5-pruned-emaonly
  • 设置潜在空间大小
  • CLIP(Contrastive Language-Image Pre-Training)对prompt做encode
  • 采样过程KSampler:
    • 种子Seed: 数字随机数,不同的种子 = 不同的图
    • 步数Steps: 到达最终图片的步数,更多的步骤需要更多的计算时间,但可能会获得更好的合成效果。根据提示词、采样器、检查点的组合差异很大。如果不确定则取15-20
    • CFG(Classifier-free Guidance):定义图片距离提示词的距离,数值越小距离越近。如果尝试创造模型没有训练过的复杂图像更高的CFG可能会有帮助。一般来说在4-9可以覆盖所有使用场景,但会受到很多因子的影响,包括正在使用的模型checkpoints。
    • 采样器和调度器共同负责处理潜在空间中的噪音,直至在规定的步骤内生成最终图像。euler+ancestraldpmpp_2m+karras是个常用的组合
  • Vae Decode阶段:图片是在一个特殊的环境中被处理的,这个环境是潜在空间,其中有很多对模型计算有用但对人没用的信息,一旦计算完成这些数据将被转换为一些人眼看得见的东西,比如像素。

LoRA-demo

LoRA(Low-rank Adaptation)是一种快速FT(Fine-tuning)方法

基座模型

重绘模型

LoRA

可以增加或减小strength_modelstrength_clip参数的值来调整lora的影响。正常情况下这两个值是一致的,但你可以尝试不同的组合来获取不同的结果,参考文章

SDXL

SDXL模型是用1024×1024的图片训练的,由两个模型组成。虽然只用基础模型是ok的,但增强模型可能会给图片带来更多清晰的细节。

把放入ComfyUI/models/checkpoints即可,有_0.9vae结尾的文件是将一个更好的VAE融合进去的版本,也可以自己用外部的 VAE

生成过程包括基础Base阶段和增强Refiner阶段,因此步数控制变成了2个参数,Total控制总步数,Base控制的是基础模型的步数,一个比较好的原则是让基础模型的步数占比是80%

这次我们用了更高级的KSampler,它是一个很重要的节点来让我们更精确的让采样器工作,我们设置了总步数是25但同时设定了在第19步结束,注意必须让return_with_leftover_noise=enable以此来让refiner可以完成剩余的工作

SDXL引入了两个新的CLIP文本编码节点分别给基础模型和增强模型,他们增加了text_gtext_lwidth/height系列条件Text G是自然语言的提示词,你仅仅和模型说人话就行。 Text L就像SD1.x/2.x那样独立的概念词组,非常多的实验结果表明一般来说G和L设置相同的值可以让模型看起来更好的理解我们想要的是什么。后续也有实验工作流来拆开这两个提示词

目前还没有完全搞清楚这几个宽高的条件是如何影响最终的结果。通过初步测试,宽高设置为 4096 时生成的细节似乎会稍微清晰一些。为了在图像分辨率更高的情况下保持正确的宽高比,将CLIP 宽度和高度设置为潜在空间尺寸的4倍会比较好。

超分 upscale

背景介绍

  • 潜在空间和像素空间的区别

图片生成过程实际发生在潜在空间,潜在空间是GPU处理所有数据信息的地方,这些信息需要被模型(VAE)解码并被转换成像素。潜在空间解码是一个有损的过程,这个过程需要很多计算资源,越大的图片就需要越多的计算资源。这就是为什么我们在最后一个阶段才转换成像素的原因。

  • 传统超分器和基于模型的超分器区别

为了超分辨率我们可以使用像bicubic、bilinear之类的传统算法或机器学习模型来达成这个目的。一般传统方法会更快但受缩放比例影响结果一般都比较模糊。

  • 降噪参数的影响

为了找回更多的细节我们可以对图片应用二次编码,这个过程包括将图像传递给第二个KSampler并使用降噪(denoise)参数。这个参数越小图片看起来会和原始的更加接近但处理效果也就越差,如果你不关心最终图像是否和原始图像1:1,你可以增大这个参数并在第一轮就获得一个虽然略有不同但效果非常鲜明非常的结果。如果你想尽可能接近原始图片那你应该使用一个较小的降噪参数

当在像素空间超分时denoise在0.25~0.5之间时足够获得比较好的结果,当然基于模型的超分器会要求耕地的降噪参数,因为被超分的图片应当已经很好了。

一个被超分的潜在空间信息会包含非常多的噪音,所以你需要更大的降噪参数,一般来说在二次编码阶段至少要0.55

这里也有基于模型的潜在空间超分器:

总之:一个图片无论用何种方式如果已经被超分过,那么尽可能用最低的降噪参数就会获得最好的结果。基于潜在空间的超分已经足够完美因为它需要更少的资源。

对潜在空间超分

这是最简单并且最快的方式,upscale_latent.json在这个工作流中我们对潜在空间超分了1.5倍,并且在二次编码降噪参数取了0.7,不巧的是超分后的潜在空间噪音较多所以最终的图片看起来和原版不太一样,好处是资源占用比较低

传统插值法对像素超分

upscale_pixel.json在这个场景中原始图片先被解码到了像素空间,然后用传统插值法做了两倍的缩放。尽管缩放比例比之前的工作流要高但因为噪音比较少所以降噪参数0.55写的比较小

用模型对像素超分

upscale_by_model.json 这就是事情变的有趣的地方,值得一提的最好结果目前可以被基于模型的像素空间超分达成。

  1. 原始图像需要首先被从潜在空间解码
  2. 紧接着需要加载超分模型,在这个例子中用的是4x-UltraSharp,没有好模型或坏模型,每一个都有它独特的目标。适用于尝试的模型可以是RealSR, Remacri。UltraSharp和这俩可以在OpenmodelDB找到
  3. 实际超分的过程
  4. 大部分超分器用固定的超分参数训练,一般是4倍的,但也可以找到8x, 3x, 2x 甚至1x(他们通常是降噪过滤器)。我们用的是4倍的所以在这一步我们选0.5来使得最终结果是2x的
  5. 在进行二次编码之前我们需要将图片转换回潜在空间,因为SD只能工作在潜在空间,这个过程使用VAE编码节点完成。如果你没有足够的显存,图片将会被自动分片平铺并分块编码,这个过程可能会耗时较长

现在超分完成并且准备好了二次编码,这次我们选择降噪参数0.25是因为原始数据已经很好了,注意二次编码仅需要很少的步数即可

SDXL对潜在空间超分

upscale_latent_SDXL.json 这个相同的概念也同样适用于SDXL,尽管在base+refiner工作流中超分可能看起来不是那么直观 如果你对完整的超分不是那么感兴趣的话,你可以只用base基础模型执行几步创建一个草稿,然后在潜在空间进行超分,最后使用base进行二次编码,然后用refiner进行三次编码

我们在二次编码使用了高级的KSampler,但设置了start_at_step=5而不是start_at_step=0,是因为这是和设置一个较低的降噪参数等价: start_at_step = 0denoise = 1.0是一样的。这个工作流会进行潜在空间的超分所以我们需要维持这个值在较低的水平,你可以进行尝试但大概20步左右3-5步通常是ok的,等价于降噪参数设置成0.6~0.7

用模型对潜在空间超分

upscale_latent_with_model.json 像前面说的我们尽可能在潜在空间工作而不是在与像素空间反复横跳,因为在潜在空间超分会引入非常多的噪音,除非你用模型。在潜在空间用模型超分不像在像素空间的传统算法,但比传统算法要好不少 在这个工作流我们使用NNLatentUpscaler自定义节点,它兼容SD1.x和SDXL的潜在空间。被超分的图片有一点模糊但没有噪音并且我们可以通过在二次编码应用较低的降噪参数找回一些细节

用ControlNet超分

upscale_tile_controlnet.json Tile是一个非常有趣的ControlNet,确认下载它并放入ComfyUI/models/controlnet/文件夹,在这个工作流我们不需要前置处理器

Tile 获取一个图片并且使用颜色信息生成一个新的图片,如果你在第一次编码生成的图片上超分,并用相同的图片引用传递给二次编码阶段,结果的细节会变得非常多并且非常接近原始图片。这个技术非常强大并且灵活所以经常被用来作为超分的方法

  1. Tile工作在像素空间,所以我们需要从潜在空间解码
  2. 图片使用简单的nearest-exact超分了2倍,我们不需要很高的分辨率因为我们在二次编码使用了很高的降噪参数
  3. 超分后的图片被移动到了潜在空间并喂给了第二个采样器。注意:在二次编码使用超分后的图片作为基础不是严格必须的,在技术上来说可以使用空的潜在空间配合1.0的降噪参数。经过一些实验后我发现在这个工作流中这样做可以有更好的效果
  4. 加载Tile control net
  5. 我们对原始图片而不是超分后的图片应用controlnet,并使用相同的提示词作为条件,强度strength=1.0是因为我们想让最终的图片尽可能接近原始的图片 最终我们运行二次编码,你可以调整controlnet的强度和降噪参数来尝试让结果距离原始图片更远或更近,通过降低降噪参数可以更近但会在二次编码丢失更多形状细节,在这张图上0.75看起来不错。

文生图

文字提示是Stable Diffusion图片生成的基础,但这里有很多方法我们可以尝试来获得更好的结果。这些工作流探索了我们可以使用的多种方法来做图片调整

Important: 不总是很轻易预测对于一个给定的任务哪种调整方法会更好。通常来说结果都是玄学的并且预测模型做什么是不可能的。唯一的方法就是实际实验,幸好ComfyUI工作流非常擅长做比较。

单词权重

word_weighting.json 这是非常简单也最广为人知的方法,你可以给一个或一系列单词或加括号。例如closeup a photo of a (freckled) woman smiling。在这个例子中我们给freckled设置了一个更高的权重,不写的默认值是1.1,我们可以通过(freckled:1.3)这样的写法继续增加更大的权重,一般来说1.1到1.4是足够的,但具体的值还是要具体模型具体分析。你也可以通过设置小于1的值来降低权重例如(freckled:0.7)

Embedding/Textual inversion

embeddings.json Embedding是一种非常简单受欢迎的调整方式,因为非常容易训练并且有时非常的有效。

为了跑这个工作流你需要下载下面的模型并放 ComfyUI/models/embeddings

想要激活embedding的语法是embedding:FileName,文件扩展名是非必须的。例如为了使用UnrealisticDream的语法是embedding:UnrealisticDream

Embeddings的行为和标准单词是一样的,所以单词的位置会有影响。例如越早出现的单词重要性越高。在下面的例子中你可以看到不同 (embedding:UnrealisticDream:1.2), embedding:BadDream

注意: 值得注意的是embedding并不是魔法所以不能解决所有的问题,有时候反而会带来更多的问题,谨慎的使用他们并多做实验

Conditioning Concat

conditioning_concat.json 通过conditioning concat节点使用提示词是一个强大的方法,模型通常不擅长在多个不同的元素间理解上下文的多重概念,例如指定不同物体的颜色就非常困难。 这个提示词a blue ball a red bucket on the beach的成功率就非常低,大约是1/25。我们通过concat增加成功率

Conditioning Average

conditioning_average.json 有时你想合并两个概念,例如zebra-chameleon。你可以简单的用提示词但更好的选项是 conditioning average节点

Area conditioning

conditioning_area.json 有时你需要将特定的物体放在特定的位置,在不用ControlNet的情况下最简单的办法是使用area conditioning节点,语法非常简单

  1. 用提示词描述你的场景
  2. 用第二个提示词描述你想的物品
  3. 链接第二个提示词到conditioning area节点并设置区域的大小和位置。在这个例子中我们有一个768×512的潜在空间,我们想让”godzilla”在右侧。所以我们设置区域是512×512并在X轴设置了256px
  4. 连接场景提示词和特殊条件到Conditioning combine

左侧的操作是将条件组合送给KSampler的正向提示词然后等待奇迹发生,当然你也可以用这个方法放置多个物体。

注意: 源码里的工作流有一点点不一样,它先设定了2个区域然后再传递给了二次编码来使得整个画面是统一的,这是在SDXL上正常工作的好办法

Timestepping

timestepping.json

ConditioningSetTimestepRange是一个新节点也是我们目前拥有的最强文本调整工具,这个节点让你可以设置每个提示词临时开始和结束位置。假设我们有20步骤,你可以让采样器从第5步开始”画”猫然后忘掉刚才的猫继续在剩余的15步生成狗

这是一种非常有效组合提示词的方式,可以进行更高层次微调。每个提示词不必等前一个结束,但他们依然会在几步内相互融合

在这个工作流里我们尝试生成freckled African-American/Japanese woman。为了达成这个目标我们需要在降噪阶段的不同的时间点混合3个概念(freckels, Japanese, African-American)

注意: 你可以设置多个节点,每个都可以设置独立的时间。但重要的是不要有空白的时间序列。例如:一个结束于0.5第二个就应当在0~0.5之间开始,否则就会有一些步骤没条件。

GLIGEN Box

gligen_box.json 这个工作流使用dreamshaper需要提前下载

GLIGEN是一个可控的文生图模型,Comfy目前仅支持box conditioning,和之前提到的area conditioning相似。为了正常工作你需要下载GLIGEN放入ComfyUI/models/gligen文件夹

第一步是编写你的场景提示词,然后你需要为每一个你想控制的场景元素创建GLIGENTextBoxApply然后链接到GLIGENLoader

在这个例子中提示词是high quality illustration of red riding hood hugging the wolf in the forest。然后我们设置了2个GLIGEN,其中一个应用于red riding hood另一个应用于wolf并且同时设定了位置。多个节点可以直接连接最终可以共同作用于采样器

结果通常会比单个area conditioning更好但GLIGEN模型未能引起人们的关注。

Image-to-Image 图生图

一图胜千言,有时候从一个参考图片开始会比从文本开始抽奖更有效率。 在开始前请确认将input的内容放入了ComfyUI/input/.

简单的图生图

img2img_SDXL.json 最简单的图生图工作流就是从一个已有图片开始,并在采样器用小于1的降噪参数,越小的降噪参数会使结果越接近原始图像

我们当然也可以用合适的提示词来影响生成过程,在这个工作流中我们使用一个女性基础图像迁移到一个男性

注意: 我们在这个例子中使用的是SDXL,潜在空间的大小是1024x1024 但基准图片只有512x512。最好让基准图片和潜在图片保持相同的尺寸,这也是例子中对原始图片缩放的原因。一般来说对每一个图生图工作流都是这样的, 包括ControlNets。特别是aspect aspect ratio不同的时候。

unCLIP model

conditioning_unclip.json 有时你想基于某个图片的风格创建新的图片,而不是在已有图片的基础上重画。这个过程可以通过unCLIP models完成,在这个例子中我们使用sd21-unclip-h.ckpt

  1. 我们加载unCLIPCheckpointLoader节点,注意因为是SD2.1所以我们用768x768潜在空间和模型训练时的保持一致
  2. 使用CLIP Vision Encode来引用原始图片
  3. 控制的过程发生在unCLIPConditioning节点noise_augmentation定义了新图片会和原始图片有多接近,0表示最接近的,一般来说设置0.1-0.3比较好。strength权重是和其他条件的关系距离,在这个例子中是text clip。就像在文本提示词中设置的一样: (red hat:1.2).

提示: 你可能已经注意到了unCLIP有两个可用模型,sd21-unclip-l.ckptsd21-unclip-h.ckpt。一般来说-h更加精确一些,-l是用来给资源不够的场景或对速度有明确要求的场景使用

Style Model

conditioning_style.json Style model和unCLIP很相似但它是一个CLIP Vision conditioning,可以被用于任何的SD1.5模型这个例子需要下载以下模型

  1. 加载CLIP Vision模型
  2. 对原始图像编码
  3. 加载Style模型
  4. 连接提示词到Apply style model节点,并提供给KSampler采样器的正向参数。注意尽管这个节点没有提供强度权重strength参数,但技术上你可以通过timestepping来调整它。

**注意:**style模型和其他图生图模型一样不能处理它不理解的概念,一个名画或人会很容易迁移风格,但更抽象的概念可能不会有更好的结果

IPAdapter image + text

IPAdapter_basic_SDXL.json

IPAdapter是一系列非常有效的微调模型,他们可以被独立使用或配合文本、ControlNet一同使用

 

SDXL Revision

revision_SDXL.json Stability AI发布了the Revision model和其他方法很相似,但是给SDXL专用的

Revision是被用来为图片(包括多张图片)进行图文微调或变体的有效工具

注意: 为了消除任何来自文本的干扰我们使用ConditioningZeroOut节点,这是可选的。仅仅为了这个例子也就意味着因为纯粹图生图没有任何外部的干扰,稍后你可以自行修改掉这个系欸但并添加自定义的提示词

In/Out Painting

当你需要改变一个图片的细节,或你想像某个方面扩展图片的时候,在Stable Diffusion中Inpainting是一个非常有效的方法

注意当重绘时候最好使用被特别训练过的模型,他们通常后缀上标记了inpainting。虽然普通的模型也可以用来重绘,但专用的模型会有更好的效果。

**提示:**大多数图片节点都会包含蒙版编辑器,右键点击任意图像并选择Open in Mask Editor即可。或者你可以自己创建一个alpha通道的蒙版,例如GIMP

Inpainting重绘

inpaint.json 这个工作流非常简单,唯一需要注意的是我们使用了VAE Encode (for Inpainting)专用节点进行了编码并设置了grow_mask_by=8,让蒙版区域大一点能让模型”看”到相邻的区域来获得更好的效果

在接缝处出现线条是很常见的,在这个例子中我们可以在二次编码时做一个值较小的降噪,或者你可以在超分过程中轻易修复这个问题。

Outpainting扩图

outpaint.json Outpainting扩图和重绘非常相似,我们继续使用相同的模型,除了Pad Image for Outpainting节点工作流和前一个基本一样,这个节点让我们添加空白区域在图片的某个边上,它提供了feathering选项但一般来说都是没用的,你可以简单的通过在VAE Encode (for Inpainting)增加grow_mask_by来获得更好的效果。

Inpainting SDXL with SD1.5

SDXL_inpaint_SD15.json

At the time of this writing SDXL only has a beta inpainting model but nothing stops us from using SD1.x/2.x for inpainting. This workflow shows you how and it also adds a final pass with the SDXL refiner to fix any possible seamline generated by the inpainting process.

Guided 可控组合

从这里开始变得因吹斯听了,文本描述或图生图只能让你走到这了, ControlNets和可控组合才能让你走的更远。

大多数本节的工作流需要下载ComfyUI’s ControlNet Auxiliary Preprocessors extension

Pose 动作

pose.json 对于所有control nets的工作流基本上是一样的,唯一不同的是你用的模型以及预处理器,第一个例子我们用openpose转换一位跳舞的人到一个实际的角色。 你可能会注意到每个Controlnet或T2Adapter可以和多个预处理器同时使用,对动作来说DWPreprocessor是一个非常有效的并且结果好于OpenPose的预处理器

Canny 线条

canny.json canny以难以置信的效率和资源占用把图片简化成线条,并且可用作新构图的参考

Depth 深度

depth.json depth controlnet是一个非常有用的网络,它可以让你在三维空间定义形状和体积,一个比较好的预处理器是Zoe.

注意: 只要你有合适的参考图片,使用预处理器并不是必须的。如果你用Blender的小工具PoseMy.Art让你可以很容易的创建一个角色。Cascadeur是另一个专业的解决方案可以让角色摆出合适的动作

提示: 为了更好的结果你永远可以串联多个controlnets

提示: 记得多试试Apply ControlNet节点的strength参数,通常降低这个值可以给模型更小的发挥空间

重要: controlnet必须匹配你当前用的SD版本

20250125comfyui安装教程

安装本体

秋叶整合包

github原版

首页 https://github.com/comfyanonymous/ComfyUI

本质上是个python web应用,所以python web的套路这里都可以用

下载 https://github.com/comfyanonymous/ComfyUI/releases/latest/download/ComfyUI_windows_portable_nvidia.7z

手动换源

hf镜像配置

main.py的入口添加一行环境变量

分离外部存储

虽然有些参数可以通过命令行参数传入,但这里选用最粗暴的方式注入配置 复制模板extra_model_paths.yaml.example到文件/data/lib/comfyui-data/extra_model_paths.yaml

main.py

启动

访问http://127.0.0.1:8188/

安装插件

默认路径ComfyUI/custom_nodes

可手动更新模型列表

安装工作流

保存位置 ComfyUI\user\default\workflows

 

工作流分享网站

https://comfyworkflows.com/

Civitai也有不少工作流分享

https://civitai.com/

安装模型

默认位置

  • ComfyUI\models
    • ComfyUI\models\checkpoints
    • ComfyUI\models\vae
    • ComfyUI\models\loras

手动下载

 

通过插件安装

ComfyUI-Manager 下载过程源码入口 custom_nodes\ComfyUI-Manager\glob\manager_server.py:1120

默认用的

查看产物

默认目录ComfyUI\output

操作技巧

  • 双击空白区域可以搜索并添加新节点
  • 点击convert [parm name] to inputconvert [parm name] to widget可以抽离可复用的参数

CONTRIBUTE

CHANGELOG

  • 20250128 继续测试一些demo
  • 20250126 测试一些demo
  • 20250125 研究原理,打印原始模型url方便手动下载
  • 20240525 安装原版跑通demo