距离上一次教大家在本地部署sd已经过去了........俺也不知道多久了,相信大家现在应该都已经很熟悉了吧,估计大家也发现了一个问题,就是本地的配置跑sd,一个是对配置要求太高了,现在的模型都特别大,没有一张3090根本玩不了,一个是内存啥的根本不够用模型加上各种插件,生成图啥的,分分钟100g上下,普通玩家属实顶不住,别急,今天就教给大家, 如何在服务器上部署一台自己的sd,让大家体验一下小学偷摸上网吧的快感。
vscode与pycharm的安装
虽然如果是用服务器的话,用vscode会比较好,但是,俺是个纯纯的颜值主义者,pycharm的界面比vscode好看一百倍!!!!!
在安装之前,建议大家全程挂上梯子,后面下模型,下插件啥的都是需要外网的,如果没梯子的话,立即推,放弃安装。
注意,本教程是基于windows的,linux系统的安装,俺也不会,建议找找其他教程
vscode安装
vscode官网如下
Visual Studio Code - Code Editing. Redefined
直接点击Download for windows,一路next,反正是服务器部署,跟本地环境没啥关系
安装完毕以后,大家需要先下载一些插件
我这里下载了一些自用的插件,如果有同学想在本地做开发的,也可以跟这下,如果只是部署着玩玩,那么就不必全部下载完,只需要下载以下插件即可,在拓展这里直接搜
Chinese
SSH
界面大概是这样,点击安装即可,我已经安装过了,所以那里显示的是卸载。
pycharm安装
我之前有写过pycharm的安装教程,但是那个是社区版的,社区版其实是不支持远程开发的,所以大家需要下载专业版,不过专业版是需要收费的,相信大家很多人也是因为这个才不下的,没有关系,今天,教给大家一点小妙招。
pycharm官网如下
PyCharm: the Python IDE for Professional Developers by JetBrains
直接点击那个黑色的DOWNLOAD,下载专业版,中间一路next,啥也不点
进去以后,大概是在这个界面,因为我已经安装过了,所以可能会跟大家不太一样
总之,他会让你输入激活码,直接微信小程序搜索程序观点,关注,然后给他发送cccc112,你就能拿到了。
激活之后,pycharm的安装就结束了。
服务器租赁与登录
市面上有很多租服务器的地方,这里我仅以autodl为例,官网如下
AutoDL算力云 | 弹性、好用、省钱。租GPU就上AutoDL
大家注册完账号,登录完以后,要充点钱,如果只是玩玩的话,建议充个10块钱的,先试试水,如果实在装不来,也不亏,把服务器关了就完了。
在算力市场这里,就可以看到各种GPU的价格以及配置,小卡大家就别看了,想跑sd,24g的显存几乎是最低配了,所以建议大家3090起租,不过俺比较阔,所以,这里以V100给大家做个例子。
在这里我选择了一台V100,并扩了他的数据盘,大家可以按照自己的情况,选择扩还是不扩,关于镜像的选择,就选择基础镜像,按照我这个配置选择即可。然后点击立即创建。
直接警告,nice
这里其实也涉及到后面如果大家需要用到服务器开发的时候,会遇到的问题之一,就是在更换镜像的时候,一定要看好你选择的镜像的cuda版本,和你选的服务器最高支持的cuda版本对不对的上,如果对不上的话,就大概率开不了机,那你就只能去jupyter里把代码拷出来了,如果你还在里面训了模型,那就只有选择一个最低版本的镜像,先开机再说,不过里面的程序大概率是跑不起来了。
开完机子以后,大家就会跳转到这个界面,到这里,服务器的租赁就完成了(确实是没有V100的机子了,只能破费租台A40了)
vscode登录
打开vscode,刚才已经让大家安装过ssh了,在左边会看到这样一个图标
点开以后,在上面点击那个加号
在这里,输入你的ssh登录指令,然后进入,你的ssh登录账户以及密码都在autodl这里
复制过去,进入以后,点第一个
右下角会弹出一个小窗口,点击连接
选Linux以后输入密码,登录
点击左边那一排的第一个,进入文件夹,进去以后,会让你再输一次密码
进来以后,你的界面应该是这样,点击左下角的第二个地方,就是有个感叹号那里,进入终端
到这里,vscode就登录成功了。
pycharm登录
pycharm的登录会比较麻烦,但是,pycharm的界面比vscode好看一百倍!!!!!!!!
点击文件,下面有个远程开发,进来以后,就是以下界面
点击ssh下面那个新建连接,如果大家刚才vscode登录成功的话,就会知道,把那个账户复制过来,里面是有用户名,端口号,以及主机名的,大家按照以下方式分别复制到里面即可
点击检查连接
输入密码
在项目目录这里选择autodl-tmp,然后点击确定,下载IDE并连接
还要再输一次密码,干
然后等他下载完
到这里,pycharm就登录完成啦!左下角那一排第二个,进入终端。
sd服务器部署
为了表示我对pycharm的绝对忠诚,这里我将全程用pycharm教大家如何在服务器部署sd
下面大家按照我的指令一条一条执行即可。
挂上学术加速
source /etc/network_turbo
echo '54.192.18.37 huggingface.co' >> /etc/hosts
从git上拉取sd项目
git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui.git
在/root/autodl-tmp/stable-diffusion-webui/webui.sh路径下找到webui.sh文件,在他的68行
# this script cannot be run as root by default
can_run_as_root=0
把0改成1,然后继续在终端执行以下指令
给进入sd路径下,./webui.sh文件权限
cd stable-diffusion-webui
chmod +x ./webui.sh
再执行该脚本
./webui.sh
这里安装时间会比较长,不同服务器速度也不一样,大家耐心等待即可。
这下载速度,我只能说,在本地想都不敢想
在这里把7860端口号加上,就可以从本地进入webui啦
芜湖,起飞!
后面还有一些插件啥的,我这里就不再赘述了,我把链接放下面,大家自行下载即可。
中文插件
GitHub - dtlnor/stable-diffusion-webui-localization-zh_CN: Simplified Chinese translation extension for AUTOMATIC1111's stable diffusion webui
面部修复插件
https://github.com/Bing-su/adetailer.git
关键词整理插件
https://github.com/Physton/sd-webui-prompt-all-in-one.git
动态阈值插件
https://github.com/mcmonkeyprojects/sd-dynamic-thresholding.git
比例控制插件
https://github.com/thomasasfk/sd-webui-aspect-ratio-helper.git
controlnet插件
https://github.com/Mikubill/sd-webui-controlnet.git
segment-anything 插件(做蒙版的)
https://github.com/continue-revolution/sd-webui-segment-anything.git
还有两个下模型的网站
liblib
www.liblibai.com
civitai
Civitai
diffusers服务器部署
后面就是开发教程了,如果只是玩玩的话,这里就可以退出了,上面的内容如果大家都已经实现了,其实已经有很多东西可以慢慢玩了。如果想要做diffusers的开发的话,下面的教程可以简单的帮大家入个门
diffusers的模型是可以下载到本地的,大家可以去huggingface上下载,这里我把diffusers的官网给大家
Stable Diffusion XL (huggingface.co)
huggingface对国内的服务器有随机污染,连不上很正常,所以如果大家要做开发的话,还是建议下载到本地。
模型加载
from diffusers import StableDiffusionXLPipeline, StableDiffusionXLImg2ImgPipeline
import torch
#从huggingface上的模型加载,这里要把整个包都下载下来,少则6g,大的话得有20个g,不建议用这种方式加载
pipeline = StableDiffusionXLPipeline.from_pretrained("stabilityai/stable-diffusion-xl-base-1.0",#模型地址
torch_dtype=torch.float16,
variant="fp16",
use_safetensors=True,
safety_checker= None).to("cuda")
#从ckpt文件加载模型,这里的模型可以直接从civitai上下载,跟webui的模型是通用的
pipeline = StableDiffusionXLImg2ImgPipeline.from_single_file("/root/autodl-tmp/stable-diffusion-webui/models/Stable-diffusion/v1-5-pruned-emaonly.safetensors",
torch_dtype=torch.float16,
use_safetensors=True,
variant="fp16",
safety_checker= None).to("cuda")
简单的文生图
from diffusers import StableDiffusionXLPipeline, StableDiffusionXLImg2ImgPipeline
import torch
from PIL import Image
#从ckpt文件加载模型,这里的模型可以直接从civitai上下载,跟webui的模型是通用的
pipeline = StableDiffusionXLPipeline.from_single_file("/root/autodl-tmp/stable-diffusion-webui/models/Stable-diffusion/v1-5-pruned-emaonly.safetensors",
torch_dtype=torch.float16,
use_safetensors=True,
variant="fp16",
safety_checker= None).to("cuda")
prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k"
image = pipeline(prompt=prompt).images[0]
image.save('succ.png')
简单的图生图
from diffusers import StableDiffusionXLPipeline, StableDiffusionXLImg2ImgPipeline
import torch
from PIL import Image
#从ckpt文件加载模型,这里的模型可以直接从civitai上下载,跟webui的模型是通用的
pipeline = StableDiffusionXLImg2ImgPipeline.from_single_file("/root/autodl-tmp/stable-diffusion-webui/models/Stable-diffusion/v1-5-pruned-emaonly.safetensors",
torch_dtype=torch.float16,
use_safetensors=True,
variant="fp16",
safety_checker= None).to("cuda")
init_image = Image.open('txt.png')#这里放上你本地的一张图片的地址
prompt = "a dog catching a frisbee in the jungle"
fin = pipeline(prompt,
image=init_image,
strength=0.8,
guidance_scale=10.5).images[0]
fin.save('succ.png')
简单的蒙版重绘
from diffusers import StableDiffusionInpaintPipeline
import torch
device = "cuda"
pipe = StableDiffusionInpaintPipeline.from_pretrained("./majicMIX_realistic_v6",
torch_dtype=torch.float16,
use_safetensors=True,
safety_checker=None).to(device)
mask = matting(image)#我接了个蒙版算法在这,分割算法多的是,你们得自己在这里接一个蒙版算法进来
pos_prompt = "film, nikon RAW photo, 8 k, Fujifilm XT3"
neg_prompt = "paintings, sketches, (low quality:2), (normal quality:2), lowres, normal quality"
width,height = image.size
out = pipe(
prompt=pos_prompt,
negative_prompt=neg_prompt,
image = image,
mask_image = mask,
width =width,
height = height,
strength=0.75,
guidance_scale=7.5,
).images[0]
out.save('succ.png')
加个lora
from diffusers import DiffusionPipeline
import torch
pipe = DiffusionPipeline.from_pretrained("./Photon_v1",
use_safetensors=True,
torch_dtype=torch.float16,
safety_checker=None).to("cuda")
#lora加载
pipe.load_lora_weights("./lora/", weight_name="asian_man.safetensors",scale = 0.2)
generator = torch.Generator(device="cuda").manual_seed(0)
out = pipe(
prompt = "beautiful girl",
negative_prompt = "nsfw",
generator = generator
).images[0]
out.save('succ.png')
突破clip长度限制,把关键词编码
from diffusers import DiffusionPipeline
import torch
def embedding_create(prompt):
tokenizer = CLIPTokenizer.from_pretrained("./majicMIX_realistic_v6/tokenizer")
text_encoder = CLIPTextModel.from_pretrained("./majicMIX_realistic_v6/text_encoder")
text_input = tokenizer(
prompt, padding="max_length", max_length=tokenizer.model_max_length, truncation=True, return_tensors="pt"
)
with torch.no_grad():
text_embeddings = text_encoder(text_input.input_ids)[0]
return text_embeddings
pipe = DiffusionPipeline.from_pretrained("./Photon_v1",
use_safetensors=True,
torch_dtype=torch.float16,
safety_checker=None).to("cuda")
pos_prompt = "balabalabala..................................................."
neg_prompt = "balabalabala..................................................."
pos_embeds = embedding_create(pos_prompt)
neg_embeds = embedding_create(neg_prompt)
generator = torch.Generator(device="cuda").manual_seed(0)
out = pipe(
prompt_embeds=pos_embeds,
negative_prompt_embeds=neg_embeds,
generator = generator
).images[0]
out.save('succ.png')
加入controlnet
from diffusers import StableDiffusionControlNetInpaintPipeline
import torch
controlnet = ControlNetModel.from_pretrained("./sd-controlnet-canny", torch_dtype=torch.float16,
Conditioning_scale=0.5,timestep = 15)
pipe = StableDiffusionControlNetInpaintPipeline.from_pretrained("./majicMIX_realistic_v6",
controlnet=controlnet,
torch_dtype=torch.float16,
safety_checker=None,
use_safetensors= True).to("cuda")
generator = torch.Generator(device="cuda").manual_seed(0)
#这里一共要进三张图,分别是原图,蒙版,以及controlnet的图,注意,这里面controlnet的图是不会帮你做预处理的,所以得自己想办法
out = pipe(
image = image,
prompt_embeds=pos_embeds,
negative_prompt_embeds=neg_embeds,
generator = generator,
mask_image=mask_image,
control_image=controlnet_image,
).images[0]
out.save('succ.png')
后面还有其他花里胡哨的东西,就等大家自己去看文档了,包括prompt的权重设置,sheduler的一些参数配置,以及社区管道的加载与贡献等,我这里就不一一赘述了,diffusers会比webui更加底层,如果有想做开发的同学,可以先从这里入手,先实现一些简单的功能,再去看huggingface。