Переглянути джерело

plugins: add sdwebui(stable diffusion) plugin

master
lanvent 1 рік тому
джерело
коміт
e6d148e729
4 змінених файлів з 218 додано та 0 видалено
  1. +0
    -0
      plugins/sdwebui/__init__.py
  2. +67
    -0
      plugins/sdwebui/config.json.template
  3. +63
    -0
      plugins/sdwebui/readme.md
  4. +88
    -0
      plugins/sdwebui/sdwebui.py

+ 0
- 0
plugins/sdwebui/__init__.py Переглянути файл


+ 67
- 0
plugins/sdwebui/config.json.template Переглянути файл

@@ -0,0 +1,67 @@
{
"start":{
"host" : "127.0.0.1",
"port" : 7860
},
"defaults": {
"params": {
"sampler_name": "DPM++ 2M Karras",
"steps": 20,
"width": 512,
"height": 512,
"cfg_scale": 7,
"prompt":"masterpiece, best quality",
"negative_prompt": "(low quality, worst quality:1.4),(bad_prompt:0.8), (monochrome:1.1), (greyscale)",
"enable_hr": false,
"hr_scale": 2,
"hr_upscaler": "Latent",
"hr_second_pass_steps": 15,
"denoising_strength": 0.7
},
"options": {
"sd_model_checkpoint": "perfectWorld_v2Baked"
}
},
"rules": [
{
"keywords": [
"横版",
"壁纸"
],
"params": {
"width": 640,
"height": 384
}
},
{
"keywords": [
"竖版"
],
"params": {
"width": 384,
"height": 640
}
},
{
"keywords": [
"高清"
],
"params": {
"enable_hr": true,
"hr_scale": 1.6
}
},
{
"keywords": [
"二次元"
],
"params": {
"negative_prompt": "(low quality, worst quality:1.4),(bad_prompt:0.8), (monochrome:1.1), (greyscale)",
"prompt": "masterpiece, best quality"
},
"options": {
"sd_model_checkpoint": "meinamix_meinaV8"
}
}
]
}

+ 63
- 0
plugins/sdwebui/readme.md Переглянути файл

@@ -0,0 +1,63 @@
本插件用于将画图请求转发给stable diffusion webui
使用前先安装stable diffusion webui,并在它的启动参数中添加 "--api"
具体参考(https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/API)

请**安装**本插件的依赖包```webuiapi```
```
```pip install webuiapi```
```
请将```config.json.template```复制为```config.json```,并修改其中的参数和规则

用户的画图请求格式为:
```
<画图触发词><关键词1> <关键词2> ... <关键词n>:<prompt>
```
本插件会对画图触发词后的关键词进行逐个匹配,如果触发了规则中的关键词,则会在画图请求中重载对应的参数。
规则会按顺序匹配,每个关键词最多匹配到1次,如果有重复的参数,则以最后一个为准:
第一个"**:**"号之后的内容会作为附加的**prompt**,接在最终的prompt后

例如: 画横版 高清 二次元:cat
会触发三个关键词 "横版", "高清", "二次元",prompt为"cat"
若默认参数是:
```
"width": 512,
"height": 512,
"enable_hr": false,
"prompt": "8k"
"negative_prompt": "nsfw",
"sd_model_checkpoint": "perfectWorld_v2Baked"
```

