FLUX 3 Image Klein Distilled: Image Edit
Edit a photo with distilled FLUX 3 Image Klein: one input image, one prompt, 16 steps, plus a before/after comparison.
Inside the workflow
A read-only preview of the source template. Open it in Cloud to explore the nodes and make changes.
Loading the graph
Open full-size workflow preview- Output
- Image
- Author
- Author unavailable
Call this model from your code
The request below uses the same prepared graph and settings as the Playground. Each submission can start a paid run; do not automatically retry a submission whose outcome is unknown.
What you need
- Runs on
- Comfy Cloud
- Key
- COMFY_API_KEY
- Your files
- Uploaded by the code from their urls
Needs a paid Cloud plan and credits.
# Python 3.10+: pip install comfy-sdk==0.4.0
import os
from comfy_sdk import Comfy
api_key = os.environ.get("COMFY_API_KEY", "").strip()
if not api_key: raise RuntimeError("Set COMFY_API_KEY")
os.environ.setdefault("COMFY_BASE_URL", "https://cloud.comfy.org")
client = Comfy(api_key=api_key)
workflow = client.workflows.from_json({
"1": {
"class_type": "UNETLoader",
"inputs": {
"unet_name": "flux3-image-klein-int8-convrot.safetensors",
"weight_dtype": "default"
},
"_meta": {
"title": "Load Diffusion Model"
}
},
"2": {
"class_type": "CLIPLoader",
"inputs": {
"clip_name": "qwen3vl_4b_int8_convrot.safetensors",
"device": "default",
"type": "flux3"
},
"_meta": {
"title": "Load CLIP"
}
},
"3": {
"class_type": "VAELoader",
"inputs": {
"vae_name": "flux2-vae.safetensors"
},
"_meta": {
"title": "Load VAE"
}
},
"4": {
"class_type": "CLIPTextEncode",
"inputs": {
"clip": [
"2",
0
],
"text": [
"52",
0
]
},
"_meta": {
"title": "Positive Prompt"
}
},
"7": {
"class_type": "KSampler",
"inputs": {
"cfg": 1,
"denoise": 1,
"latent_image": [
"17",
2
],
"model": [
"1",
0
],
"negative": [
"17",
1
],
"positive": [
"17",
0
],
"sampler_name": "euler",
"scheduler": "simple",
"seed": 563228241303057,
"steps": 16
},
"_meta": {
"title": "KSampler"
}
},
"8": {
"class_type": "VAEDecode",
"inputs": {
"samples": [
"7",
0
],
"vae": [
"3",
0
]
},
"_meta": {
"title": "VAE Decode"
}
},
"9": {
"class_type": "SaveImage",
"inputs": {
"filename_prefix": "image_flux3_klein_distilled_image_edit",
"images": [
"8",
0
]
},
"_meta": {
"title": "Save Image"
}
},
"11": {
"class_type": "LoadImage",
"inputs": {
"image": "UPLOADED_image1_FILENAME"
},
"_meta": {
"title": "Load Image"
}
},
"17": {
"class_type": "ReferenceMultiLatent",
"inputs": {
"images.image0": [
"11",
0
],
"negative": [
"32",
0
],
"positive": [
"4",
0
],
"resolution": "resize",
"resolution.megapixels": 1,
"vae": [
"3",
0
]
},
"_meta": {
"title": "Set Reference Multi Latent"
}
},
"18": {
"class_type": "ImageCompare",
"inputs": {
"compare_view": None,
"image_a": [
"11",
0
],
"image_b": [
"9",
0
]
},
"_meta": {
"title": "Compare Images"
}
},
"32": {
"class_type": "ConditioningZeroOut",
"inputs": {
"conditioning": [
"4",
0
]
},
"_meta": {
"title": "Conditioning Zero Out"
}
},
"33": {
"class_type": "CreateBoundingBoxes",
"inputs": {
"background": [
"11",
0
],
"editor_state": {
"__value__": []
},
"height": 752,
"last_incoming": {
"__value__": [
{
"height": 224,
"metadata": {
"desc": "earring",
"palette": [],
"text": "",
"type": "obj"
},
"width": 224,
"x": 512,
"y": 288
}
]
},
"width": 1360
},
"_meta": {
"title": "Create Bounding Boxes"
}
},
"34": {
"class_type": "PreviewAny",
"inputs": {
"source": [
"49",
0
]
},
"_meta": {
"title": "Preview as Text"
}
},
"44": {
"class_type": "EmptyFlux2LatentImage",
"inputs": {
"batch_size": 1,
"height": 1024,
"width": 1024
},
"_meta": {
"title": "Empty Flux 2 Latent"
}
},
"46": {
"class_type": "CLIPLoader",
"inputs": {
"clip_name": "qwen3.5_9b_flux3_prompt_upsampler_w4a8.safetensors",
"device": "default",
"type": "flux3"
},
"_meta": {
"title": "Load CLIP"
}
},
"47": {
"class_type": "TextGenerate",
"inputs": {
"clip": [
"46",
0
],
"image": [
"50",
0
],
"max_length": 3584,
"mtp": "off",
"prompt": [
"34",
0
],
"sampling_mode": "on",
"sampling_mode.min_p": 0,
"sampling_mode.presence_penalty": 0,
"sampling_mode.repetition_penalty": 1.05,
"sampling_mode.seed": 0,
"sampling_mode.temperature": 1,
"sampling_mode.top_k": 1,
"sampling_mode.top_p": 0.95,
"system_prompt": [
"48",
0
],
"thinking": False,
"use_default_template": True
},
"_meta": {
"title": "Generate Text"
}
},
"48": {
"class_type": "PrimitiveStringMultiline",
"inputs": {
"value": "You are the prompt upsampler of an image-editing model. You see the reference image(s), attached in order (the first image, the second image, ...), and the user's short request. Expand it into ONE detailed, self-contained instruction: the caption the editing model receives together with the same images. Output only the instruction as one continuous English prose block, with no greetings, explanations, Markdown, JSON, coordinates, ids or angle-bracket tokens. Read a vague or conversational request as the most plausible edit of the supplied images.\\n\\nPick the voice by task shape. When one reference stays and gets bounded changes, write an imperative editing instruction on it (\\\"Remove the ...\\\", \\\"Change the ... to ...\\\", \\\"Zoom in on ...\\\"); a whole-image transformation opens with its scope (\\\"Convert the entire image into ...\\\", \\\"Apply a ... filter over the entire scene\\\", \\\"Horizontally flip the entire image so that ...\\\", \\\"Shift the camera viewpoint to ...\\\", then where the major elements should now be). When the references are drawn into a newly composed frame (combining subjects, a new scene, a garment, object or style donor), write a generation request (\\\"Create a photograph of ...\\\", \\\"Create an anime-style illustration of ...\\\", \\\"Generate a new image featuring ...\\\") that says what to take from each image, by ordinal, and what is newly generated.\\n\\nKeep every explicit edit, constraint, count, position, style cue and piece of wording, and decide what is left open as one concrete plan. Ground everything in what is actually visible: identify each referent unambiguously by its real appearance, never mention content that is not there, and use every image the user attached. State every end state concretely (which color, how large, which pose, which material) and give new content enough appearance to be generated. Cover the knock-on effects of the change (shadows, reflections, occlusion, perspective, scale, lighting) and say what fills a removed region. A zoom-in names what stays in frame and which neighbors are cropped out; an outpainting continues the scene in the same medium. Describe the change, not the whole scene, and close an editing instruction with one compact clause naming what stays unchanged; transferred people keep their identity, face and accessories unless asked otherwise. Transcribe on-image text verbatim in its original language inside double quotes, with line breaks as \\\\n, and match the original font, size and color when replacing it. Name recognizable public figures, brands and landmarks you can see. Directions are frame-relative; use no evaluative or quality words. Typical length is 50 to 150 words.\\n\\nOutput only the instruction."
},
"_meta": {
"title": "Text (System prompt)"
}
},
"49": {
"class_type": "Flux3LayoutPrompt",
"inputs": {
"element": [
"33",
2
],
"prompt": "In <ref_image_0>, replace the layered gold statement earring with a single sculptural earring in brushed matte silver: one curved crescent plate with a fine engraved line along its edge, sitting on the same ear at the same size and angle, catching the light the way the gold one did. Keep her profile, braided hair, skin tone, lip texture and the teal turtleneck exactly as they are, and leave the warm sand-coloured wall and the soft window light untouched. Match the existing shadow under the jaw and the highlight along the shoulder. Photorealistic jewellery detail, clean edges, no extra jewellery, no text."
},
"_meta": {
"title": "FLUX 3 Image Layout Prompt"
}
},
"50": {
"class_type": "BatchImagesNode",
"inputs": {
"images.image0": [
"11",
0
]
},
"_meta": {
"title": "Batch Images"
}
},
"51": {
"class_type": "ComfySwitchNode",
"inputs": {
"on_false": [
"47",
0
],
"on_true": [
"34",
0
],
"switch": False
},
"_meta": {
"title": "If/Else Switch"
}
},
"52": {
"class_type": "PreviewAny",
"inputs": {
"source": [
"51",
0
]
},
"_meta": {
"title": "Preview as Text"
}
}
})
workflow.set_input("11", "image", client.assets.from_url("https://comfy.org/catalog-media/26100fc3-3ef0-466e-a5f5-8b72916e5aba/56143c66-1f38-4181-ae7c-ad1d581a72f9"))
# run() also passes api_key to the partner nodes in this workflow.
job = client.run(workflow, api_key=api_key)
for output in job.get_outputs("9"):
output.to_file(output.name)Try an example
About this workflow
Distilled counterpart of the FLUX 3 Image Klein edit template. Int8 distilled weights sample in 16 steps at cfg 1 with ConditioningZeroOut on the negative branch, ReferenceMultiLatent resizes the input, and ImageCompare shows the original beside the edit. The qwen3.5 9B prompt upsampler rewrites a short request into a full instruction and CreateBoundingBoxes marks the area to change, so a one-line edit still lands where you mean.