# OpenAI-Compatible HTTP Adapter for ComfyUI

Small FastAPI bridge that exposes `POST /v1/images/generations` (OpenAI format) and maps it to ComfyUI's `POST /api/prompt`.

## When to use

- OpenWebUI, Bifrost, or any other tool that speaks OpenAI `/v1/images/generations` needs to generate images with ComfyUI.
- ComfyUI itself has no native OpenAI-compatible endpoint.
- The adapter is especially useful for **FLUX.2 workflows** that OpenWebUI's built-in ComfyUI connector cannot handle (different nodes: Qwen3VL, `EmptyFlux2LatentImage`, TAEF2).

## Architecture

```
OpenWebUI / Bifrost / Client
   POST /v1/images/generations
            |
            v
   [FastAPI Adapter]  (Docker or systemd)
            |
            v
   POST http://<comfyui>:8188/api/prompt
   GET  http://<comfyui>:8188/history/<prompt_id>
   GET  http://<comfyui>:8188/view
```

## Example: Minimal FLUX.2 Adapter (Docker)

### `Dockerfile`

```dockerfile
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY adapter.py .
EXPOSE 9000
CMD ["uvicorn", "adapter:app", "--host", "0.0.0.0", "--port", "9000"]
```

### `requirements.txt`

```
fastapi>=0.110.0
uvicorn>=0.29.0
httpx>=0.27.0
pydantic>=2.0.0
```

### `adapter.py` — FLUX.2 Variant

The node names must match what is installed on the target ComfyUI instance.
Query the running server first with `GET /object_info` to confirm.

Key requirements for FLUX.2:
- `CLIPLoaderGGUF` with `"type": "flux2"` (loads Qwen3VL)
- `EmptyFlux2LatentImage` (128-channel latents)
- `VAELoader` with `"vae_name": "taef2"` (or dedicated `flux2_vae.safetensors`)
- `UnetLoaderGGUF` with the FLUX.2 UNet GGUF

See `scripts/adapter_flux2.py` for a ready-to-use file.

### Build & run

```bash
docker build -t comfyui-openai-adapter:latest .
docker run -d --name comfyui-openai-adapter --network host \
  -e COMFYUI_URL=http://10.0.30.97:8188 \
  -e WORKFLOW_PREFIX=oai_adapter \
  --restart unless-stopped \
  comfyui-openai-adapter:latest
```

## Verifying node availability

Before deploying the adapter, confirm the target ComfyUI instance has the required nodes:

```bash
curl -s http://<comfyui>:8188/object_info | \
  python3 -c "import sys,json; d=json.load(sys.stdin); \
  [print(f'{n}: {n in d}') for n in \
  ['CLIPLoaderGGUF','UnetLoaderGGUF','EmptyFlux2LatentImage','VAELoader','KSampler']]"
```

## OpenWebUI configuration

Admin Panel → Settings → Images → Image Generation

| Setting | Value |
|---------|-------|
| Engine | `Open AI` |
| API Base URL | `http://<adapter-ip>:9000/v1` |
| API Key | dummy (adapter does not enforce auth) |
| Model | `flux2` |

## Bifrost integration

Bifrost is an LLM gateway with no native ComfyUI provider. The adapter fills that gap:
- Register the adapter as an OpenAI-compatible provider in Bifrost, or
- Point OpenWebUI directly at the adapter (recommended; keeps image path separate from chat routing).

## Pitfalls

1. **Node names are exact.** Use `GET /object_info` to verify every `class_type` exists; missing custom nodes produce cryptic "class_type not found" errors from ComfyUI.
2. **Model names are exact and case-sensitive.** `flux-2-klein-9b-Q4_K_S.gguf` != `flux-2-klein-9b-q4_k_s.gguf`.
3. **TAEF2 vs full VAE.** `taef2` resolves tiny encoder/decoder `pth` files; the full `flux2_vae.safetensors` requires manual download from a gated repo.
4. **Seed injection.** Always rewrite the seed per image when `n > 1`; otherwise every image in the batch is identical.
5. **Timeout tuning.** FLUX.2 on ROCm gfx1150 takes ~110s for 1024x1024 @ 4 steps. Set `wait_for_image` timeout >= 300s.