"横版"触发的规则参数为:
```
"width": 640,
"height": 384,
```
"高清"触发的规则参数为:
```
"enable_hr": true,
"hr_scale": 1.6,
```
"二次元"触发的规则参数为:
```
"negative_prompt": "(low quality, worst quality:1.4),(bad_prompt:0.8), (monochrome:1.1), (greyscale)",
"steps": 20,
"prompt": "masterpiece, best quality",

"sd_model_checkpoint": "meinamix_meinaV8"
```
最后将第一个":"后的内容cat连接在prompt后,得到最终参数为:
```
"width": 640,
"height": 384,
"enable_hr": true,
"hr_scale": 1.6,
"negative_prompt": "(low quality, worst quality:1.4),(bad_prompt:0.8), (monochrome:1.1), (greyscale)",
"steps": 20,
"prompt": "masterpiece, best quality, cat",
"sd_model_checkpoint": "meinamix_meinaV8"
```
PS: 参数分为两部分,
一部分是params,为画画的参数;参数名**必须**与webuiapi包中[txt2img api](https://github.com/mix1009/sdwebuiapi/blob/fb2054e149c0a4e25125c0cd7e7dca06bda839d4/webuiapi/webuiapi.py#L163)的参数名一致
另一部分是options,指sdwebui的设置,使用的模型和vae需要写在里面。它和http://127.0.0.1:7860/sdapi/v1/options所返回的键一致。

+ 88
- 0
plugins/sdwebui/sdwebui.py Переглянути файл

@@ -0,0 +1,88 @@
# encoding:utf-8

import json
import os
from bridge.context import ContextType
from bridge.reply import Reply, ReplyType
import plugins
from plugins import *
from common.log import logger
import webuiapi
import io


@plugins.register(name="sdwebui", desc="利用stable-diffusion webui来画图", version="2.0", author="lanvent")
class SDWebUI(Plugin):
def __init__(self):
super().__init__()
curdir = os.path.dirname(__file__)
config_path = os.path.join(curdir, "config.json")
try:
with open(config_path, "r", encoding="utf-8") as f:
config = json.load(f)
self.rules = config["rules"]
defaults = config["defaults"]
self.default_params = defaults["params"]
self.default_options = defaults["options"]
self.start_args = config["start"]
self.api = webuiapi.WebUIApi(**self.start_args)
self.handlers[Event.ON_HANDLE_CONTEXT] = self.on_handle_context
logger.info("[SD] inited")
except FileNotFoundError:
logger.error(f"[SD] init failed, {config_path} not found")
except Exception as e:
logger.error("[SD] init failed, exception: %s" % e)
def on_handle_context(self, e_context: EventContext):

if e_context['context'].type != ContextType.IMAGE_CREATE:
return

logger.debug("[SD] on_handle_context. content: %s" %e_context['context'].content)

logger.info("[SD] image_query={}".format(e_context['context'].content))
reply = Reply()
try:
content = e_context['context'].content[:]
# 解析用户输入 如"横版 高清 二次元:cat"
keywords, prompt = content.split(":", 1)
keywords = keywords.split()

rule_params = {}
rule_options = {}
for keyword in keywords:
matched = False
for rule in self.rules:
if keyword in rule["keywords"]:
for key in rule["params"]:
rule_params[key] = rule["params"][key]
if "options" in rule:
for key in rule["options"]:
rule_options[key] = rule["options"][key]
matched = True
break # 一个关键词只匹配一个规则
if not matched:
logger.warning("[SD] keyword not matched: %s" % keyword)
params = {**self.default_params, **rule_params}
options = {**self.default_options, **rule_options}
params["prompt"] = params.get("prompt", "")+f", {prompt}"
if len(options) > 0:
logger.info("[SD] cover rule_options={}".format(rule_options))
self.api.set_options(options)
logger.info("[SD] params={}".format(params))
result = self.api.txt2img(
**params
)
reply.type = ReplyType.IMAGE
b_img = io.BytesIO()
result.image.save(b_img, format="PNG")
reply.content = b_img
e_context.action = EventAction.BREAK_PASS # 事件结束后,不跳过处理context的默认逻辑
except Exception as e:
reply.type = ReplyType.ERROR
reply.content = "[SD] "+str(e)
logger.error("[SD] exception: %s" % e)
e_context.action = EventAction.CONTINUE # 事件继续,交付给下个插件或默认逻辑
finally:
e_context['reply'] = reply

Завантаження…
Відмінити
Зберегти