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