| # Serverless client scripts |
|
|
| Standalone callers (Python 3.8+, stdlib only β no pip installs) for the |
| deployed RunPod endpoints. Each endpoint has a sync script (`/runsync`, blocks |
| until done) and an async one (`/run` β submit, poll, fire-and-forget with |
| `--no-wait`, collect with `--job-id`, `--cancel`). |
|
|
| | endpoint | id | sync | async | workflow copy | |
| |---|---|---|---|---| |
| | qwen-edit-turbo | `dom5lwr0o5wq6u` | `qwen_edit_sync.py` | `qwen_edit_async.py` | `qwen-edit-turbo-v4.json` | |
| | qwen-edit-nsfw | `tplcz9jtzihoxa` | `qwen_edit_nsfw_sync.py` | `qwen_edit_nsfw_async.py` | `qwen-edit-nsfw.json` | |
| | faceswap-lissie | `qkeibkeoefcrk3` | `faceswap_lissie_sync.py` | `faceswap_lissie_async.py` | `new-faceswap-lissie-v4.json` | |
|
|
| Endpoint ids are baked in as defaults; override with `--endpoint-id`. Auth via |
| `--api-key` or `RUNPOD_API_KEY` env. Results are saved into `--out` (default |
| `.`); the seed used is always printed so runs are reproducible with `--seed`. |
|
|
| ## Examples |
|
|
| ```bash |
| export RUNPOD_API_KEY=... |
| |
| # turbo outfit transfer (two images) |
| python qwen_edit_sync.py --image person.jpg --ref-image outfit.png \ |
| --prompt "replace the outfit of the person in image 1 with the outfit in image 2" \ |
| --mode turbo-8 --out ./results |
| |
| # nsfw single-image edit, 8 steps |
| python qwen_edit_nsfw_sync.py --image person.jpg \ |
| --prompt "replace the outfit with ..." --out ./results |
| |
| # head swap: face from face.jpg onto scene.jpg |
| python faceswap_lissie_sync.py --body-image scene.jpg --face-image face.jpg \ |
| --out ./results |
| |
| # any of them, fire-and-forget |
| job=$(python qwen_edit_nsfw_async.py --image a.jpg --prompt "..." --no-wait) |
| python qwen_edit_nsfw_async.py --job-id "$job" --out ./results |
| ``` |
|
|
| ## Common arguments (all scripts) |
|
|
| `--api-key`, `--endpoint-id`, `--seed`, `--out`, `--timeout`, |
| `--set NODE.INPUT=VALUE` (raw graph override, repeatable), |
| `--workflow NAME` (another workflow baked in that image), |
| `--workflow-json FILE` (**full custom API-format graph** β the endpoints are |
| workflow-agnostic; uploaded images are matched to your graph's `LoadImage` |
| nodes by filename). Async extras: `--no-wait`, `--job-id`, `--poll`, `--cancel`. |
|
|
| Per-endpoint knobs are documented in each script's `--help`; the full |
| param-name β node mapping lives in `../endpoints/<endpoint>/params/`. |
|
|
| ## Expectations (measured 2026-07-23/24, H100) |
|
|
| | endpoint | warm exec | notes | |
| |---|---|---| |
| | qwen-edit-turbo | turbo-4 β 29-42 s, turbo-8 β 60 s | 2048px, 2560px output upscale | |
| | qwen-edit-nsfw | β 32 s @ 8 steps, 1 MP | webp output | |
| | faceswap-lissie | β 11 s @ 5 steps | VL captioner kept in VRAM | |
|
|
| Cold starts: FlashBoot resume β 0.5 s delay with models still in VRAM; a |
| brand-new host pays a one-time image pull (~10-15 min) then ~1-2 min of model |
| loading on the first job. Payload limits ~10 MB (`/run`) / ~20 MB (`/runsync`) |
| with base64 adding ~33% β keep inputs under ~7 MB combined or use async. |
|
|
| Raw HTTP shape (same for all endpoints): |
|
|
| ```bash |
| curl -s -X POST "https://api.runpod.ai/v2/<ENDPOINT_ID>/runsync" \ |
| -H "Authorization: Bearer $RUNPOD_API_KEY" -H "Content-Type: application/json" \ |
| -d '{"input": {"images": [{"name": "a.jpg", "image": "<base64>"}], |
| "params": {"prompt": "..."}}}' |
| ``` |
|
|