Upload 23 files
Browse files- api/api.py +996 -0
- api/models.py +326 -0
- config.json +327 -0
- models/ControlNet/diffusion_pytorch_model.safetensors +3 -0
- models/ControlNet/ip-adapter.bin +3 -0
- models/ESRGAN/4x_NMKD-Siax_2000k.pth +3 -0
- models/ESRGAN/ESRGAN_4x.pth +3 -0
- models/Stable-diffusion/Put Stable Diffusion checkpoints here.txt +0 -0
- models/Stable-diffusion/moxieDiffusionXL_v16.safetensors +3 -0
- models/VAE-approx/model.pt +3 -0
- models/VAE-approx/vaeapprox-sdxl.pt +3 -0
- models/VAE/Put VAE here.txt +0 -0
- models/VAE/sdxl_vae.safetensors +3 -0
- models/deepbooru/Put your deepbooru release project folder here.txt +0 -0
- models/diffusers/version_diffusers_cache.txt +1 -0
- models/insightface/models/antelopev2/1k3d68.onnx +3 -0
- models/insightface/models/antelopev2/2d106det.onnx +3 -0
- models/insightface/models/antelopev2/genderage.onnx +3 -0
- models/insightface/models/antelopev2/glintr100.onnx +3 -0
- models/insightface/models/antelopev2/scrfd_10g_bnkps.onnx +3 -0
- models/karlo/ViT-L-14_stats.th +0 -0
- models/svd/put svd here.txt +0 -0
- models/z123/put zero123 here.txt +0 -0
api/api.py
ADDED
@@ -0,0 +1,996 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import base64
|
2 |
+
import io
|
3 |
+
import os
|
4 |
+
import time
|
5 |
+
import itertools
|
6 |
+
import datetime
|
7 |
+
import uvicorn
|
8 |
+
import ipaddress
|
9 |
+
import requests
|
10 |
+
import gradio as gr
|
11 |
+
import numpy as np
|
12 |
+
from threading import Lock
|
13 |
+
from io import BytesIO
|
14 |
+
from fastapi import APIRouter, Depends, FastAPI, Request, Response
|
15 |
+
from fastapi.security import HTTPBasic, HTTPBasicCredentials
|
16 |
+
from fastapi.exceptions import HTTPException
|
17 |
+
from fastapi.responses import JSONResponse
|
18 |
+
from fastapi.encoders import jsonable_encoder
|
19 |
+
from secrets import compare_digest
|
20 |
+
|
21 |
+
import modules.shared as shared
|
22 |
+
from modules import sd_samplers, deepbooru, sd_hijack, images, scripts, ui, postprocessing, errors, restart, shared_items, script_callbacks, infotext_utils, sd_models
|
23 |
+
from modules.api import models
|
24 |
+
from modules.shared import opts
|
25 |
+
from modules.processing import StableDiffusionProcessingTxt2Img, StableDiffusionProcessingImg2Img, process_images
|
26 |
+
from modules.textual_inversion.textual_inversion import create_embedding, train_embedding
|
27 |
+
from modules.hypernetworks.hypernetwork import create_hypernetwork, train_hypernetwork
|
28 |
+
from PIL import PngImagePlugin, Image
|
29 |
+
from modules.sd_models_config import find_checkpoint_config_near_filename
|
30 |
+
from modules.realesrgan_model import get_realesrgan_models
|
31 |
+
from modules import devices
|
32 |
+
from typing import Any
|
33 |
+
import piexif
|
34 |
+
import piexif.helper
|
35 |
+
from contextlib import closing
|
36 |
+
from modules.progress import create_task_id, add_task_to_queue, start_task, finish_task, current_task
|
37 |
+
|
38 |
+
def script_name_to_index(name, scripts):
|
39 |
+
try:
|
40 |
+
return [script.title().lower() for script in scripts].index(name.lower())
|
41 |
+
except Exception as e:
|
42 |
+
raise HTTPException(status_code=422, detail=f"Script '{name}' not found") from e
|
43 |
+
|
44 |
+
|
45 |
+
def validate_sampler_name(name):
|
46 |
+
config = sd_samplers.all_samplers_map.get(name, None)
|
47 |
+
if config is None:
|
48 |
+
raise HTTPException(status_code=404, detail="Sampler not found")
|
49 |
+
|
50 |
+
return name
|
51 |
+
|
52 |
+
|
53 |
+
def setUpscalers(req: dict):
|
54 |
+
reqDict = vars(req)
|
55 |
+
reqDict['extras_upscaler_1'] = reqDict.pop('upscaler_1', None)
|
56 |
+
reqDict['extras_upscaler_2'] = reqDict.pop('upscaler_2', None)
|
57 |
+
return reqDict
|
58 |
+
|
59 |
+
|
60 |
+
def verify_url(url):
|
61 |
+
"""Returns True if the url refers to a global resource."""
|
62 |
+
|
63 |
+
import socket
|
64 |
+
from urllib.parse import urlparse
|
65 |
+
try:
|
66 |
+
parsed_url = urlparse(url)
|
67 |
+
domain_name = parsed_url.netloc
|
68 |
+
host = socket.gethostbyname_ex(domain_name)
|
69 |
+
for ip in host[2]:
|
70 |
+
ip_addr = ipaddress.ip_address(ip)
|
71 |
+
if not ip_addr.is_global:
|
72 |
+
return False
|
73 |
+
except Exception:
|
74 |
+
return False
|
75 |
+
|
76 |
+
return True
|
77 |
+
|
78 |
+
|
79 |
+
def decode_base64_to_image(encoding):
|
80 |
+
if encoding.startswith("http://") or encoding.startswith("https://"):
|
81 |
+
if not opts.api_enable_requests:
|
82 |
+
raise HTTPException(status_code=500, detail="Requests not allowed")
|
83 |
+
|
84 |
+
if opts.api_forbid_local_requests and not verify_url(encoding):
|
85 |
+
raise HTTPException(status_code=500, detail="Request to local resource not allowed")
|
86 |
+
|
87 |
+
headers = {'user-agent': opts.api_useragent} if opts.api_useragent else {}
|
88 |
+
response = requests.get(encoding, timeout=30, headers=headers)
|
89 |
+
try:
|
90 |
+
image = Image.open(BytesIO(response.content))
|
91 |
+
return image
|
92 |
+
except Exception as e:
|
93 |
+
raise HTTPException(status_code=500, detail="Invalid image url") from e
|
94 |
+
|
95 |
+
if encoding.startswith("data:image/"):
|
96 |
+
encoding = encoding.split(";")[1].split(",")[1]
|
97 |
+
try:
|
98 |
+
image = Image.open(BytesIO(base64.b64decode(encoding)))
|
99 |
+
return image
|
100 |
+
except Exception as e:
|
101 |
+
raise HTTPException(status_code=500, detail="Invalid encoded image") from e
|
102 |
+
|
103 |
+
|
104 |
+
def encode_pil_to_base64(image):
|
105 |
+
with io.BytesIO() as output_bytes:
|
106 |
+
if isinstance(image, str):
|
107 |
+
return image
|
108 |
+
if isinstance(image, np.ndarray):
|
109 |
+
image = Image.fromarray(image)
|
110 |
+
if opts.samples_format.lower() == 'png':
|
111 |
+
use_metadata = False
|
112 |
+
metadata = PngImagePlugin.PngInfo()
|
113 |
+
for key, value in image.info.items():
|
114 |
+
if isinstance(key, str) and isinstance(value, str):
|
115 |
+
metadata.add_text(key, value)
|
116 |
+
use_metadata = True
|
117 |
+
image.save(output_bytes, format="PNG", pnginfo=(metadata if use_metadata else None), quality=opts.jpeg_quality)
|
118 |
+
|
119 |
+
elif opts.samples_format.lower() in ("jpg", "jpeg", "webp"):
|
120 |
+
if image.mode == "RGBA":
|
121 |
+
image = image.convert("RGB")
|
122 |
+
parameters = image.info.get('parameters', None)
|
123 |
+
exif_bytes = piexif.dump({
|
124 |
+
"Exif": { piexif.ExifIFD.UserComment: piexif.helper.UserComment.dump(parameters or "", encoding="unicode") }
|
125 |
+
})
|
126 |
+
if opts.samples_format.lower() in ("jpg", "jpeg"):
|
127 |
+
image.save(output_bytes, format="JPEG", exif = exif_bytes, quality=opts.jpeg_quality)
|
128 |
+
else:
|
129 |
+
image.save(output_bytes, format="WEBP", exif = exif_bytes, quality=opts.jpeg_quality)
|
130 |
+
|
131 |
+
else:
|
132 |
+
raise HTTPException(status_code=500, detail="Invalid image format")
|
133 |
+
|
134 |
+
bytes_data = output_bytes.getvalue()
|
135 |
+
|
136 |
+
return base64.b64encode(bytes_data)
|
137 |
+
|
138 |
+
|
139 |
+
def api_middleware(app: FastAPI):
|
140 |
+
rich_available = False
|
141 |
+
try:
|
142 |
+
if os.environ.get('WEBUI_RICH_EXCEPTIONS', None) is not None:
|
143 |
+
import anyio # importing just so it can be placed on silent list
|
144 |
+
import starlette # importing just so it can be placed on silent list
|
145 |
+
from rich.console import Console
|
146 |
+
console = Console()
|
147 |
+
rich_available = True
|
148 |
+
except Exception:
|
149 |
+
pass
|
150 |
+
|
151 |
+
@app.middleware("http")
|
152 |
+
async def log_and_time(req: Request, call_next):
|
153 |
+
ts = time.time()
|
154 |
+
res: Response = await call_next(req)
|
155 |
+
duration = str(round(time.time() - ts, 4))
|
156 |
+
res.headers["X-Process-Time"] = duration
|
157 |
+
endpoint = req.scope.get('path', 'err')
|
158 |
+
if shared.cmd_opts.api_log and endpoint.startswith('/sdapi'):
|
159 |
+
print('API {t} {code} {prot}/{ver} {method} {endpoint} {cli} {duration}'.format(
|
160 |
+
t=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f"),
|
161 |
+
code=res.status_code,
|
162 |
+
ver=req.scope.get('http_version', '0.0'),
|
163 |
+
cli=req.scope.get('client', ('0:0.0.0', 0))[0],
|
164 |
+
prot=req.scope.get('scheme', 'err'),
|
165 |
+
method=req.scope.get('method', 'err'),
|
166 |
+
endpoint=endpoint,
|
167 |
+
duration=duration,
|
168 |
+
))
|
169 |
+
return res
|
170 |
+
|
171 |
+
def handle_exception(request: Request, e: Exception):
|
172 |
+
err = {
|
173 |
+
"error": type(e).__name__,
|
174 |
+
"detail": vars(e).get('detail', ''),
|
175 |
+
"body": vars(e).get('body', ''),
|
176 |
+
"errors": str(e),
|
177 |
+
}
|
178 |
+
if not isinstance(e, HTTPException): # do not print backtrace on known httpexceptions
|
179 |
+
message = f"API error: {request.method}: {request.url} {err}"
|
180 |
+
if rich_available:
|
181 |
+
print(message)
|
182 |
+
console.print_exception(show_locals=True, max_frames=2, extra_lines=1, suppress=[anyio, starlette], word_wrap=False, width=min([console.width, 200]))
|
183 |
+
else:
|
184 |
+
errors.report(message, exc_info=True)
|
185 |
+
return JSONResponse(status_code=vars(e).get('status_code', 500), content=jsonable_encoder(err))
|
186 |
+
|
187 |
+
@app.middleware("http")
|
188 |
+
async def exception_handling(request: Request, call_next):
|
189 |
+
try:
|
190 |
+
return await call_next(request)
|
191 |
+
except Exception as e:
|
192 |
+
return handle_exception(request, e)
|
193 |
+
|
194 |
+
@app.exception_handler(Exception)
|
195 |
+
async def fastapi_exception_handler(request: Request, e: Exception):
|
196 |
+
return handle_exception(request, e)
|
197 |
+
|
198 |
+
@app.exception_handler(HTTPException)
|
199 |
+
async def http_exception_handler(request: Request, e: HTTPException):
|
200 |
+
return handle_exception(request, e)
|
201 |
+
|
202 |
+
|
203 |
+
class Api:
|
204 |
+
def __init__(self, app: FastAPI, queue_lock: Lock):
|
205 |
+
if shared.cmd_opts.api_auth:
|
206 |
+
self.credentials = {}
|
207 |
+
for auth in shared.cmd_opts.api_auth.split(","):
|
208 |
+
user, password = auth.split(":")
|
209 |
+
self.credentials[user] = password
|
210 |
+
|
211 |
+
self.router = APIRouter()
|
212 |
+
self.app = app
|
213 |
+
self.queue_lock = queue_lock
|
214 |
+
api_middleware(self.app)
|
215 |
+
self.add_api_route("/sdapi/v1/txt2img", self.text2imgapi, methods=["POST"], response_model=models.TextToImageResponse)
|
216 |
+
self.add_api_route("/sdapi/v1/txt2imgmod", self.text2imgapimod, methods=["POST"], response_model=models.TextToImageResponseMod)
|
217 |
+
self.add_api_route("/sdapi/v1/img2img", self.img2imgapi, methods=["POST"], response_model=models.ImageToImageResponse)
|
218 |
+
self.add_api_route("/sdapi/v1/extra-single-image", self.extras_single_image_api, methods=["POST"], response_model=models.ExtrasSingleImageResponse)
|
219 |
+
self.add_api_route("/sdapi/v1/extra-batch-images", self.extras_batch_images_api, methods=["POST"], response_model=models.ExtrasBatchImagesResponse)
|
220 |
+
self.add_api_route("/sdapi/v1/png-info", self.pnginfoapi, methods=["POST"], response_model=models.PNGInfoResponse)
|
221 |
+
self.add_api_route("/sdapi/v1/progress", self.progressapi, methods=["GET"], response_model=models.ProgressResponse)
|
222 |
+
self.add_api_route("/sdapi/v1/interrogate", self.interrogateapi, methods=["POST"])
|
223 |
+
self.add_api_route("/sdapi/v1/interrupt", self.interruptapi, methods=["POST"])
|
224 |
+
self.add_api_route("/sdapi/v1/skip", self.skip, methods=["POST"])
|
225 |
+
self.add_api_route("/sdapi/v1/options", self.get_config, methods=["GET"], response_model=models.OptionsModel)
|
226 |
+
self.add_api_route("/sdapi/v1/options", self.set_config, methods=["POST"])
|
227 |
+
self.add_api_route("/sdapi/v1/cmd-flags", self.get_cmd_flags, methods=["GET"], response_model=models.FlagsModel)
|
228 |
+
self.add_api_route("/sdapi/v1/samplers", self.get_samplers, methods=["GET"], response_model=list[models.SamplerItem])
|
229 |
+
self.add_api_route("/sdapi/v1/upscalers", self.get_upscalers, methods=["GET"], response_model=list[models.UpscalerItem])
|
230 |
+
self.add_api_route("/sdapi/v1/latent-upscale-modes", self.get_latent_upscale_modes, methods=["GET"], response_model=list[models.LatentUpscalerModeItem])
|
231 |
+
self.add_api_route("/sdapi/v1/sd-models", self.get_sd_models, methods=["GET"], response_model=list[models.SDModelItem])
|
232 |
+
self.add_api_route("/sdapi/v1/sd-vae", self.get_sd_vaes, methods=["GET"], response_model=list[models.SDVaeItem])
|
233 |
+
self.add_api_route("/sdapi/v1/hypernetworks", self.get_hypernetworks, methods=["GET"], response_model=list[models.HypernetworkItem])
|
234 |
+
self.add_api_route("/sdapi/v1/face-restorers", self.get_face_restorers, methods=["GET"], response_model=list[models.FaceRestorerItem])
|
235 |
+
self.add_api_route("/sdapi/v1/realesrgan-models", self.get_realesrgan_models, methods=["GET"], response_model=list[models.RealesrganItem])
|
236 |
+
self.add_api_route("/sdapi/v1/prompt-styles", self.get_prompt_styles, methods=["GET"], response_model=list[models.PromptStyleItem])
|
237 |
+
self.add_api_route("/sdapi/v1/embeddings", self.get_embeddings, methods=["GET"], response_model=models.EmbeddingsResponse)
|
238 |
+
self.add_api_route("/sdapi/v1/refresh-embeddings", self.refresh_embeddings, methods=["POST"])
|
239 |
+
self.add_api_route("/sdapi/v1/refresh-checkpoints", self.refresh_checkpoints, methods=["POST"])
|
240 |
+
self.add_api_route("/sdapi/v1/refresh-vae", self.refresh_vae, methods=["POST"])
|
241 |
+
self.add_api_route("/sdapi/v1/create/embedding", self.create_embedding, methods=["POST"], response_model=models.CreateResponse)
|
242 |
+
self.add_api_route("/sdapi/v1/create/hypernetwork", self.create_hypernetwork, methods=["POST"], response_model=models.CreateResponse)
|
243 |
+
self.add_api_route("/sdapi/v1/train/embedding", self.train_embedding, methods=["POST"], response_model=models.TrainResponse)
|
244 |
+
self.add_api_route("/sdapi/v1/train/hypernetwork", self.train_hypernetwork, methods=["POST"], response_model=models.TrainResponse)
|
245 |
+
self.add_api_route("/sdapi/v1/memory", self.get_memory, methods=["GET"], response_model=models.MemoryResponse)
|
246 |
+
self.add_api_route("/sdapi/v1/unload-checkpoint", self.unloadapi, methods=["POST"])
|
247 |
+
self.add_api_route("/sdapi/v1/reload-checkpoint", self.reloadapi, methods=["POST"])
|
248 |
+
self.add_api_route("/sdapi/v1/scripts", self.get_scripts_list, methods=["GET"], response_model=models.ScriptsList)
|
249 |
+
self.add_api_route("/sdapi/v1/script-info", self.get_script_info, methods=["GET"], response_model=list[models.ScriptInfo])
|
250 |
+
self.add_api_route("/sdapi/v1/extensions", self.get_extensions_list, methods=["GET"], response_model=list[models.ExtensionItem])
|
251 |
+
|
252 |
+
if shared.cmd_opts.api_server_stop:
|
253 |
+
self.add_api_route("/sdapi/v1/server-kill", self.kill_webui, methods=["POST"])
|
254 |
+
self.add_api_route("/sdapi/v1/server-restart", self.restart_webui, methods=["POST"])
|
255 |
+
self.add_api_route("/sdapi/v1/server-stop", self.stop_webui, methods=["POST"])
|
256 |
+
|
257 |
+
self.default_script_arg_txt2img = []
|
258 |
+
self.default_script_arg_img2img = []
|
259 |
+
|
260 |
+
txt2img_script_runner = scripts.scripts_txt2img
|
261 |
+
img2img_script_runner = scripts.scripts_img2img
|
262 |
+
|
263 |
+
if not txt2img_script_runner.scripts or not img2img_script_runner.scripts:
|
264 |
+
ui.create_ui()
|
265 |
+
|
266 |
+
if not txt2img_script_runner.scripts:
|
267 |
+
txt2img_script_runner.initialize_scripts(False)
|
268 |
+
if not self.default_script_arg_txt2img:
|
269 |
+
self.default_script_arg_txt2img = self.init_default_script_args(txt2img_script_runner)
|
270 |
+
|
271 |
+
if not img2img_script_runner.scripts:
|
272 |
+
img2img_script_runner.initialize_scripts(True)
|
273 |
+
if not self.default_script_arg_img2img:
|
274 |
+
self.default_script_arg_img2img = self.init_default_script_args(img2img_script_runner)
|
275 |
+
|
276 |
+
|
277 |
+
|
278 |
+
def add_api_route(self, path: str, endpoint, **kwargs):
|
279 |
+
if shared.cmd_opts.api_auth:
|
280 |
+
return self.app.add_api_route(path, endpoint, dependencies=[Depends(self.auth)], **kwargs)
|
281 |
+
return self.app.add_api_route(path, endpoint, **kwargs)
|
282 |
+
|
283 |
+
def auth(self, credentials: HTTPBasicCredentials = Depends(HTTPBasic())):
|
284 |
+
if credentials.username in self.credentials:
|
285 |
+
if compare_digest(credentials.password, self.credentials[credentials.username]):
|
286 |
+
return True
|
287 |
+
|
288 |
+
raise HTTPException(status_code=401, detail="Incorrect username or password", headers={"WWW-Authenticate": "Basic"})
|
289 |
+
|
290 |
+
def get_selectable_script(self, script_name, script_runner):
|
291 |
+
if script_name is None or script_name == "":
|
292 |
+
return None, None
|
293 |
+
|
294 |
+
script_idx = script_name_to_index(script_name, script_runner.selectable_scripts)
|
295 |
+
script = script_runner.selectable_scripts[script_idx]
|
296 |
+
return script, script_idx
|
297 |
+
|
298 |
+
def get_scripts_list(self):
|
299 |
+
t2ilist = [script.name for script in scripts.scripts_txt2img.scripts if script.name is not None]
|
300 |
+
i2ilist = [script.name for script in scripts.scripts_img2img.scripts if script.name is not None]
|
301 |
+
|
302 |
+
return models.ScriptsList(txt2img=t2ilist, img2img=i2ilist)
|
303 |
+
|
304 |
+
def get_script_info(self):
|
305 |
+
res = []
|
306 |
+
|
307 |
+
for script_list in [scripts.scripts_txt2img.scripts, scripts.scripts_img2img.scripts]:
|
308 |
+
res += [script.api_info for script in script_list if script.api_info is not None]
|
309 |
+
|
310 |
+
return res
|
311 |
+
|
312 |
+
def get_script(self, script_name, script_runner):
|
313 |
+
if script_name is None or script_name == "":
|
314 |
+
return None, None
|
315 |
+
|
316 |
+
script_idx = script_name_to_index(script_name, script_runner.scripts)
|
317 |
+
return script_runner.scripts[script_idx]
|
318 |
+
|
319 |
+
def init_default_script_args(self, script_runner):
|
320 |
+
#find max idx from the scripts in runner and generate a none array to init script_args
|
321 |
+
last_arg_index = 1
|
322 |
+
for script in script_runner.scripts:
|
323 |
+
if last_arg_index < script.args_to:
|
324 |
+
last_arg_index = script.args_to
|
325 |
+
# None everywhere except position 0 to initialize script args
|
326 |
+
script_args = [None]*last_arg_index
|
327 |
+
script_args[0] = 0
|
328 |
+
|
329 |
+
# get default values
|
330 |
+
with gr.Blocks(): # will throw errors calling ui function without this
|
331 |
+
for script in script_runner.scripts:
|
332 |
+
if script.ui(script.is_img2img):
|
333 |
+
ui_default_values = []
|
334 |
+
for elem in script.ui(script.is_img2img):
|
335 |
+
ui_default_values.append(elem.value)
|
336 |
+
script_args[script.args_from:script.args_to] = ui_default_values
|
337 |
+
return script_args
|
338 |
+
|
339 |
+
def init_script_args(self, request, default_script_args, selectable_scripts, selectable_idx, script_runner, *, input_script_args=None):
|
340 |
+
script_args = default_script_args.copy()
|
341 |
+
|
342 |
+
if input_script_args is not None:
|
343 |
+
for index, value in input_script_args.items():
|
344 |
+
script_args[index] = value
|
345 |
+
|
346 |
+
# position 0 in script_arg is the idx+1 of the selectable script that is going to be run when using scripts.scripts_*2img.run()
|
347 |
+
if selectable_scripts:
|
348 |
+
script_args[selectable_scripts.args_from:selectable_scripts.args_to] = request.script_args
|
349 |
+
script_args[0] = selectable_idx + 1
|
350 |
+
|
351 |
+
# Now check for always on scripts
|
352 |
+
if request.alwayson_scripts:
|
353 |
+
for alwayson_script_name in request.alwayson_scripts.keys():
|
354 |
+
alwayson_script = self.get_script(alwayson_script_name, script_runner)
|
355 |
+
if alwayson_script is None:
|
356 |
+
raise HTTPException(status_code=422, detail=f"always on script {alwayson_script_name} not found")
|
357 |
+
# Selectable script in always on script param check
|
358 |
+
if alwayson_script.alwayson is False:
|
359 |
+
raise HTTPException(status_code=422, detail="Cannot have a selectable script in the always on scripts params")
|
360 |
+
# always on script with no arg should always run so you don't really need to add them to the requests
|
361 |
+
if "args" in request.alwayson_scripts[alwayson_script_name]:
|
362 |
+
# min between arg length in scriptrunner and arg length in the request
|
363 |
+
for idx in range(0, min((alwayson_script.args_to - alwayson_script.args_from), len(request.alwayson_scripts[alwayson_script_name]["args"]))):
|
364 |
+
script_args[alwayson_script.args_from + idx] = request.alwayson_scripts[alwayson_script_name]["args"][idx]
|
365 |
+
return script_args
|
366 |
+
|
367 |
+
def apply_infotext(self, request, tabname, *, script_runner=None, mentioned_script_args=None):
|
368 |
+
"""Processes `infotext` field from the `request`, and sets other fields of the `request` accoring to what's in infotext.
|
369 |
+
|
370 |
+
If request already has a field set, and that field is encountered in infotext too, the value from infotext is ignored.
|
371 |
+
|
372 |
+
Additionally, fills `mentioned_script_args` dict with index: value pairs for script arguments read from infotext.
|
373 |
+
"""
|
374 |
+
|
375 |
+
if not request.infotext:
|
376 |
+
return {}
|
377 |
+
|
378 |
+
possible_fields = infotext_utils.paste_fields[tabname]["fields"]
|
379 |
+
set_fields = request.model_dump(exclude_unset=True) if hasattr(request, "request") else request.dict(exclude_unset=True) # pydantic v1/v2 have differenrt names for this
|
380 |
+
params = infotext_utils.parse_generation_parameters(request.infotext)
|
381 |
+
|
382 |
+
def get_field_value(field, params):
|
383 |
+
value = field.function(params) if field.function else params.get(field.label)
|
384 |
+
if value is None:
|
385 |
+
return None
|
386 |
+
|
387 |
+
if field.api in request.__fields__:
|
388 |
+
target_type = request.__fields__[field.api].type_
|
389 |
+
else:
|
390 |
+
target_type = type(field.component.value)
|
391 |
+
|
392 |
+
if target_type == type(None):
|
393 |
+
return None
|
394 |
+
|
395 |
+
if isinstance(value, dict) and value.get('__type__') == 'generic_update': # this is a gradio.update rather than a value
|
396 |
+
value = value.get('value')
|
397 |
+
|
398 |
+
if value is not None and not isinstance(value, target_type):
|
399 |
+
value = target_type(value)
|
400 |
+
|
401 |
+
return value
|
402 |
+
|
403 |
+
for field in possible_fields:
|
404 |
+
if not field.api:
|
405 |
+
continue
|
406 |
+
|
407 |
+
if field.api in set_fields:
|
408 |
+
continue
|
409 |
+
|
410 |
+
value = get_field_value(field, params)
|
411 |
+
if value is not None:
|
412 |
+
setattr(request, field.api, value)
|
413 |
+
|
414 |
+
if request.override_settings is None:
|
415 |
+
request.override_settings = {}
|
416 |
+
|
417 |
+
overriden_settings = infotext_utils.get_override_settings(params)
|
418 |
+
for _, setting_name, value in overriden_settings:
|
419 |
+
if setting_name not in request.override_settings:
|
420 |
+
request.override_settings[setting_name] = value
|
421 |
+
|
422 |
+
if script_runner is not None and mentioned_script_args is not None:
|
423 |
+
indexes = {v: i for i, v in enumerate(script_runner.inputs)}
|
424 |
+
script_fields = ((field, indexes[field.component]) for field in possible_fields if field.component in indexes)
|
425 |
+
|
426 |
+
for field, index in script_fields:
|
427 |
+
value = get_field_value(field, params)
|
428 |
+
|
429 |
+
if value is None:
|
430 |
+
continue
|
431 |
+
|
432 |
+
mentioned_script_args[index] = value
|
433 |
+
|
434 |
+
return params
|
435 |
+
|
436 |
+
def text2imgapi(self, txt2imgreq: models.StableDiffusionTxt2ImgProcessingAPI):
|
437 |
+
task_id = txt2imgreq.force_task_id or create_task_id("txt2img")
|
438 |
+
|
439 |
+
script_runner = scripts.scripts_txt2img
|
440 |
+
|
441 |
+
infotext_script_args = {}
|
442 |
+
self.apply_infotext(txt2imgreq, "txt2img", script_runner=script_runner, mentioned_script_args=infotext_script_args)
|
443 |
+
|
444 |
+
selectable_scripts, selectable_script_idx = self.get_selectable_script(txt2imgreq.script_name, script_runner)
|
445 |
+
|
446 |
+
populate = txt2imgreq.copy(update={ # Override __init__ params
|
447 |
+
"sampler_name": validate_sampler_name(txt2imgreq.sampler_name or txt2imgreq.sampler_index),
|
448 |
+
"do_not_save_samples": not txt2imgreq.save_images,
|
449 |
+
"do_not_save_grid": not txt2imgreq.save_images,
|
450 |
+
})
|
451 |
+
if populate.sampler_name:
|
452 |
+
populate.sampler_index = None # prevent a warning later on
|
453 |
+
|
454 |
+
args = vars(populate)
|
455 |
+
args.pop('script_name', None)
|
456 |
+
args.pop('script_args', None) # will refeed them to the pipeline directly after initializing them
|
457 |
+
args.pop('alwayson_scripts', None)
|
458 |
+
args.pop('infotext', None)
|
459 |
+
|
460 |
+
script_args = self.init_script_args(txt2imgreq, self.default_script_arg_txt2img, selectable_scripts, selectable_script_idx, script_runner, input_script_args=infotext_script_args)
|
461 |
+
|
462 |
+
send_images = args.pop('send_images', True)
|
463 |
+
args.pop('save_images', None)
|
464 |
+
|
465 |
+
add_task_to_queue(task_id)
|
466 |
+
|
467 |
+
with self.queue_lock:
|
468 |
+
with closing(StableDiffusionProcessingTxt2Img(sd_model=shared.sd_model, **args)) as p:
|
469 |
+
p.is_api = True
|
470 |
+
p.scripts = script_runner
|
471 |
+
p.outpath_grids = opts.outdir_txt2img_grids
|
472 |
+
p.outpath_samples = opts.outdir_txt2img_samples
|
473 |
+
|
474 |
+
try:
|
475 |
+
shared.state.begin(job="scripts_txt2img")
|
476 |
+
start_task(task_id)
|
477 |
+
if selectable_scripts is not None:
|
478 |
+
p.script_args = script_args
|
479 |
+
processed = scripts.scripts_txt2img.run(p, *p.script_args) # Need to pass args as list here
|
480 |
+
else:
|
481 |
+
p.script_args = tuple(script_args) # Need to pass args as tuple here
|
482 |
+
processed = process_images(p)
|
483 |
+
finish_task(task_id)
|
484 |
+
finally:
|
485 |
+
shared.state.end()
|
486 |
+
shared.total_tqdm.clear()
|
487 |
+
|
488 |
+
b64images = [
|
489 |
+
encode_pil_to_base64(image)
|
490 |
+
for image in itertools.chain(processed.images, processed.extra_images)
|
491 |
+
if send_images
|
492 |
+
]
|
493 |
+
|
494 |
+
return models.TextToImageResponse(images=b64images, parameters=vars(txt2imgreq), info=processed.js())
|
495 |
+
|
496 |
+
def text2imgapimod(self, txt2imgreq: models.StableDiffusionTxt2ImgProcessingAPI):
|
497 |
+
task_id = txt2imgreq.force_task_id or create_task_id("txt2img")
|
498 |
+
|
499 |
+
script_runner = scripts.scripts_txt2img
|
500 |
+
|
501 |
+
infotext_script_args = {}
|
502 |
+
self.apply_infotext(txt2imgreq, "txt2img", script_runner=script_runner, mentioned_script_args=infotext_script_args)
|
503 |
+
|
504 |
+
selectable_scripts, selectable_script_idx = self.get_selectable_script(txt2imgreq.script_name, script_runner)
|
505 |
+
|
506 |
+
populate = txt2imgreq.copy(update={ # Override __init__ params
|
507 |
+
"sampler_name": validate_sampler_name(txt2imgreq.sampler_name or txt2imgreq.sampler_index),
|
508 |
+
"do_not_save_samples": not txt2imgreq.save_images,
|
509 |
+
"do_not_save_grid": not txt2imgreq.save_images,
|
510 |
+
})
|
511 |
+
if populate.sampler_name:
|
512 |
+
populate.sampler_index = None # prevent a warning later on
|
513 |
+
|
514 |
+
args = vars(populate)
|
515 |
+
args.pop('script_name', None)
|
516 |
+
args.pop('script_args', None) # will refeed them to the pipeline directly after initializing them
|
517 |
+
args.pop('alwayson_scripts', None)
|
518 |
+
args.pop('infotext', None)
|
519 |
+
|
520 |
+
script_args = self.init_script_args(txt2imgreq, self.default_script_arg_txt2img, selectable_scripts, selectable_script_idx, script_runner, input_script_args=infotext_script_args)
|
521 |
+
|
522 |
+
send_images = args.pop('send_images', True)
|
523 |
+
args.pop('save_images', None)
|
524 |
+
|
525 |
+
add_task_to_queue(task_id)
|
526 |
+
|
527 |
+
with self.queue_lock:
|
528 |
+
with closing(StableDiffusionProcessingTxt2Img(sd_model=shared.sd_model, **args)) as p:
|
529 |
+
p.is_api = True
|
530 |
+
p.scripts = script_runner
|
531 |
+
p.outpath_grids = opts.outdir_txt2img_grids
|
532 |
+
p.outpath_samples = opts.outdir_txt2img_samples
|
533 |
+
|
534 |
+
try:
|
535 |
+
shared.state.begin(job="scripts_txt2img")
|
536 |
+
start_task(task_id)
|
537 |
+
if selectable_scripts is not None:
|
538 |
+
p.script_args = script_args
|
539 |
+
processed = scripts.scripts_txt2img.run(p, *p.script_args) # Need to pass args as list here
|
540 |
+
else:
|
541 |
+
p.script_args = tuple(script_args) # Need to pass args as tuple here
|
542 |
+
processed = process_images(p)
|
543 |
+
finish_task(task_id)
|
544 |
+
finally:
|
545 |
+
shared.state.end()
|
546 |
+
shared.total_tqdm.clear()
|
547 |
+
|
548 |
+
for image in itertools.chain(processed.images, processed.extra_images):
|
549 |
+
# <PIL.Image.Image image mode=RGB size=512x512 at 0x241AA93FD90>█
|
550 |
+
# save image and return path
|
551 |
+
temp_dir = "temp"
|
552 |
+
# Create folder
|
553 |
+
if not os.path.exists(temp_dir):
|
554 |
+
os.makedirs(temp_dir)
|
555 |
+
|
556 |
+
timestampp = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
|
557 |
+
temp_file = os.path.join(temp_dir, f'temp_{timestampp}.png')
|
558 |
+
image.save(temp_file)
|
559 |
+
|
560 |
+
full_temp_path = os.path.abspath(temp_file)
|
561 |
+
|
562 |
+
return models.TextToImageResponseMod(image=full_temp_path)
|
563 |
+
# print(image)
|
564 |
+
|
565 |
+
b64images = [
|
566 |
+
encode_pil_to_base64(image)
|
567 |
+
for image in itertools.chain(processed.images, processed.extra_images)
|
568 |
+
if send_images
|
569 |
+
]
|
570 |
+
|
571 |
+
def img2imgapi(self, img2imgreq: models.StableDiffusionImg2ImgProcessingAPI):
|
572 |
+
task_id = img2imgreq.force_task_id or create_task_id("img2img")
|
573 |
+
|
574 |
+
init_images = img2imgreq.init_images
|
575 |
+
if init_images is None:
|
576 |
+
raise HTTPException(status_code=404, detail="Init image not found")
|
577 |
+
|
578 |
+
mask = img2imgreq.mask
|
579 |
+
if mask:
|
580 |
+
mask = decode_base64_to_image(mask)
|
581 |
+
|
582 |
+
script_runner = scripts.scripts_img2img
|
583 |
+
|
584 |
+
infotext_script_args = {}
|
585 |
+
self.apply_infotext(img2imgreq, "img2img", script_runner=script_runner, mentioned_script_args=infotext_script_args)
|
586 |
+
|
587 |
+
selectable_scripts, selectable_script_idx = self.get_selectable_script(img2imgreq.script_name, script_runner)
|
588 |
+
|
589 |
+
populate = img2imgreq.copy(update={ # Override __init__ params
|
590 |
+
"sampler_name": validate_sampler_name(img2imgreq.sampler_name or img2imgreq.sampler_index),
|
591 |
+
"do_not_save_samples": not img2imgreq.save_images,
|
592 |
+
"do_not_save_grid": not img2imgreq.save_images,
|
593 |
+
"mask": mask,
|
594 |
+
})
|
595 |
+
if populate.sampler_name:
|
596 |
+
populate.sampler_index = None # prevent a warning later on
|
597 |
+
|
598 |
+
args = vars(populate)
|
599 |
+
args.pop('include_init_images', None) # this is meant to be done by "exclude": True in model, but it's for a reason that I cannot determine.
|
600 |
+
args.pop('script_name', None)
|
601 |
+
args.pop('script_args', None) # will refeed them to the pipeline directly after initializing them
|
602 |
+
args.pop('alwayson_scripts', None)
|
603 |
+
args.pop('infotext', None)
|
604 |
+
|
605 |
+
script_args = self.init_script_args(img2imgreq, self.default_script_arg_img2img, selectable_scripts, selectable_script_idx, script_runner, input_script_args=infotext_script_args)
|
606 |
+
|
607 |
+
send_images = args.pop('send_images', True)
|
608 |
+
args.pop('save_images', None)
|
609 |
+
|
610 |
+
add_task_to_queue(task_id)
|
611 |
+
|
612 |
+
with self.queue_lock:
|
613 |
+
with closing(StableDiffusionProcessingImg2Img(sd_model=shared.sd_model, **args)) as p:
|
614 |
+
p.init_images = [decode_base64_to_image(x) for x in init_images]
|
615 |
+
p.is_api = True
|
616 |
+
p.scripts = script_runner
|
617 |
+
p.outpath_grids = opts.outdir_img2img_grids
|
618 |
+
p.outpath_samples = opts.outdir_img2img_samples
|
619 |
+
|
620 |
+
try:
|
621 |
+
shared.state.begin(job="scripts_img2img")
|
622 |
+
start_task(task_id)
|
623 |
+
if selectable_scripts is not None:
|
624 |
+
p.script_args = script_args
|
625 |
+
processed = scripts.scripts_img2img.run(p, *p.script_args) # Need to pass args as list here
|
626 |
+
else:
|
627 |
+
p.script_args = tuple(script_args) # Need to pass args as tuple here
|
628 |
+
processed = process_images(p)
|
629 |
+
finish_task(task_id)
|
630 |
+
finally:
|
631 |
+
shared.state.end()
|
632 |
+
shared.total_tqdm.clear()
|
633 |
+
|
634 |
+
b64images = [
|
635 |
+
encode_pil_to_base64(image)
|
636 |
+
for image in itertools.chain(processed.images, processed.extra_images)
|
637 |
+
if send_images
|
638 |
+
]
|
639 |
+
|
640 |
+
if not img2imgreq.include_init_images:
|
641 |
+
img2imgreq.init_images = None
|
642 |
+
img2imgreq.mask = None
|
643 |
+
|
644 |
+
return models.ImageToImageResponse(images=b64images, parameters=vars(img2imgreq), info=processed.js())
|
645 |
+
|
646 |
+
def extras_single_image_api(self, req: models.ExtrasSingleImageRequest):
|
647 |
+
reqDict = setUpscalers(req)
|
648 |
+
|
649 |
+
reqDict['image'] = decode_base64_to_image(reqDict['image'])
|
650 |
+
|
651 |
+
with self.queue_lock:
|
652 |
+
result = postprocessing.run_extras(extras_mode=0, image_folder="", input_dir="", output_dir="", save_output=False, **reqDict)
|
653 |
+
|
654 |
+
return models.ExtrasSingleImageResponse(image=encode_pil_to_base64(result[0][0]), html_info=result[1])
|
655 |
+
|
656 |
+
def extras_batch_images_api(self, req: models.ExtrasBatchImagesRequest):
|
657 |
+
reqDict = setUpscalers(req)
|
658 |
+
|
659 |
+
image_list = reqDict.pop('imageList', [])
|
660 |
+
image_folder = [decode_base64_to_image(x.data) for x in image_list]
|
661 |
+
|
662 |
+
with self.queue_lock:
|
663 |
+
result = postprocessing.run_extras(extras_mode=1, image_folder=image_folder, image="", input_dir="", output_dir="", save_output=False, **reqDict)
|
664 |
+
|
665 |
+
return models.ExtrasBatchImagesResponse(images=list(map(encode_pil_to_base64, result[0])), html_info=result[1])
|
666 |
+
|
667 |
+
def pnginfoapi(self, req: models.PNGInfoRequest):
|
668 |
+
image = decode_base64_to_image(req.image.strip())
|
669 |
+
if image is None:
|
670 |
+
return models.PNGInfoResponse(info="")
|
671 |
+
|
672 |
+
geninfo, items = images.read_info_from_image(image)
|
673 |
+
if geninfo is None:
|
674 |
+
geninfo = ""
|
675 |
+
|
676 |
+
params = infotext_utils.parse_generation_parameters(geninfo)
|
677 |
+
script_callbacks.infotext_pasted_callback(geninfo, params)
|
678 |
+
|
679 |
+
return models.PNGInfoResponse(info=geninfo, items=items, parameters=params)
|
680 |
+
|
681 |
+
def progressapi(self, req: models.ProgressRequest = Depends()):
|
682 |
+
# copy from check_progress_call of ui.py
|
683 |
+
|
684 |
+
if shared.state.job_count == 0:
|
685 |
+
return models.ProgressResponse(progress=0, eta_relative=0, state=shared.state.dict(), textinfo=shared.state.textinfo)
|
686 |
+
|
687 |
+
# avoid dividing zero
|
688 |
+
progress = 0.01
|
689 |
+
|
690 |
+
if shared.state.job_count > 0:
|
691 |
+
progress += shared.state.job_no / shared.state.job_count
|
692 |
+
if shared.state.sampling_steps > 0:
|
693 |
+
progress += 1 / shared.state.job_count * shared.state.sampling_step / shared.state.sampling_steps
|
694 |
+
|
695 |
+
time_since_start = time.time() - shared.state.time_start
|
696 |
+
eta = (time_since_start/progress)
|
697 |
+
eta_relative = eta-time_since_start
|
698 |
+
|
699 |
+
progress = min(progress, 1)
|
700 |
+
|
701 |
+
shared.state.set_current_image()
|
702 |
+
|
703 |
+
current_image = None
|
704 |
+
if shared.state.current_image and not req.skip_current_image:
|
705 |
+
current_image = encode_pil_to_base64(shared.state.current_image)
|
706 |
+
|
707 |
+
return models.ProgressResponse(progress=progress, eta_relative=eta_relative, state=shared.state.dict(), current_image=current_image, textinfo=shared.state.textinfo, current_task=current_task)
|
708 |
+
|
709 |
+
def interrogateapi(self, interrogatereq: models.InterrogateRequest):
|
710 |
+
image_b64 = interrogatereq.image
|
711 |
+
if image_b64 is None:
|
712 |
+
raise HTTPException(status_code=404, detail="Image not found")
|
713 |
+
|
714 |
+
img = decode_base64_to_image(image_b64)
|
715 |
+
img = img.convert('RGB')
|
716 |
+
|
717 |
+
# Override object param
|
718 |
+
with self.queue_lock:
|
719 |
+
if interrogatereq.model == "clip":
|
720 |
+
processed = shared.interrogator.interrogate(img)
|
721 |
+
elif interrogatereq.model == "deepdanbooru":
|
722 |
+
processed = deepbooru.model.tag(img)
|
723 |
+
else:
|
724 |
+
raise HTTPException(status_code=404, detail="Model not found")
|
725 |
+
|
726 |
+
return models.InterrogateResponse(caption=processed)
|
727 |
+
|
728 |
+
def interruptapi(self):
|
729 |
+
shared.state.interrupt()
|
730 |
+
|
731 |
+
return {}
|
732 |
+
|
733 |
+
def unloadapi(self):
|
734 |
+
sd_models.unload_model_weights()
|
735 |
+
|
736 |
+
return {}
|
737 |
+
|
738 |
+
def reloadapi(self):
|
739 |
+
sd_models.send_model_to_device(shared.sd_model)
|
740 |
+
|
741 |
+
return {}
|
742 |
+
|
743 |
+
def skip(self):
|
744 |
+
shared.state.skip()
|
745 |
+
|
746 |
+
def get_config(self):
|
747 |
+
options = {}
|
748 |
+
for key in shared.opts.data.keys():
|
749 |
+
metadata = shared.opts.data_labels.get(key)
|
750 |
+
if(metadata is not None):
|
751 |
+
options.update({key: shared.opts.data.get(key, shared.opts.data_labels.get(key).default)})
|
752 |
+
else:
|
753 |
+
options.update({key: shared.opts.data.get(key, None)})
|
754 |
+
|
755 |
+
return options
|
756 |
+
|
757 |
+
def set_config(self, req: dict[str, Any]):
|
758 |
+
checkpoint_name = req.get("sd_model_checkpoint", None)
|
759 |
+
if checkpoint_name is not None and checkpoint_name not in sd_models.checkpoint_aliases:
|
760 |
+
raise RuntimeError(f"model {checkpoint_name!r} not found")
|
761 |
+
|
762 |
+
for k, v in req.items():
|
763 |
+
shared.opts.set(k, v, is_api=True)
|
764 |
+
|
765 |
+
shared.opts.save(shared.config_filename)
|
766 |
+
return
|
767 |
+
|
768 |
+
def get_cmd_flags(self):
|
769 |
+
return vars(shared.cmd_opts)
|
770 |
+
|
771 |
+
def get_samplers(self):
|
772 |
+
return [{"name": sampler[0], "aliases":sampler[2], "options":sampler[3]} for sampler in sd_samplers.all_samplers]
|
773 |
+
|
774 |
+
def get_upscalers(self):
|
775 |
+
return [
|
776 |
+
{
|
777 |
+
"name": upscaler.name,
|
778 |
+
"model_name": upscaler.scaler.model_name,
|
779 |
+
"model_path": upscaler.data_path,
|
780 |
+
"model_url": None,
|
781 |
+
"scale": upscaler.scale,
|
782 |
+
}
|
783 |
+
for upscaler in shared.sd_upscalers
|
784 |
+
]
|
785 |
+
|
786 |
+
def get_latent_upscale_modes(self):
|
787 |
+
return [
|
788 |
+
{
|
789 |
+
"name": upscale_mode,
|
790 |
+
}
|
791 |
+
for upscale_mode in [*(shared.latent_upscale_modes or {})]
|
792 |
+
]
|
793 |
+
|
794 |
+
def get_sd_models(self):
|
795 |
+
import modules.sd_models as sd_models
|
796 |
+
return [{"title": x.title, "model_name": x.model_name, "hash": x.shorthash, "sha256": x.sha256, "filename": x.filename, "config": find_checkpoint_config_near_filename(x)} for x in sd_models.checkpoints_list.values()]
|
797 |
+
|
798 |
+
def get_sd_vaes(self):
|
799 |
+
import modules.sd_vae as sd_vae
|
800 |
+
return [{"model_name": x, "filename": sd_vae.vae_dict[x]} for x in sd_vae.vae_dict.keys()]
|
801 |
+
|
802 |
+
def get_hypernetworks(self):
|
803 |
+
return [{"name": name, "path": shared.hypernetworks[name]} for name in shared.hypernetworks]
|
804 |
+
|
805 |
+
def get_face_restorers(self):
|
806 |
+
return [{"name":x.name(), "cmd_dir": getattr(x, "cmd_dir", None)} for x in shared.face_restorers]
|
807 |
+
|
808 |
+
def get_realesrgan_models(self):
|
809 |
+
return [{"name":x.name,"path":x.data_path, "scale":x.scale} for x in get_realesrgan_models(None)]
|
810 |
+
|
811 |
+
def get_prompt_styles(self):
|
812 |
+
styleList = []
|
813 |
+
for k in shared.prompt_styles.styles:
|
814 |
+
style = shared.prompt_styles.styles[k]
|
815 |
+
styleList.append({"name":style[0], "prompt": style[1], "negative_prompt": style[2]})
|
816 |
+
|
817 |
+
return styleList
|
818 |
+
|
819 |
+
def get_embeddings(self):
|
820 |
+
db = sd_hijack.model_hijack.embedding_db
|
821 |
+
|
822 |
+
def convert_embedding(embedding):
|
823 |
+
return {
|
824 |
+
"step": embedding.step,
|
825 |
+
"sd_checkpoint": embedding.sd_checkpoint,
|
826 |
+
"sd_checkpoint_name": embedding.sd_checkpoint_name,
|
827 |
+
"shape": embedding.shape,
|
828 |
+
"vectors": embedding.vectors,
|
829 |
+
}
|
830 |
+
|
831 |
+
def convert_embeddings(embeddings):
|
832 |
+
return {embedding.name: convert_embedding(embedding) for embedding in embeddings.values()}
|
833 |
+
|
834 |
+
return {
|
835 |
+
"loaded": convert_embeddings(db.word_embeddings),
|
836 |
+
"skipped": convert_embeddings(db.skipped_embeddings),
|
837 |
+
}
|
838 |
+
|
839 |
+
def refresh_embeddings(self):
|
840 |
+
with self.queue_lock:
|
841 |
+
sd_hijack.model_hijack.embedding_db.load_textual_inversion_embeddings(force_reload=True)
|
842 |
+
|
843 |
+
def refresh_checkpoints(self):
|
844 |
+
with self.queue_lock:
|
845 |
+
shared.refresh_checkpoints()
|
846 |
+
|
847 |
+
def refresh_vae(self):
|
848 |
+
with self.queue_lock:
|
849 |
+
shared_items.refresh_vae_list()
|
850 |
+
|
851 |
+
def create_embedding(self, args: dict):
|
852 |
+
try:
|
853 |
+
shared.state.begin(job="create_embedding")
|
854 |
+
filename = create_embedding(**args) # create empty embedding
|
855 |
+
sd_hijack.model_hijack.embedding_db.load_textual_inversion_embeddings() # reload embeddings so new one can be immediately used
|
856 |
+
return models.CreateResponse(info=f"create embedding filename: {filename}")
|
857 |
+
except AssertionError as e:
|
858 |
+
return models.TrainResponse(info=f"create embedding error: {e}")
|
859 |
+
finally:
|
860 |
+
shared.state.end()
|
861 |
+
|
862 |
+
|
863 |
+
def create_hypernetwork(self, args: dict):
|
864 |
+
try:
|
865 |
+
shared.state.begin(job="create_hypernetwork")
|
866 |
+
filename = create_hypernetwork(**args) # create empty embedding
|
867 |
+
return models.CreateResponse(info=f"create hypernetwork filename: {filename}")
|
868 |
+
except AssertionError as e:
|
869 |
+
return models.TrainResponse(info=f"create hypernetwork error: {e}")
|
870 |
+
finally:
|
871 |
+
shared.state.end()
|
872 |
+
|
873 |
+
def train_embedding(self, args: dict):
|
874 |
+
try:
|
875 |
+
shared.state.begin(job="train_embedding")
|
876 |
+
apply_optimizations = shared.opts.training_xattention_optimizations
|
877 |
+
error = None
|
878 |
+
filename = ''
|
879 |
+
if not apply_optimizations:
|
880 |
+
sd_hijack.undo_optimizations()
|
881 |
+
try:
|
882 |
+
embedding, filename = train_embedding(**args) # can take a long time to complete
|
883 |
+
except Exception as e:
|
884 |
+
error = e
|
885 |
+
finally:
|
886 |
+
if not apply_optimizations:
|
887 |
+
sd_hijack.apply_optimizations()
|
888 |
+
return models.TrainResponse(info=f"train embedding complete: filename: {filename} error: {error}")
|
889 |
+
except Exception as msg:
|
890 |
+
return models.TrainResponse(info=f"train embedding error: {msg}")
|
891 |
+
finally:
|
892 |
+
shared.state.end()
|
893 |
+
|
894 |
+
def train_hypernetwork(self, args: dict):
|
895 |
+
try:
|
896 |
+
shared.state.begin(job="train_hypernetwork")
|
897 |
+
shared.loaded_hypernetworks = []
|
898 |
+
apply_optimizations = shared.opts.training_xattention_optimizations
|
899 |
+
error = None
|
900 |
+
filename = ''
|
901 |
+
if not apply_optimizations:
|
902 |
+
sd_hijack.undo_optimizations()
|
903 |
+
try:
|
904 |
+
hypernetwork, filename = train_hypernetwork(**args)
|
905 |
+
except Exception as e:
|
906 |
+
error = e
|
907 |
+
finally:
|
908 |
+
shared.sd_model.cond_stage_model.to(devices.device)
|
909 |
+
shared.sd_model.first_stage_model.to(devices.device)
|
910 |
+
if not apply_optimizations:
|
911 |
+
sd_hijack.apply_optimizations()
|
912 |
+
shared.state.end()
|
913 |
+
return models.TrainResponse(info=f"train embedding complete: filename: {filename} error: {error}")
|
914 |
+
except Exception as exc:
|
915 |
+
return models.TrainResponse(info=f"train embedding error: {exc}")
|
916 |
+
finally:
|
917 |
+
shared.state.end()
|
918 |
+
|
919 |
+
def get_memory(self):
|
920 |
+
try:
|
921 |
+
import os
|
922 |
+
import psutil
|
923 |
+
process = psutil.Process(os.getpid())
|
924 |
+
res = process.memory_info() # only rss is cross-platform guaranteed so we dont rely on other values
|
925 |
+
ram_total = 100 * res.rss / process.memory_percent() # and total memory is calculated as actual value is not cross-platform safe
|
926 |
+
ram = { 'free': ram_total - res.rss, 'used': res.rss, 'total': ram_total }
|
927 |
+
except Exception as err:
|
928 |
+
ram = { 'error': f'{err}' }
|
929 |
+
try:
|
930 |
+
import torch
|
931 |
+
if torch.cuda.is_available():
|
932 |
+
s = torch.cuda.mem_get_info()
|
933 |
+
system = { 'free': s[0], 'used': s[1] - s[0], 'total': s[1] }
|
934 |
+
s = dict(torch.cuda.memory_stats(shared.device))
|
935 |
+
allocated = { 'current': s['allocated_bytes.all.current'], 'peak': s['allocated_bytes.all.peak'] }
|
936 |
+
reserved = { 'current': s['reserved_bytes.all.current'], 'peak': s['reserved_bytes.all.peak'] }
|
937 |
+
active = { 'current': s['active_bytes.all.current'], 'peak': s['active_bytes.all.peak'] }
|
938 |
+
inactive = { 'current': s['inactive_split_bytes.all.current'], 'peak': s['inactive_split_bytes.all.peak'] }
|
939 |
+
warnings = { 'retries': s['num_alloc_retries'], 'oom': s['num_ooms'] }
|
940 |
+
cuda = {
|
941 |
+
'system': system,
|
942 |
+
'active': active,
|
943 |
+
'allocated': allocated,
|
944 |
+
'reserved': reserved,
|
945 |
+
'inactive': inactive,
|
946 |
+
'events': warnings,
|
947 |
+
}
|
948 |
+
else:
|
949 |
+
cuda = {'error': 'unavailable'}
|
950 |
+
except Exception as err:
|
951 |
+
cuda = {'error': f'{err}'}
|
952 |
+
return models.MemoryResponse(ram=ram, cuda=cuda)
|
953 |
+
|
954 |
+
def get_extensions_list(self):
|
955 |
+
from modules import extensions
|
956 |
+
extensions.list_extensions()
|
957 |
+
ext_list = []
|
958 |
+
for ext in extensions.extensions:
|
959 |
+
ext: extensions.Extension
|
960 |
+
ext.read_info_from_repo()
|
961 |
+
if ext.remote is not None:
|
962 |
+
ext_list.append({
|
963 |
+
"name": ext.name,
|
964 |
+
"remote": ext.remote,
|
965 |
+
"branch": ext.branch,
|
966 |
+
"commit_hash":ext.commit_hash,
|
967 |
+
"commit_date":ext.commit_date,
|
968 |
+
"version":ext.version,
|
969 |
+
"enabled":ext.enabled
|
970 |
+
})
|
971 |
+
return ext_list
|
972 |
+
|
973 |
+
def launch(self, server_name, port, root_path):
|
974 |
+
self.app.include_router(self.router)
|
975 |
+
uvicorn.run(
|
976 |
+
self.app,
|
977 |
+
host=server_name,
|
978 |
+
port=port,
|
979 |
+
timeout_keep_alive=shared.cmd_opts.timeout_keep_alive,
|
980 |
+
root_path=root_path,
|
981 |
+
ssl_keyfile=shared.cmd_opts.tls_keyfile,
|
982 |
+
ssl_certfile=shared.cmd_opts.tls_certfile
|
983 |
+
)
|
984 |
+
|
985 |
+
def kill_webui(self):
|
986 |
+
restart.stop_program()
|
987 |
+
|
988 |
+
def restart_webui(self):
|
989 |
+
if restart.is_restartable():
|
990 |
+
restart.restart_program()
|
991 |
+
return Response(status_code=501)
|
992 |
+
|
993 |
+
def stop_webui(request):
|
994 |
+
shared.state.server_command = "stop"
|
995 |
+
return Response("Stopping.")
|
996 |
+
|
api/models.py
ADDED
@@ -0,0 +1,326 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import inspect
|
2 |
+
|
3 |
+
from pydantic import BaseModel, Field, create_model
|
4 |
+
from typing import Any, Optional, Literal
|
5 |
+
from inflection import underscore
|
6 |
+
from modules.processing import StableDiffusionProcessingTxt2Img, StableDiffusionProcessingImg2Img
|
7 |
+
from modules.shared import sd_upscalers, opts, parser
|
8 |
+
|
9 |
+
API_NOT_ALLOWED = [
|
10 |
+
"self",
|
11 |
+
"kwargs",
|
12 |
+
"sd_model",
|
13 |
+
"outpath_samples",
|
14 |
+
"outpath_grids",
|
15 |
+
"sampler_index",
|
16 |
+
# "do_not_save_samples",
|
17 |
+
# "do_not_save_grid",
|
18 |
+
"extra_generation_params",
|
19 |
+
"overlay_images",
|
20 |
+
"do_not_reload_embeddings",
|
21 |
+
"seed_enable_extras",
|
22 |
+
"prompt_for_display",
|
23 |
+
"sampler_noise_scheduler_override",
|
24 |
+
"ddim_discretize"
|
25 |
+
]
|
26 |
+
|
27 |
+
class ModelDef(BaseModel):
|
28 |
+
"""Assistance Class for Pydantic Dynamic Model Generation"""
|
29 |
+
|
30 |
+
field: str
|
31 |
+
field_alias: str
|
32 |
+
field_type: Any
|
33 |
+
field_value: Any
|
34 |
+
field_exclude: bool = False
|
35 |
+
|
36 |
+
|
37 |
+
class PydanticModelGenerator:
|
38 |
+
"""
|
39 |
+
Takes in created classes and stubs them out in a way FastAPI/Pydantic is happy about:
|
40 |
+
source_data is a snapshot of the default values produced by the class
|
41 |
+
params are the names of the actual keys required by __init__
|
42 |
+
"""
|
43 |
+
|
44 |
+
def __init__(
|
45 |
+
self,
|
46 |
+
model_name: str = None,
|
47 |
+
class_instance = None,
|
48 |
+
additional_fields = None,
|
49 |
+
):
|
50 |
+
def field_type_generator(k, v):
|
51 |
+
field_type = v.annotation
|
52 |
+
|
53 |
+
if field_type == 'Image':
|
54 |
+
# images are sent as base64 strings via API
|
55 |
+
field_type = 'str'
|
56 |
+
|
57 |
+
return Optional[field_type]
|
58 |
+
|
59 |
+
def merge_class_params(class_):
|
60 |
+
all_classes = list(filter(lambda x: x is not object, inspect.getmro(class_)))
|
61 |
+
parameters = {}
|
62 |
+
for classes in all_classes:
|
63 |
+
parameters = {**parameters, **inspect.signature(classes.__init__).parameters}
|
64 |
+
return parameters
|
65 |
+
|
66 |
+
self._model_name = model_name
|
67 |
+
self._class_data = merge_class_params(class_instance)
|
68 |
+
|
69 |
+
self._model_def = [
|
70 |
+
ModelDef(
|
71 |
+
field=underscore(k),
|
72 |
+
field_alias=k,
|
73 |
+
field_type=field_type_generator(k, v),
|
74 |
+
field_value=None if isinstance(v.default, property) else v.default
|
75 |
+
)
|
76 |
+
for (k,v) in self._class_data.items() if k not in API_NOT_ALLOWED
|
77 |
+
]
|
78 |
+
|
79 |
+
for fields in additional_fields:
|
80 |
+
self._model_def.append(ModelDef(
|
81 |
+
field=underscore(fields["key"]),
|
82 |
+
field_alias=fields["key"],
|
83 |
+
field_type=fields["type"],
|
84 |
+
field_value=fields["default"],
|
85 |
+
field_exclude=fields["exclude"] if "exclude" in fields else False))
|
86 |
+
|
87 |
+
def generate_model(self):
|
88 |
+
"""
|
89 |
+
Creates a pydantic BaseModel
|
90 |
+
from the json and overrides provided at initialization
|
91 |
+
"""
|
92 |
+
fields = {
|
93 |
+
d.field: (d.field_type, Field(default=d.field_value, alias=d.field_alias, exclude=d.field_exclude)) for d in self._model_def
|
94 |
+
}
|
95 |
+
DynamicModel = create_model(self._model_name, **fields)
|
96 |
+
DynamicModel.__config__.allow_population_by_field_name = True
|
97 |
+
DynamicModel.__config__.allow_mutation = True
|
98 |
+
return DynamicModel
|
99 |
+
|
100 |
+
StableDiffusionTxt2ImgProcessingAPI = PydanticModelGenerator(
|
101 |
+
"StableDiffusionProcessingTxt2Img",
|
102 |
+
StableDiffusionProcessingTxt2Img,
|
103 |
+
[
|
104 |
+
{"key": "sampler_index", "type": str, "default": "Euler"},
|
105 |
+
{"key": "script_name", "type": str, "default": None},
|
106 |
+
{"key": "script_args", "type": list, "default": []},
|
107 |
+
{"key": "send_images", "type": bool, "default": True},
|
108 |
+
{"key": "save_images", "type": bool, "default": False},
|
109 |
+
{"key": "alwayson_scripts", "type": dict, "default": {}},
|
110 |
+
{"key": "force_task_id", "type": str, "default": None},
|
111 |
+
{"key": "infotext", "type": str, "default": None},
|
112 |
+
]
|
113 |
+
).generate_model()
|
114 |
+
|
115 |
+
StableDiffusionImg2ImgProcessingAPI = PydanticModelGenerator(
|
116 |
+
"StableDiffusionProcessingImg2Img",
|
117 |
+
StableDiffusionProcessingImg2Img,
|
118 |
+
[
|
119 |
+
{"key": "sampler_index", "type": str, "default": "Euler"},
|
120 |
+
{"key": "init_images", "type": list, "default": None},
|
121 |
+
{"key": "denoising_strength", "type": float, "default": 0.75},
|
122 |
+
{"key": "mask", "type": str, "default": None},
|
123 |
+
{"key": "include_init_images", "type": bool, "default": False, "exclude" : True},
|
124 |
+
{"key": "script_name", "type": str, "default": None},
|
125 |
+
{"key": "script_args", "type": list, "default": []},
|
126 |
+
{"key": "send_images", "type": bool, "default": True},
|
127 |
+
{"key": "save_images", "type": bool, "default": False},
|
128 |
+
{"key": "alwayson_scripts", "type": dict, "default": {}},
|
129 |
+
{"key": "force_task_id", "type": str, "default": None},
|
130 |
+
{"key": "infotext", "type": str, "default": None},
|
131 |
+
]
|
132 |
+
).generate_model()
|
133 |
+
|
134 |
+
class TextToImageResponse(BaseModel):
|
135 |
+
images: list[str] = Field(default=None, title="Image", description="The generated image in base64 format.")
|
136 |
+
parameters: dict
|
137 |
+
info: str
|
138 |
+
|
139 |
+
class ImageToImageResponse(BaseModel):
|
140 |
+
images: list[str] = Field(default=None, title="Image", description="The generated image in base64 format.")
|
141 |
+
parameters: dict
|
142 |
+
info: str
|
143 |
+
|
144 |
+
class TextToImageResponseMod(BaseModel):
|
145 |
+
# Изменяем под формат изображения, не base64
|
146 |
+
image: str
|
147 |
+
|
148 |
+
class ExtrasBaseRequest(BaseModel):
|
149 |
+
resize_mode: Literal[0, 1] = Field(default=0, title="Resize Mode", description="Sets the resize mode: 0 to upscale by upscaling_resize amount, 1 to upscale up to upscaling_resize_h x upscaling_resize_w.")
|
150 |
+
show_extras_results: bool = Field(default=True, title="Show results", description="Should the backend return the generated image?")
|
151 |
+
gfpgan_visibility: float = Field(default=0, title="GFPGAN Visibility", ge=0, le=1, allow_inf_nan=False, description="Sets the visibility of GFPGAN, values should be between 0 and 1.")
|
152 |
+
codeformer_visibility: float = Field(default=0, title="CodeFormer Visibility", ge=0, le=1, allow_inf_nan=False, description="Sets the visibility of CodeFormer, values should be between 0 and 1.")
|
153 |
+
codeformer_weight: float = Field(default=0, title="CodeFormer Weight", ge=0, le=1, allow_inf_nan=False, description="Sets the weight of CodeFormer, values should be between 0 and 1.")
|
154 |
+
upscaling_resize: float = Field(default=2, title="Upscaling Factor", ge=1, le=8, description="By how much to upscale the image, only used when resize_mode=0.")
|
155 |
+
upscaling_resize_w: int = Field(default=512, title="Target Width", ge=1, description="Target width for the upscaler to hit. Only used when resize_mode=1.")
|
156 |
+
upscaling_resize_h: int = Field(default=512, title="Target Height", ge=1, description="Target height for the upscaler to hit. Only used when resize_mode=1.")
|
157 |
+
upscaling_crop: bool = Field(default=True, title="Crop to fit", description="Should the upscaler crop the image to fit in the chosen size?")
|
158 |
+
upscaler_1: str = Field(default="None", title="Main upscaler", description=f"The name of the main upscaler to use, it has to be one of this list: {' , '.join([x.name for x in sd_upscalers])}")
|
159 |
+
upscaler_2: str = Field(default="None", title="Secondary upscaler", description=f"The name of the secondary upscaler to use, it has to be one of this list: {' , '.join([x.name for x in sd_upscalers])}")
|
160 |
+
extras_upscaler_2_visibility: float = Field(default=0, title="Secondary upscaler visibility", ge=0, le=1, allow_inf_nan=False, description="Sets the visibility of secondary upscaler, values should be between 0 and 1.")
|
161 |
+
upscale_first: bool = Field(default=False, title="Upscale first", description="Should the upscaler run before restoring faces?")
|
162 |
+
|
163 |
+
class ExtraBaseResponse(BaseModel):
|
164 |
+
html_info: str = Field(title="HTML info", description="A series of HTML tags containing the process info.")
|
165 |
+
|
166 |
+
class ExtrasSingleImageRequest(ExtrasBaseRequest):
|
167 |
+
image: str = Field(default="", title="Image", description="Image to work on, must be a Base64 string containing the image's data.")
|
168 |
+
|
169 |
+
class ExtrasSingleImageResponse(ExtraBaseResponse):
|
170 |
+
image: str = Field(default=None, title="Image", description="The generated image in base64 format.")
|
171 |
+
|
172 |
+
class FileData(BaseModel):
|
173 |
+
data: str = Field(title="File data", description="Base64 representation of the file")
|
174 |
+
name: str = Field(title="File name")
|
175 |
+
|
176 |
+
class ExtrasBatchImagesRequest(ExtrasBaseRequest):
|
177 |
+
imageList: list[FileData] = Field(title="Images", description="List of images to work on. Must be Base64 strings")
|
178 |
+
|
179 |
+
class ExtrasBatchImagesResponse(ExtraBaseResponse):
|
180 |
+
images: list[str] = Field(title="Images", description="The generated images in base64 format.")
|
181 |
+
|
182 |
+
class PNGInfoRequest(BaseModel):
|
183 |
+
image: str = Field(title="Image", description="The base64 encoded PNG image")
|
184 |
+
|
185 |
+
class PNGInfoResponse(BaseModel):
|
186 |
+
info: str = Field(title="Image info", description="A string with the parameters used to generate the image")
|
187 |
+
items: dict = Field(title="Items", description="A dictionary containing all the other fields the image had")
|
188 |
+
parameters: dict = Field(title="Parameters", description="A dictionary with parsed generation info fields")
|
189 |
+
|
190 |
+
class ProgressRequest(BaseModel):
|
191 |
+
skip_current_image: bool = Field(default=False, title="Skip current image", description="Skip current image serialization")
|
192 |
+
|
193 |
+
class ProgressResponse(BaseModel):
|
194 |
+
progress: float = Field(title="Progress", description="The progress with a range of 0 to 1")
|
195 |
+
eta_relative: float = Field(title="ETA in secs")
|
196 |
+
state: dict = Field(title="State", description="The current state snapshot")
|
197 |
+
current_image: str = Field(default=None, title="Current image", description="The current image in base64 format. opts.show_progress_every_n_steps is required for this to work.")
|
198 |
+
textinfo: str = Field(default=None, title="Info text", description="Info text used by WebUI.")
|
199 |
+
|
200 |
+
class InterrogateRequest(BaseModel):
|
201 |
+
image: str = Field(default="", title="Image", description="Image to work on, must be a Base64 string containing the image's data.")
|
202 |
+
model: str = Field(default="clip", title="Model", description="The interrogate model used.")
|
203 |
+
|
204 |
+
class InterrogateResponse(BaseModel):
|
205 |
+
caption: str = Field(default=None, title="Caption", description="The generated caption for the image.")
|
206 |
+
|
207 |
+
class TrainResponse(BaseModel):
|
208 |
+
info: str = Field(title="Train info", description="Response string from train embedding or hypernetwork task.")
|
209 |
+
|
210 |
+
class CreateResponse(BaseModel):
|
211 |
+
info: str = Field(title="Create info", description="Response string from create embedding or hypernetwork task.")
|
212 |
+
|
213 |
+
fields = {}
|
214 |
+
for key, metadata in opts.data_labels.items():
|
215 |
+
value = opts.data.get(key)
|
216 |
+
optType = opts.typemap.get(type(metadata.default), type(metadata.default)) if metadata.default else Any
|
217 |
+
|
218 |
+
if metadata is not None:
|
219 |
+
fields.update({key: (Optional[optType], Field(default=metadata.default, description=metadata.label))})
|
220 |
+
else:
|
221 |
+
fields.update({key: (Optional[optType], Field())})
|
222 |
+
|
223 |
+
OptionsModel = create_model("Options", **fields)
|
224 |
+
|
225 |
+
flags = {}
|
226 |
+
_options = vars(parser)['_option_string_actions']
|
227 |
+
for key in _options:
|
228 |
+
if(_options[key].dest != 'help'):
|
229 |
+
flag = _options[key]
|
230 |
+
_type = str
|
231 |
+
if _options[key].default is not None:
|
232 |
+
_type = type(_options[key].default)
|
233 |
+
flags.update({flag.dest: (_type, Field(default=flag.default, description=flag.help))})
|
234 |
+
|
235 |
+
FlagsModel = create_model("Flags", **flags)
|
236 |
+
|
237 |
+
class SamplerItem(BaseModel):
|
238 |
+
name: str = Field(title="Name")
|
239 |
+
aliases: list[str] = Field(title="Aliases")
|
240 |
+
options: dict[str, str] = Field(title="Options")
|
241 |
+
|
242 |
+
class UpscalerItem(BaseModel):
|
243 |
+
name: str = Field(title="Name")
|
244 |
+
model_name: Optional[str] = Field(title="Model Name")
|
245 |
+
model_path: Optional[str] = Field(title="Path")
|
246 |
+
model_url: Optional[str] = Field(title="URL")
|
247 |
+
scale: Optional[float] = Field(title="Scale")
|
248 |
+
|
249 |
+
class LatentUpscalerModeItem(BaseModel):
|
250 |
+
name: str = Field(title="Name")
|
251 |
+
|
252 |
+
class SDModelItem(BaseModel):
|
253 |
+
title: str = Field(title="Title")
|
254 |
+
model_name: str = Field(title="Model Name")
|
255 |
+
hash: Optional[str] = Field(title="Short hash")
|
256 |
+
sha256: Optional[str] = Field(title="sha256 hash")
|
257 |
+
filename: str = Field(title="Filename")
|
258 |
+
config: Optional[str] = Field(title="Config file")
|
259 |
+
|
260 |
+
class SDVaeItem(BaseModel):
|
261 |
+
model_name: str = Field(title="Model Name")
|
262 |
+
filename: str = Field(title="Filename")
|
263 |
+
|
264 |
+
class HypernetworkItem(BaseModel):
|
265 |
+
name: str = Field(title="Name")
|
266 |
+
path: Optional[str] = Field(title="Path")
|
267 |
+
|
268 |
+
class FaceRestorerItem(BaseModel):
|
269 |
+
name: str = Field(title="Name")
|
270 |
+
cmd_dir: Optional[str] = Field(title="Path")
|
271 |
+
|
272 |
+
class RealesrganItem(BaseModel):
|
273 |
+
name: str = Field(title="Name")
|
274 |
+
path: Optional[str] = Field(title="Path")
|
275 |
+
scale: Optional[int] = Field(title="Scale")
|
276 |
+
|
277 |
+
class PromptStyleItem(BaseModel):
|
278 |
+
name: str = Field(title="Name")
|
279 |
+
prompt: Optional[str] = Field(title="Prompt")
|
280 |
+
negative_prompt: Optional[str] = Field(title="Negative Prompt")
|
281 |
+
|
282 |
+
|
283 |
+
class EmbeddingItem(BaseModel):
|
284 |
+
step: Optional[int] = Field(title="Step", description="The number of steps that were used to train this embedding, if available")
|
285 |
+
sd_checkpoint: Optional[str] = Field(title="SD Checkpoint", description="The hash of the checkpoint this embedding was trained on, if available")
|
286 |
+
sd_checkpoint_name: Optional[str] = Field(title="SD Checkpoint Name", description="The name of the checkpoint this embedding was trained on, if available. Note that this is the name that was used by the trainer; for a stable identifier, use `sd_checkpoint` instead")
|
287 |
+
shape: int = Field(title="Shape", description="The length of each individual vector in the embedding")
|
288 |
+
vectors: int = Field(title="Vectors", description="The number of vectors in the embedding")
|
289 |
+
|
290 |
+
class EmbeddingsResponse(BaseModel):
|
291 |
+
loaded: dict[str, EmbeddingItem] = Field(title="Loaded", description="Embeddings loaded for the current model")
|
292 |
+
skipped: dict[str, EmbeddingItem] = Field(title="Skipped", description="Embeddings skipped for the current model (likely due to architecture incompatibility)")
|
293 |
+
|
294 |
+
class MemoryResponse(BaseModel):
|
295 |
+
ram: dict = Field(title="RAM", description="System memory stats")
|
296 |
+
cuda: dict = Field(title="CUDA", description="nVidia CUDA memory stats")
|
297 |
+
|
298 |
+
|
299 |
+
class ScriptsList(BaseModel):
|
300 |
+
txt2img: list = Field(default=None, title="Txt2img", description="Titles of scripts (txt2img)")
|
301 |
+
img2img: list = Field(default=None, title="Img2img", description="Titles of scripts (img2img)")
|
302 |
+
|
303 |
+
|
304 |
+
class ScriptArg(BaseModel):
|
305 |
+
label: str = Field(default=None, title="Label", description="Name of the argument in UI")
|
306 |
+
value: Optional[Any] = Field(default=None, title="Value", description="Default value of the argument")
|
307 |
+
minimum: Optional[Any] = Field(default=None, title="Minimum", description="Minimum allowed value for the argumentin UI")
|
308 |
+
maximum: Optional[Any] = Field(default=None, title="Minimum", description="Maximum allowed value for the argumentin UI")
|
309 |
+
step: Optional[Any] = Field(default=None, title="Minimum", description="Step for changing value of the argumentin UI")
|
310 |
+
choices: Optional[list[str]] = Field(default=None, title="Choices", description="Possible values for the argument")
|
311 |
+
|
312 |
+
|
313 |
+
class ScriptInfo(BaseModel):
|
314 |
+
name: str = Field(default=None, title="Name", description="Script name")
|
315 |
+
is_alwayson: bool = Field(default=None, title="IsAlwayson", description="Flag specifying whether this script is an alwayson script")
|
316 |
+
is_img2img: bool = Field(default=None, title="IsImg2img", description="Flag specifying whether this script is an img2img script")
|
317 |
+
args: list[ScriptArg] = Field(title="Arguments", description="List of script's arguments")
|
318 |
+
|
319 |
+
class ExtensionItem(BaseModel):
|
320 |
+
name: str = Field(title="Name", description="Extension name")
|
321 |
+
remote: str = Field(title="Remote", description="Extension Repository URL")
|
322 |
+
branch: str = Field(title="Branch", description="Extension Repository Branch")
|
323 |
+
commit_hash: str = Field(title="Commit Hash", description="Extension Repository Commit Hash")
|
324 |
+
version: str = Field(title="Version", description="Extension Version")
|
325 |
+
commit_date: str = Field(title="Commit Date", description="Extension Repository Commit Date")
|
326 |
+
enabled: bool = Field(title="Enabled", description="Flag specifying whether this extension is enabled")
|
config.json
ADDED
@@ -0,0 +1,327 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"ldsr_steps": 100,
|
3 |
+
"ldsr_cached": false,
|
4 |
+
"SCUNET_tile": 256,
|
5 |
+
"SCUNET_tile_overlap": 8,
|
6 |
+
"SWIN_tile": 192,
|
7 |
+
"SWIN_tile_overlap": 8,
|
8 |
+
"SWIN_torch_compile": false,
|
9 |
+
"control_net_detectedmap_dir": "detected_maps",
|
10 |
+
"control_net_models_path": "",
|
11 |
+
"control_net_modules_path": "",
|
12 |
+
"control_net_unit_count": 3,
|
13 |
+
"control_net_model_cache_size": 5,
|
14 |
+
"control_net_no_detectmap": false,
|
15 |
+
"control_net_detectmap_autosaving": false,
|
16 |
+
"control_net_allow_script_control": false,
|
17 |
+
"control_net_sync_field_args": true,
|
18 |
+
"controlnet_show_batch_images_in_ui": false,
|
19 |
+
"controlnet_increment_seed_during_batch": false,
|
20 |
+
"controlnet_disable_openpose_edit": false,
|
21 |
+
"controlnet_disable_photopea_edit": false,
|
22 |
+
"controlnet_photopea_warning": true,
|
23 |
+
"controlnet_input_thumbnail": true,
|
24 |
+
"sd_checkpoint_hash": "0fe2e39405369d15d576f0f8bf1405e53899613711f867c528d2a0d57fefba48",
|
25 |
+
"sd_model_checkpoint": "moxieDiffusionXL_v16.safetensors",
|
26 |
+
"CLIP_stop_at_last_layers": 2,
|
27 |
+
"sd_vae": "sdxl_vae.safetensors",
|
28 |
+
"api_display_include_base64_images": false,
|
29 |
+
"outdir_samples": "",
|
30 |
+
"outdir_txt2img_samples": "output\\txt2img-images",
|
31 |
+
"outdir_img2img_samples": "output\\img2img-images",
|
32 |
+
"outdir_extras_samples": "output\\extras-images",
|
33 |
+
"outdir_grids": "",
|
34 |
+
"outdir_txt2img_grids": "output\\txt2img-grids",
|
35 |
+
"outdir_img2img_grids": "output\\img2img-grids",
|
36 |
+
"outdir_save": "log\\images",
|
37 |
+
"outdir_init_images": "output\\init-images",
|
38 |
+
"samples_save": true,
|
39 |
+
"samples_format": "png",
|
40 |
+
"samples_filename_pattern": "",
|
41 |
+
"save_images_add_number": true,
|
42 |
+
"save_images_replace_action": "Replace",
|
43 |
+
"grid_save": true,
|
44 |
+
"grid_format": "png",
|
45 |
+
"grid_extended_filename": false,
|
46 |
+
"grid_only_if_multiple": true,
|
47 |
+
"grid_prevent_empty_spots": false,
|
48 |
+
"grid_zip_filename_pattern": "",
|
49 |
+
"n_rows": -1,
|
50 |
+
"font": "",
|
51 |
+
"grid_text_active_color": "#000000",
|
52 |
+
"grid_text_inactive_color": "#999999",
|
53 |
+
"grid_background_color": "#ffffff",
|
54 |
+
"save_images_before_face_restoration": false,
|
55 |
+
"save_images_before_highres_fix": false,
|
56 |
+
"save_images_before_color_correction": false,
|
57 |
+
"save_mask": false,
|
58 |
+
"save_mask_composite": false,
|
59 |
+
"jpeg_quality": 80,
|
60 |
+
"webp_lossless": false,
|
61 |
+
"export_for_4chan": true,
|
62 |
+
"img_downscale_threshold": 4.0,
|
63 |
+
"target_side_length": 4000.0,
|
64 |
+
"img_max_size_mp": 200.0,
|
65 |
+
"use_original_name_batch": true,
|
66 |
+
"use_upscaler_name_as_suffix": true,
|
67 |
+
"save_selected_only": true,
|
68 |
+
"save_init_img": false,
|
69 |
+
"temp_dir": "",
|
70 |
+
"clean_temp_dir_at_start": false,
|
71 |
+
"save_incomplete_images": false,
|
72 |
+
"notification_audio": true,
|
73 |
+
"notification_volume": 100,
|
74 |
+
"save_to_dirs": true,
|
75 |
+
"grid_save_to_dirs": true,
|
76 |
+
"use_save_to_dirs_for_ui": false,
|
77 |
+
"directories_filename_pattern": "[date]",
|
78 |
+
"directories_max_prompt_words": 8,
|
79 |
+
"auto_backcompat": true,
|
80 |
+
"use_old_emphasis_implementation": false,
|
81 |
+
"use_old_karras_scheduler_sigmas": false,
|
82 |
+
"no_dpmpp_sde_batch_determinism": false,
|
83 |
+
"use_old_hires_fix_width_height": false,
|
84 |
+
"dont_fix_second_order_samplers_schedule": false,
|
85 |
+
"hires_fix_use_firstpass_conds": false,
|
86 |
+
"use_old_scheduling": false,
|
87 |
+
"use_downcasted_alpha_bar": false,
|
88 |
+
"lora_functional": false,
|
89 |
+
"extra_networks_show_hidden_directories": true,
|
90 |
+
"extra_networks_dir_button_function": false,
|
91 |
+
"extra_networks_hidden_models": "When searched",
|
92 |
+
"extra_networks_default_multiplier": 1,
|
93 |
+
"extra_networks_card_width": 0.0,
|
94 |
+
"extra_networks_card_height": 0.0,
|
95 |
+
"extra_networks_card_text_scale": 1,
|
96 |
+
"extra_networks_card_show_desc": true,
|
97 |
+
"extra_networks_card_description_is_html": false,
|
98 |
+
"extra_networks_card_order_field": "Path",
|
99 |
+
"extra_networks_card_order": "Ascending",
|
100 |
+
"extra_networks_tree_view_default_enabled": false,
|
101 |
+
"extra_networks_add_text_separator": " ",
|
102 |
+
"ui_extra_networks_tab_reorder": "",
|
103 |
+
"textual_inversion_print_at_load": false,
|
104 |
+
"textual_inversion_add_hashes_to_infotext": true,
|
105 |
+
"sd_hypernetwork": "None",
|
106 |
+
"sd_lora": "None",
|
107 |
+
"lora_preferred_name": "Alias from file",
|
108 |
+
"lora_add_hashes_to_infotext": true,
|
109 |
+
"lora_show_all": false,
|
110 |
+
"lora_hide_unknown_for_versions": [],
|
111 |
+
"lora_in_memory_limit": 0,
|
112 |
+
"lora_not_found_warning_console": false,
|
113 |
+
"lora_not_found_gradio_warning": false,
|
114 |
+
"cross_attention_optimization": "Automatic",
|
115 |
+
"s_min_uncond": 0,
|
116 |
+
"token_merging_ratio": 0,
|
117 |
+
"token_merging_ratio_img2img": 0,
|
118 |
+
"token_merging_ratio_hr": 0,
|
119 |
+
"pad_cond_uncond": false,
|
120 |
+
"pad_cond_uncond_v0": false,
|
121 |
+
"persistent_cond_cache": true,
|
122 |
+
"batch_cond_uncond": true,
|
123 |
+
"fp8_storage": "Disable",
|
124 |
+
"cache_fp16_weight": false,
|
125 |
+
"hide_samplers": [],
|
126 |
+
"eta_ddim": 0,
|
127 |
+
"eta_ancestral": 1,
|
128 |
+
"ddim_discretize": "uniform",
|
129 |
+
"s_churn": 0,
|
130 |
+
"s_tmin": 0,
|
131 |
+
"s_tmax": 0,
|
132 |
+
"s_noise": 1,
|
133 |
+
"k_sched_type": "Automatic",
|
134 |
+
"sigma_min": 0.0,
|
135 |
+
"sigma_max": 0.0,
|
136 |
+
"rho": 0.0,
|
137 |
+
"eta_noise_seed_delta": 0,
|
138 |
+
"always_discard_next_to_last_sigma": false,
|
139 |
+
"sgm_noise_multiplier": false,
|
140 |
+
"uni_pc_variant": "bh1",
|
141 |
+
"uni_pc_skip_type": "time_uniform",
|
142 |
+
"uni_pc_order": 3,
|
143 |
+
"uni_pc_lower_order_final": true,
|
144 |
+
"sd_noise_schedule": "Default",
|
145 |
+
"sd_checkpoints_limit": 1,
|
146 |
+
"sd_checkpoints_keep_in_cpu": true,
|
147 |
+
"sd_checkpoint_cache": 0,
|
148 |
+
"sd_unet": "Automatic",
|
149 |
+
"enable_quantization": false,
|
150 |
+
"emphasis": "Original",
|
151 |
+
"enable_batch_seeds": true,
|
152 |
+
"comma_padding_backtrack": 20,
|
153 |
+
"upcast_attn": false,
|
154 |
+
"randn_source": "GPU",
|
155 |
+
"tiling": false,
|
156 |
+
"hires_fix_refiner_pass": "second pass",
|
157 |
+
"enable_prompt_comments": true,
|
158 |
+
"sdxl_crop_top": 0.0,
|
159 |
+
"sdxl_crop_left": 0.0,
|
160 |
+
"sdxl_refiner_low_aesthetic_score": 2.5,
|
161 |
+
"sdxl_refiner_high_aesthetic_score": 6.0,
|
162 |
+
"sd_vae_checkpoint_cache": 0,
|
163 |
+
"sd_vae_overrides_per_model_preferences": true,
|
164 |
+
"auto_vae_precision_bfloat16": false,
|
165 |
+
"auto_vae_precision": true,
|
166 |
+
"sd_vae_encode_method": "Full",
|
167 |
+
"sd_vae_decode_method": "Full",
|
168 |
+
"inpainting_mask_weight": 1,
|
169 |
+
"initial_noise_multiplier": 1,
|
170 |
+
"img2img_extra_noise": 0,
|
171 |
+
"img2img_color_correction": false,
|
172 |
+
"img2img_fix_steps": false,
|
173 |
+
"img2img_background_color": "#ffffff",
|
174 |
+
"img2img_editor_height": 720,
|
175 |
+
"img2img_sketch_default_brush_color": "#ffffff",
|
176 |
+
"img2img_inpaint_mask_brush_color": "#ffffff",
|
177 |
+
"img2img_inpaint_sketch_default_brush_color": "#ffffff",
|
178 |
+
"return_mask": false,
|
179 |
+
"return_mask_composite": false,
|
180 |
+
"img2img_batch_show_results_limit": 32,
|
181 |
+
"overlay_inpaint": true,
|
182 |
+
"return_grid": true,
|
183 |
+
"do_not_show_images": false,
|
184 |
+
"js_modal_lightbox": true,
|
185 |
+
"js_modal_lightbox_initially_zoomed": true,
|
186 |
+
"js_modal_lightbox_gamepad": false,
|
187 |
+
"js_modal_lightbox_gamepad_repeat": 250.0,
|
188 |
+
"sd_webui_modal_lightbox_icon_opacity": 1,
|
189 |
+
"sd_webui_modal_lightbox_toolbar_opacity": 0.9,
|
190 |
+
"gallery_height": "",
|
191 |
+
"open_dir_button_choice": "Subdirectory",
|
192 |
+
"enable_pnginfo": true,
|
193 |
+
"save_txt": false,
|
194 |
+
"add_model_name_to_info": true,
|
195 |
+
"add_model_hash_to_info": true,
|
196 |
+
"add_vae_name_to_info": true,
|
197 |
+
"add_vae_hash_to_info": true,
|
198 |
+
"add_user_name_to_info": false,
|
199 |
+
"add_version_to_infotext": true,
|
200 |
+
"disable_weights_auto_swap": true,
|
201 |
+
"infotext_skip_pasting": [],
|
202 |
+
"infotext_styles": "Apply if any",
|
203 |
+
"show_progressbar": true,
|
204 |
+
"live_previews_enable": true,
|
205 |
+
"live_previews_image_format": "png",
|
206 |
+
"show_progress_grid": true,
|
207 |
+
"show_progress_every_n_steps": 10,
|
208 |
+
"show_progress_type": "Approx NN",
|
209 |
+
"live_preview_allow_lowvram_full": false,
|
210 |
+
"live_preview_content": "Prompt",
|
211 |
+
"live_preview_refresh_period": 1000.0,
|
212 |
+
"live_preview_fast_interrupt": false,
|
213 |
+
"js_live_preview_in_modal_lightbox": false,
|
214 |
+
"keyedit_precision_attention": 0.1,
|
215 |
+
"keyedit_precision_extra": 0.05,
|
216 |
+
"keyedit_delimiters": ".,\\/!?%^*;:{}=`~() ",
|
217 |
+
"keyedit_delimiters_whitespace": [
|
218 |
+
"Tab",
|
219 |
+
"Carriage Return",
|
220 |
+
"Line Feed"
|
221 |
+
],
|
222 |
+
"keyedit_move": true,
|
223 |
+
"disable_token_counters": false,
|
224 |
+
"include_styles_into_token_counters": true,
|
225 |
+
"extra_options_txt2img": [],
|
226 |
+
"extra_options_img2img": [],
|
227 |
+
"extra_options_cols": 1,
|
228 |
+
"extra_options_accordion": false,
|
229 |
+
"compact_prompt_box": false,
|
230 |
+
"samplers_in_dropdown": true,
|
231 |
+
"dimensions_and_batch_together": true,
|
232 |
+
"sd_checkpoint_dropdown_use_short": false,
|
233 |
+
"hires_fix_show_sampler": false,
|
234 |
+
"hires_fix_show_prompts": false,
|
235 |
+
"txt2img_settings_accordion": false,
|
236 |
+
"img2img_settings_accordion": false,
|
237 |
+
"interrupt_after_current": true,
|
238 |
+
"localization": "None",
|
239 |
+
"quicksettings_list": [
|
240 |
+
"sd_model_checkpoint",
|
241 |
+
"sd_vae",
|
242 |
+
"CLIP_stop_at_last_layers"
|
243 |
+
],
|
244 |
+
"ui_tab_order": [],
|
245 |
+
"hidden_tabs": [],
|
246 |
+
"ui_reorder_list": [],
|
247 |
+
"gradio_theme": "Default",
|
248 |
+
"gradio_themes_cache": true,
|
249 |
+
"show_progress_in_title": true,
|
250 |
+
"send_seed": true,
|
251 |
+
"send_size": true,
|
252 |
+
"api_enable_requests": true,
|
253 |
+
"api_forbid_local_requests": true,
|
254 |
+
"api_useragent": "",
|
255 |
+
"auto_launch_browser": "Local",
|
256 |
+
"enable_console_prompts": false,
|
257 |
+
"show_warnings": false,
|
258 |
+
"show_gradio_deprecation_warnings": true,
|
259 |
+
"memmon_poll_rate": 8,
|
260 |
+
"samples_log_stdout": false,
|
261 |
+
"multiple_tqdm": true,
|
262 |
+
"enable_upscale_progressbar": true,
|
263 |
+
"print_hypernet_extra": false,
|
264 |
+
"list_hidden_files": true,
|
265 |
+
"disable_mmap_load_safetensors": false,
|
266 |
+
"hide_ldm_prints": true,
|
267 |
+
"dump_stacks_on_signal": false,
|
268 |
+
"face_restoration": false,
|
269 |
+
"face_restoration_model": "CodeFormer",
|
270 |
+
"code_former_weight": 0.5,
|
271 |
+
"face_restoration_unload": false,
|
272 |
+
"postprocessing_enable_in_main_ui": [],
|
273 |
+
"postprocessing_operation_order": [],
|
274 |
+
"upscaling_max_images_in_cache": 5,
|
275 |
+
"postprocessing_existing_caption_action": "Ignore",
|
276 |
+
"ESRGAN_tile": 192,
|
277 |
+
"ESRGAN_tile_overlap": 8,
|
278 |
+
"realesrgan_enabled_models": [
|
279 |
+
"R-ESRGAN 4x+",
|
280 |
+
"R-ESRGAN 4x+ Anime6B"
|
281 |
+
],
|
282 |
+
"dat_enabled_models": [
|
283 |
+
"DAT x2",
|
284 |
+
"DAT x3",
|
285 |
+
"DAT x4"
|
286 |
+
],
|
287 |
+
"DAT_tile": 192,
|
288 |
+
"DAT_tile_overlap": 8,
|
289 |
+
"unload_models_when_training": false,
|
290 |
+
"pin_memory": false,
|
291 |
+
"save_optimizer_state": false,
|
292 |
+
"save_training_settings_to_txt": true,
|
293 |
+
"dataset_filename_word_regex": "",
|
294 |
+
"dataset_filename_join_string": " ",
|
295 |
+
"training_image_repeats_per_epoch": 1,
|
296 |
+
"training_write_csv_every": 500.0,
|
297 |
+
"training_xattention_optimizations": false,
|
298 |
+
"training_enable_tensorboard": false,
|
299 |
+
"training_tensorboard_save_images": false,
|
300 |
+
"training_tensorboard_flush_every": 120.0,
|
301 |
+
"canvas_hotkey_zoom": "Alt",
|
302 |
+
"canvas_hotkey_adjust": "Ctrl",
|
303 |
+
"canvas_hotkey_shrink_brush": "Q",
|
304 |
+
"canvas_hotkey_grow_brush": "W",
|
305 |
+
"canvas_hotkey_move": "F",
|
306 |
+
"canvas_hotkey_fullscreen": "S",
|
307 |
+
"canvas_hotkey_reset": "R",
|
308 |
+
"canvas_hotkey_overlap": "O",
|
309 |
+
"canvas_show_tooltip": true,
|
310 |
+
"canvas_auto_expand": true,
|
311 |
+
"canvas_blur_prompt": false,
|
312 |
+
"canvas_disabled_functions": [
|
313 |
+
"Overlap"
|
314 |
+
],
|
315 |
+
"interrogate_keep_models_in_memory": false,
|
316 |
+
"interrogate_return_ranks": false,
|
317 |
+
"interrogate_clip_num_beams": 1,
|
318 |
+
"interrogate_clip_min_length": 24,
|
319 |
+
"interrogate_clip_max_length": 48,
|
320 |
+
"interrogate_clip_dict_limit": 1500.0,
|
321 |
+
"interrogate_clip_skip_categories": [],
|
322 |
+
"interrogate_deepbooru_score_threshold": 0.5,
|
323 |
+
"deepbooru_sort_alpha": true,
|
324 |
+
"deepbooru_use_spaces": true,
|
325 |
+
"deepbooru_escape": true,
|
326 |
+
"deepbooru_filter_tags": ""
|
327 |
+
}
|
models/ControlNet/diffusion_pytorch_model.safetensors
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:c8127be9f174101ebdafee9964d856b49b634435cf6daa396d3f593cf0bbbb05
|
3 |
+
size 2502139136
|
models/ControlNet/ip-adapter.bin
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:02b3618e36d803784166660520098089a81388e61a93ef8002aa79a5b1c546e1
|
3 |
+
size 1691134141
|
models/ESRGAN/4x_NMKD-Siax_2000k.pth
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:560424d9f68625713fc47e9e7289a98aabe1d744e1cd6a9ae5a35e9957fd127e
|
3 |
+
size 66957746
|
models/ESRGAN/ESRGAN_4x.pth
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:65fece06e1ccb48853242aa972bdf00ad07a7dd8938d2dcbdf4221b59f6372ce
|
3 |
+
size 66929193
|
models/Stable-diffusion/Put Stable Diffusion checkpoints here.txt
ADDED
File without changes
|
models/Stable-diffusion/moxieDiffusionXL_v16.safetensors
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:0fe2e39405369d15d576f0f8bf1405e53899613711f867c528d2a0d57fefba48
|
3 |
+
size 6938051578
|
models/VAE-approx/model.pt
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:4f88c9078bb2238cdd0d8864671dd33e3f42e091e41f08903f3c15e4a54a9b39
|
3 |
+
size 213777
|
models/VAE-approx/vaeapprox-sdxl.pt
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:6c8db511f910184436a613807ce06a729f4cf96bbf7977c7c6c40d5b3e4a8333
|
3 |
+
size 213777
|
models/VAE/Put VAE here.txt
ADDED
File without changes
|
models/VAE/sdxl_vae.safetensors
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:63aeecb90ff7bc1c115395962d3e803571385b61938377bc7089b36e81e92e2e
|
3 |
+
size 334641164
|
models/deepbooru/Put your deepbooru release project folder here.txt
ADDED
File without changes
|
models/diffusers/version_diffusers_cache.txt
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
1
|
models/insightface/models/antelopev2/1k3d68.onnx
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:df5c06b8a0c12e422b2ed8947b8869faa4105387f199c477af038aa01f9a45cc
|
3 |
+
size 143607619
|
models/insightface/models/antelopev2/2d106det.onnx
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:f001b856447c413801ef5c42091ed0cd516fcd21f2d6b79635b1e733a7109dbf
|
3 |
+
size 5030888
|
models/insightface/models/antelopev2/genderage.onnx
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:4fde69b1c810857b88c64a335084f1c3fe8f01246c9a191b48c7bb756d6652fb
|
3 |
+
size 1322532
|
models/insightface/models/antelopev2/glintr100.onnx
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:4ab1d6435d639628a6f3e5008dd4f929edf4c4124b1a7169e1048f9fef534cdf
|
3 |
+
size 260665334
|
models/insightface/models/antelopev2/scrfd_10g_bnkps.onnx
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:5838f7fe053675b1c7a08b633df49e7af5495cee0493c7dcf6697200b85b5b91
|
3 |
+
size 16923827
|
models/karlo/ViT-L-14_stats.th
ADDED
Binary file (7.08 kB). View file
|
|
models/svd/put svd here.txt
ADDED
File without changes
|
models/z123/put zero123 here.txt
ADDED
File without changes
|