arkennemasis fal · Flux 2 Klein 9B Edit LoRA · $0.015/MP
Edit a photo with your own LoRA, on someone else's GPU
- image_1
- image_2
- image_3
- image_4
- image_5
- image_6
- images
- image_paths
- timings
- has_nsfw_concepts
- seed
- prompt
- info
This is the same FLUX.2 [klein] 9B editor as the plain Edit node, with one extra field: a JSON list of LoRAs that fal will load on top before your instruction runs. The use case is narrow and real - you trained something on Klein 9B, or you're renting a style LoRA off the hub, and you want that applied while you edit rather than trying to describe it in prose.
Why the LoRA slot exists
Klein is the reason a lot of people stopped maintaining separate generate and edit checkpoints - one model does text-to-image, single-reference and multi-reference editing. The LoRA ecosystem followed it, and it's livelier than Flux 2 Dev's ever was, because Klein actually trains on consumer cards: roughly 14GB for the 9B in int8, ~22GB in bf16. The published LoRAs mostly target klein-base-9B and then get applied to the distilled 9B at inference - which is exactly what this node does.
The two things worth remembering from the KB: 4B and 9B LoRAs are not interchangeable, and Klein tolerates stacking better than Z-Image Turbo - three LoRAs at strength 1.0 each is a documented working recipe here, not a meltdown.
Inputs
image_1 (plus sockets up to image_6; four pictures maximum across all of them, batches counted in socket order) is what you're editing. prompt is the instruction - write it as an action on the file, not a description of a scene you'd like to see, or the model drifts into generator mode and reinvents your subject.
loras is fal's own JSON field, passed through as typed: a list of up to three, where each entry can be a URL, a HuggingFace repo ID, or a local path. Leave it empty and the field is omitted entirely. There's no picker and no scale box on the node, so the JSON is on you - and if fal's schema grows a field this node doesn't expose, extra_json merges a raw object into the request last.
The rest is Klein distilled being Klein distilled: num_inference_steps 4–8 (default 4 - use 8), image_size defaulting to square_hd so an unedited aspect ratio comes back square, num_images 1–4 which multiplies the bill, seed at -1 meaning the model picks, output_format, and enable_safety_checker on by default with flagged output returned as black images.
max_cost_usd ($20 default) is a genuine pre-flight cap: if the estimate is above it, the node stops before uploading anything. reuse_identical_run fingerprints the settings and the bytes of your pictures, so an identical re-run comes back from the ledger for free. max_concurrent keeps paid fal calls serialised unless you raise it.
Outputs
images is your edited image as a normal IMAGE batch - save it, upscale it, mask it. image_paths is the on-disk location, seed lets you reproduce a take, prompt passes the instruction through, timings and has_nsfw_concepts are fal's scalars, and info is the JSON record with request id, estimate and the full answer. That last one is the only place you'll see what you actually paid.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/Hishamahmer/comfyui-arkennemasis
Restart ComfyUI and add your key to the .env beside run_nvidia_gpu.bat:
FAL_KEY=your-key-from-fal.ai/dashboard/keys
No pip install is needed for the fal nodes - that provider runs on the standard library. Manager install works too: search the pack title, or paste the repo URL via Install via Git URL.
Where people get burned
The most common one is a LoRA that does nothing: a 4B LoRA on a 9B endpoint, or a Flux.1 LoRA on Flux 2. Architecture incompatibility is absolute, so check the base before you blame the node. Second: LoRAs are billed through fal on the request, and this endpoint charges $0.015 per megapixel of input and output - a 1024×1024 output with a 512×512 input lands at $0.03, and each extra image in num_images adds another output megapixel on top. Third: your input pictures are uploaded to fal's CDN before the job runs, so anything you wouldn't hand a third party doesn't belong here. Keep the cheap, local, throwaway edits local; reach for this when the edit genuinely needs the model you can't fit.
Inputs (20)
| Name | Type | Default | Description |
|---|---|---|---|
| prompt | STRING | The prompt to edit the image. | |
| seed | INT | -1-1–2147483647 | The seed to use for the generation. If not provided, a random seed will be used. -1 leaves it to the model. |
| num_inference_steps | INT | 44–8 | The number of inference steps to perform. |
| image_size | COMBO | square_hd | The size of the generated image. If not provided, uses the input image size. 'custom' uses the width and height below. |
| image_size_width | INT | 102416–14142 | Width in pixels when image_size is 'custom'. |
| image_size_height | INT | 102416–14142 | Height in pixels when image_size is 'custom'. |
| num_images | INT | 11–4 | The number of images to generate. |
| enable_safety_checker | BOOLEAN | true | If set to true, the safety checker will be enabled. Disabling it requires account authorization; unauthorized requests are always checked, and images flagged as unsafe are returned as black images. |
| output_format | COMBO | png | The format of the generated image. |
| image_1 | IMAGE | The URLs of the images for editing. A maximum of 4 images are allowed. Each socket may carry a batch; they are sent in socket order (the first picture of socket 1 is number 1). | |
| loras | STRING | List of LoRA weights to apply (maximum 3). JSON. Empty leaves it out. | |
| image_2opt | IMAGE | The URLs of the images for editing. A maximum of 4 images are allowed. Each socket may carry a batch; they are sent in socket order (the first picture of socket 1 is number 1). | |
| image_3opt | IMAGE | The URLs of the images for editing. A maximum of 4 images are allowed. Each socket may carry a batch; they are sent in socket order (the first picture of socket 1 is number 1). | |
| image_4opt | IMAGE | The URLs of the images for editing. A maximum of 4 images are allowed. Each socket may carry a batch; they are sent in socket order (the first picture of socket 1 is number 1). | |
| image_5opt | IMAGE | The URLs of the images for editing. A maximum of 4 images are allowed. Each socket may carry a batch; they are sent in socket order (the first picture of socket 1 is number 1). | |
| image_6opt | IMAGE | The URLs of the images for editing. A maximum of 4 images are allowed. Each socket may carry a batch; they are sent in socket order (the first picture of socket 1 is number 1). | |
| max_cost_usdopt | FLOAT | 20.00–100000 | Safety cap. If the estimated cost of this run is above this many US dollars the node stops BEFORE sending anything to fal. 0 = no cap. |
| reuse_identical_runopt | BOOLEAN | true | If these exact inputs (the settings AND the same pictures/clips/audio) were already paid for and the files are still in output/fal, return them instead of paying again - also after a ComfyUI restart. Turn off for a fresh take with the same settings. |
| extra_jsonopt | STRING | Advanced: a JSON object merged into the request last, for any fal field this node has no box for. Example: {"seed": 7}. Leave empty normally. | |
| max_concurrentopt | INT | 11–32 | How many paid fal calls may run at the same time in one run, across every fal node. 1 (default) = one after another. This node starts its paid part only while fewer than this many fal calls are running. Once any fal node fails, the ones still waiting are not started, so nothing more is billed. |
Outputs (7)
| Name | Type | Description |
|---|---|---|
| images | IMAGE | — |
| image_paths | STRING | — |
| timings | STRING | — |
| has_nsfw_concepts | STRING | — |
| seed | INT | — |
| prompt | STRING | — |
| info | STRING | JSON: request id, cost estimate, saved files and fal's full answer. |