comfykiosk | ||
docker | ||
frontend | ||
sample-workflows | ||
.dockerignore | ||
.gitignore | ||
readme.md | ||
requirements.txt | ||
sample-advanced.py | ||
sample.py | ||
workflow.json |
ComfyKiosk
A "kiosk-mode" interface for ComfyUI workflows, with built-in image caching and workflow management capabilities.
In short, allows you to expose a ComfyUI server with very fine-grained control over what can be generated with it.
Features
- (Optional) FastAPI-based HTTP interface for image generation
- Image caching and storage management
- Seed-based deterministic image generation
Coming in v0.2
- Tags - Group workflows, generate randomly from a single endpoint
- Templating - Mark parameters in the workflow to be randomized with each request
Installation
Docker
docker build -t comfykiosk ./docker/Dockerfile
should create an image with the library and sample.py
Not Docker
Create a venv
with Python 3.12 and install all required packages
python3.12 -m venv .venv && source .venv/bin/activate && pip install -r requirements.txt
Quick Start
Docker
- Copy
docker/.env.template
todocker/.env
- You will almost certainly need to change
COMFYUI_URL
- Run
docker compose -f ./docker/sample-docker-compose.yml up
- Assuming the defaults and the sample
docker-compose.yml
, you should be able to generate an image athttp://localhost:8000/workflows/1/image
Not Docker
A helper function is provided for making a dead-simple application that hosts a single workflow or directory of workflows. Requests are proxied directly to the ComfyUI server, with no caching.
This is likely unsuitable for public use, but is the absolute fastest way to get started.
It's also almost exactly what sample-docker-compose.yml
is doing.
from comfykiosk import EasyComfyKiosk
from comfykiosk.fastapi import create_app
# Create the image generation service
comfy = EasyComfyKiosk()
# Attach FastAPI routes to it
app = create_app(comfy)
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="127.0.0.1", port=8000)
By default, it will look for workflows in a directory called ./workflows
,
or a single workflow at ./workflow.json
, but you can specify the path yourself...
comfy = EasyComfyKiosk(path="./custom_workflows")
When a directory of workflows is loaded, their handle
is based on the filename.
Run the app:
python ./sample.py
Optionally, specify where to find the ComfyUI server:
COMFYUI_URL=127.0.0.1:8188 python ./sample.py
Open a browser and navigate to http://127.0.0.1:8000/workflows
to see the available workflows.
To actually generate images, navigate to http://127.0.0.1:8000/workflows/{workflow_id}/image
or http://127.0.0.1:8000/workflows/by-handle/{handle}/image
Advanced Usage
This example can be found in sample-advanced.py
and docker/advanced-sample-docker-compose.yml
Let's create a webapp with a folder of workflows, and let users generate from any of them. So they don't need to wait, we'll generate a few images from each, ahead of time. When someone asks for a "new" image, it will be served from that buffer.
We'll also use a filesystem cache to avoid re-generating images that have already been generated.
from comfykiosk import ComfyKiosk, ComfyGenerator, SimpleWorkflowLoader
from comfykiosk.image_sources.filesystem import FileSystemImageSource
from comfykiosk.image_sources.pregenerate import PreparedGenPool
from comfykiosk.fastapi import create_app
# You can compose ComfyKiosk as an alternate way to override defaults
filesystem_source = FileSystemImageSource(directory="./output")
comfyui_backend = ComfyGenerator()
# You can also use the default workflow loader
loader = SimpleWorkflowLoader(directory="./sample-workflows")
# In this example, each workflow can have up to 10 prepared images.
# The generator will make 5 images before switching workflows.
# This is to amortize the time spent loading models into VRAM.
pregen_pool = PreparedGenPool(bucket_max=10, batch_size=5, generator=comfyui_backend, saver=filesystem_source)
# When a request comes in, each image source will be tried in this order.
comfy = ComfyKiosk(loaders=loader,
image_sources=[filesystem_source, pregen_pool])
# Attach FastAPI routes to it
app = create_app(comfy)
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000, log_level="info", log_config=None # Use our logging config instead of uvicorn's)
Creating Workflows
From ComfyUI, use the "Export (API)" option in the Workflow menu. There must be exactly one "Save Image" node in the graph.
At the moment ComfyKiosk only changes the seed. The eventual goal is to allow you to specify which paramaters can be changed, and the allowed range of those choices.
In the absense of user input, any changeable parameters will be deterministically selected based on the request seed.
API Endpoints
Given that this is a FastAPI app, you can also view the API docs as generated by Swagger at /docs
.
GET /workflows
- List all available workflowsGET /workflows/by-handle
- List workflows sorted by handleGET /workflows/{workflow_id}
- Get workflow informationGET /workflows/{workflow_id}/image
- Generate image using specified workflowGET /workflows/by-handle/{handle}/image
- Generate image using workflow handleGET /workflows/{workflow_id}/image/{seed}
- Generate image with specific seed