CoolFace
Modelpublic

ns2agi/notion-avatar-qwen-image-edit-2509-lora

sourceHugging Faceapache-2.0updated 8d agoView on Hugging Face
0likes120downloads
Model Card

Notion-style avatar LoRA for Qwen-Image-Edit-2509

Turns a webcam photo into a black-on-white, Notion-style line avatar of the person in front of the camera. North Star built it for a booth where a Dobot Magician pen plotter draws each visitor's avatar on a card, so the output favours clean, closed strokes over shading.

[image]

Files

FileTrained onCharacter
e2_real_synth.safetensors (default)Full set, 2,000 stepsBest likeness, keeps glasses, headwear, facial hair and other identifying details
e1_real.safetensorsSmall early set, 1,200 stepsLighter, more open line style with less solid fill, slightly cheaper to plot

Both are rank-16 LoRAs on the transformer only, trained at 512 px with ostris ai-toolkit (AdamW 8-bit, learning rate 1e-4, batch 1, fp8 base). They render fine at 1024 px.

Usage

python
import torch
from diffusers import QwenImageEditPlusPipeline
from PIL import Image

pipe = QwenImageEditPlusPipeline.from_pretrained(
    "Qwen/Qwen-Image-Edit-2509", torch_dtype=torch.bfloat16
).to("cuda")
pipe.load_lora_weights(
    "ns2agi/notion-avatar-qwen-image-edit-2509-lora",
    weight_name="e2_real_synth.safetensors",
    adapter_name="style",
)

photo = Image.open("visitor.jpg").convert("RGB")  # square crop around the face works best
avatar = pipe(
    image=[photo],
    prompt="Redraw this person as a Notion-style line avatar",
    negative_prompt=" ",
    num_inference_steps=30,
    true_cfg_scale=4.0,
    height=1024,
    width=1024,
).images[0]
avatar.save("avatar.png")

For a booth, stack the Lightning 8-step LoRA and drop to 8 steps with true_cfg_scale=1.0. On an A100 80 GB that is 12 to 14 seconds per avatar in bf16 with no visible loss against 30 steps:

python
pipe.load_lora_weights(
    "lightx2v/Qwen-Image-Lightning",
    weight_name="Qwen-Image-Edit-2509/Qwen-Image-Edit-2509-Lightning-8steps-V1.0-bf16.safetensors",
    adapter_name="lightning",
)
pipe.set_adapters(["style", "lightning"], adapter_weights=[1.0, 1.0])

The caption is fixed. The LoRA learned the mapping from the image pair, so the text carries little information and other prompts are not needed.

What to expect

  • —Works on photos of one person, head and shoulders, in any lighting, including near darkness, strict profiles, glasses, face masks, hats, hijabs, helmets and heavy makeup.
  • —Draws everyone in frame at their true scale. Crop to the nearest face before inference when the photo has several people or a wide framing.
  • —Full-body or distant subjects come out as small figures, so crop to the face before running the model.
  • —Not a person: a dog becomes a line-art dog, a marble bust stays a bust.

Training data

The bulk of the training set is 600 synthetic portraits generated with RealVisXL 5.0 from templated prompts covering age, heritage, hair, facial hair, glasses, expression, angle, clothing, venue and lighting, paired with targets rendered by gpt-image-2.5-sunburst using the booth's production prompt and style sheet. The training set is not distributed.

Training targets came from OpenAI image outputs, which OpenAI's terms allow the customer to use. The base model and the Lightning LoRA are Apache-2.0; this LoRA is released under Apache-2.0 as well.

Reference server

The booth serves this LoRA from Modal (A100 80 GB, scale to zero after 15 idle minutes, nearest-face crop, Lightning 8-step). The deploy file lives in the magician repository under deploy/modal_avatar.py.

Credits

Trained by North Star (ns2agi.com) in September 2026 on a Scaleway L40S. Base model by the Qwen team, Lightning LoRA by lightx2v.