mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(dev_reload): use jurigged to hot reload changes to Python source (#4313)
This commit is contained in:
commit
6b462f2ed5
@ -35,18 +35,17 @@ access.
|
|||||||
|
|
||||||
## Backend
|
## Backend
|
||||||
|
|
||||||
The backend is contained within the `./invokeai/backend` folder structure. To
|
The backend is contained within the `./invokeai/backend` and `./invokeai/app` directories.
|
||||||
get started however please install the development dependencies.
|
To get started please install the development dependencies.
|
||||||
|
|
||||||
From the root of the repository run the following command. Note the use of `"`.
|
From the root of the repository run the following command. Note the use of `"`.
|
||||||
|
|
||||||
```zsh
|
```zsh
|
||||||
pip install ".[test]"
|
pip install ".[dev,test]"
|
||||||
```
|
```
|
||||||
|
|
||||||
This in an optional group of packages which is defined within the
|
These are optional groups of packages which are defined within the `pyproject.toml`
|
||||||
`pyproject.toml` and will be required for testing the changes you make the the
|
and will be required for testing the changes you make to the code.
|
||||||
code.
|
|
||||||
|
|
||||||
### Running Tests
|
### Running Tests
|
||||||
|
|
||||||
@ -76,6 +75,20 @@ pytest --cov; open ./coverage/html/index.html
|
|||||||
|
|
||||||
![html-detail](../assets/contributing/html-detail.png)
|
![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
|
## Front End
|
||||||
|
|
||||||
<!--#TODO: get input from blessedcoolant here, for the moment inserted the frontend README via snippets extension.-->
|
<!--#TODO: get input from blessedcoolant here, for the moment inserted the frontend README via snippets extension.-->
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
# Copyright (c) 2022-2023 Kyle Schouviller (https://github.com/kyle0654) and the InvokeAI Team
|
# Copyright (c) 2022-2023 Kyle Schouviller (https://github.com/kyle0654) and the InvokeAI Team
|
||||||
import asyncio
|
import asyncio
|
||||||
from inspect import signature
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import uvicorn
|
|
||||||
import socket
|
import socket
|
||||||
|
from inspect import signature
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import uvicorn
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
from fastapi.middleware.cors import CORSMiddleware
|
from fastapi.middleware.cors import CORSMiddleware
|
||||||
from fastapi.openapi.docs import get_redoc_html, get_swagger_ui_html
|
from fastapi.openapi.docs import get_redoc_html, get_swagger_ui_html
|
||||||
@ -13,7 +13,6 @@ from fastapi.openapi.utils import get_openapi
|
|||||||
from fastapi.staticfiles import StaticFiles
|
from fastapi.staticfiles import StaticFiles
|
||||||
from fastapi_events.handlers.local import local_handler
|
from fastapi_events.handlers.local import local_handler
|
||||||
from fastapi_events.middleware import EventHandlerASGIMiddleware
|
from fastapi_events.middleware import EventHandlerASGIMiddleware
|
||||||
from pathlib import Path
|
|
||||||
from pydantic.schema import schema
|
from pydantic.schema import schema
|
||||||
|
|
||||||
from .services.config import InvokeAIAppConfig
|
from .services.config import InvokeAIAppConfig
|
||||||
@ -30,9 +29,12 @@ from .api.sockets import SocketIO
|
|||||||
from .invocations.baseinvocation import BaseInvocation, _InputField, _OutputField, UIConfigBase
|
from .invocations.baseinvocation import BaseInvocation, _InputField, _OutputField, UIConfigBase
|
||||||
|
|
||||||
import torch
|
import torch
|
||||||
|
|
||||||
|
# noinspection PyUnresolvedReferences
|
||||||
import invokeai.backend.util.hotfixes # noqa: F401 (monkeypatching on import)
|
import invokeai.backend.util.hotfixes # noqa: F401 (monkeypatching on import)
|
||||||
|
|
||||||
if torch.backends.mps.is_available():
|
if torch.backends.mps.is_available():
|
||||||
|
# noinspection PyUnresolvedReferences
|
||||||
import invokeai.backend.util.mps_fixes # noqa: F401 (monkeypatching on import)
|
import invokeai.backend.util.mps_fixes # noqa: F401 (monkeypatching on import)
|
||||||
|
|
||||||
|
|
||||||
@ -40,7 +42,6 @@ app_config = InvokeAIAppConfig.get_config()
|
|||||||
app_config.parse_args()
|
app_config.parse_args()
|
||||||
logger = InvokeAILogger.getLogger(config=app_config)
|
logger = InvokeAILogger.getLogger(config=app_config)
|
||||||
|
|
||||||
|
|
||||||
# fix for windows mimetypes registry entries being borked
|
# fix for windows mimetypes registry entries being borked
|
||||||
# see https://github.com/invoke-ai/InvokeAI/discussions/3684#discussioncomment-6391352
|
# see https://github.com/invoke-ai/InvokeAI/discussions/3684#discussioncomment-6391352
|
||||||
mimetypes.add_type("application/javascript", ".js")
|
mimetypes.add_type("application/javascript", ".js")
|
||||||
@ -208,6 +209,17 @@ def invoke_api():
|
|||||||
|
|
||||||
check_invokeai_root(app_config) # note, may exit with an exception if root not set up
|
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)
|
port = find_port(app_config.port)
|
||||||
if port != app_config.port:
|
if port != app_config.port:
|
||||||
logger.warn(f"Port {app_config.port} in use, using port {port}")
|
logger.warn(f"Port {app_config.port} in use, using port {port}")
|
||||||
|
@ -169,11 +169,13 @@ two configs are kept in separate sections of the config file:
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import os
|
import os
|
||||||
from omegaconf import OmegaConf, DictConfig
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from typing import ClassVar, Dict, List, Literal, Union, get_type_hints, Optional
|
||||||
|
|
||||||
|
from omegaconf import OmegaConf, DictConfig
|
||||||
from pydantic import Field, parse_obj_as
|
from pydantic import Field, parse_obj_as
|
||||||
from typing import ClassVar, Dict, List, Literal, Union, Optional, get_type_hints
|
|
||||||
|
|
||||||
from .base import InvokeAISettings
|
from .base import InvokeAISettings
|
||||||
|
|
||||||
@ -233,6 +235,8 @@ class InvokeAIAppConfig(InvokeAISettings):
|
|||||||
log_format : Literal['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_format : Literal['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["debug", "info", "warning", "error", "critical"] = Field(default="info", description="Emit logging messages at this level or higher", category="Logging")
|
log_level : Literal["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")
|
version : bool = Field(default=False, description="Show InvokeAI version and exit", category="Other")
|
||||||
|
|
||||||
# CACHE
|
# CACHE
|
||||||
|
@ -93,6 +93,7 @@ dependencies = [
|
|||||||
"mkdocs-redirects==1.2.0",
|
"mkdocs-redirects==1.2.0",
|
||||||
]
|
]
|
||||||
"dev" = [
|
"dev" = [
|
||||||
|
"jurigged",
|
||||||
"pudb",
|
"pudb",
|
||||||
]
|
]
|
||||||
"test" = [
|
"test" = [
|
||||||
|
Loading…
Reference in New Issue
Block a user