147 lines
5.2 KiB
Markdown
147 lines
5.2 KiB
Markdown
# 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` to `docker/.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 at `http://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.
|
|
|
|
```python
|
|
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...
|
|
|
|
```python
|
|
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.
|
|
|
|
```python
|
|
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 workflows
|
|
- `GET /workflows/by-handle` - List workflows sorted by handle
|
|
- `GET /workflows/{workflow_id}` - Get workflow information
|
|
- `GET /workflows/{workflow_id}/image` - Generate image using specified workflow
|
|
- `GET /workflows/by-handle/{handle}/image` - Generate image using workflow handle
|
|
- `GET /workflows/{workflow_id}/image/{seed}` - Generate image with specific seed
|
|
|