# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Running the Services Each service runs independently and must be started separately: ```bash # Single-image edit service (port 12221) python change1/service1.py # Shirt-only try-on service (port 12222) python change2/service2.py # Shirt + pants try-on service (port 12223) python change3/service3.py # Gateway router (port 28888) — requires Flask python change_app.py ``` ComfyUI must be reachable at the URL configured in each service (currently `http://112.126.94.241:28188`, with `:38188` as backup). ## Dependencies ```bash pip install fastapi uvicorn httpx pydantic flask requests oss2 pillow ``` ## Architecture This is an AI virtual try-on / image-edit system built around ComfyUI, fronted by three FastAPI workers and a Flask gateway. ``` Client └─► change_app.py (Flask, port 28888) ← Gateway router ├─► change1/service1.py (FastAPI, 12221) ← single image (model only) ├─► change2/service2.py (FastAPI, 12222) ← model + shirt └─► change3/service3.py (FastAPI, 12223) ← model + shirt + pants └─► ComfyUI ``` **Gateway** (`change_app.py`): Accepts `POST /change_cloth_base64` with `human_img` (required) and optional `cloth_img` / `kuzi_img` / `change_desc`. Routing rules: - `kuzi_img` present → `service3` (12223) - `cloth_img` present (no `kuzi_img`) → `service2` (12222) - only `human_img` → `service1` (12221) All backends expose `POST /try-on` and return `{ "result_url": "" }`. The gateway wraps that into `{ "ret": 0, "state": 0, "msg": "success", "data": }`. **service1** (`change1/service1.py`): Single-image edit (e.g. background replacement, full-body generation from a reference). Exposes `POST /try-on` with `model_image` + optional `change_desc`. Uses ComfyUI workflow `change1.json`. **service2** (`change2/service2.py`): Shirt-only try-on. Exposes `POST /try-on` with `model_image` + `shirt_image` + optional `change_desc`. Uses ComfyUI workflow `change2_1_ex.json`. **service3** (`change3/service3.py`): Shirt + pants try-on. Exposes `POST /try-on` with `model_image` + `shirt_image` + `pants_image` + optional `change_desc`. Uses ComfyUI workflow `change2_2_0308.json`. ### ComfyUI Workflow Integration Each service dynamically modifies a JSON workflow template before submission: | Node ID | Purpose | service1 | service2 | service3 | |---------|---------|----------|----------|----------| | `"11"` | Model/person image (LoadImage) | ✓ | ✓ | ✓ | | `"10"` | Shirt image (LoadImage) | — | ✓ | ✓ | | `"4"` | Pants image (LoadImage) | — | — | ✓ | | `"31"` | Text prompt (PrimitiveStringMultiline, overridden when `change_desc` is non-empty) | ✓ | ✓ | ✓ | | `"33"` | Output image (SaveImage) | ✓ | ✓ | ✓ | The request flow within each service: 1. Pick a healthy ComfyUI host (primary, fallback to backup) 2. Decode base64 images 3. Upload images to ComfyUI (`/upload/image`) with UUID-prefixed filenames to avoid cache collisions 4. Inject filenames into workflow node inputs; if `change_desc` is non-empty, replace node `31` inputs with `{"value": change_desc}` 5. Submit workflow to ComfyUI queue (`/prompt`) 6. Poll `/history/{prompt_id}` until `status.completed` is true (max 300s timeout, 2s poll interval) 7. Download the result from `/view`, push it to Aliyun OSS, and return the signed URL ### Frontend Each service has its own test UI at `/` (served from `/static/index.html`): - `change1` UI: 1 upload card (model) + prompt panel - `change2` UI: 2 upload cards (model, shirt) + prompt panel - `change3` UI: 3 upload cards (model, shirt, pants) + prompt panel All three POST directly to the service's own `/try-on` endpoint.