2022-09-03 17:08:45 +08:00
import base64
import html
import io
import json
2022-09-10 16:10:00 +08:00
import math
2022-09-03 17:08:45 +08:00
import mimetypes
import os
2022-09-06 04:08:06 +08:00
import random
2022-09-03 17:08:45 +08:00
import sys
import time
import traceback
2022-09-28 16:31:53 +08:00
import platform
import subprocess as sp
2022-09-30 03:47:06 +08:00
from functools import reduce
2022-09-03 17:08:45 +08:00
2022-09-07 00:33:51 +08:00
import numpy as np
import torch
2022-09-28 22:05:23 +08:00
from PIL import Image , PngImagePlugin
2022-09-29 22:54:45 +08:00
import piexif
2022-09-03 17:08:45 +08:00
import gradio as gr
import gradio . utils
2022-09-03 22:21:15 +08:00
import gradio . routes
2022-09-03 17:08:45 +08:00
2022-10-02 20:03:39 +08:00
from modules import sd_hijack
2022-09-03 17:08:45 +08:00
from modules . paths import script_path
from modules . shared import opts , cmd_opts
2022-10-09 00:02:56 +08:00
if cmd_opts . deepdanbooru :
from modules . deepbooru import get_deepbooru_tags
2022-09-03 17:08:45 +08:00
import modules . shared as shared
from modules . sd_samplers import samplers , samplers_for_img2img
2022-09-28 03:56:18 +08:00
from modules . sd_hijack import model_hijack
2022-09-21 21:06:37 +08:00
import modules . ldsr_model
2022-09-03 22:21:15 +08:00
import modules . scripts
2022-09-07 18:35:02 +08:00
import modules . gfpgan_model
import modules . codeformer_model
2022-09-10 04:16:02 +08:00
import modules . styles
2022-09-24 03:49:21 +08:00
import modules . generation_parameters_copypaste
2022-10-06 04:16:27 +08:00
from modules import prompt_parser
2022-10-05 00:19:50 +08:00
from modules . images import save_image
2022-10-02 20:03:39 +08:00
import modules . textual_inversion . ui
2022-10-11 20:51:22 +08:00
import modules . hypernetworks . ui
2022-09-03 17:08:45 +08:00
2022-10-09 03:12:24 +08:00
# this is a fix for Windows users. Without it, javascript files will be served with text/html content-type and the browser will not show any UI
2022-09-03 17:08:45 +08:00
mimetypes . init ( )
mimetypes . add_type ( ' application/javascript ' , ' .js ' )
2022-09-06 00:37:11 +08:00
if not cmd_opts . share and not cmd_opts . listen :
2022-09-03 17:08:45 +08:00
# fix gradio phoning home
gradio . utils . version_check = lambda : None
gradio . utils . get_local_ip_address = lambda : ' 127.0.0.1 '
2022-10-11 17:40:27 +08:00
if cmd_opts . ngrok != None :
import modules . ngrok as ngrok
print ( ' ngrok authtoken detected, trying to connect... ' )
ngrok . connect ( cmd_opts . ngrok , cmd_opts . port if cmd_opts . port != None else 7860 )
2022-09-03 17:08:45 +08:00
def gr_show ( visible = True ) :
return { " visible " : visible , " __type__ " : " update " }
sample_img2img = " assets/stable-samples/img2img/sketch-mountains-input.jpg "
sample_img2img = sample_img2img if os . path . exists ( sample_img2img ) else None
css_hide_progressbar = """
. wrap . m - 12 svg { display : none ! important ; }
2022-09-27 15:44:00 +08:00
. wrap . m - 12 : : before { content : " Loading... " }
2022-09-03 17:08:45 +08:00
. progress - bar { display : none ! important ; }
. meta - text { display : none ! important ; }
"""
2022-09-17 03:20:56 +08:00
# Using constants for these since the variation selector isn't visible.
# Important that they exactly match script.js for tooltip to work.
random_symbol = ' \U0001f3b2 \ufe0f ' # 🎲️
reuse_symbol = ' \u267b \ufe0f ' # ♻️
2022-09-24 03:49:21 +08:00
art_symbol = ' \U0001f3a8 ' # 🎨
paste_symbol = ' \u2199 \ufe0f ' # ↙
2022-10-03 03:08:23 +08:00
folder_symbol = ' \U0001f4c2 ' # 📂
2022-09-17 03:20:56 +08:00
2022-09-03 17:08:45 +08:00
def plaintext_to_html ( text ) :
2022-09-10 19:53:38 +08:00
text = " <p> " + " <br> \n " . join ( [ f " { html . escape ( x ) } " for x in text . split ( ' \n ' ) ] ) + " </p> "
2022-09-03 17:08:45 +08:00
return text
def image_from_url_text ( filedata ) :
if type ( filedata ) == list :
if len ( filedata ) == 0 :
return None
filedata = filedata [ 0 ]
if filedata . startswith ( " data:image/png;base64, " ) :
filedata = filedata [ len ( " data:image/png;base64, " ) : ]
filedata = base64 . decodebytes ( filedata . encode ( ' utf-8 ' ) )
image = Image . open ( io . BytesIO ( filedata ) )
return image
def send_gradio_gallery_to_image ( x ) :
if len ( x ) == 0 :
return None
return image_from_url_text ( x [ 0 ] )
2022-09-14 10:15:37 +08:00
2022-10-08 13:09:29 +08:00
def save_files ( js_data , images , do_make_zip , index ) :
2022-09-28 16:53:40 +08:00
import csv
2022-09-03 17:08:45 +08:00
filenames = [ ]
2022-10-08 13:09:29 +08:00
fullfns = [ ]
2022-09-03 17:08:45 +08:00
2022-10-09 03:12:24 +08:00
#quick dictionary to class object conversion. Its necessary due apply_filename_pattern requiring it
2022-09-28 16:53:40 +08:00
class MyObject :
def __init__ ( self , d = None ) :
if d is not None :
for key , value in d . items ( ) :
setattr ( self , key , value )
2022-09-03 17:08:45 +08:00
data = json . loads ( js_data )
2022-09-29 18:19:13 +08:00
2022-09-28 16:53:40 +08:00
p = MyObject ( data )
path = opts . outdir_save
2022-10-03 00:15:31 +08:00
save_to_dirs = opts . use_save_to_dirs_for_ui
2022-10-05 00:19:50 +08:00
extension : str = opts . samples_format
start_index = 0
2022-09-29 18:19:13 +08:00
2022-09-28 22:05:23 +08:00
if index > - 1 and opts . save_selected_only and ( index > = data [ " index_of_first_image " ] ) : # ensures we are looking at a specific non-grid picture, and we have save_selected_only
2022-09-29 18:19:13 +08:00
2022-09-14 10:11:46 +08:00
images = [ images [ index ] ]
2022-10-05 00:19:50 +08:00
start_index = index
2022-09-03 17:08:45 +08:00
2022-09-04 02:33:47 +08:00
with open ( os . path . join ( opts . outdir_save , " log.csv " ) , " a " , encoding = " utf8 " , newline = ' ' ) as file :
2022-09-03 17:08:45 +08:00
at_start = file . tell ( ) == 0
writer = csv . writer ( file )
if at_start :
2022-09-13 00:57:31 +08:00
writer . writerow ( [ " prompt " , " seed " , " width " , " height " , " sampler " , " cfgs " , " steps " , " filename " , " negative_prompt " ] )
2022-09-03 17:08:45 +08:00
2022-10-05 00:19:50 +08:00
for image_index , filedata in enumerate ( images , start_index ) :
2022-09-03 17:08:45 +08:00
if filedata . startswith ( " data:image/png;base64, " ) :
filedata = filedata [ len ( " data:image/png;base64, " ) : ]
2022-09-28 22:05:23 +08:00
image = Image . open ( io . BytesIO ( base64 . decodebytes ( filedata . encode ( ' utf-8 ' ) ) ) )
2022-09-03 17:08:45 +08:00
2022-10-05 00:19:50 +08:00
is_grid = image_index < p . index_of_first_image
i = 0 if is_grid else ( image_index - p . index_of_first_image )
2022-10-09 13:01:10 +08:00
fullfn , txt_fullfn = save_image ( image , path , " " , seed = p . all_seeds [ i ] , prompt = p . all_prompts [ i ] , extension = extension , info = p . infotexts [ image_index ] , grid = is_grid , p = p , save_to_dirs = save_to_dirs )
2022-10-05 00:19:50 +08:00
filename = os . path . relpath ( fullfn , path )
2022-09-03 17:08:45 +08:00
filenames . append ( filename )
2022-10-08 13:09:29 +08:00
fullfns . append ( fullfn )
2022-10-09 13:01:10 +08:00
if txt_fullfn :
filenames . append ( os . path . basename ( txt_fullfn ) )
fullfns . append ( txt_fullfn )
2022-09-03 17:08:45 +08:00
2022-09-13 00:57:31 +08:00
writer . writerow ( [ data [ " prompt " ] , data [ " seed " ] , data [ " width " ] , data [ " height " ] , data [ " sampler " ] , data [ " cfg_scale " ] , data [ " steps " ] , filenames [ 0 ] , data [ " negative_prompt " ] ] )
2022-09-03 17:08:45 +08:00
2022-10-08 13:09:29 +08:00
# Make Zip
if do_make_zip :
zip_filepath = os . path . join ( path , " images.zip " )
from zipfile import ZipFile
with ZipFile ( zip_filepath , " w " ) as zip_file :
for i in range ( len ( fullfns ) ) :
with open ( fullfns [ i ] , mode = " rb " ) as f :
zip_file . writestr ( filenames [ i ] , f . read ( ) )
fullfns . insert ( 0 , zip_filepath )
2022-10-09 16:59:41 +08:00
return gr . File . update ( value = fullfns , visible = True ) , ' ' , ' ' , plaintext_to_html ( f " Saved: { filenames [ 0 ] } " )
2022-09-03 17:08:45 +08:00
2022-10-02 20:03:39 +08:00
def wrap_gradio_call ( func , extra_outputs = None ) :
def f ( * args , extra_outputs_array = extra_outputs , * * kwargs ) :
2022-09-18 19:03:17 +08:00
run_memmon = opts . memmon_poll_rate > 0 and not shared . mem_mon . disabled
if run_memmon :
2022-09-18 17:20:33 +08:00
shared . mem_mon . monitor ( )
2022-09-03 17:08:45 +08:00
t = time . perf_counter ( )
try :
res = list ( func ( * args , * * kwargs ) )
except Exception as e :
print ( " Error completing request " , file = sys . stderr )
print ( " Arguments: " , args , kwargs , file = sys . stderr )
print ( traceback . format_exc ( ) , file = sys . stderr )
2022-09-07 00:33:51 +08:00
shared . state . job = " "
shared . state . job_count = 0
2022-10-02 20:03:39 +08:00
if extra_outputs_array is None :
extra_outputs_array = [ None , ' ' ]
res = extra_outputs_array + [ f " <div class= ' error ' > { plaintext_to_html ( type ( e ) . __name__ + ' : ' + str ( e ) ) } </div> " ]
2022-09-03 17:08:45 +08:00
elapsed = time . perf_counter ( ) - t
2022-10-05 03:12:38 +08:00
elapsed_m = int ( elapsed / / 60 )
elapsed_s = elapsed % 60
elapsed_text = f " { elapsed_s : .2f } s "
if ( elapsed_m > 0 ) :
elapsed_text = f " { elapsed_m } m " + elapsed_text
2022-09-03 17:08:45 +08:00
2022-09-18 19:03:17 +08:00
if run_memmon :
2022-09-18 17:20:33 +08:00
mem_stats = { k : - ( v / / - ( 1024 * 1024 ) ) for k , v in shared . mem_mon . stop ( ) . items ( ) }
active_peak = mem_stats [ ' active_peak ' ]
reserved_peak = mem_stats [ ' reserved_peak ' ]
sys_peak = mem_stats [ ' system_peak ' ]
sys_total = mem_stats [ ' total ' ]
sys_pct = round ( sys_peak / max ( sys_total , 1 ) * 100 , 2 )
2022-09-19 05:10:32 +08:00
vram_html = f " <p class= ' vram ' >Torch active/reserved: { active_peak } / { reserved_peak } MiB, <wbr>Sys VRAM: { sys_peak } / { sys_total } MiB ( { sys_pct } %)</p> "
2022-09-18 17:20:33 +08:00
else :
vram_html = ' '
2022-09-17 14:23:31 +08:00
2022-09-03 17:08:45 +08:00
# last item is always HTML
2022-10-05 03:12:38 +08:00
res [ - 1 ] + = f " <div class= ' performance ' ><p class= ' time ' >Time taken: <wbr> { elapsed_text } </p> { vram_html } </div> "
2022-09-03 17:08:45 +08:00
2022-10-05 11:56:30 +08:00
shared . state . skipped = False
2022-09-03 17:08:45 +08:00
shared . state . interrupted = False
2022-10-02 20:03:39 +08:00
shared . state . job_count = 0
2022-09-03 17:08:45 +08:00
return tuple ( res )
return f
2022-09-24 01:46:02 +08:00
def check_progress_call ( id_part ) :
2022-09-06 07:09:01 +08:00
if shared . state . job_count == 0 :
2022-10-02 20:03:39 +08:00
return " " , gr_show ( False ) , gr_show ( False ) , gr_show ( False )
2022-09-06 07:09:01 +08:00
2022-09-06 15:11:25 +08:00
progress = 0
if shared . state . job_count > 0 :
progress + = shared . state . job_no / shared . state . job_count
2022-09-06 07:09:01 +08:00
if shared . state . sampling_steps > 0 :
progress + = 1 / shared . state . job_count * shared . state . sampling_step / shared . state . sampling_steps
progress = min ( progress , 1 )
2022-09-07 00:33:51 +08:00
progressbar = " "
if opts . show_progressbar :
progressbar = f """ <div class= ' progressDiv ' ><div class= ' progress ' style= " width: { progress * 100 } % " > { str ( int ( progress * 100 ) ) + " % " if progress > 0.01 else " " } </div></div> """
image = gr_show ( False )
preview_visibility = gr_show ( False )
if opts . show_progress_every_n_steps > 0 :
2022-09-07 04:10:12 +08:00
if shared . parallel_processing_allowed :
2022-09-07 00:33:51 +08:00
2022-09-07 04:10:12 +08:00
if shared . state . sampling_step - shared . state . current_image_sampling_step > = opts . show_progress_every_n_steps and shared . state . current_latent is not None :
shared . state . current_image = modules . sd_samplers . sample_to_image ( shared . state . current_latent )
shared . state . current_image_sampling_step = shared . state . sampling_step
2022-09-07 01:26:09 +08:00
2022-09-07 00:33:51 +08:00
image = shared . state . current_image
2022-09-24 14:16:54 +08:00
if image is None :
2022-09-07 00:33:51 +08:00
image = gr . update ( value = None )
else :
preview_visibility = gr_show ( True )
2022-09-06 07:09:01 +08:00
2022-10-02 20:03:39 +08:00
if shared . state . textinfo is not None :
textinfo_result = gr . HTML . update ( value = shared . state . textinfo , visible = True )
else :
textinfo_result = gr_show ( False )
return f " <span id= ' { id_part } _progress_span ' style= ' display: none ' > { time . time ( ) } </span><p> { progressbar } </p> " , preview_visibility , image , textinfo_result
2022-09-06 07:09:01 +08:00
2022-09-24 01:46:02 +08:00
def check_progress_call_initial ( id_part ) :
2022-09-18 16:14:42 +08:00
shared . state . job_count = - 1
2022-09-18 21:36:34 +08:00
shared . state . current_latent = None
shared . state . current_image = None
2022-10-02 20:03:39 +08:00
shared . state . textinfo = None
2022-09-18 16:14:42 +08:00
2022-09-24 01:46:02 +08:00
return check_progress_call ( id_part )
2022-09-18 16:14:42 +08:00
2022-09-06 04:08:06 +08:00
def roll_artist ( prompt ) :
allowed_cats = set ( [ x for x in shared . artist_db . categories ( ) if len ( opts . random_artist_categories ) == 0 or x in opts . random_artist_categories ] )
artist = random . choice ( [ x for x in shared . artist_db . artists if x . category in allowed_cats ] )
return prompt + " , " + artist . name if prompt != ' ' else artist . name
2022-09-04 18:52:01 +08:00
def visit ( x , func , path = " " ) :
if hasattr ( x , ' children ' ) :
for c in x . children :
visit ( c , func , path )
elif x . label is not None :
func ( path + " / " + str ( x . label ) , x )
2022-09-03 17:08:45 +08:00
2022-09-11 22:35:12 +08:00
def add_style ( name : str , prompt : str , negative_prompt : str ) :
if name is None :
2022-09-10 04:16:02 +08:00
return [ gr_show ( ) , gr_show ( ) ]
2022-09-11 22:35:12 +08:00
style = modules . styles . PromptStyle ( name , prompt , negative_prompt )
2022-09-14 22:56:21 +08:00
shared . prompt_styles . styles [ style . name ] = style
2022-09-11 22:35:12 +08:00
# Save all loaded prompt styles: this allows us to update the storage format in the future more easily, because we
# reserialize all styles every time we save them
2022-09-14 22:56:21 +08:00
shared . prompt_styles . save_styles ( shared . styles_filename )
2022-09-10 04:16:02 +08:00
2022-09-24 01:46:02 +08:00
return [ gr . Dropdown . update ( visible = True , choices = list ( shared . prompt_styles . styles ) ) for _ in range ( 4 ) ]
2022-09-14 22:56:21 +08:00
def apply_styles ( prompt , prompt_neg , style1_name , style2_name ) :
prompt = shared . prompt_styles . apply_styles_to_prompt ( prompt , [ style1_name , style2_name ] )
prompt_neg = shared . prompt_styles . apply_negative_styles_to_prompt ( prompt_neg , [ style1_name , style2_name ] )
return [ gr . Textbox . update ( value = prompt ) , gr . Textbox . update ( value = prompt_neg ) , gr . Dropdown . update ( value = " None " ) , gr . Dropdown . update ( value = " None " ) ]
2022-09-10 04:16:02 +08:00
2022-09-11 23:48:36 +08:00
def interrogate ( image ) :
Interrogate: add option to include ranks in output
Since the UI also allows users to specify ranks, it can be useful to show people what ranks are being returned by interrogate
This can also give much better results when feeding the interrogate results back into either img2img or txt2img, especially when trying to generate a specific character or scene for which you have a similar concept image
Testing Steps:
Launch Webui with command line arg: --deepdanbooru
Navigate to img2img tab, use interrogate DeepBooru, verify tags appears as before. Use "Interrogate CLIP", verify prompt appears as before
Navigate to Settings tab, enable new option, click "apply settings"
Navigate to img2img, Interrogate DeepBooru again, verify that weights appear and are properly formatted. Note that "Interrogate CLIP" prompt is still unchanged
In my testing, this change has no effect to "Interrogate CLIP", as it seems to generate a sentence-structured caption, and not a set of tags.
(reproduce changes from https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/2149/commits/6ed4faac46c45ca7353f228aca9b436bbaba7bc7)
2022-10-12 09:02:41 +08:00
prompt = shared . interrogator . interrogate ( image , include_ranks = opts . interrogate_return_ranks )
2022-09-11 23:48:36 +08:00
return gr_show ( True ) if prompt is None else prompt
2022-09-14 22:56:21 +08:00
2022-10-06 02:50:10 +08:00
def interrogate_deepbooru ( image ) :
Interrogate: add option to include ranks in output
Since the UI also allows users to specify ranks, it can be useful to show people what ranks are being returned by interrogate
This can also give much better results when feeding the interrogate results back into either img2img or txt2img, especially when trying to generate a specific character or scene for which you have a similar concept image
Testing Steps:
Launch Webui with command line arg: --deepdanbooru
Navigate to img2img tab, use interrogate DeepBooru, verify tags appears as before. Use "Interrogate CLIP", verify prompt appears as before
Navigate to Settings tab, enable new option, click "apply settings"
Navigate to img2img, Interrogate DeepBooru again, verify that weights appear and are properly formatted. Note that "Interrogate CLIP" prompt is still unchanged
In my testing, this change has no effect to "Interrogate CLIP", as it seems to generate a sentence-structured caption, and not a set of tags.
(reproduce changes from https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/2149/commits/6ed4faac46c45ca7353f228aca9b436bbaba7bc7)
2022-10-12 09:02:41 +08:00
prompt = get_deepbooru_tags ( image , opts . interrogate_deepbooru_score_threshold , opts . interrogate_return_ranks )
2022-10-06 02:50:10 +08:00
return gr_show ( True ) if prompt is None else prompt
2022-09-17 03:20:56 +08:00
def create_seed_inputs ( ) :
with gr . Row ( ) :
with gr . Box ( ) :
with gr . Row ( elem_id = ' seed_row ' ) :
2022-09-21 01:10:01 +08:00
seed = ( gr . Textbox if cmd_opts . use_textbox_seed else gr . Number ) ( label = ' Seed ' , value = - 1 )
2022-09-17 03:20:56 +08:00
seed . style ( container = False )
2022-09-18 23:10:22 +08:00
random_seed = gr . Button ( random_symbol , elem_id = ' random_seed ' )
reuse_seed = gr . Button ( reuse_symbol , elem_id = ' reuse_seed ' )
2022-09-17 03:20:56 +08:00
with gr . Box ( elem_id = ' subseed_show_box ' ) :
seed_checkbox = gr . Checkbox ( label = ' Extra ' , elem_id = ' subseed_show ' , value = False )
# Components to show/hide based on the 'Extra' checkbox
seed_extras = [ ]
with gr . Row ( visible = False ) as seed_extra_row_1 :
seed_extras . append ( seed_extra_row_1 )
with gr . Box ( ) :
with gr . Row ( elem_id = ' subseed_row ' ) :
subseed = gr . Number ( label = ' Variation seed ' , value = - 1 )
subseed . style ( container = False )
random_subseed = gr . Button ( random_symbol , elem_id = ' random_subseed ' )
reuse_subseed = gr . Button ( reuse_symbol , elem_id = ' reuse_subseed ' )
subseed_strength = gr . Slider ( label = ' Variation strength ' , value = 0.0 , minimum = 0 , maximum = 1 , step = 0.01 )
with gr . Row ( visible = False ) as seed_extra_row_2 :
seed_extras . append ( seed_extra_row_2 )
seed_resize_from_w = gr . Slider ( minimum = 0 , maximum = 2048 , step = 64 , label = " Resize seed from width " , value = 0 )
seed_resize_from_h = gr . Slider ( minimum = 0 , maximum = 2048 , step = 64 , label = " Resize seed from height " , value = 0 )
random_seed . click ( fn = lambda : - 1 , show_progress = False , inputs = [ ] , outputs = [ seed ] )
random_subseed . click ( fn = lambda : - 1 , show_progress = False , inputs = [ ] , outputs = [ subseed ] )
def change_visibility ( show ) :
return { comp : gr_show ( show ) for comp in seed_extras }
seed_checkbox . change ( change_visibility , show_progress = False , inputs = [ seed_checkbox ] , outputs = seed_extras )
2022-09-21 18:34:10 +08:00
return seed , reuse_seed , subseed , reuse_subseed , subseed_strength , seed_resize_from_h , seed_resize_from_w , seed_checkbox
2022-09-17 03:20:56 +08:00
2022-09-19 14:02:10 +08:00
def connect_reuse_seed ( seed : gr . Number , reuse_seed : gr . Button , generation_info : gr . Textbox , dummy_component , is_subseed ) :
""" Connects a ' reuse (sub)seed ' button ' s click event so that it copies last used
( sub ) seed value from generation info the to the seed field . If copying subseed and subseed strength
2022-09-17 03:20:56 +08:00
was 0 , i . e . no variation seed was used , it copies the normal seed value instead . """
2022-09-19 14:02:10 +08:00
def copy_seed ( gen_info_string : str , index ) :
res = - 1
2022-09-17 03:20:56 +08:00
try :
gen_info = json . loads ( gen_info_string )
2022-09-19 14:02:10 +08:00
index - = gen_info . get ( ' index_of_first_image ' , 0 )
if is_subseed and gen_info . get ( ' subseed_strength ' , 0 ) > 0 :
all_subseeds = gen_info . get ( ' all_subseeds ' , [ - 1 ] )
res = all_subseeds [ index if 0 < = index < len ( all_subseeds ) else 0 ]
2022-09-17 03:20:56 +08:00
else :
2022-09-19 14:02:10 +08:00
all_seeds = gen_info . get ( ' all_seeds ' , [ - 1 ] )
res = all_seeds [ index if 0 < = index < len ( all_seeds ) else 0 ]
2022-09-17 03:20:56 +08:00
except json . decoder . JSONDecodeError as e :
if gen_info_string != ' ' :
print ( " Error parsing JSON generation info: " , file = sys . stderr )
print ( gen_info_string , file = sys . stderr )
2022-09-19 14:02:10 +08:00
return [ res , gr_show ( False ) ]
2022-09-17 03:20:56 +08:00
reuse_seed . click (
fn = copy_seed ,
2022-09-19 14:02:10 +08:00
_js = " (x, y) => [x, selected_gallery_index()] " ,
2022-09-17 03:20:56 +08:00
show_progress = False ,
2022-09-19 14:02:10 +08:00
inputs = [ generation_info , dummy_component ] ,
outputs = [ seed , dummy_component ]
2022-09-17 03:20:56 +08:00
)
2022-10-04 19:35:12 +08:00
2022-09-30 03:47:06 +08:00
def update_token_counter ( text , steps ) :
2022-10-04 19:35:12 +08:00
try :
2022-10-06 04:16:27 +08:00
_ , prompt_flat_list , _ = prompt_parser . get_multicond_prompt_list ( [ text ] )
prompt_schedules = prompt_parser . get_learned_conditioning_prompt_schedules ( prompt_flat_list , steps )
2022-10-04 19:35:12 +08:00
except Exception :
# a parsing error can happen here during typing, and we don't want to bother the user with
# messages related to it in console
prompt_schedules = [ [ [ steps , text ] ] ]
2022-09-30 03:47:06 +08:00
flat_prompts = reduce ( lambda list1 , list2 : list1 + list2 , prompt_schedules )
2022-10-04 19:35:12 +08:00
prompts = [ prompt_text for step , prompt_text in flat_prompts ]
2022-09-30 03:47:06 +08:00
tokens , token_count , max_length = max ( [ model_hijack . tokenize ( prompt ) for prompt in prompts ] , key = lambda args : args [ 1 ] )
2022-09-28 07:29:53 +08:00
style_class = ' class= " red " ' if ( token_count > max_length ) else " "
return f " <span { style_class } > { token_count } / { max_length } </span> "
2022-09-19 21:42:56 +08:00
2022-10-04 19:35:12 +08:00
2022-09-14 22:56:21 +08:00
def create_toprow ( is_img2img ) :
2022-09-24 01:46:02 +08:00
id_part = " img2img " if is_img2img else " txt2img "
2022-09-14 22:56:21 +08:00
with gr . Row ( elem_id = " toprow " ) :
with gr . Column ( scale = 4 ) :
with gr . Row ( ) :
2022-09-24 01:54:17 +08:00
with gr . Column ( scale = 80 ) :
2022-09-14 22:56:21 +08:00
with gr . Row ( ) :
2022-09-28 07:29:53 +08:00
prompt = gr . Textbox ( label = " Prompt " , elem_id = f " { id_part } _prompt " , show_label = False , placeholder = " Prompt " , lines = 2 )
2022-09-14 22:56:21 +08:00
2022-09-24 03:49:21 +08:00
with gr . Column ( scale = 1 , elem_id = " roll_col " ) :
roll = gr . Button ( value = art_symbol , elem_id = " roll " , visible = len ( shared . artist_db . artists ) > 0 )
paste = gr . Button ( value = paste_symbol , elem_id = " paste " )
2022-09-28 03:56:18 +08:00
token_counter = gr . HTML ( value = " <span></span> " , elem_id = f " { id_part } _token_counter " )
2022-09-30 03:47:06 +08:00
token_button = gr . Button ( visible = False , elem_id = f " { id_part } _token_button " )
2022-09-24 01:46:02 +08:00
with gr . Column ( scale = 10 , elem_id = " style_pos_col " ) :
prompt_style = gr . Dropdown ( label = " Style 1 " , elem_id = f " { id_part } _style_index " , choices = [ k for k , v in shared . prompt_styles . styles . items ( ) ] , value = next ( iter ( shared . prompt_styles . styles . keys ( ) ) ) , visible = len ( shared . prompt_styles . styles ) > 1 )
2022-09-14 22:56:21 +08:00
with gr . Row ( ) :
with gr . Column ( scale = 8 ) :
2022-10-11 15:08:45 +08:00
with gr . Row ( ) :
negative_prompt = gr . Textbox ( label = " Negative prompt " , elem_id = " negative_prompt " , show_label = False , placeholder = " Negative prompt " , lines = 2 )
with gr . Column ( scale = 1 , elem_id = " roll_col " ) :
sh = gr . Button ( elem_id = " sh " , visible = True )
2022-09-14 22:56:21 +08:00
with gr . Column ( scale = 1 , elem_id = " style_neg_col " ) :
2022-09-24 01:46:02 +08:00
prompt_style2 = gr . Dropdown ( label = " Style 2 " , elem_id = f " { id_part } _style2_index " , choices = [ k for k , v in shared . prompt_styles . styles . items ( ) ] , value = next ( iter ( shared . prompt_styles . styles . keys ( ) ) ) , visible = len ( shared . prompt_styles . styles ) > 1 )
2022-09-14 22:56:21 +08:00
with gr . Column ( scale = 1 ) :
with gr . Row ( ) :
2022-10-05 11:56:30 +08:00
skip = gr . Button ( ' Skip ' , elem_id = f " { id_part } _skip " )
2022-09-24 01:46:02 +08:00
interrupt = gr . Button ( ' Interrupt ' , elem_id = f " { id_part } _interrupt " )
2022-10-01 04:31:00 +08:00
submit = gr . Button ( ' Generate ' , elem_id = f " { id_part } _generate " , variant = ' primary ' )
2022-09-22 09:12:39 +08:00
2022-10-05 11:56:30 +08:00
skip . click (
fn = lambda : shared . state . skip ( ) ,
inputs = [ ] ,
outputs = [ ] ,
)
2022-09-22 09:12:39 +08:00
interrupt . click (
fn = lambda : shared . state . interrupt ( ) ,
inputs = [ ] ,
outputs = [ ] ,
)
2022-09-14 22:56:21 +08:00
2022-10-06 02:50:10 +08:00
with gr . Row ( scale = 1 ) :
2022-09-14 22:56:21 +08:00
if is_img2img :
2022-10-06 02:50:10 +08:00
interrogate = gr . Button ( ' Interrogate \n CLIP ' , elem_id = " interrogate " )
2022-10-09 00:02:56 +08:00
if cmd_opts . deepdanbooru :
deepbooru = gr . Button ( ' Interrogate \n DeepBooru ' , elem_id = " deepbooru " )
else :
deepbooru = None
2022-09-14 22:56:21 +08:00
else :
interrogate = None
2022-10-06 02:50:10 +08:00
deepbooru = None
2022-09-14 22:56:21 +08:00
prompt_style_apply = gr . Button ( ' Apply style ' , elem_id = " style_apply " )
save_style = gr . Button ( ' Create style ' , elem_id = " style_create " )
2022-10-06 02:50:10 +08:00
return prompt , roll , prompt_style , negative_prompt , prompt_style2 , submit , interrogate , deepbooru , prompt_style_apply , save_style , paste , token_counter , token_button
2022-09-14 22:56:21 +08:00
2022-10-02 20:03:39 +08:00
def setup_progressbar ( progressbar , preview , id_part , textinfo = None ) :
if textinfo is None :
textinfo = gr . HTML ( visible = False )
2022-09-18 16:14:42 +08:00
2022-09-24 01:46:02 +08:00
check_progress = gr . Button ( ' Check progress ' , elem_id = f " { id_part } _check_progress " , visible = False )
2022-09-18 16:14:42 +08:00
check_progress . click (
2022-09-24 01:46:02 +08:00
fn = lambda : check_progress_call ( id_part ) ,
2022-09-18 16:14:42 +08:00
show_progress = False ,
inputs = [ ] ,
2022-10-02 20:03:39 +08:00
outputs = [ progressbar , preview , preview , textinfo ] ,
2022-09-18 16:14:42 +08:00
)
2022-09-24 01:46:02 +08:00
check_progress_initial = gr . Button ( ' Check progress (first) ' , elem_id = f " { id_part } _check_progress_initial " , visible = False )
2022-09-18 16:14:42 +08:00
check_progress_initial . click (
2022-09-24 01:46:02 +08:00
fn = lambda : check_progress_call_initial ( id_part ) ,
2022-09-18 16:14:42 +08:00
show_progress = False ,
inputs = [ ] ,
2022-10-02 20:03:39 +08:00
outputs = [ progressbar , preview , preview , textinfo ] ,
2022-09-18 16:14:42 +08:00
)
2022-09-14 22:56:21 +08:00
2022-10-02 20:03:39 +08:00
def create_ui ( wrap_gradio_gpu_call ) :
import modules . img2img
import modules . txt2img
2022-09-03 17:08:45 +08:00
with gr . Blocks ( analytics_enabled = False ) as txt2img_interface :
2022-10-06 02:50:10 +08:00
txt2img_prompt , roll , txt2img_prompt_style , txt2img_negative_prompt , txt2img_prompt_style2 , submit , _ , _ , txt2img_prompt_style_apply , txt2img_save_style , paste , token_counter , token_button = create_toprow ( is_img2img = False )
2022-09-19 14:02:10 +08:00
dummy_component = gr . Label ( visible = False )
2022-09-03 17:08:45 +08:00
2022-09-24 01:46:02 +08:00
with gr . Row ( elem_id = ' txt2img_progress_row ' ) :
with gr . Column ( scale = 1 ) :
pass
2022-09-22 09:12:39 +08:00
2022-09-24 01:46:02 +08:00
with gr . Column ( scale = 1 ) :
progressbar = gr . HTML ( elem_id = " txt2img_progressbar " )
2022-09-22 09:12:39 +08:00
txt2img_preview = gr . Image ( elem_id = ' txt2img_preview ' , visible = False )
2022-09-24 01:46:02 +08:00
setup_progressbar ( progressbar , txt2img_preview , ' txt2img ' )
2022-09-22 09:12:39 +08:00
2022-09-03 17:08:45 +08:00
with gr . Row ( ) . style ( equal_height = False ) :
with gr . Column ( variant = ' panel ' ) :
steps = gr . Slider ( minimum = 1 , maximum = 150 , step = 1 , label = " Sampling Steps " , value = 20 )
sampler_index = gr . Radio ( label = ' Sampling method ' , elem_id = " txt2img_sampling " , choices = [ x . name for x in samplers ] , value = samplers [ 0 ] . name , type = " index " )
2022-09-25 13:40:29 +08:00
with gr . Group ( ) :
width = gr . Slider ( minimum = 64 , maximum = 2048 , step = 64 , label = " Width " , value = 512 )
height = gr . Slider ( minimum = 64 , maximum = 2048 , step = 64 , label = " Height " , value = 512 )
2022-09-03 17:08:45 +08:00
with gr . Row ( ) :
2022-09-07 17:32:28 +08:00
restore_faces = gr . Checkbox ( label = ' Restore faces ' , value = False , visible = len ( shared . face_restorers ) > 1 )
2022-09-05 08:25:37 +08:00
tiling = gr . Checkbox ( label = ' Tiling ' , value = False )
2022-09-19 21:42:56 +08:00
enable_hr = gr . Checkbox ( label = ' Highres. fix ' , value = False )
with gr . Row ( visible = False ) as hr_options :
2022-09-21 00:32:26 +08:00
scale_latent = gr . Checkbox ( label = ' Scale latent ' , value = False )
2022-09-19 21:42:56 +08:00
denoising_strength = gr . Slider ( minimum = 0.0 , maximum = 1.0 , step = 0.01 , label = ' Denoising strength ' , value = 0.7 )
2022-09-03 17:08:45 +08:00
with gr . Row ( ) :
2022-10-10 09:44:11 +08:00
batch_count = gr . Slider ( minimum = 1 , step = 1 , label = ' Batch count ' , value = 1 )
2022-09-03 17:08:45 +08:00
batch_size = gr . Slider ( minimum = 1 , maximum = 8 , step = 1 , label = ' Batch size ' , value = 1 )
2022-09-12 16:55:27 +08:00
cfg_scale = gr . Slider ( minimum = 1.0 , maximum = 30.0 , step = 0.5 , label = ' CFG Scale ' , value = 7.0 )
2022-09-03 17:08:45 +08:00
2022-09-21 18:34:10 +08:00
seed , reuse_seed , subseed , reuse_subseed , subseed_strength , seed_resize_from_h , seed_resize_from_w , seed_checkbox = create_seed_inputs ( )
2022-09-03 17:08:45 +08:00
2022-09-03 22:21:15 +08:00
with gr . Group ( ) :
2022-09-04 06:29:43 +08:00
custom_inputs = modules . scripts . scripts_txt2img . setup_ui ( is_img2img = False )
2022-09-03 17:08:45 +08:00
with gr . Column ( variant = ' panel ' ) :
2022-09-17 17:38:15 +08:00
2022-09-03 17:08:45 +08:00
with gr . Group ( ) :
2022-09-07 00:33:51 +08:00
txt2img_preview = gr . Image ( elem_id = ' txt2img_preview ' , visible = False )
2022-09-22 17:30:11 +08:00
txt2img_gallery = gr . Gallery ( label = ' Output ' , show_label = False , elem_id = ' txt2img_gallery ' ) . style ( grid = 4 )
2022-09-03 17:08:45 +08:00
with gr . Group ( ) :
with gr . Row ( ) :
save = gr . Button ( ' Save ' )
send_to_img2img = gr . Button ( ' Send to img2img ' )
send_to_inpaint = gr . Button ( ' Send to inpaint ' )
send_to_extras = gr . Button ( ' Send to extras ' )
2022-09-28 16:40:05 +08:00
button_id = " hidden_element " if shared . cmd_opts . hide_ui_dir_config else ' open_folder '
2022-09-28 16:31:53 +08:00
open_txt2img_folder = gr . Button ( folder_symbol , elem_id = button_id )
2022-09-03 17:08:45 +08:00
2022-10-11 02:37:16 +08:00
with gr . Row ( ) :
do_make_zip = gr . Checkbox ( label = " Make Zip when Save? " , value = False )
2022-10-08 13:09:29 +08:00
2022-10-11 02:37:16 +08:00
with gr . Row ( ) :
download_files = gr . File ( None , file_count = " multiple " , interactive = False , show_label = False , visible = False )
2022-10-08 13:09:29 +08:00
2022-10-11 02:37:16 +08:00
with gr . Group ( ) :
html_info = gr . HTML ( )
generation_info = gr . Textbox ( visible = False )
2022-09-03 17:08:45 +08:00
2022-09-19 14:02:10 +08:00
connect_reuse_seed ( seed , reuse_seed , generation_info , dummy_component , is_subseed = False )
connect_reuse_seed ( subseed , reuse_subseed , generation_info , dummy_component , is_subseed = True )
2022-09-17 03:20:56 +08:00
2022-09-03 17:08:45 +08:00
txt2img_args = dict (
2022-10-02 20:03:39 +08:00
fn = wrap_gradio_gpu_call ( modules . txt2img . txt2img ) ,
2022-09-06 07:09:01 +08:00
_js = " submit " ,
2022-09-03 17:08:45 +08:00
inputs = [
2022-09-10 04:16:02 +08:00
txt2img_prompt ,
2022-09-11 22:35:12 +08:00
txt2img_negative_prompt ,
2022-09-10 04:16:02 +08:00
txt2img_prompt_style ,
2022-09-14 22:56:21 +08:00
txt2img_prompt_style2 ,
2022-09-03 17:08:45 +08:00
steps ,
sampler_index ,
2022-09-07 17:32:28 +08:00
restore_faces ,
2022-09-05 08:25:37 +08:00
tiling ,
2022-09-03 17:08:45 +08:00
batch_count ,
batch_size ,
cfg_scale ,
seed ,
2022-09-21 18:34:10 +08:00
subseed , subseed_strength , seed_resize_from_h , seed_resize_from_w , seed_checkbox ,
2022-09-03 17:08:45 +08:00
height ,
width ,
2022-09-19 21:42:56 +08:00
enable_hr ,
scale_latent ,
denoising_strength ,
2022-09-03 22:21:15 +08:00
] + custom_inputs ,
2022-09-03 17:08:45 +08:00
outputs = [
txt2img_gallery ,
generation_info ,
html_info
2022-09-18 16:14:42 +08:00
] ,
show_progress = False ,
2022-09-03 17:08:45 +08:00
)
2022-09-10 04:16:02 +08:00
txt2img_prompt . submit ( * * txt2img_args )
2022-09-03 17:08:45 +08:00
submit . click ( * * txt2img_args )
2022-09-19 21:42:56 +08:00
enable_hr . change (
fn = lambda x : gr_show ( x ) ,
inputs = [ enable_hr ] ,
outputs = [ hr_options ] ,
)
2022-09-03 17:08:45 +08:00
save . click (
fn = wrap_gradio_call ( save_files ) ,
2022-10-08 13:09:29 +08:00
_js = " (x, y, z, w) => [x, y, z, selected_gallery_index()] " ,
2022-09-03 17:08:45 +08:00
inputs = [
generation_info ,
txt2img_gallery ,
2022-10-08 13:09:29 +08:00
do_make_zip ,
2022-09-19 14:02:10 +08:00
html_info ,
2022-09-03 17:08:45 +08:00
] ,
outputs = [
2022-10-08 13:09:29 +08:00
download_files ,
2022-09-03 17:08:45 +08:00
html_info ,
html_info ,
html_info ,
]
)
2022-09-06 04:08:06 +08:00
roll . click (
fn = roll_artist ,
2022-10-01 00:12:44 +08:00
_js = " update_txt2img_tokens " ,
2022-09-06 04:08:06 +08:00
inputs = [
2022-09-10 04:16:02 +08:00
txt2img_prompt ,
2022-09-06 04:08:06 +08:00
] ,
outputs = [
2022-09-10 04:16:02 +08:00
txt2img_prompt ,
2022-09-06 04:08:06 +08:00
]
)
2022-09-25 14:25:28 +08:00
txt2img_paste_fields = [
( txt2img_prompt , " Prompt " ) ,
( txt2img_negative_prompt , " Negative prompt " ) ,
( steps , " Steps " ) ,
( sampler_index , " Sampler " ) ,
( restore_faces , " Face restoration " ) ,
( cfg_scale , " CFG scale " ) ,
( seed , " Seed " ) ,
( width , " Size-1 " ) ,
( height , " Size-2 " ) ,
( batch_size , " Batch size " ) ,
( subseed , " Variation seed " ) ,
( subseed_strength , " Variation seed strength " ) ,
( seed_resize_from_w , " Seed resize from-1 " ) ,
( seed_resize_from_h , " Seed resize from-2 " ) ,
( denoising_strength , " Denoising strength " ) ,
( enable_hr , lambda d : " Denoising strength " in d ) ,
( hr_options , lambda d : gr . Row . update ( visible = " Denoising strength " in d ) ) ,
]
2022-09-24 03:49:21 +08:00
modules . generation_parameters_copypaste . connect_paste ( paste , txt2img_paste_fields , txt2img_prompt )
2022-09-30 03:47:06 +08:00
token_button . click ( fn = update_token_counter , inputs = [ txt2img_prompt , steps ] , outputs = [ token_counter ] )
2022-09-24 03:49:21 +08:00
2022-09-03 17:08:45 +08:00
with gr . Blocks ( analytics_enabled = False ) as img2img_interface :
2022-10-06 02:50:10 +08:00
img2img_prompt , roll , img2img_prompt_style , img2img_negative_prompt , img2img_prompt_style2 , submit , img2img_interrogate , img2img_deepbooru , img2img_prompt_style_apply , img2img_save_style , paste , token_counter , token_button = create_toprow ( is_img2img = True )
2022-09-03 17:08:45 +08:00
2022-09-24 01:46:02 +08:00
with gr . Row ( elem_id = ' img2img_progress_row ' ) :
with gr . Column ( scale = 1 ) :
pass
2022-09-22 09:12:39 +08:00
2022-09-24 01:46:02 +08:00
with gr . Column ( scale = 1 ) :
progressbar = gr . HTML ( elem_id = " img2img_progressbar " )
2022-09-22 09:12:39 +08:00
img2img_preview = gr . Image ( elem_id = ' img2img_preview ' , visible = False )
2022-09-24 01:46:02 +08:00
setup_progressbar ( progressbar , img2img_preview , ' img2img ' )
2022-09-22 17:11:48 +08:00
2022-09-03 17:08:45 +08:00
with gr . Row ( ) . style ( equal_height = False ) :
with gr . Column ( variant = ' panel ' ) :
2022-09-10 00:43:16 +08:00
2022-09-22 17:11:48 +08:00
with gr . Tabs ( elem_id = " mode_img2img " ) as tabs_img2img_mode :
2022-09-24 03:49:21 +08:00
with gr . TabItem ( ' img2img ' , id = ' img2img ' ) :
2022-10-05 01:49:54 +08:00
init_img = gr . Image ( label = " Image for img2img " , elem_id = " img2img_image " , show_label = False , source = " upload " , interactive = True , type = " pil " , tool = cmd_opts . gradio_img2img_tool )
2022-09-03 17:08:45 +08:00
2022-09-24 03:49:21 +08:00
with gr . TabItem ( ' Inpaint ' , id = ' inpaint ' ) :
2022-09-22 17:11:48 +08:00
init_img_with_mask = gr . Image ( label = " Image for inpainting with mask " , show_label = False , elem_id = " img2maskimg " , source = " upload " , interactive = True , type = " pil " , tool = " sketch " , image_mode = " RGBA " )
2022-09-27 04:57:31 +08:00
init_img_inpaint = gr . Image ( label = " Image for img2img " , show_label = False , source = " upload " , interactive = True , type = " pil " , visible = False , elem_id = " img_inpaint_base " )
init_mask_inpaint = gr . Image ( label = " Mask " , source = " upload " , interactive = True , type = " pil " , visible = False , elem_id = " img_inpaint_mask " )
2022-09-22 17:11:48 +08:00
mask_blur = gr . Slider ( label = ' Mask blur ' , minimum = 0 , maximum = 64 , step = 1 , value = 4 )
with gr . Row ( ) :
2022-09-27 04:57:31 +08:00
mask_mode = gr . Radio ( label = " Mask mode " , show_label = False , choices = [ " Draw mask " , " Upload mask " ] , type = " index " , value = " Draw mask " , elem_id = " mask_mode " )
2022-09-22 17:11:48 +08:00
inpainting_mask_invert = gr . Radio ( label = ' Masking mode ' , show_label = False , choices = [ ' Inpaint masked ' , ' Inpaint not masked ' ] , value = ' Inpaint masked ' , type = " index " )
2022-09-30 23:07:49 +08:00
inpainting_fill = gr . Radio ( label = ' Masked content ' , choices = [ ' fill ' , ' original ' , ' latent noise ' , ' latent nothing ' ] , value = ' original ' , type = " index " )
2022-09-22 17:11:48 +08:00
with gr . Row ( ) :
inpaint_full_res = gr . Checkbox ( label = ' Inpaint at full resolution ' , value = False )
inpaint_full_res_padding = gr . Slider ( label = ' Inpaint at full resolution padding, pixels ' , minimum = 0 , maximum = 256 , step = 4 , value = 32 )
2022-09-24 03:49:21 +08:00
with gr . TabItem ( ' Batch img2img ' , id = ' batch ' ) :
2022-09-24 21:29:20 +08:00
hidden = ' <br>Disabled when launched with --hide-ui-dir-config. ' if shared . cmd_opts . hide_ui_dir_config else ' '
2022-10-03 16:48:19 +08:00
gr . HTML ( f " <p class= \" text-gray-500 \" >Process images in a directory on the same machine where the server is running.<br>Use an empty output directory to save pictures normally instead of writing to the output directory. { hidden } </p> " )
2022-09-24 21:29:20 +08:00
img2img_batch_input_dir = gr . Textbox ( label = " Input directory " , * * shared . hide_dirs )
img2img_batch_output_dir = gr . Textbox ( label = " Output directory " , * * shared . hide_dirs )
2022-09-03 17:08:45 +08:00
with gr . Row ( ) :
2022-09-22 17:11:48 +08:00
resize_mode = gr . Radio ( label = " Resize mode " , elem_id = " resize_mode " , show_label = False , choices = [ " Just resize " , " Crop and resize " , " Resize and fill " ] , type = " index " , value = " Just resize " )
steps = gr . Slider ( minimum = 1 , maximum = 150 , step = 1 , label = " Sampling Steps " , value = 20 )
sampler_index = gr . Radio ( label = ' Sampling method ' , choices = [ x . name for x in samplers_for_img2img ] , value = samplers_for_img2img [ 0 ] . name , type = " index " )
2022-09-04 02:02:38 +08:00
2022-09-25 13:40:29 +08:00
with gr . Group ( ) :
width = gr . Slider ( minimum = 64 , maximum = 2048 , step = 64 , label = " Width " , value = 512 )
height = gr . Slider ( minimum = 64 , maximum = 2048 , step = 64 , label = " Height " , value = 512 )
2022-09-04 02:02:38 +08:00
with gr . Row ( ) :
2022-09-07 17:32:28 +08:00
restore_faces = gr . Checkbox ( label = ' Restore faces ' , value = False , visible = len ( shared . face_restorers ) > 1 )
2022-09-05 08:25:37 +08:00
tiling = gr . Checkbox ( label = ' Tiling ' , value = False )
2022-09-03 17:08:45 +08:00
with gr . Row ( ) :
2022-10-10 09:44:11 +08:00
batch_count = gr . Slider ( minimum = 1 , step = 1 , label = ' Batch count ' , value = 1 )
2022-09-03 17:08:45 +08:00
batch_size = gr . Slider ( minimum = 1 , maximum = 8 , step = 1 , label = ' Batch size ' , value = 1 )
with gr . Group ( ) :
2022-09-12 16:55:27 +08:00
cfg_scale = gr . Slider ( minimum = 1.0 , maximum = 30.0 , step = 0.5 , label = ' CFG Scale ' , value = 7.0 )
2022-09-08 20:02:06 +08:00
denoising_strength = gr . Slider ( minimum = 0.0 , maximum = 1.0 , step = 0.01 , label = ' Denoising strength ' , value = 0.75 )
2022-09-03 17:08:45 +08:00
2022-09-21 18:34:10 +08:00
seed , reuse_seed , subseed , reuse_subseed , subseed_strength , seed_resize_from_h , seed_resize_from_w , seed_checkbox = create_seed_inputs ( )
2022-09-03 17:08:45 +08:00
2022-09-03 22:21:15 +08:00
with gr . Group ( ) :
2022-09-04 06:29:43 +08:00
custom_inputs = modules . scripts . scripts_img2img . setup_ui ( is_img2img = True )
2022-09-03 22:21:15 +08:00
2022-09-03 17:08:45 +08:00
with gr . Column ( variant = ' panel ' ) :
2022-09-17 17:38:15 +08:00
2022-09-03 17:08:45 +08:00
with gr . Group ( ) :
2022-09-07 00:33:51 +08:00
img2img_preview = gr . Image ( elem_id = ' img2img_preview ' , visible = False )
2022-09-22 17:30:11 +08:00
img2img_gallery = gr . Gallery ( label = ' Output ' , show_label = False , elem_id = ' img2img_gallery ' ) . style ( grid = 4 )
2022-09-03 17:08:45 +08:00
with gr . Group ( ) :
with gr . Row ( ) :
save = gr . Button ( ' Save ' )
2022-09-07 00:33:51 +08:00
img2img_send_to_img2img = gr . Button ( ' Send to img2img ' )
img2img_send_to_inpaint = gr . Button ( ' Send to inpaint ' )
2022-09-03 17:08:45 +08:00
img2img_send_to_extras = gr . Button ( ' Send to extras ' )
2022-09-28 16:40:05 +08:00
button_id = " hidden_element " if shared . cmd_opts . hide_ui_dir_config else ' open_folder '
2022-09-28 16:31:53 +08:00
open_img2img_folder = gr . Button ( folder_symbol , elem_id = button_id )
2022-09-03 17:08:45 +08:00
2022-10-11 02:37:16 +08:00
with gr . Row ( ) :
do_make_zip = gr . Checkbox ( label = " Make Zip when Save? " , value = False )
2022-10-08 13:09:29 +08:00
2022-10-11 02:37:16 +08:00
with gr . Row ( ) :
download_files = gr . File ( None , file_count = " multiple " , interactive = False , show_label = False , visible = False )
2022-10-08 13:09:29 +08:00
2022-10-11 02:37:16 +08:00
with gr . Group ( ) :
html_info = gr . HTML ( )
generation_info = gr . Textbox ( visible = False )
2022-09-03 17:08:45 +08:00
2022-09-19 14:02:10 +08:00
connect_reuse_seed ( seed , reuse_seed , generation_info , dummy_component , is_subseed = False )
connect_reuse_seed ( subseed , reuse_subseed , generation_info , dummy_component , is_subseed = True )
2022-09-17 03:20:56 +08:00
2022-09-10 00:43:16 +08:00
mask_mode . change (
2022-09-22 17:11:48 +08:00
lambda mode , img : {
2022-09-10 00:43:16 +08:00
init_img_with_mask : gr_show ( mode == 0 ) ,
2022-09-22 17:11:48 +08:00
init_img_inpaint : gr_show ( mode == 1 ) ,
init_mask_inpaint : gr_show ( mode == 1 ) ,
2022-09-10 00:43:16 +08:00
} ,
2022-09-22 17:11:48 +08:00
inputs = [ mask_mode , init_img_with_mask ] ,
2022-09-10 00:43:16 +08:00
outputs = [
init_img_with_mask ,
2022-09-22 17:11:48 +08:00
init_img_inpaint ,
init_mask_inpaint ,
2022-09-10 00:43:16 +08:00
] ,
)
2022-09-03 17:08:45 +08:00
img2img_args = dict (
2022-10-02 20:03:39 +08:00
fn = wrap_gradio_gpu_call ( modules . img2img . img2img ) ,
2022-09-22 17:11:48 +08:00
_js = " submit_img2img " ,
2022-09-03 17:08:45 +08:00
inputs = [
2022-09-22 17:11:48 +08:00
dummy_component ,
2022-09-10 04:16:02 +08:00
img2img_prompt ,
2022-09-11 22:35:12 +08:00
img2img_negative_prompt ,
2022-09-10 04:16:02 +08:00
img2img_prompt_style ,
2022-09-14 22:56:21 +08:00
img2img_prompt_style2 ,
2022-09-03 17:08:45 +08:00
init_img ,
init_img_with_mask ,
2022-09-22 17:11:48 +08:00
init_img_inpaint ,
init_mask_inpaint ,
2022-09-10 00:43:16 +08:00
mask_mode ,
2022-09-03 17:08:45 +08:00
steps ,
sampler_index ,
mask_blur ,
inpainting_fill ,
2022-09-07 17:32:28 +08:00
restore_faces ,
2022-09-05 08:25:37 +08:00
tiling ,
2022-09-03 17:08:45 +08:00
batch_count ,
batch_size ,
cfg_scale ,
denoising_strength ,
seed ,
2022-09-21 18:34:10 +08:00
subseed , subseed_strength , seed_resize_from_h , seed_resize_from_w , seed_checkbox ,
2022-09-03 17:08:45 +08:00
height ,
width ,
resize_mode ,
inpaint_full_res ,
2022-09-22 17:11:48 +08:00
inpaint_full_res_padding ,
2022-09-04 02:02:38 +08:00
inpainting_mask_invert ,
2022-09-22 17:11:48 +08:00
img2img_batch_input_dir ,
img2img_batch_output_dir ,
2022-09-03 22:21:15 +08:00
] + custom_inputs ,
2022-09-03 17:08:45 +08:00
outputs = [
img2img_gallery ,
generation_info ,
html_info
2022-09-18 16:14:42 +08:00
] ,
show_progress = False ,
2022-09-03 17:08:45 +08:00
)
2022-09-10 04:16:02 +08:00
img2img_prompt . submit ( * * img2img_args )
2022-09-03 17:08:45 +08:00
submit . click ( * * img2img_args )
2022-09-11 23:48:36 +08:00
img2img_interrogate . click (
fn = interrogate ,
inputs = [ init_img ] ,
outputs = [ img2img_prompt ] ,
)
2022-10-09 00:02:56 +08:00
if cmd_opts . deepdanbooru :
img2img_deepbooru . click (
fn = interrogate_deepbooru ,
inputs = [ init_img ] ,
outputs = [ img2img_prompt ] ,
)
2022-10-06 02:50:10 +08:00
2022-09-03 17:08:45 +08:00
save . click (
fn = wrap_gradio_call ( save_files ) ,
2022-10-08 13:09:29 +08:00
_js = " (x, y, z, w) => [x, y, z, selected_gallery_index()] " ,
2022-09-03 17:08:45 +08:00
inputs = [
generation_info ,
img2img_gallery ,
2022-10-08 13:09:29 +08:00
do_make_zip ,
html_info ,
2022-09-03 17:08:45 +08:00
] ,
outputs = [
2022-10-08 13:09:29 +08:00
download_files ,
2022-09-03 17:08:45 +08:00
html_info ,
html_info ,
html_info ,
]
)
2022-09-14 22:56:21 +08:00
roll . click (
fn = roll_artist ,
2022-10-01 00:12:44 +08:00
_js = " update_img2img_tokens " ,
2022-09-14 22:56:21 +08:00
inputs = [
img2img_prompt ,
] ,
outputs = [
img2img_prompt ,
]
)
prompts = [ ( txt2img_prompt , txt2img_negative_prompt ) , ( img2img_prompt , img2img_negative_prompt ) ]
style_dropdowns = [ ( txt2img_prompt_style , txt2img_prompt_style2 ) , ( img2img_prompt_style , img2img_prompt_style2 ) ]
2022-10-01 00:12:44 +08:00
style_js_funcs = [ " update_txt2img_tokens " , " update_img2img_tokens " ]
2022-09-14 22:56:21 +08:00
for button , ( prompt , negative_prompt ) in zip ( [ txt2img_save_style , img2img_save_style ] , prompts ) :
2022-09-10 04:16:02 +08:00
button . click (
fn = add_style ,
_js = " ask_for_style_name " ,
2022-09-11 22:35:12 +08:00
# Have to pass empty dummy component here, because the JavaScript and Python function have to accept
# the same number of parameters, but we only know the style-name after the JavaScript prompt
inputs = [ dummy_component , prompt , negative_prompt ] ,
2022-09-14 22:56:21 +08:00
outputs = [ txt2img_prompt_style , img2img_prompt_style , txt2img_prompt_style2 , img2img_prompt_style2 ] ,
)
2022-09-30 02:40:47 +08:00
for button , ( prompt , negative_prompt ) , ( style1 , style2 ) , js_func in zip ( [ txt2img_prompt_style_apply , img2img_prompt_style_apply ] , prompts , style_dropdowns , style_js_funcs ) :
2022-09-14 22:56:21 +08:00
button . click (
fn = apply_styles ,
2022-09-30 02:40:47 +08:00
_js = js_func ,
2022-09-14 22:56:21 +08:00
inputs = [ prompt , negative_prompt , style1 , style2 ] ,
outputs = [ prompt , negative_prompt , style1 , style2 ] ,
2022-09-10 04:16:02 +08:00
)
2022-09-25 14:25:28 +08:00
img2img_paste_fields = [
( img2img_prompt , " Prompt " ) ,
( img2img_negative_prompt , " Negative prompt " ) ,
( steps , " Steps " ) ,
( sampler_index , " Sampler " ) ,
( restore_faces , " Face restoration " ) ,
( cfg_scale , " CFG scale " ) ,
( seed , " Seed " ) ,
( width , " Size-1 " ) ,
( height , " Size-2 " ) ,
( batch_size , " Batch size " ) ,
( subseed , " Variation seed " ) ,
( subseed_strength , " Variation seed strength " ) ,
( seed_resize_from_w , " Seed resize from-1 " ) ,
( seed_resize_from_h , " Seed resize from-2 " ) ,
( denoising_strength , " Denoising strength " ) ,
]
2022-09-24 03:49:21 +08:00
modules . generation_parameters_copypaste . connect_paste ( paste , img2img_paste_fields , img2img_prompt )
2022-09-30 03:47:06 +08:00
token_button . click ( fn = update_token_counter , inputs = [ img2img_prompt , steps ] , outputs = [ token_counter ] )
2022-09-24 03:49:21 +08:00
2022-09-03 17:08:45 +08:00
with gr . Blocks ( analytics_enabled = False ) as extras_interface :
with gr . Row ( ) . style ( equal_height = False ) :
with gr . Column ( variant = ' panel ' ) :
2022-09-22 17:11:48 +08:00
with gr . Tabs ( elem_id = " mode_extras " ) :
2022-09-16 11:23:37 +08:00
with gr . TabItem ( ' Single Image ' ) :
2022-09-24 03:49:21 +08:00
extras_image = gr . Image ( label = " Source " , source = " upload " , interactive = True , type = " pil " )
2022-09-16 11:23:37 +08:00
with gr . TabItem ( ' Batch Process ' ) :
2022-09-16 15:21:59 +08:00
image_batch = gr . File ( label = " Batch Process " , file_count = " multiple " , interactive = True , type = " file " )
2022-09-04 23:54:12 +08:00
upscaling_resize = gr . Slider ( minimum = 1.0 , maximum = 4.0 , step = 0.05 , label = " Resize " , value = 2 )
with gr . Group ( ) :
extras_upscaler_1 = gr . Radio ( label = ' Upscaler 1 ' , choices = [ x . name for x in shared . sd_upscalers ] , value = shared . sd_upscalers [ 0 ] . name , type = " index " )
with gr . Group ( ) :
extras_upscaler_2 = gr . Radio ( label = ' Upscaler 2 ' , choices = [ x . name for x in shared . sd_upscalers ] , value = shared . sd_upscalers [ 0 ] . name , type = " index " )
extras_upscaler_2_visibility = gr . Slider ( minimum = 0.0 , maximum = 1.0 , step = 0.001 , label = " Upscaler 2 visibility " , value = 1 )
with gr . Group ( ) :
2022-09-07 18:35:02 +08:00
gfpgan_visibility = gr . Slider ( minimum = 0.0 , maximum = 1.0 , step = 0.001 , label = " GFPGAN visibility " , value = 0 , interactive = modules . gfpgan_model . have_gfpgan )
with gr . Group ( ) :
codeformer_visibility = gr . Slider ( minimum = 0.0 , maximum = 1.0 , step = 0.001 , label = " CodeFormer visibility " , value = 0 , interactive = modules . codeformer_model . have_codeformer )
2022-09-07 18:46:08 +08:00
codeformer_weight = gr . Slider ( minimum = 0.0 , maximum = 1.0 , step = 0.001 , label = " CodeFormer weight (0 = maximum effect, 1 = minimum effect) " , value = 0 , interactive = modules . codeformer_model . have_codeformer )
2022-09-03 17:08:45 +08:00
submit = gr . Button ( ' Generate ' , elem_id = " extras_generate " , variant = ' primary ' )
with gr . Column ( variant = ' panel ' ) :
2022-09-22 17:30:11 +08:00
result_images = gr . Gallery ( label = " Result " , show_label = False )
2022-09-03 17:08:45 +08:00
html_info_x = gr . HTML ( )
html_info = gr . HTML ( )
2022-09-23 11:40:39 +08:00
extras_send_to_img2img = gr . Button ( ' Send to img2img ' )
2022-09-23 19:17:23 +08:00
extras_send_to_inpaint = gr . Button ( ' Send to inpaint ' )
2022-09-28 16:40:05 +08:00
button_id = " hidden_element " if shared . cmd_opts . hide_ui_dir_config else ' '
2022-09-28 16:31:53 +08:00
open_extras_folder = gr . Button ( ' Open output directory ' , elem_id = button_id )
2022-09-03 17:08:45 +08:00
2022-09-22 17:11:48 +08:00
submit . click (
2022-10-02 20:03:39 +08:00
fn = wrap_gradio_gpu_call ( modules . extras . run_extras ) ,
2022-09-22 17:11:48 +08:00
_js = " get_extras_tab_index " ,
2022-09-03 17:08:45 +08:00
inputs = [
2022-09-22 17:11:48 +08:00
dummy_component ,
2022-09-24 03:49:21 +08:00
extras_image ,
2022-09-16 11:23:37 +08:00
image_batch ,
2022-09-07 18:35:02 +08:00
gfpgan_visibility ,
codeformer_visibility ,
codeformer_weight ,
2022-09-04 23:54:12 +08:00
upscaling_resize ,
extras_upscaler_1 ,
extras_upscaler_2 ,
extras_upscaler_2_visibility ,
2022-09-03 17:08:45 +08:00
] ,
outputs = [
2022-09-16 11:23:37 +08:00
result_images ,
2022-09-03 17:08:45 +08:00
html_info_x ,
html_info ,
]
)
2022-09-23 11:40:39 +08:00
extras_send_to_img2img . click (
fn = lambda x : image_from_url_text ( x ) ,
_js = " extract_image_from_gallery_img2img " ,
inputs = [ result_images ] ,
outputs = [ init_img ] ,
)
2022-09-23 19:17:23 +08:00
extras_send_to_inpaint . click (
fn = lambda x : image_from_url_text ( x ) ,
2022-10-10 23:46:48 +08:00
_js = " extract_image_from_gallery_inpaint " ,
2022-09-23 19:17:23 +08:00
inputs = [ result_images ] ,
outputs = [ init_img_with_mask ] ,
)
2022-09-03 17:08:45 +08:00
2022-09-24 03:49:21 +08:00
with gr . Blocks ( analytics_enabled = False ) as pnginfo_interface :
with gr . Row ( ) . style ( equal_height = False ) :
with gr . Column ( variant = ' panel ' ) :
image = gr . Image ( elem_id = " pnginfo_image " , label = " Source " , source = " upload " , interactive = True , type = " pil " )
with gr . Column ( variant = ' panel ' ) :
html = gr . HTML ( )
generation_info = gr . Textbox ( visible = False )
html2 = gr . HTML ( )
with gr . Row ( ) :
pnginfo_send_to_txt2img = gr . Button ( ' Send to txt2img ' )
pnginfo_send_to_img2img = gr . Button ( ' Send to img2img ' )
image . change (
2022-10-02 20:03:39 +08:00
fn = wrap_gradio_call ( modules . extras . run_pnginfo ) ,
2022-09-24 03:49:21 +08:00
inputs = [ image ] ,
outputs = [ html , generation_info , html2 ] ,
)
2022-09-03 17:08:45 +08:00
2022-09-26 07:22:12 +08:00
with gr . Blocks ( ) as modelmerger_interface :
with gr . Row ( ) . style ( equal_height = False ) :
with gr . Column ( variant = ' panel ' ) :
2022-09-29 06:00:48 +08:00
gr . HTML ( value = " <p>A merger of the two checkpoints will be generated in your <b>checkpoint</b> directory.</p> " )
2022-10-02 20:03:39 +08:00
2022-09-28 03:21:25 +08:00
with gr . Row ( ) :
2022-09-29 05:59:44 +08:00
primary_model_name = gr . Dropdown ( modules . sd_models . checkpoint_tiles ( ) , elem_id = " modelmerger_primary_model_name " , label = " Primary Model Name " )
secondary_model_name = gr . Dropdown ( modules . sd_models . checkpoint_tiles ( ) , elem_id = " modelmerger_secondary_model_name " , label = " Secondary Model Name " )
2022-09-29 07:50:34 +08:00
custom_name = gr . Textbox ( label = " Custom Name (Optional) " )
2022-09-26 22:50:21 +08:00
interp_amount = gr . Slider ( minimum = 0.0 , maximum = 1.0 , step = 0.05 , label = ' Interpolation Amount ' , value = 0.3 )
2022-09-28 20:52:46 +08:00
interp_method = gr . Radio ( choices = [ " Weighted Sum " , " Sigmoid " , " Inverse Sigmoid " ] , value = " Weighted Sum " , label = " Interpolation Method " )
2022-10-08 21:48:15 +08:00
save_as_half = gr . Checkbox ( value = False , label = " Save as float16 " )
2022-09-29 05:59:44 +08:00
modelmerger_merge = gr . Button ( elem_id = " modelmerger_merge " , label = " Merge " , variant = ' primary ' )
2022-10-02 20:03:39 +08:00
2022-09-26 07:22:12 +08:00
with gr . Column ( variant = ' panel ' ) :
2022-09-27 15:44:00 +08:00
submit_result = gr . Textbox ( elem_id = " modelmerger_result " , show_label = False )
2022-09-26 07:22:12 +08:00
2022-10-02 20:03:39 +08:00
sd_hijack . model_hijack . embedding_db . load_textual_inversion_embeddings ( )
with gr . Blocks ( ) as textual_inversion_interface :
with gr . Row ( ) . style ( equal_height = False ) :
with gr . Column ( ) :
with gr . Group ( ) :
2022-10-03 03:41:21 +08:00
gr . HTML ( value = " <p style= ' margin-bottom: 0.7em ' >See <b><a href= \" https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Textual-Inversion \" >wiki</a></b> for detailed explanation.</p> " )
2022-10-02 20:03:39 +08:00
gr . HTML ( value = " <p style= ' margin-bottom: 0.7em ' >Create a new embedding</p> " )
new_embedding_name = gr . Textbox ( label = " Name " )
2022-10-03 00:40:51 +08:00
initialization_text = gr . Textbox ( label = " Initialization text " , value = " * " )
2022-10-02 20:03:39 +08:00
nvpt = gr . Slider ( label = " Number of vectors per token " , minimum = 1 , maximum = 75 , step = 1 , value = 1 )
with gr . Row ( ) :
with gr . Column ( scale = 3 ) :
gr . HTML ( value = " " )
with gr . Column ( ) :
2022-10-11 19:53:02 +08:00
create_embedding = gr . Button ( value = " Create embedding " , variant = ' primary ' )
2022-10-02 20:03:39 +08:00
2022-10-08 04:22:22 +08:00
with gr . Group ( ) :
gr . HTML ( value = " <p style= ' margin-bottom: 0.7em ' >Create a new hypernetwork</p> " )
new_hypernetwork_name = gr . Textbox ( label = " Name " )
2022-10-11 23:04:47 +08:00
new_hypernetwork_sizes = gr . CheckboxGroup ( label = " Modules " , value = [ " 768 " , " 320 " , " 640 " , " 1280 " ] , choices = [ " 768 " , " 320 " , " 640 " , " 1280 " ] )
2022-10-08 04:22:22 +08:00
with gr . Row ( ) :
with gr . Column ( scale = 3 ) :
gr . HTML ( value = " " )
with gr . Column ( ) :
2022-10-11 19:53:02 +08:00
create_hypernetwork = gr . Button ( value = " Create hypernetwork " , variant = ' primary ' )
2022-10-02 20:03:39 +08:00
2022-10-03 03:41:21 +08:00
with gr . Group ( ) :
gr . HTML ( value = " <p style= ' margin-bottom: 0.7em ' >Preprocess images</p> " )
process_src = gr . Textbox ( label = ' Source directory ' )
process_dst = gr . Textbox ( label = ' Destination directory ' )
2022-10-10 21:35:35 +08:00
process_width = gr . Slider ( minimum = 64 , maximum = 2048 , step = 64 , label = " Width " , value = 512 )
process_height = gr . Slider ( minimum = 64 , maximum = 2048 , step = 64 , label = " Height " , value = 512 )
2022-10-03 03:41:21 +08:00
with gr . Row ( ) :
2022-10-09 00:50:01 +08:00
process_flip = gr . Checkbox ( label = ' Create flipped copies ' )
process_split = gr . Checkbox ( label = ' Split oversized images into two ' )
2022-10-09 00:56:28 +08:00
process_caption = gr . Checkbox ( label = ' Use BLIP caption as filename ' )
2022-10-03 03:41:21 +08:00
with gr . Row ( ) :
with gr . Column ( scale = 3 ) :
gr . HTML ( value = " " )
with gr . Column ( ) :
run_preprocess = gr . Button ( value = " Preprocess " , variant = ' primary ' )
2022-10-02 20:03:39 +08:00
with gr . Group ( ) :
2022-10-10 16:07:46 +08:00
gr . HTML ( value = " <p style= ' margin-bottom: 0.7em ' >Train an embedding; must specify a directory with a set of 1:1 ratio images</p> " )
2022-10-02 20:03:39 +08:00
train_embedding_name = gr . Dropdown ( label = ' Embedding ' , choices = sorted ( sd_hijack . model_hijack . embedding_db . word_embeddings . keys ( ) ) )
2022-10-08 04:22:22 +08:00
train_hypernetwork_name = gr . Dropdown ( label = ' Hypernetwork ' , choices = [ x for x in shared . hypernetworks . keys ( ) ] )
2022-10-12 03:03:05 +08:00
learn_rate = gr . Textbox ( label = ' Learning rate ' , placeholder = " Learning rate " , value = " 0.005 " )
2022-10-02 20:03:39 +08:00
dataset_directory = gr . Textbox ( label = ' Dataset directory ' , placeholder = " Path to directory with input images " )
log_directory = gr . Textbox ( label = ' Log directory ' , placeholder = " Path to directory where to write outputs " , value = " textual_inversion " )
template_file = gr . Textbox ( label = ' Prompt template file ' , value = os . path . join ( script_path , " textual_inversion_templates " , " style_filewords.txt " ) )
2022-10-10 21:35:35 +08:00
training_width = gr . Slider ( minimum = 64 , maximum = 2048 , step = 64 , label = " Width " , value = 512 )
training_height = gr . Slider ( minimum = 64 , maximum = 2048 , step = 64 , label = " Height " , value = 512 )
2022-10-02 20:03:39 +08:00
steps = gr . Number ( label = ' Max steps ' , value = 100000 , precision = 0 )
2022-10-10 16:07:46 +08:00
num_repeats = gr . Number ( label = ' Number of repeats for a single input image per epoch ' , value = 100 , precision = 0 )
2022-10-03 03:59:01 +08:00
create_image_every = gr . Number ( label = ' Save an image to log directory every N steps, 0 to disable ' , value = 500 , precision = 0 )
save_embedding_every = gr . Number ( label = ' Save a copy of embedding to log directory every N steps, 0 to disable ' , value = 500 , precision = 0 )
2022-10-08 04:22:22 +08:00
preview_image_prompt = gr . Textbox ( label = ' Preview prompt ' , value = " " )
2022-10-02 20:03:39 +08:00
with gr . Row ( ) :
2022-10-08 04:22:22 +08:00
interrupt_training = gr . Button ( value = " Interrupt " )
train_hypernetwork = gr . Button ( value = " Train Hypernetwork " , variant = ' primary ' )
train_embedding = gr . Button ( value = " Train Embedding " , variant = ' primary ' )
2022-10-02 20:03:39 +08:00
with gr . Column ( ) :
progressbar = gr . HTML ( elem_id = " ti_progressbar " )
ti_output = gr . Text ( elem_id = " ti_output " , value = " " , show_label = False )
ti_gallery = gr . Gallery ( label = ' Output ' , show_label = False , elem_id = ' ti_gallery ' ) . style ( grid = 4 )
ti_preview = gr . Image ( elem_id = ' ti_preview ' , visible = False )
ti_progress = gr . HTML ( elem_id = " ti_progress " , value = " " )
ti_outcome = gr . HTML ( elem_id = " ti_error " , value = " " )
setup_progressbar ( progressbar , ti_preview , ' ti ' , textinfo = ti_progress )
create_embedding . click (
fn = modules . textual_inversion . ui . create_embedding ,
inputs = [
new_embedding_name ,
2022-10-03 00:40:51 +08:00
initialization_text ,
2022-10-02 20:03:39 +08:00
nvpt ,
] ,
outputs = [
train_embedding_name ,
ti_output ,
ti_outcome ,
]
)
2022-10-08 04:22:22 +08:00
create_hypernetwork . click (
2022-10-11 20:54:34 +08:00
fn = modules . hypernetworks . ui . create_hypernetwork ,
2022-10-08 04:22:22 +08:00
inputs = [
new_hypernetwork_name ,
2022-10-11 23:04:47 +08:00
new_hypernetwork_sizes ,
2022-10-08 04:22:22 +08:00
] ,
outputs = [
train_hypernetwork_name ,
ti_output ,
ti_outcome ,
]
)
2022-10-03 03:41:21 +08:00
run_preprocess . click (
fn = wrap_gradio_gpu_call ( modules . textual_inversion . ui . preprocess , extra_outputs = [ gr . update ( ) ] ) ,
_js = " start_training_textual_inversion " ,
inputs = [
process_src ,
process_dst ,
2022-10-10 21:35:35 +08:00
process_width ,
process_height ,
2022-10-03 03:41:21 +08:00
process_flip ,
process_split ,
process_caption ,
] ,
outputs = [
ti_output ,
ti_outcome ,
] ,
)
2022-10-02 20:03:39 +08:00
train_embedding . click (
fn = wrap_gradio_gpu_call ( modules . textual_inversion . ui . train_embedding , extra_outputs = [ gr . update ( ) ] ) ,
_js = " start_training_textual_inversion " ,
inputs = [
train_embedding_name ,
learn_rate ,
dataset_directory ,
log_directory ,
2022-10-10 21:35:35 +08:00
training_width ,
training_height ,
2022-10-02 20:03:39 +08:00
steps ,
2022-10-10 16:07:46 +08:00
num_repeats ,
2022-10-02 20:03:39 +08:00
create_image_every ,
save_embedding_every ,
template_file ,
2022-10-11 19:53:02 +08:00
preview_image_prompt ,
2022-10-02 20:03:39 +08:00
] ,
outputs = [
ti_output ,
ti_outcome ,
]
)
2022-10-08 04:22:22 +08:00
train_hypernetwork . click (
2022-10-11 20:54:34 +08:00
fn = wrap_gradio_gpu_call ( modules . hypernetworks . ui . train_hypernetwork , extra_outputs = [ gr . update ( ) ] ) ,
2022-10-08 04:22:22 +08:00
_js = " start_training_textual_inversion " ,
inputs = [
train_hypernetwork_name ,
learn_rate ,
dataset_directory ,
log_directory ,
steps ,
create_image_every ,
save_embedding_every ,
template_file ,
preview_image_prompt ,
2022-10-02 20:03:39 +08:00
] ,
outputs = [
ti_output ,
ti_outcome ,
]
)
interrupt_training . click (
fn = lambda : shared . state . interrupt ( ) ,
inputs = [ ] ,
outputs = [ ] ,
)
2022-10-08 04:22:22 +08:00
2022-09-03 17:08:45 +08:00
def create_setting_component ( key ) :
def fun ( ) :
return opts . data [ key ] if key in opts . data else opts . data_labels [ key ] . default
info = opts . data_labels [ key ]
t = type ( info . default )
2022-09-12 04:00:42 +08:00
args = info . component_args ( ) if callable ( info . component_args ) else info . component_args
2022-09-03 17:08:45 +08:00
if info . component is not None :
2022-09-12 04:00:42 +08:00
comp = info . component
2022-09-03 17:08:45 +08:00
elif t == str :
2022-09-12 04:00:42 +08:00
comp = gr . Textbox
2022-09-03 17:08:45 +08:00
elif t == int :
2022-09-12 04:00:42 +08:00
comp = gr . Number
2022-09-03 17:08:45 +08:00
elif t == bool :
2022-09-12 04:00:42 +08:00
comp = gr . Checkbox
2022-09-03 17:08:45 +08:00
else :
raise Exception ( f ' bad options item type: { str ( t ) } for key { key } ' )
2022-09-12 04:00:42 +08:00
return comp ( label = info . label , value = fun , * * ( args or { } ) )
2022-09-03 17:08:45 +08:00
2022-09-10 16:10:00 +08:00
components = [ ]
2022-09-29 05:59:44 +08:00
component_dict = { }
2022-09-10 16:10:00 +08:00
2022-09-28 05:02:11 +08:00
def open_folder ( f ) :
2022-10-09 17:33:37 +08:00
if not os . path . isdir ( f ) :
print ( f """
WARNING
An open_folder request was made with an argument that is not a folder .
This could be an error or a malicious attempt to run code on your computer .
Requested path was : { f }
""" , file=sys.stderr)
return
2022-09-28 16:31:53 +08:00
if not shared . cmd_opts . hide_ui_dir_config :
path = os . path . normpath ( f )
if platform . system ( ) == " Windows " :
os . startfile ( path )
elif platform . system ( ) == " Darwin " :
sp . Popen ( [ " open " , path ] )
else :
sp . Popen ( [ " xdg-open " , path ] )
2022-09-28 05:02:11 +08:00
2022-09-03 17:08:45 +08:00
def run_settings ( * args ) :
2022-09-23 22:27:30 +08:00
changed = 0
for key , value , comp in zip ( opts . data_labels . keys ( ) , args , components ) :
2022-10-10 03:24:07 +08:00
if comp != dummy_component and not opts . same_type ( value , opts . data_labels [ key ] . default ) :
return f " Bad value for setting { key } : { value } ; expecting { type ( opts . data_labels [ key ] . default ) . __name__ } " , opts . dumpjson ( )
2022-09-03 17:08:45 +08:00
2022-09-10 16:10:00 +08:00
for key , value , comp in zip ( opts . data_labels . keys ( ) , args , components ) :
2022-10-10 03:24:07 +08:00
if comp == dummy_component :
continue
2022-09-12 04:00:42 +08:00
comp_args = opts . data_labels [ key ] . component_args
if comp_args and isinstance ( comp_args , dict ) and comp_args . get ( ' visible ' ) is False :
continue
2022-09-17 17:05:04 +08:00
oldval = opts . data . get ( key , None )
2022-09-03 17:08:45 +08:00
opts . data [ key ] = value
2022-09-17 17:05:04 +08:00
2022-09-23 22:27:30 +08:00
if oldval != value :
if opts . data_labels [ key ] . onchange is not None :
opts . data_labels [ key ] . onchange ( )
2022-09-17 17:05:04 +08:00
2022-09-23 22:27:30 +08:00
changed + = 1
2022-09-03 17:08:45 +08:00
opts . save ( shared . config_filename )
2022-09-24 05:13:32 +08:00
return f ' { changed } settings changed. ' , opts . dumpjson ( )
2022-09-03 17:08:45 +08:00
2022-10-10 03:24:07 +08:00
def run_settings_single ( value , key ) :
if not opts . same_type ( value , opts . data_labels [ key ] . default ) :
return gr . update ( visible = True ) , opts . dumpjson ( )
oldval = opts . data . get ( key , None )
opts . data [ key ] = value
if oldval != value :
if opts . data_labels [ key ] . onchange is not None :
opts . data_labels [ key ] . onchange ( )
opts . save ( shared . config_filename )
return gr . update ( value = value ) , opts . dumpjson ( )
2022-09-10 16:10:00 +08:00
with gr . Blocks ( analytics_enabled = False ) as settings_interface :
2022-09-19 03:25:18 +08:00
settings_submit = gr . Button ( value = " Apply settings " , variant = ' primary ' )
2022-09-10 16:10:00 +08:00
result = gr . HTML ( )
2022-09-23 02:32:44 +08:00
settings_cols = 3
items_per_col = int ( len ( opts . data_labels ) * 0.9 / settings_cols )
2022-09-10 16:10:00 +08:00
2022-10-10 03:24:07 +08:00
quicksettings_list = [ ]
2022-09-23 02:32:44 +08:00
cols_displayed = 0
items_displayed = 0
previous_section = None
column = None
with gr . Row ( elem_id = " settings " ) . style ( equal_height = False ) :
for i , ( k , item ) in enumerate ( opts . data_labels . items ( ) ) :
2022-09-23 00:26:26 +08:00
2022-09-23 02:32:44 +08:00
if previous_section != item . section :
if cols_displayed < settings_cols and ( items_displayed > = items_per_col or previous_section is None ) :
if column is not None :
column . __exit__ ( )
2022-09-23 00:26:26 +08:00
2022-09-23 02:32:44 +08:00
column = gr . Column ( variant = ' panel ' )
column . __enter__ ( )
2022-09-10 16:10:00 +08:00
2022-09-23 02:32:44 +08:00
items_displayed = 0
cols_displayed + = 1
previous_section = item . section
gr . HTML ( elem_id = " settings_header_text_ {} " . format ( item . section [ 0 ] ) , value = ' <h1 class= " gr-button-lg " > {} </h1> ' . format ( item . section [ 1 ] ) )
2022-10-10 03:24:07 +08:00
if item . show_on_main_page :
quicksettings_list . append ( ( i , k , item ) )
components . append ( dummy_component )
else :
component = create_setting_component ( k )
component_dict [ k ] = component
components . append ( component )
items_displayed + = 1
2022-09-03 17:08:45 +08:00
2022-09-22 18:15:33 +08:00
request_notifications = gr . Button ( value = ' Request browser notifications ' , elem_id = " request_notifications " )
2022-09-19 09:41:57 +08:00
request_notifications . click (
fn = lambda : None ,
inputs = [ ] ,
outputs = [ ] ,
2022-09-22 18:15:33 +08:00
_js = ' function() {} '
2022-09-19 09:41:57 +08:00
)
2022-10-02 08:36:30 +08:00
with gr . Row ( ) :
2022-10-03 02:26:06 +08:00
reload_script_bodies = gr . Button ( value = ' Reload custom script bodies (No ui updates, No restart) ' , variant = ' secondary ' )
restart_gradio = gr . Button ( value = ' Restart Gradio and Refresh components (Custom Scripts, ui.py, js and css only) ' , variant = ' primary ' )
2022-10-02 01:33:31 +08:00
2022-10-02 08:19:55 +08:00
def reload_scripts ( ) :
2022-10-03 02:26:06 +08:00
modules . scripts . reload_script_body_only ( )
2022-10-02 08:19:55 +08:00
reload_script_bodies . click (
fn = reload_scripts ,
inputs = [ ] ,
outputs = [ ] ,
_js = ' function() {} '
)
2022-10-02 08:36:30 +08:00
def request_restart ( ) :
2022-10-05 11:43:05 +08:00
shared . state . interrupt ( )
2022-10-03 02:26:06 +08:00
settings_interface . gradio_ref . do_restart = True
2022-10-02 08:36:30 +08:00
2022-10-11 08:57:43 +08:00
2022-10-02 08:36:30 +08:00
restart_gradio . click (
fn = request_restart ,
inputs = [ ] ,
outputs = [ ] ,
_js = ' function() { restart_reload()} '
)
2022-10-02 01:33:31 +08:00
2022-09-23 02:32:44 +08:00
if column is not None :
column . __exit__ ( )
2022-09-03 17:08:45 +08:00
interfaces = [
2022-09-10 16:10:00 +08:00
( txt2img_interface , " txt2img " , " txt2img " ) ,
( img2img_interface , " img2img " , " img2img " ) ,
( extras_interface , " Extras " , " extras " ) ,
( pnginfo_interface , " PNG Info " , " pnginfo " ) ,
2022-09-26 07:22:12 +08:00
( modelmerger_interface , " Checkpoint Merger " , " modelmerger " ) ,
2022-10-02 20:03:39 +08:00
( textual_inversion_interface , " Textual inversion " , " ti " ) ,
2022-09-10 16:10:00 +08:00
( settings_interface , " Settings " , " settings " ) ,
2022-09-03 17:08:45 +08:00
]
with open ( os . path . join ( script_path , " style.css " ) , " r " , encoding = " utf8 " ) as file :
css = file . read ( )
2022-09-17 21:35:58 +08:00
if os . path . exists ( os . path . join ( script_path , " user.css " ) ) :
2022-09-17 21:28:19 +08:00
with open ( os . path . join ( script_path , " user.css " ) , " r " , encoding = " utf8 " ) as file :
usercss = file . read ( )
css + = usercss
2022-09-03 17:08:45 +08:00
if not cmd_opts . no_progressbar_hiding :
css + = css_hide_progressbar
2022-09-10 16:10:00 +08:00
with gr . Blocks ( css = css , analytics_enabled = False , title = " Stable Diffusion " ) as demo :
2022-10-10 03:24:07 +08:00
with gr . Row ( elem_id = " quicksettings " ) :
for i , k , item in quicksettings_list :
component = create_setting_component ( k )
component_dict [ k ] = component
2022-10-02 01:33:31 +08:00
settings_interface . gradio_ref = demo
2022-09-10 16:10:00 +08:00
with gr . Tabs ( ) as tabs :
for interface , label , ifid in interfaces :
2022-10-11 13:22:46 +08:00
with gr . TabItem ( label , id = ifid , elem_id = ' tab_ ' + ifid ) :
2022-09-10 16:10:00 +08:00
interface . render ( )
2022-09-27 04:57:31 +08:00
if os . path . exists ( os . path . join ( script_path , " notification.mp3 " ) ) :
audio_notification = gr . Audio ( interactive = False , value = os . path . join ( script_path , " notification.mp3 " ) , elem_id = " audio_notification " , visible = False )
2022-09-10 16:10:00 +08:00
2022-09-19 22:16:04 +08:00
text_settings = gr . Textbox ( elem_id = " settings_json " , value = lambda : opts . dumpjson ( ) , visible = False )
2022-09-19 03:25:18 +08:00
settings_submit . click (
2022-09-24 05:13:32 +08:00
fn = run_settings ,
inputs = components ,
outputs = [ result , text_settings ] ,
2022-09-19 03:25:18 +08:00
)
2022-10-10 03:24:07 +08:00
for i , k , item in quicksettings_list :
component = component_dict [ k ]
component . change (
fn = lambda value , k = k : run_settings_single ( value , key = k ) ,
inputs = [ component ] ,
outputs = [ component , text_settings ] ,
)
2022-09-29 07:50:34 +08:00
def modelmerger ( * args ) :
try :
2022-10-02 20:03:39 +08:00
results = modules . extras . run_modelmerger ( * args )
2022-09-29 07:50:34 +08:00
except Exception as e :
print ( " Error loading/saving model file: " , file = sys . stderr )
print ( traceback . format_exc ( ) , file = sys . stderr )
2022-10-02 20:03:39 +08:00
modules . sd_models . list_models ( ) # to remove the potentially missing models from the list
2022-09-29 07:50:34 +08:00
return [ " Error loading/saving model file. It doesn ' t exist or the name contains illegal characters " ] + [ gr . Dropdown . update ( choices = modules . sd_models . checkpoint_tiles ( ) ) for _ in range ( 3 ) ]
return results
2022-09-19 03:25:18 +08:00
2022-09-29 05:59:44 +08:00
modelmerger_merge . click (
2022-09-29 07:50:34 +08:00
fn = modelmerger ,
2022-09-29 05:59:44 +08:00
inputs = [
primary_model_name ,
secondary_model_name ,
interp_method ,
interp_amount ,
save_as_half ,
2022-09-29 07:50:34 +08:00
custom_name ,
2022-09-29 05:59:44 +08:00
] ,
outputs = [
submit_result ,
primary_model_name ,
secondary_model_name ,
component_dict [ ' sd_model_checkpoint ' ] ,
]
)
2022-09-26 04:09:43 +08:00
paste_field_names = [ ' Prompt ' , ' Negative prompt ' , ' Steps ' , ' Face restoration ' , ' Seed ' , ' Size-1 ' , ' Size-2 ' ]
txt2img_fields = [ field for field , name in txt2img_paste_fields if name in paste_field_names ]
img2img_fields = [ field for field , name in img2img_paste_fields if name in paste_field_names ]
2022-09-10 16:10:00 +08:00
send_to_img2img . click (
2022-09-26 04:09:43 +08:00
fn = lambda img , * args : ( image_from_url_text ( img ) , * args ) ,
_js = " (gallery, ...args) => [extract_image_from_gallery_img2img(gallery), ...args] " ,
inputs = [ txt2img_gallery ] + txt2img_fields ,
outputs = [ init_img ] + img2img_fields ,
2022-09-10 16:10:00 +08:00
)
send_to_inpaint . click (
2022-09-26 04:09:43 +08:00
fn = lambda x , * args : ( image_from_url_text ( x ) , * args ) ,
_js = " (gallery, ...args) => [extract_image_from_gallery_inpaint(gallery), ...args] " ,
inputs = [ txt2img_gallery ] + txt2img_fields ,
outputs = [ init_img_with_mask ] + img2img_fields ,
2022-09-10 16:10:00 +08:00
)
img2img_send_to_img2img . click (
fn = lambda x : image_from_url_text ( x ) ,
2022-09-24 03:49:21 +08:00
_js = " extract_image_from_gallery_img2img " ,
2022-09-10 16:10:00 +08:00
inputs = [ img2img_gallery ] ,
outputs = [ init_img ] ,
)
img2img_send_to_inpaint . click (
fn = lambda x : image_from_url_text ( x ) ,
2022-09-24 03:49:21 +08:00
_js = " extract_image_from_gallery_inpaint " ,
2022-09-10 16:10:00 +08:00
inputs = [ img2img_gallery ] ,
outputs = [ init_img_with_mask ] ,
)
send_to_extras . click (
fn = lambda x : image_from_url_text ( x ) ,
2022-09-11 05:21:47 +08:00
_js = " extract_image_from_gallery_extras " ,
2022-09-10 16:10:00 +08:00
inputs = [ txt2img_gallery ] ,
2022-09-24 03:49:21 +08:00
outputs = [ extras_image ] ,
2022-09-10 16:10:00 +08:00
)
2022-09-28 05:02:11 +08:00
open_txt2img_folder . click (
fn = lambda : open_folder ( opts . outdir_samples or opts . outdir_txt2img_samples ) ,
inputs = [ ] ,
outputs = [ ] ,
)
open_img2img_folder . click (
fn = lambda : open_folder ( opts . outdir_samples or opts . outdir_img2img_samples ) ,
inputs = [ ] ,
outputs = [ ] ,
)
open_extras_folder . click (
fn = lambda : open_folder ( opts . outdir_samples or opts . outdir_extras_samples ) ,
inputs = [ ] ,
outputs = [ ] ,
)
2022-09-10 16:10:00 +08:00
img2img_send_to_extras . click (
fn = lambda x : image_from_url_text ( x ) ,
2022-09-11 05:21:47 +08:00
_js = " extract_image_from_gallery_extras " ,
2022-09-10 16:10:00 +08:00
inputs = [ img2img_gallery ] ,
2022-09-24 03:49:21 +08:00
outputs = [ extras_image ] ,
2022-09-10 16:10:00 +08:00
)
2022-09-03 17:08:45 +08:00
2022-09-24 03:49:21 +08:00
modules . generation_parameters_copypaste . connect_paste ( pnginfo_send_to_txt2img , txt2img_paste_fields , generation_info , ' switch_to_txt2img ' )
modules . generation_parameters_copypaste . connect_paste ( pnginfo_send_to_img2img , img2img_paste_fields , generation_info , ' switch_to_img2img_img2img ' )
2022-09-10 13:18:54 +08:00
ui_config_file = cmd_opts . ui_config_file
2022-09-04 18:52:01 +08:00
ui_settings = { }
settings_count = len ( ui_settings )
error_loading = False
try :
if os . path . exists ( ui_config_file ) :
with open ( ui_config_file , " r " , encoding = " utf8 " ) as file :
ui_settings = json . load ( file )
except Exception :
error_loading = True
print ( " Error loading settings: " , file = sys . stderr )
print ( traceback . format_exc ( ) , file = sys . stderr )
def loadsave ( path , x ) :
2022-09-06 00:11:29 +08:00
def apply_field ( obj , field , condition = None ) :
2022-09-04 18:52:01 +08:00
key = path + " / " + field
2022-09-25 13:56:50 +08:00
if getattr ( obj , ' custom_script_source ' , None ) is not None :
key = ' customscript/ ' + obj . custom_script_source + ' / ' + key
2022-09-25 13:34:03 +08:00
2022-09-26 00:43:42 +08:00
if getattr ( obj , ' do_not_save_to_config ' , False ) :
return
2022-09-25 13:34:03 +08:00
2022-09-04 18:52:01 +08:00
saved_value = ui_settings . get ( key , None )
if saved_value is None :
ui_settings [ key ] = getattr ( obj , field )
2022-09-06 00:11:29 +08:00
elif condition is None or condition ( saved_value ) :
2022-09-04 18:52:01 +08:00
setattr ( obj , field , saved_value )
2022-09-26 00:43:42 +08:00
if type ( x ) in [ gr . Slider , gr . Radio , gr . Checkbox , gr . Textbox , gr . Number ] and x . visible :
apply_field ( x , ' visible ' )
2022-09-04 18:52:01 +08:00
if type ( x ) == gr . Slider :
apply_field ( x , ' value ' )
apply_field ( x , ' minimum ' )
apply_field ( x , ' maximum ' )
apply_field ( x , ' step ' )
if type ( x ) == gr . Radio :
2022-09-06 00:11:29 +08:00
apply_field ( x , ' value ' , lambda val : val in x . choices )
2022-09-04 18:52:01 +08:00
2022-09-25 13:31:02 +08:00
if type ( x ) == gr . Checkbox :
2022-09-25 13:40:37 +08:00
apply_field ( x , ' value ' )
2022-09-25 13:31:02 +08:00
if type ( x ) == gr . Textbox :
2022-09-25 13:40:37 +08:00
apply_field ( x , ' value ' )
2022-09-25 13:39:22 +08:00
if type ( x ) == gr . Number :
2022-09-25 13:40:37 +08:00
apply_field ( x , ' value ' )
2022-09-25 13:39:22 +08:00
2022-09-04 18:52:01 +08:00
visit ( txt2img_interface , loadsave , " txt2img " )
visit ( img2img_interface , loadsave , " img2img " )
2022-09-11 16:31:16 +08:00
visit ( extras_interface , loadsave , " extras " )
2022-09-04 18:52:01 +08:00
if not error_loading and ( not os . path . exists ( ui_config_file ) or settings_count != len ( ui_settings ) ) :
with open ( ui_config_file , " w " , encoding = " utf8 " ) as file :
json . dump ( ui_settings , file , indent = 4 )
2022-09-03 17:08:45 +08:00
return demo
2022-09-03 22:21:15 +08:00
with open ( os . path . join ( script_path , " script.js " ) , " r " , encoding = " utf8 " ) as jsfile :
2022-09-18 13:37:03 +08:00
javascript = f ' <script> { jsfile . read ( ) } </script> '
jsdir = os . path . join ( script_path , " javascript " )
2022-09-23 10:05:42 +08:00
for filename in sorted ( os . listdir ( jsdir ) ) :
2022-09-18 13:37:03 +08:00
with open ( os . path . join ( jsdir , filename ) , " r " , encoding = " utf8 " ) as jsfile :
javascript + = f " \n <script> { jsfile . read ( ) } </script> "
2022-09-03 17:08:45 +08:00
2022-10-02 05:43:45 +08:00
if ' gradio_routes_templates_response ' not in globals ( ) :
2022-10-03 02:26:06 +08:00
def template_response ( * args , * * kwargs ) :
res = gradio_routes_templates_response ( * args , * * kwargs )
res . body = res . body . replace ( b ' </head> ' , f ' { javascript } </head> ' . encode ( " utf8 " ) )
res . init_headers ( )
return res
gradio_routes_templates_response = gradio . routes . templates . TemplateResponse
gradio . routes . templates . TemplateResponse = template_response