Skip to content

Commit

Permalink
Merge branch 'portrai' into portrai-macos-experimental
Browse files Browse the repository at this point in the history
  • Loading branch information
dcvz committed Nov 2, 2023
2 parents db9cdd8 + 9f90588 commit 072eca2
Show file tree
Hide file tree
Showing 7 changed files with 288 additions and 2 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ __pycache__
/SwinIR/*
/repositories
/venv
/venv-torch-nightly
/tmp
/model.ckpt
/models/**/*
/GFPGANv1.3.pth
/gfpgan/weights/*.pth
/ui-config.json
/outputs
/config.json
/log
/webui.settings.bat
/embeddings
Expand Down
158 changes: 158 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
{
"samples_save": true,
"samples_format": "png",
"samples_filename_pattern": "",
"save_images_add_number": true,
"grid_save": true,
"grid_format": "png",
"grid_extended_filename": false,
"grid_only_if_multiple": true,
"grid_prevent_empty_spots": false,
"n_rows": -1,
"enable_pnginfo": false,
"save_txt": false,
"save_images_before_face_restoration": false,
"save_images_before_highres_fix": false,
"save_images_before_color_correction": false,
"save_mask": false,
"save_mask_composite": false,
"jpeg_quality": 80,
"webp_lossless": false,
"export_for_4chan": true,
"img_downscale_threshold": 4.0,
"target_side_length": 4000,
"img_max_size_mp": 200,
"use_original_name_batch": true,
"use_upscaler_name_as_suffix": false,
"save_selected_only": true,
"do_not_add_watermark": false,
"temp_dir": "",
"clean_temp_dir_at_start": false,
"outdir_samples": "",
"outdir_txt2img_samples": "outputs/txt2img-images",
"outdir_img2img_samples": "outputs/img2img-images",
"outdir_extras_samples": "outputs/extras-images",
"outdir_grids": "",
"outdir_txt2img_grids": "outputs/txt2img-grids",
"outdir_img2img_grids": "outputs/img2img-grids",
"outdir_save": "log/images",
"save_to_dirs": true,
"grid_save_to_dirs": true,
"use_save_to_dirs_for_ui": false,
"directories_filename_pattern": "[date]",
"directories_max_prompt_words": 8,
"ESRGAN_tile": 192,
"ESRGAN_tile_overlap": 8,
"realesrgan_enabled_models": [
"R-ESRGAN 4x+",
"R-ESRGAN 4x+ Anime6B"
],
"upscaler_for_img2img": null,
"face_restoration_model": "CodeFormer",
"code_former_weight": 0.5,
"face_restoration_unload": false,
"show_warnings": false,
"memmon_poll_rate": 8,
"samples_log_stdout": false,
"multiple_tqdm": true,
"print_hypernet_extra": false,
"unload_models_when_training": false,
"pin_memory": false,
"save_optimizer_state": false,
"save_training_settings_to_txt": true,
"dataset_filename_word_regex": "",
"dataset_filename_join_string": " ",
"training_image_repeats_per_epoch": 1,
"training_write_csv_every": 500,
"training_xattention_optimizations": false,
"training_enable_tensorboard": false,
"training_tensorboard_save_images": false,
"training_tensorboard_flush_every": 120,
"sd_model_checkpoint": "deliberate_v2.safetensors [9aba26abdf]",
"sd_checkpoint_cache": 0,
"sd_vae_checkpoint_cache": 0,
"sd_vae": "Automatic",
"sd_vae_as_default": true,
"inpainting_mask_weight": 1.0,
"initial_noise_multiplier": 1.0,
"img2img_color_correction": false,
"img2img_fix_steps": false,
"img2img_background_color": "#ffffff",
"enable_quantization": false,
"enable_emphasis": true,
"enable_batch_seeds": true,
"comma_padding_backtrack": 20,
"CLIP_stop_at_last_layers": 1,
"upcast_attn": false,
"use_old_emphasis_implementation": false,
"use_old_karras_scheduler_sigmas": false,
"no_dpmpp_sde_batch_determinism": false,
"use_old_hires_fix_width_height": false,
"interrogate_keep_models_in_memory": false,
"interrogate_return_ranks": false,
"interrogate_clip_num_beams": 1,
"interrogate_clip_min_length": 24,
"interrogate_clip_max_length": 48,
"interrogate_clip_dict_limit": 1500,
"interrogate_clip_skip_categories": [],
"interrogate_deepbooru_score_threshold": 0.5,
"deepbooru_sort_alpha": true,
"deepbooru_use_spaces": false,
"deepbooru_escape": true,
"deepbooru_filter_tags": "",
"extra_networks_default_view": "cards",
"extra_networks_default_multiplier": 1.0,
"extra_networks_card_width": 0,
"extra_networks_card_height": 0,
"extra_networks_add_text_separator": " ",
"sd_hypernetwork": "None",
"return_grid": true,
"return_mask": false,
"return_mask_composite": false,
"do_not_show_images": false,
"add_model_hash_to_info": true,
"add_model_name_to_info": true,
"disable_weights_auto_swap": true,
"send_seed": true,
"send_size": true,
"font": "",
"js_modal_lightbox": true,
"js_modal_lightbox_initially_zoomed": true,
"show_progress_in_title": true,
"samplers_in_dropdown": true,
"dimensions_and_batch_together": true,
"keyedit_precision_attention": 0.1,
"keyedit_precision_extra": 0.05,
"quicksettings": "sd_model_checkpoint",
"hidden_tabs": [],
"ui_reorder": "inpaint, sampler, checkboxes, hires_fix, dimensions, cfg, seed, batch, override_settings, scripts",
"ui_extra_networks_tab_reorder": "",
"localization": "None",
"show_progressbar": true,
"live_previews_enable": true,
"show_progress_grid": true,
"show_progress_every_n_steps": 4,
"show_progress_type": "Approx NN",
"live_preview_content": "Prompt",
"live_preview_refresh_period": 1000,
"hide_samplers": [],
"eta_ddim": 0.0,
"eta_ancestral": 1.0,
"ddim_discretize": "uniform",
"s_churn": 0.0,
"s_tmin": 0.0,
"s_noise": 1.0,
"eta_noise_seed_delta": 0,
"always_discard_next_to_last_sigma": false,
"uni_pc_variant": "bh1",
"uni_pc_skip_type": "time_uniform",
"uni_pc_order": 3,
"uni_pc_lower_order_final": true,
"postprocessing_enable_in_main_ui": [],
"postprocessing_operation_order": [],
"upscaling_max_images_in_cache": 5,
"disabled_extensions": [],
"disable_all_extensions": "none",
"sd_checkpoint_hash": "9aba26abdfcd46073e0a1d42027a3a3bcc969f562d58a03637bf0a0ded6586c9",
"restore_config_state_file": ""
}
59 changes: 59 additions & 0 deletions modules/api/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@
import piexif.helper
from contextlib import closing

from modules.api import jobs

current_task = None
pending_tasks = {}
finished_tasks = []

def script_name_to_index(name, scripts):
try:
Expand Down Expand Up @@ -215,6 +220,10 @@ def __init__(self, app: FastAPI, queue_lock: Lock):
self.add_api_route("/sdapi/v1/extra-batch-images", self.extras_batch_images_api, methods=["POST"], response_model=models.ExtrasBatchImagesResponse)
self.add_api_route("/sdapi/v1/png-info", self.pnginfoapi, methods=["POST"], response_model=models.PNGInfoResponse)
self.add_api_route("/sdapi/v1/progress", self.progressapi, methods=["GET"], response_model=models.ProgressResponse)

self.add_api_route("/sdapi/v1/new-progress", self.newprogressapi, methods=["POST"], response_model=models.NewProgressResponse)
self.add_api_route("/sdapi/v1/cancel", self.cancel, methods=["POST"])

self.add_api_route("/sdapi/v1/interrogate", self.interrogateapi, methods=["POST"])
self.add_api_route("/sdapi/v1/interrupt", self.interruptapi, methods=["POST"])
self.add_api_route("/sdapi/v1/skip", self.skip, methods=["POST"])
Expand Down Expand Up @@ -338,6 +347,7 @@ def init_script_args(self, request, default_script_args, selectable_scripts, sel
return script_args

def text2imgapi(self, txt2imgreq: models.StableDiffusionTxt2ImgProcessingAPI):
global current_task
script_runner = scripts.scripts_txt2img
if not script_runner.scripts:
script_runner.initialize_scripts(False)
Expand All @@ -363,7 +373,9 @@ def text2imgapi(self, txt2imgreq: models.StableDiffusionTxt2ImgProcessingAPI):

send_images = args.pop('send_images', True)
args.pop('save_images', None)
args.pop('generation_id', None)

jobs.add_task_to_queue(txt2imgreq.generation_id)
with self.queue_lock:
with closing(StableDiffusionProcessingTxt2Img(sd_model=shared.sd_model, **args)) as p:
p.is_api = True
Expand All @@ -373,13 +385,17 @@ def text2imgapi(self, txt2imgreq: models.StableDiffusionTxt2ImgProcessingAPI):

try:
shared.state.begin(job="scripts_txt2img")
jobs.start_task(txt2imgreq.generation_id)
if selectable_scripts is not None:
p.script_args = script_args
processed = scripts.scripts_txt2img.run(p, *p.script_args) # Need to pass args as list here
else:
p.script_args = tuple(script_args) # Need to pass args as tuple here
processed = process_images(p)
finally:
jobs.record_results(txt2imgreq.generation_id, processed)
jobs.finish_task(txt2imgreq.generation_id)

shared.state.end()
shared.total_tqdm.clear()

Expand Down Expand Up @@ -515,6 +531,49 @@ def progressapi(self, req: models.ProgressRequest = Depends()):

return models.ProgressResponse(progress=progress, eta_relative=eta_relative, state=shared.state.dict(), current_image=current_image, textinfo=shared.state.textinfo)

def newprogressapi(self, req: models.NewProgressRequest):
active = req.id_task == jobs.current_task
queued = req.id_task in jobs.pending_tasks
completed = req.id_task in jobs.finished_tasks

if not active:
position_in_queue = sum(1 for job_id, timestamp in jobs.pending_tasks.items() if timestamp < jobs.pending_tasks[req.id_task]) + 1
return models.NewProgressResponse(active=active, queued=queued, completed=completed, eta=position_in_queue, textinfo="In queue..." if queued else "Waiting...")

progress = 0

job_count, job_no = shared.state.job_count, shared.state.job_no
sampling_steps, sampling_step = shared.state.sampling_steps, shared.state.sampling_step

if job_count > 0:
progress += job_no / job_count
if sampling_steps > 0 and job_count > 0:
progress += 1 / job_count * sampling_step / sampling_steps

progress = min(progress, 1)

elapsed_since_start = time.time() - shared.state.time_start
predicted_duration = elapsed_since_start / progress if progress > 0 else None
eta = predicted_duration - elapsed_since_start if predicted_duration is not None else None

shared.state.set_current_image()
image = shared.state.current_image

if image is not None:
buffered = io.BytesIO()
image.save(buffered, format="png")
live_preview = base64.b64encode(buffered.getvalue()).decode("ascii")
else:
live_preview = None

return models.NewProgressResponse(active=active, queued=queued, completed=completed, progress=progress, eta=eta, live_preview=live_preview, textinfo=shared.state.textinfo)

def cancel(self, req: models.CancelRequest):
if req.id_task == jobs.current_task:
shared.state.interrupt()

jobs.cancel_task(req.id_task)

def interrogateapi(self, interrogatereq: models.InterrogateRequest):
image_b64 = interrogatereq.image
if image_b64 is None:
Expand Down
40 changes: 40 additions & 0 deletions modules/api/jobs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import time

current_task = None
pending_tasks = {}
finished_tasks = []
recorded_results = []
recorded_results_limit = 2

def start_task(id_task):
global current_task

current_task = id_task
pending_tasks.pop(id_task, None)

def finish_task(id_task):
global current_task

if current_task == id_task:
current_task = None

finished_tasks.append(id_task)
if len(finished_tasks) > 16:
finished_tasks.pop(0)

def cancel_task(id_task):
global current_task

if current_task == id_task:
current_task = None

pending_tasks.pop(id_task, None)

def record_results(id_task, res):
recorded_results.append((id_task, res))
if len(recorded_results) > recorded_results_limit:
recorded_results.pop(0)


def add_task_to_queue(id_job):
pending_tasks[id_job] = time.time()
16 changes: 16 additions & 0 deletions modules/api/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ def generate_model(self):
{"key": "send_images", "type": bool, "default": True},
{"key": "save_images", "type": bool, "default": False},
{"key": "alwayson_scripts", "type": dict, "default": {}},
{"key": "generation_id", "type": str, "default": None},
]
).generate_model()

Expand Down Expand Up @@ -182,13 +183,28 @@ class PNGInfoResponse(BaseModel):
class ProgressRequest(BaseModel):
skip_current_image: bool = Field(default=False, title="Skip current image", description="Skip current image serialization")

class NewProgressRequest(BaseModel):
id_task: str = Field(default=None, title="Task ID", description="id of the task to get progress for")

class CancelRequest(BaseModel):
id_task: str = Field(default=None, title="Task ID", description="id of the task to cancel")

class ProgressResponse(BaseModel):
progress: float = Field(title="Progress", description="The progress with a range of 0 to 1")
eta_relative: float = Field(title="ETA in secs")
state: dict = Field(title="State", description="The current state snapshot")
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.")
textinfo: str = Field(default=None, title="Info text", description="Info text used by WebUI.")

class NewProgressResponse(BaseModel):
active: bool = Field(title="Whether the task is being worked on right now")
queued: bool = Field(title="Whether the task is in queue")
completed: bool = Field(title="Whether the task has already finished")
progress: float = Field(default=None, title="Progress", description="The progress with a range of 0 to 1")
eta: float = Field(default=None, title="ETA in secs")
live_preview: str = Field(default=None, title="Live preview image", description="Current live preview; a data: uri")
textinfo: str = Field(default=None, title="Info text", description="Info text used by WebUI.")

class InterrogateRequest(BaseModel):
image: str = Field(default="", title="Image", description="Image to work on, must be a Base64 string containing the image's data.")
model: str = Field(default="clip", title="Model", description="The interrogate model used.")
Expand Down
2 changes: 1 addition & 1 deletion webui-user.bat
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
set PYTHON=
set GIT=
set VENV_DIR=
set COMMANDLINE_ARGS=
set COMMANDLINE_ARGS=--listen --nowebui --port=7860 --cors-allow-origins=*

call webui.bat
Loading

0 comments on commit 072eca2

Please sign in to comment.