Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

learning #15071

Closed
wants to merge 1 commit into from
Closed

learning #15071

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions modules/cmd_args.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
parser.add_argument("--api-auth", type=str, help='Set authentication for API like "username:password"; or comma-delimit multiple like "u1:p1,u2:p2,u3:p3"', default=None)
parser.add_argument("--api-log", action='store_true', help="use api-log=True to enable logging of all API requests")
parser.add_argument("--nowebui", action='store_true', help="use api=True to launch the API instead of the webui")
parser.add_argument("--ui-only", action='store_true', help="ui only")
parser.add_argument("--ui-debug-mode", action='store_true', help="Don't load model to quickly launch UI")
parser.add_argument("--device-id", type=str, help="Select the default CUDA device to use (export CUDA_VISIBLE_DEVICES=0,1,etc might be needed before)", default=None)
parser.add_argument("--administrator", action='store_true', help="Administrator rights", default=False)
Expand Down
1 change: 1 addition & 0 deletions modules/initialize.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ def initialize():
initialize_util.fix_asyncio_event_loop_policy()
initialize_util.validate_tls_options()
initialize_util.configure_sigint_handler()
# Theme is initialized here
initialize_util.configure_opts_onchange()

from modules import modelloader
Expand Down
3 changes: 3 additions & 0 deletions modules/launch_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -458,8 +458,11 @@ def configure_for_tests():
def start():
print(f"Launching {'API server' if '--nowebui' in sys.argv else 'Web UI'} with arguments: {' '.join(sys.argv[1:])}")
import webui
import ui_only
if '--nowebui' in sys.argv:
webui.api_only()
if '--ui-only' in sys.argv:
ui_only.webui()
else:
webui.webui()

Expand Down
46 changes: 46 additions & 0 deletions modules/processing.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,52 @@ class StableDiffusionProcessing:

is_api: bool = field(default=False, init=False)

def processing_infotext(self):
self.setup_prompts()

return create_infotext(self, self.all_prompts, ['-1'], self.all_subseeds, [], iteration=self.iteration, position_in_batch=0)

def processing_js(self):
# not fully implemented
self.setup_prompts()

obj = {
"prompt": self.all_prompts[0],
"all_prompts": self.all_prompts,
"negative_prompt": self.all_negative_prompts[0],
"all_negative_prompts": self.all_negative_prompts,
"seed": self.seed,
"all_seeds": self.all_seeds or [self.seed],
"subseed": self.subseed,
"all_subseeds": self.all_subseeds,
"subseed_strength": self.subseed_strength,
"width": self.width,
"height": self.height,
"sampler_name": self.sampler_name,
"cfg_scale": self.cfg_scale,
"steps": self.steps,
"batch_size": self.batch_size,
"restore_faces": self.restore_faces,
"face_restoration_model": self.face_restoration_model if self.restore_faces else None,
"sd_model_name": self.sd_model_name,
"sd_model_hash": self.sd_model_hash,
"sd_vae_name": self.sd_vae_name,
"sd_vae_hash": self.sd_vae_hash,
"seed_resize_from_w": self.seed_resize_from_w,
"seed_resize_from_h": self.seed_resize_from_h,
"denoising_strength": self.denoising_strength,
"extra_generation_params": self.extra_generation_params,
"index_of_first_image": 0,
"infotexts": self.infotexts,
"styles": self.styles,
"job_timestamp": self.job_timestamp,
"clip_skip": self.clip_skip,
"is_using_inpainting_conditioning": self.is_using_inpainting_conditioning,
"version": self.version,
}

return json.dumps(obj)

