From 654dcd453f72c5f4d0117702ca6e2e2ca1357637 Mon Sep 17 00:00:00 2001 From: Kevin Turner <83819+keturn@users.noreply.github.com> Date: Thu, 17 Aug 2023 18:48:04 -0700 Subject: [PATCH 1/3] feat(dev_reload): use jurigged to hot reload changes to Python source --- invokeai/app/api_app.py | 21 +++++++++++++++++---- invokeai/app/services/config.py | 10 +++++++--- pyproject.toml | 1 + 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/invokeai/app/api_app.py b/invokeai/app/api_app.py index 20b2781ef0..e5e6e26e88 100644 --- a/invokeai/app/api_app.py +++ b/invokeai/app/api_app.py @@ -1,12 +1,12 @@ # Copyright (c) 2022-2023 Kyle Schouviller (https://github.com/kyle0654) and the InvokeAI Team import asyncio +import logging +import socket import sys from inspect import signature +from pathlib import Path -import logging import uvicorn -import socket - from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from fastapi.openapi.docs import get_redoc_html, get_swagger_ui_html @@ -14,7 +14,6 @@ from fastapi.openapi.utils import get_openapi from fastapi.staticfiles import StaticFiles from fastapi_events.handlers.local import local_handler from fastapi_events.middleware import EventHandlerASGIMiddleware -from pathlib import Path from pydantic.schema import schema # This should come early so that modules can log their initialization properly @@ -42,9 +41,12 @@ from .invocations.baseinvocation import BaseInvocation, _InputField, _OutputFiel import torch + +# noinspection PyUnresolvedReferences import invokeai.backend.util.hotfixes if torch.backends.mps.is_available(): + # noinspection PyUnresolvedReferences import invokeai.backend.util.mps_fixes # fix for windows mimetypes registry entries being borked @@ -213,6 +215,17 @@ def invoke_api(): check_invokeai_root(app_config) # note, may exit with an exception if root not set up + if app_config.dev_reload: + try: + import jurigged + except ImportError as e: + logger.error( + "Can't start `--dev_reload` because jurigged is not found; `pip install -e '.[dev]'` to include development dependencies.", + exc_info=e, + ) + else: + jurigged.watch(logger=InvokeAILogger.getLogger(name="jurigged").info) + port = find_port(app_config.port) if port != app_config.port: logger.warn(f"Port {app_config.port} in use, using port {port}") diff --git a/invokeai/app/services/config.py b/invokeai/app/services/config.py index 9ff43467c5..fec07d90ba 100644 --- a/invokeai/app/services/config.py +++ b/invokeai/app/services/config.py @@ -159,15 +159,17 @@ two configs are kept in separate sections of the config file: """ from __future__ import annotations + import argparse -import pydoc import os +import pydoc import sys from argparse import ArgumentParser -from omegaconf import OmegaConf, DictConfig, ListConfig from pathlib import Path +from typing import ClassVar, Dict, List, Literal, Union, get_origin, get_type_hints, get_args + +from omegaconf import OmegaConf, DictConfig, ListConfig from pydantic import BaseSettings, Field, parse_obj_as -from typing import ClassVar, Dict, List, Set, Literal, Union, get_origin, get_type_hints, get_args INIT_FILE = Path("invokeai.yaml") DB_FILE = Path("invokeai.db") @@ -418,6 +420,8 @@ class InvokeAIAppConfig(InvokeAISettings): log_format : Literal[tuple(['plain','color','syslog','legacy'])] = Field(default="color", description='Log format. Use "plain" for text-only, "color" for colorized output, "legacy" for 2.3-style logging and "syslog" for syslog-style', category="Logging") log_level : Literal[tuple(["debug","info","warning","error","critical"])] = Field(default="info", description="Emit logging messages at this level or higher", category="Logging") + dev_reload : bool = Field(default=False, description="Automatically reload when Python sources are changed.", category="Development") + version : bool = Field(default=False, description="Show InvokeAI version and exit", category="Other") # fmt: on diff --git a/pyproject.toml b/pyproject.toml index e13ae607b9..ffa22b839e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -93,6 +93,7 @@ dependencies = [ "mkdocs-redirects==1.2.0", ] "dev" = [ + "jurigged", "pudb", ] "test" = ["pytest>6.0.0", "pytest-cov", "pytest-datadir", "black"] From 3039f92e69329525bd21867b6a02b863b36bebcc Mon Sep 17 00:00:00 2001 From: Kevin Turner <83819+keturn@users.noreply.github.com> Date: Mon, 21 Aug 2023 16:38:47 -0700 Subject: [PATCH 2/3] doc(development): small updates to backend development intro --- docs/contributing/LOCAL_DEVELOPMENT.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/docs/contributing/LOCAL_DEVELOPMENT.md b/docs/contributing/LOCAL_DEVELOPMENT.md index b2a5cd581d..b0b03e42a4 100644 --- a/docs/contributing/LOCAL_DEVELOPMENT.md +++ b/docs/contributing/LOCAL_DEVELOPMENT.md @@ -35,18 +35,17 @@ access. ## Backend -The backend is contained within the `./invokeai/backend` folder structure. To -get started however please install the development dependencies. +The backend is contained within the `./invokeai/backend` and `./invokeai/app` directories. +To get started please install the development dependencies. From the root of the repository run the following command. Note the use of `"`. ```zsh -pip install ".[test]" +pip install ".[dev,test]" ``` -This in an optional group of packages which is defined within the -`pyproject.toml` and will be required for testing the changes you make the the -code. +These are optional groups of packages which are defined within the `pyproject.toml` +and will be required for testing the changes you make to the code. ### Running Tests From 76750b0121533a77c56f190487075dcb4da23f4c Mon Sep 17 00:00:00 2001 From: Kevin Turner <83819+keturn@users.noreply.github.com> Date: Mon, 21 Aug 2023 16:40:07 -0700 Subject: [PATCH 3/3] doc(development): add section on hot reloading with --dev_reload --- docs/contributing/LOCAL_DEVELOPMENT.md | 14 ++++++++++++++ invokeai/app/api_app.py | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/docs/contributing/LOCAL_DEVELOPMENT.md b/docs/contributing/LOCAL_DEVELOPMENT.md index b0b03e42a4..f93ec56e96 100644 --- a/docs/contributing/LOCAL_DEVELOPMENT.md +++ b/docs/contributing/LOCAL_DEVELOPMENT.md @@ -75,6 +75,20 @@ pytest --cov; open ./coverage/html/index.html ![html-detail](../assets/contributing/html-detail.png) +### Reloading Changes + +Experimenting with changes to the Python source code is a drag if you have to re-start the server — +and re-load those multi-gigabyte models — +after every change. + +For a faster development workflow, add the `--dev_reload` flag when starting the server. +The server will watch for changes to all the Python files in the `invokeai` directory and apply those changes to the +running server on the fly. + +This will allow you to avoid restarting the server (and reloading models) in most cases, but there are some caveats; see +the [jurigged documentation](https://github.com/breuleux/jurigged#caveats) for details. + + ## Front End diff --git a/invokeai/app/api_app.py b/invokeai/app/api_app.py index 7ed2dedd44..e167e6903c 100644 --- a/invokeai/app/api_app.py +++ b/invokeai/app/api_app.py @@ -213,7 +213,7 @@ def invoke_api(): import jurigged except ImportError as e: logger.error( - "Can't start `--dev_reload` because jurigged is not found; `pip install -e '.[dev]'` to include development dependencies.", + 'Can\'t start `--dev_reload` because jurigged is not found; `pip install -e ".[dev]"` to include development dependencies.', exc_info=e, ) else: