上一篇关于stable diffusion(以下简称sd)的api基础知识已经更新很久了,现在AI相关的技术也发生了非常多的变化
比较大的例如sdxl的更新,以及gpt4 turbo的出现,这个进步是越来越快了啊,居安思危
因为在忙着实际项目的开发,也蛮久没有看知乎更新了,最近看到有人在评论区问一些sd 第三方插件的api调用方法
第三方插件是sd远端调用的重要部分,我相信不会有太多人只通过调用sd本体,就能出来非常优秀并且稳定的图片,但是由于第三方开发者都各不相同,每个开发者的代码习惯还有规范都不一致,导致各家的api调用方法都有所不同,甚至有的在初版并没有提供api调用
所以这各系列主要:以部分插件为例讲解我们如何查看sd插件的api调用方式(一),通过debug解决遇到的问题(二),甚至在最后,可以做到添加自己想要的api功能模块(三)
关于此篇文章的前提知识,可参考下面文章
CreepOnSky:stable diffusion 远端跑图—— Api基础知识掌握135 赞同 · 115 评论文章编辑
该篇文章涉及软件:postman、vscode(其他可使用python并可debug'的IDE皆可)、以及一个已经安装好的sd工程
该篇文章还是偏技术小白一点的,本人技术也很有限,不会太深入,只需要一些python基础知识即可
最后一个插话,我正在创建一个ai交流讨论群,之前很多对ai感兴趣的人找我我当时都没有创建一个群,最近才开始,感兴趣的话请私聊我,无论是做技术还是其他,对ai感兴趣就行~
另外,本篇会涉及不少的sd webui以及插件源代码,图文都会比较多,我会尽量减少深入,只注重当前问题
正式开始
目前熟知的第三方插件非常多,我们就以我这边常用的几个为例,分别是 :
先说必要前提,sdwebui工程将所有第三方插件能够提供的api参数都放在了body中的alwayson_scripts
alwayson_scripts中的每一个插件的调用怎么写,提供哪些参数,基本由第三方自己决定,所以这也是这篇文章的存在前提
0.安装各个插件
对应的github链接我已放入,第一步当然是安装各个插件,比较简单,打开你的sd webui
将对应的插件网址放入 扩展 -> 从网址安装 -> 扩展的 git 仓库链接中然后点击安装即可
注意,此步需要能够正常访问github,如果不能正常访问,参考其他的github国内代理教程
1.检查插件否有文档
当我们需要知道一个功能是否提供以及如何使用,最有效并且系统的就是查看官方文档,虽然很繁琐,但是是最细节并且最全的公开资料
这次节选的三个插件,我们分别在github仓库中查看readme文件
- controlnet
文档最后 提到了一点,然后给出了一些例子,我们跟着这里的链接,查看例子
在这个路径下:/sd-webui-controlnet/example/txt2img_example/api_txt2img.py
于是我们vscode打开sd项目工程,sd是个比较大的项目,有很多分支文件夹,我们这次注重于两个文件夹
extensions 是第三方插件的文件夹,我们所有安装的第三方插件都在这里
modules 是sd-webui的代码主要文件夹,有很多api相关的代码都在这里面的(modules/api中)可以找到
然后找到extionsion路径下的/sd-webui-controlnet/example/txt2img_example/api_txt2img.py
查看代码,我们就可以直接得到controlnet的文生图(txt2img)基本调用规则!
- face editor
同样查看文档,在这里得到答案!
顺便提一句,几个月前我第一次用faceeditor的时候他并没有在文档中写这些提示,我就只能直接通过代码去找调用方法,会麻烦很多,接下来我们也会提到用代码如何去找
- roop
roop的文档就不太一样了,并没有相关的例子和链接,只有一个第三方api平台的相关赞助者,不必理会
所以roop这种情况就需要我们延伸到第二个步骤来查找如何调用api了
2.查看源代码
在查看插件的源代码之前,我们需要对sd-webui提供的api相关支持的源代码看一遍
这里涉及背后执行的前后方法非常多,我尽量不展开,只关注重点
打开sd项目的modules\api\api.py 路径,这是我们api调用的主要代码,关于sd本身的api调用上一篇已经阐述,这里不再重复
我们将目光集中在其中的init_script_args函数,红框部分,sd给第三方插件执行的代码就在这
从这几行代码我们可以看出我们先要有alwayson_script_name,这个是第三方开发者自己定义的名字,会在sd初始化中的插件初始化周期中进行写入
我们用controlnet的alwayson_script_name举例子
这是controlenet代码中声明的alwayson_script_name,也就是title,可以发现这个名字就是我们api调用的名字是一样的,回到第一步中的controlenet文档提供的example
至于为什么大小写不对应,api.py中找到叫做script_name_to_index会说明,这里不深入
回到init_script_args中继续往下看,当找到对应的alwayson_script_name之后,会将对应的输入参数都取出来
if "args" in request.alwayson_scripts[alwayson_script_name]:
# min between arg length in scriptrunner and arg length in the request
for idx in range(0, min((alwayson_script.args_to - alwayson_script.args_from), len(request.alwayson_scripts[alwayson_script_name]["args"]))):
script_args[alwayson_script.args_from + idx] = request.alwayson_scripts[alwayson_script_name]["args"][idx]
注意这里的取参数是按照index,也就是排序去一一取出,其实就导致很多插件前期的做法,也是跟着这是直接写的是数组,而不是key value对应的形式,我用roop举例子
roop
这里是roop的调用方式,他是直接使用数组来调用,我们如果不看代码,根本不知道每一位对应的是什么
face editor
这是face editor的调用方式,是不是优雅很多?
相当于sd规定的格式中,已经限制args里面得是数组了。所以你不能直接使用key value字典来对应,而比较好的实现方式就是上图face editor的,将数组中的参数再包一层,这样方便阅读很多,也更容易维护~
"插件名字": {
"args": []
}
然后当所有的插件的参数都赋给这里的script_args之后,将会执行process
script_args可以简单阐述一下,他里面是所有我们这一次生产或者这一次命令所执行需要的所有参数都在里面,也就是每一个插件的参数包括sd本身的参数,都在这里
process是从 : img2imgapi( or text2imgapi)-> process_images -> process_images_inner -> process 一步步执行而来,中间不阐述
process是sdwebui官方预留的一个第三方插件在生成阶段可以自由执行的模块,除此之外还有before_process、before_process_batch、before_process_batch等等,都可以在processing.py中的process_images_inner找到。
在这里,sd会将之前收集到的script_args包括一些其他需要的参数,一起作为process或者其他方法的传参,供插件处理,而刚才提到script_args中含有除controlnet以外的其他参数,这就是为什么我们的第三方插件也可以识别sd的基本参数了,比如mask,seed,width等
前提讲完,回到正题
上述插件中,roop并没有在文档中写明api调用方式,我们只能来看源代码了
roop算是一个轻量插件,代码非常少,但即使如此,是不是也不知道从哪个文件看起?这里有一个叫做api.py的文件,应该从他开始看吗?
打开后会发现并不是,extensions\sd-webui-roop\scripts\api.py这个文件是roop用来增加额外的属于roop自己的api的代码,这也就是我提到的如何扩展api的部分,并非我们调用sd本身的文生图、图生图这样的api的代码
而我们前面提到了process,这就是我们搜索的关键之一,右键roop文件夹,选择find in folder
然后搜索 process( 即可发现固定的一个方法
而这里就是我们的目的地了,前提提要我们在args中的每一位参数都会复制给script_args,而这里的复制是按照顺序,index来赋值!
而这里的process也将会是index,顺序写入!
那我们就知道了怎么去组装这个args,这里就是个例子,你可以和上图的顺序一一对应。
如果你的process没有搜出来东西,那也有可能是before_process、before_process_batch、before_process_batch等方法
那我们到这一步,其实就已经知道大部分第三方插件如何去写入参数了
但是,并不是所有的插件都会用到process,因为有的插件是图片生成后的后处理。有的是在之前处理,各不一样
如果我们要精确的知道每个插件都用到什么地方处理,这还真有点麻烦,我们这里又要稍微深入一点
process只是一个稍微取巧的办法,我们要真正知道第三方插件和sdwebui的交互,还有很多知识需要了解
这里只说明一点,第三方插件需要继承sdwebui代码中的Script类(modules\scripts.py),来声明自己是sd的插件
所以我们可以搜索scripts.Script,这样固定会有一些继承的类,然后再来里面查询对应的参数接口
如果想了解sd的插件生态教程,强烈建议阅读sdwebui官方的教程
里面有一张很关键的图,来阐述刚才我提到的process、before_process、before_process_batch、before_process_batch等的关系,这是原图,各位可以自行下载
至此,我们还有很多sd执行的背后逻辑,还有插件背后扩展,以及如何debug没有说明,但是限于篇幅(我已经觉得这是一篇又臭又长的文章了),我们就留到下次来探讨吧~正如标题所说,这是第一篇
如果大家对本类内容感兴趣,或者其他sd应用层面、插件扩展、甚至是 ai相关技术科普都可以留言私信交流