comfykiosk/readme.md

5.2 KiB

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.

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 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