def __post_init__(self):
if self.sampler_index is not None:
print("sampler_index argument for StableDiffusionProcessing does not do anything; use sampler_name", file=sys.stderr)
Expand Down
3 changes: 3 additions & 0 deletions modules/txt2img.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ def txt2img(id_task: str, prompt: str, negative_prompt: str, prompt_styles, step

p.user = request.username

pre_generation_info_text = p.processing_infotext()
print(pre_generation_info_text)

if shared.opts.enable_console_prompts:
print(f"\ntxt2img: {prompt}", file=shared.progress_print_out)

Expand Down
991 changes: 991 additions & 0 deletions modules/ui_only.py

Large diffs are not rendered by default.

161 changes: 161 additions & 0 deletions ui_only.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
from __future__ import annotations

import os
import time

from modules import timer
from modules import initialize_util
from modules import initialize

startup_timer = timer.startup_timer
startup_timer.record("launcher")

initialize.imports()

initialize.check_versions()


def create_api(app):
from modules.api.api import Api
from modules.call_queue import queue_lock

api = Api(app, queue_lock)
return api


def api_only():
from fastapi import FastAPI
from modules.shared_cmd_options import cmd_opts

initialize.initialize()

app = FastAPI()
initialize_util.setup_middleware(app)
api = create_api(app)

from modules import script_callbacks
script_callbacks.before_ui_callback()
script_callbacks.app_started_callback(None, app)

print(f"Startup time: {startup_timer.summary()}.")
api.launch(
server_name="0.0.0.0" if cmd_opts.listen else "127.0.0.1",
port=cmd_opts.port if cmd_opts.port else 7861,
root_path=f"/{cmd_opts.subpath}" if cmd_opts.subpath else ""
)


def webui():
from modules.shared_cmd_options import cmd_opts

launch_api = cmd_opts.api
initialize.initialize()

from modules import shared, ui_tempdir, script_callbacks, ui_only, progress, ui_extra_networks

while 1:
if shared.opts.clean_temp_dir_at_start:
ui_tempdir.cleanup_tmpdr()
startup_timer.record("cleanup temp dir")

script_callbacks.before_ui_callback()
startup_timer.record("scripts before_ui_callback")

shared.demo = ui_only.create_ui()
startup_timer.record("create ui")

if not cmd_opts.no_gradio_queue:
shared.demo.queue(64)

gradio_auth_creds = list(initialize_util.get_gradio_auth_creds()) or None

auto_launch_browser = False
if os.getenv('SD_WEBUI_RESTARTING') != '1':
if shared.opts.auto_launch_browser == "Remote" or cmd_opts.autolaunch:
auto_launch_browser = True
elif shared.opts.auto_launch_browser == "Local":
auto_launch_browser = not cmd_opts.webui_is_non_local

app, local_url, share_url = shared.demo.launch(
server_name=initialize_util.gradio_server_name(),
server_port=cmd_opts.port,
ssl_keyfile=cmd_opts.tls_keyfile,
ssl_certfile=cmd_opts.tls_certfile,
ssl_verify=cmd_opts.disable_tls_verify,
debug=cmd_opts.gradio_debug,
auth=gradio_auth_creds,
inbrowser=auto_launch_browser,
prevent_thread_lock=True,
allowed_paths=cmd_opts.gradio_allowed_path,
app_kwargs={
"docs_url": "/docs",
"redoc_url": "/redoc",
},
root_path=f"/{cmd_opts.subpath}" if cmd_opts.subpath else "",
)

startup_timer.record("gradio launch")

# gradio uses a very open CORS policy via app.user_middleware, which makes it possible for
# an attacker to trick the user into opening a malicious HTML page, which makes a request to the
# running web ui and do whatever the attacker wants, including installing an extension and
# running its code. We disable this here. Suggested by RyotaK.
app.user_middleware = [x for x in app.user_middleware if x.cls.__name__ != 'CORSMiddleware']

initialize_util.setup_middleware(app)

progress.setup_progress_api(app)
ui_only.setup_ui_api(app)

if launch_api:
create_api(app)

ui_extra_networks.add_pages_to_demo(app)

startup_timer.record("add APIs")

with startup_timer.subcategory("app_started_callback"):
script_callbacks.app_started_callback(shared.demo, app)

timer.startup_record = startup_timer.dump()
print(f"Startup time: {startup_timer.summary()}.")

try:
while True:
server_command = shared.state.wait_for_server_command(timeout=5)
if server_command:
if server_command in ("stop", "restart"):
break
else:
print(f"Unknown server command: {server_command}")
except KeyboardInterrupt:
print('Caught KeyboardInterrupt, stopping...')
server_command = "stop"

if server_command == "stop":
print("Stopping server...")
# If we catch a keyboard interrupt, we want to stop the server and exit.
shared.demo.close()
break

# disable auto launch webui in browser for subsequent UI Reload
os.environ.setdefault('SD_WEBUI_RESTARTING', '1')

print('Restarting UI...')
shared.demo.close()
time.sleep(0.5)
startup_timer.reset()
script_callbacks.app_reload_callback()
startup_timer.record("app reload callback")
script_callbacks.script_unloaded_callback()
startup_timer.record("scripts unloaded callback")
initialize.initialize_rest(reload_script_modules=True)


if __name__ == "__main__":
from modules.shared_cmd_options import cmd_opts

if cmd_opts.nowebui:
api_only()
else:
webui()
69 changes: 69 additions & 0 deletions worklog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@


# Generate a well known ssl cert CA store to be trusted
https://pypi.org/project/certifi/

pip install certifi

python -m certifi


# Check venv ssl cert trust settings
https://stackoverflow.com/questions/39356413/how-to-add-a-custom-ca-root-certificate-to-the-ca-store-used-by-pip-in-windows
python -c "import ssl; print(ssl.get_default_verify_paths())"



# Use the generated truststore and move it to the location being used
cp /Users/samuelwang/sd/stable-diffusion-webui/venv/lib/python3.10/site-packages/certifi/cacert.pem /Library/Frameworks/Python.framework/Versions/3.10/etc/openssl/cert.pem



# Prompt Process
UI inputs provided by users
users click on the generate button
call queue wrap inputs and invoke txt2img run process (call_queue.py)
the result is stored in an Processed instance
the json inputs are generated from the Processed instance

We do not want to wait until it is processed because we won't process images locally.
So we need to create a js() method pre process, aka, Processing


def js(self):
obj = {
"prompt": self.all_prompts[0],
"all_prompts": self.all_prompts,
"negative_prompt": self.all_negative_prompts[0],
"all_negative_prompts": self.all_negative_prompts,
"seed": self.seed,
"all_seeds": self.all_seeds,
"subseed": self.subseed,
"all_subseeds": self.all_subseeds,
"subseed_strength": self.subseed_strength,
"width": self.width,
"height": self.height,
"sampler_name": self.sampler_name,
"cfg_scale": self.cfg_scale,
"steps": self.steps,
"batch_size": self.batch_size,
"restore_faces": self.restore_faces,
"face_restoration_model": self.face_restoration_model,
"sd_model_name": self.sd_model_name,
"sd_model_hash": self.sd_model_hash,
"sd_vae_name": self.sd_vae_name,
"sd_vae_hash": self.sd_vae_hash,
"seed_resize_from_w": self.seed_resize_from_w,
"seed_resize_from_h": self.seed_resize_from_h,
"denoising_strength": self.denoising_strength,
"extra_generation_params": self.extra_generation_params,
"index_of_first_image": self.index_of_first_image,
"infotexts": self.infotexts,
"styles": self.styles,
"job_timestamp": self.job_timestamp,
"clip_skip": self.clip_skip,
"is_using_inpainting_conditioning": self.is_using_inpainting_conditioning,
"version": self.version,
}

return json.dumps(obj)
Loading