diff --git a/CHANGELOG.md b/CHANGELOG.md index 95f23e3..2e3e3ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,27 @@ All notable changes to this project will be documented in this file. +## [1.3.0 - 2025-03-xx] + +This release contains breaking changes, first you need to uninstall old app **with its data removal** and after that install this version. + +## Added + +- Many flows were updated, some new flows were added. +- **Optional** remote token decoding using HuggingFace for some flows were added. +- `Surprise Me` - new feature to use LLM to create a random prompt. +- Many useful small UI additions(`Export flow`, `Editing flow` actions). +- Added support for `HaRP` deploy type - successor of `DSP`(Nextcloud 32+ only). + +## Changes + +- Visionatrix service has been updated from version `1.11.1` to `2.0.1`. +- Now Visionatrix **correctly stores all models and configs** in the configured ExApp storage and no more breaking changes expected. + +## Fixes + +- Fixed broken flows **Mad Scientist** and **PhotoStickers 2**. + ## [1.2.1 - 2025-02-23] The Visionatrix service has been updated from version `1.11.0` to `1.11.1`. diff --git a/Dockerfile b/Dockerfile index e61db7e..3e584cf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,8 +6,7 @@ ARG BUILD_TYPE ENV VIX_HOST="127.0.0.1" ENV VIX_PORT=8288 ENV USER_BACKENDS="vix_db;nextcloud" -ENV MODELS_DIR="/nc_app_visionatrix_data/vix_models" -ENV TASKS_FILES_DIR="/nc_app_visionatrix_data/vix_tasks_files" +ENV BASE_DATA_DIR="/nc_app_visionatrix_data" ENV VIX_SERVER_FULL_MODELS="1" RUN apt-get update && apt-get install -y git \ @@ -38,7 +37,7 @@ RUN cd /Visionatrix && \ echo "Installing PyTorch for ARM64"; \ venv/bin/python -m pip install torch==2.6.0 torchvision torchaudio; \ elif [ "$BUILD_TYPE" = "rocm" ]; then \ - venv/bin/python -m pip install torch==2.4.1 torchvision torchaudio --index-url https://download.pytorch.org/whl/rocm6.1; \ + venv/bin/python -m pip install torch==2.6.0 torchvision torchaudio --index-url https://download.pytorch.org/whl/rocm6.2.4; \ elif [ "$BUILD_TYPE" = "cpu" ]; then \ venv/bin/python -m pip install torch==2.6.0 torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu; \ else \ @@ -49,11 +48,7 @@ RUN cd /Visionatrix && \ RUN cd /Visionatrix && \ venv/bin/python -m pip install "psycopg[binary]" greenlet && \ venv/bin/python -m pip install . && \ - rm -rf ~/.cache/pip - -RUN cd /Visionatrix && \ - venv/bin/python -m visionatrix install && \ - AUTO_INIT_CONFIG_MODELS_DIR=$MODELS_DIR venv/bin/python scripts/easy_install.py && \ + venv/bin/python -m visionatrix install && \ rm visionatrix.db && \ rm -rf ~/.cache/pip @@ -80,7 +75,6 @@ RUN cd /Visionatrix && \ # Setup ExApp dependencies COPY ex_app_scripts/init_pgsql.sh /ex_app_scripts/init_pgsql.sh COPY ex_app_scripts/entrypoint.sh /ex_app_scripts/entrypoint.sh -COPY ex_app_scripts/run_visionatrix.sh /ex_app_scripts/run_visionatrix.sh RUN chmod +x /ex_app_scripts/*.sh @@ -99,7 +93,6 @@ WORKDIR /Visionatrix CMD ["/bin/sh", \ "/ex_app_scripts/entrypoint.sh", \ - "/ex_app/lib/main.py", \ - "/ex_app_scripts/run_visionatrix.sh"] + "/ex_app/lib/main.py"] HEALTHCHECK --interval=5s --timeout=2s --retries=300 CMD /healthcheck.sh diff --git a/appinfo/info.xml b/appinfo/info.xml index 55a6f3f..3ab8d2f 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -34,7 +34,7 @@ Share your custom workflows, big or small. For guidance on creating AI workflows 📚 For more details, visit the [repository](https://github.com/cloud-py-api/visionatrix) readme. ]]> - 1.2.1 + 1.3.0 MIT Andrey Borysenko Alexander Piskun @@ -55,7 +55,7 @@ Share your custom workflows, big or small. For guidance on creating AI workflows ghcr.io cloud-py-api/visionatrix - 1.11.1 + 2.0.1.dev0 diff --git a/ex_app/lib/main.py b/ex_app/lib/main.py index 921f3c8..663551f 100644 --- a/ex_app/lib/main.py +++ b/ex_app/lib/main.py @@ -22,7 +22,6 @@ from nc_py_api.ex_app import ( AppAPIAuthMiddleware, nc_app, - persistent_storage, run_app, setup_nextcloud_logging, ) @@ -43,8 +42,12 @@ # os.environ["APP_PORT"] = "24000" # os.environ["APP_ID"] = "visionatrix" # os.environ["APP_SECRET"] = "12345" # noqa +# os.environ["NC_DEV_SKIP_RUN"] = "1" # ---------Enf of configuration values for manual deploy--------- +SUPERUSER_NAME = "visionatrix_admin" +SUPERUSER_PASSWORD = "".join(random.choice(string.ascii_letters + string.digits) for i in range(10)) # noqa + SERVICE_URL = os.environ.get("VISIONATRIX_URL", "http://127.0.0.1:8288") logging.basicConfig( @@ -60,10 +63,7 @@ current_translator.set(translation(os.getenv("APP_ID"), LOCALE_DIR, languages=["en"], fallback=True)) ENABLED_FLAG = NextcloudApp().enabled_state -SUPERUSER_PASSWORD_PATH = Path(persistent_storage()).joinpath("superuser.txt") -SUPERUSER_NAME = "visionatrix_admin" -SUPERUSER_PASSWORD: str = "" -print(str(SUPERUSER_PASSWORD_PATH), flush=True) # for development only + INSTALLED_FLOWS = [] PROJECT_ROOT_FOLDER = Path(__file__).parent.parent.parent @@ -90,9 +90,9 @@ async def dispatch(self, request: Request, call_next): async def lifespan(_app: FastAPI): global SUPERUSER_PASSWORD + SUPERUSER_PASSWORD = os.environ["ADMIN_OVERRIDE"].split(":")[1] print(_("Visionatrix"), flush=True) setup_nextcloud_logging("visionatrix", logging_level=logging.WARNING) - SUPERUSER_PASSWORD = Path(SUPERUSER_PASSWORD_PATH).read_text() _t1 = asyncio.create_task(start_nextcloud_provider_registration()) # noqa _t2 = asyncio.create_task(start_nextcloud_tasks_polling()) # noqa yield @@ -285,16 +285,20 @@ def poll_tasks(nc: NextcloudApp, basic_auth: httpx.BasicAuth, webhook_url: str, if not reply_from_nc: return False task_info = reply_from_nc["task"] + data = { + "prompt": task_info["input"]["input"], + "batch_size": min(task_info["input"]["numberOfImages"], 4), + "webhook_url": webhook_url + f"/{task_info['id']}", + "webhook_headers": webhook_headers, + } + flow_name = reply_from_nc["provider"]["name"].removeprefix("v_") + if flow_name in ("flux1_dev", "flux1_schnell"): + data["diffusion_precision"] = "fp8_e4m3fn" with httpx.Client(base_url=f"{SERVICE_URL}/vapi") as client: vix_task = client.put( - url=f"/tasks/create/{reply_from_nc['provider']['name'].removeprefix('v_')}", + url=f"/tasks/create/{flow_name}", auth=basic_auth, - data={ - "prompt": task_info["input"]["input"], - "batch_size": min(task_info["input"]["numberOfImages"], 4), - "webhook_url": webhook_url + f"/{task_info['id']}", - "webhook_headers": webhook_headers, - }, + data=data, ) LOGGER.debug("task passed to visionatrix, return code: %s", vix_task.status_code) return True @@ -349,36 +353,48 @@ async def start_nextcloud_provider_registration(): await asyncio.to_thread(background_provider_registration) -def generate_random_string(length=10): - letters = string.ascii_letters + string.digits # You can include other characters if needed - return "".join(random.choice(letters) for i in range(length)) # noqa - - -def venv_run(command: str) -> None: - command = f". /Visionatrix/venv/bin/activate && {command}" - try: - print(f"executing(pwf={os.getcwd()}): {command}", flush=True) - subprocess.check_call(command, shell=True) - except subprocess.CalledProcessError as e: - print("An error occurred while executing command in venv:", str(e), flush=True) - raise - +def start_visionatrix() -> None: + if os.environ.get("NC_DEV_SKIP_RUN") != "1": + visionatrix_python = "/Visionatrix/venv/bin/python" + if os.environ.get("DISABLE_WORKER") != "1": + # Run server in background and redirect output to server.log + server_log = open("server.log", "wb") + subprocess.Popen( + [visionatrix_python, "-m", "visionatrix", "run", "--mode=SERVER"], + stdout=server_log, + stderr=subprocess.STDOUT, + ) + print("[DEBUG]: Launched Visionatrix server in background", flush=True) + # Wait a bit to let the server start up + sleep(15) + # Run worker in background and redirect output to worker.log + worker_log = open("worker.log", "wb") + subprocess.Popen( + [visionatrix_python, "-m", "visionatrix", "run", "--mode=WORKER", "--disable-smart-memory"], + stdout=worker_log, + stderr=subprocess.STDOUT, + ) + print("[DEBUG]: Launched Visionatrix worker in background", flush=True) + else: + # Only run server when worker is disabled + server_log = open("server.log", "wb") + subprocess.Popen( + [visionatrix_python, "-m", "visionatrix", "run", "--mode=SERVER"], + stdout=server_log, + stderr=subprocess.STDOUT, + ) + print("[DEBUG]: Launched Visionatrix server (worker disabled)", flush=True) -def initialize_visionatrix() -> None: while True: # Let's wait until Visionatrix opens the port. with contextlib.suppress(httpx.ReadError, httpx.ConnectError, httpx.RemoteProtocolError): r = httpx.get(SERVICE_URL) if r.status_code in (200, 204, 401, 403): break sleep(5) - if not SUPERUSER_PASSWORD_PATH.exists(): - password = generate_random_string() - # password = "12345" # uncomment this line and comment next for the developing with local Visionatrix version. - venv_run(f"python3 -m visionatrix create-user --name {SUPERUSER_NAME} --password {password}") - Path(SUPERUSER_PASSWORD_PATH).write_text(password) if __name__ == "__main__": - initialize_visionatrix() + os.environ["ADMIN_OVERRIDE"] = f"{SUPERUSER_NAME}:{SUPERUSER_PASSWORD}" + start_visionatrix() os.chdir(Path(__file__).parent) run_app("main:APP", log_level="trace") diff --git a/ex_app/lib/supported_flows.py b/ex_app/lib/supported_flows.py index bb752e6..38ccfcd 100644 --- a/ex_app/lib/supported_flows.py +++ b/ex_app/lib/supported_flows.py @@ -3,7 +3,7 @@ "juggernaut_lite", "playground_2_5_aesthetic", "stable_cascade", - "flux1_dev_8bit", - "flux1_schnell_8bit", + "flux1_dev", + "flux1_schnell", "hunyuan_dit", ] diff --git a/ex_app_scripts/run_visionatrix.sh b/ex_app_scripts/run_visionatrix.sh deleted file mode 100644 index 4a25614..0000000 --- a/ex_app_scripts/run_visionatrix.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -. /etc/environment - -if [ "$DISABLE_WORKER" != "1" ]; then - /Visionatrix/venv/bin/python -m visionatrix run --mode=SERVER > /server.log 2>&1 & - sleep 15 - /Visionatrix/venv/bin/python -m visionatrix run --mode=WORKER --disable-smart-memory > /worker.log 2>&1 -else - VIX_SERVER_FULL_MODELS=0 /Visionatrix/venv/bin/python -m visionatrix run --mode=SERVER > /server.log 2>&1 -fi diff --git a/pyproject.toml b/pyproject.toml index 162ff78..8f5add4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,8 +6,8 @@ preview = true [tool.ruff] line-length = 120 target-version = "py310" -select = ["A", "B", "C", "E", "F", "G", "I", "S", "SIM", "PIE", "Q", "RET", "RUF", "UP" , "W"] -extend-ignore = ["I001", "RUF100", "D400", "D415", "S602"] +lint.select = ["A", "B", "C", "E", "F", "G", "I", "S", "SIM", "PIE", "Q", "RET", "RUF", "UP" , "W"] +lint.extend-ignore = ["I001", "RUF100", "D400", "D415", "S602", "S603", "SIM115"] [tool.isort] profile = "black" diff --git a/requirements.txt b/requirements.txt index e2ee84c..ccac244 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ -nc-py-api[app]>=0.16.0 +nc-py-api[app]>=0.19.1 anyio==4.6.2