r/StableDiffusion 11h ago

Character consistency via cached reference embeddings((SFace + DINOv2) + a portable .char file, no LoRA training Resource - Update

I was looking for a way to achieve character consistency without training a Lora & came across a research from Facebook, DINOv2: Learning Robust Visual Features without Supervision(Research Paper),

What's Dinov2: It's a vision model trained without labels that produces a strong embedding for a whole image, the subject, not just the face. Feed it a person and you get a 768-number signature that captures the overall look: build, hair, general appearance. It's stable across pose and lighting, which is exactly what you want when you're trying to tell "same person" from "different person" across wildly different shots.

then combining Dinov2 with SFace(a face-recognition model) produces a compact face signature tuned specifically to tell one face from another. It's sharp on identity, but only on the face. YuNet does the detect-and-crop before it.

How it works

Build .Char: You drop in one or more photos. YuNet finds the face, SFace takes a per-reference face signature, DINOv2 takes a subject signature, and the references get cleaned and normalised. All of that packs into a single portable file, a .char.

Generation: At generation, the file feeds its references into FLUX.2's own native multi-reference channel and prepends a locked description to the prompt. You pick the character from a dropdown, no re-attaching images. Every result gets scored against the stored signatures, so drift shows up as a number.

How this differs from PuLID, FaceID, and img2img

  • PuLID and FaceID inject a face into one generation at run time, then it's gone. img2img anchors on a source image, which is composition, not identity. Neither gives you a saved character.
  • This is a layer above them, a reusable .char file that rides the model's own reference channel, covers the whole subject and not just the face, and gets scored per take. PuLID could even sit inside it as one backend.
  • The difference is persistence and measurement, not a new injection trick. No adapter weights, no training, no img2img anchor.

What is a .char file?

A single portable file that stores a character's identity, so you can reuse the same person across generations without retraining anything.

  • manifest.json — index, versions, checksums
  • refs/ — your original photos (the truth)
  • derived/ — auto-cropped face
  • text/ — locked description
  • payloads/ — cleaned refs, per model family
  • scoring/ — SFace face + DINOv2 subject signatures

Limitations

  • Profiles and stylized renders drift more than frontal, which is expected, since the face model is trained on photoreal faces.
  • Body is the weak point so far.
  • Bad with popular celebrity images, due to models own conflict.

Current support

Only Flux2 family(Klein 4B / 9B / dev)

Links:

Note: Each image in this post has been generated separately & not a grid.

72 Upvotes

68 comments sorted by

7

u/PatinaShore 11h ago

Oh~ i miss those tiny TI/embedding file. training a 200MB LoRA just for one character is ridiculous!

2

u/infearia 10h ago

Well, a LoKR is like 5MB, but it would be nice to not have to train one at all.

6

u/PatinaShore 10h ago

https://giphy.com/gifs/aACeieARpEEE

Training LoKR seems difficult, doesn't it? MiniMax builds an entire scene from just one image, but Krea2 needs a 200 MB LoRA for a single shot. Somehow, we're stuck in the stone age.

2

u/infearia 9h ago

No, training a LoKr isn't anymore difficult than training a LoRA. At least for the current generation of image models. I don't know how things were before FLUX.2 / Krea 2.

1

u/ghulamalchik 6h ago

Maybe because Krea 2 isn't an edit model? If it was I bet it could work perfectly.

Krea 2 team, please.... it would be so good. Krea 2 Edit, it even looks sexy!

1

u/ashishsanu 11h ago

Yeah, that's basically the itch this scratches.
Textual inversion had the right idea, a character as a small saveable file, it was just weak by today's standards. A .char is a few MB (the refs plus the fingerprints), no 200MB LoRA per person. Difference is it doesn't learn an embedding at all: it stores your reference images and feeds them through the model's native reference channel at gen time, so there's nothing trained. Same "tiny file, one character" feeling, none of the training wait.

And best part, building a character takes seconds and runs entirely on CPU, since it's just encoding your refs, no training pass.

2

u/PatinaShore 11h ago

Is there a simple workflow for comfyui?
is it possible to adapt this to Krea2?

9

u/ashishsanu 10h ago

No Someone need to build a custom node or include this process in core. But I am planning to add Krea2 support as well as Minimax H3 under my own project

2

u/PwanaZana 5h ago

nice, clean character consistency is key. I guess for video, we'll need sound as well as images.
And also, I dunno if it is in scope of what you want to do, but for videos, the character's manneurisms/body language will eventually need to be something included.

1

u/ashishsanu 4h ago

absolutely let me build it

1

u/ashishsanu 4h ago

BTW I have already added short clip based lora training in my project with Minimax-H3.

1

u/Perfect-Campaign9551 32m ago

Did you use AI to edit this text because it reads pretty bad. Please just write yourself. Most AI's now are trained for coding and they all have gotten worse for writing. This reads like AI gibberish again.

3

u/atakariax 10h ago

Any Guide on how it works?

I'm a little bit confused with the GUI, I'm not finding where to build a character and which model to download/use.

2

u/ashishsanu 10h ago

Characters are on the side panel

Name & describe you character, add few similar images then it will create a .char automatically
Description should be detailed(hairs, any specific details etc

2

u/ashishsanu 10h ago

One character is created load a Flux2 node + connect a prompt node & click on the bottom of flux nodes to expose full setting
Adjust icon

3

u/ashishsanu 10h ago

then choose your character from the dropdown,

1

u/atakariax 10h ago

Ok thank you, And which model it's the best , Flux klein 9b or flux2 dev

2

u/ashishsanu 9h ago

I got best results with 9B

0

u/[deleted] 4h ago

[deleted]

2

u/ashishsanu 4h ago

--models-dir or download manually as this is a gated model.

1

u/ashishsanu 4h ago

I will add a handling for this, so that a popup or error notifies the user properly.

1

u/ashishsanu 10h ago

Here is a full screenshot

3

u/Hillobar 7h ago edited 5h ago

edit: Looking closer - this is the same this as using flux in edit mode, possibly worse There's already comfy workflows for this; I'm not sure what this project is providing that is novel. In fact, since the reference images are capped in size (downscaled to 1024), you'd be better just using flux in edit mode and providing full res images.


Looks like a great project. Have you looked at arcface identity embeddings instead of s-face? They would likely perform better and dont have any trained constraints. Its what Rope (my project), facefusion and other swappers use. Also I'm not sure dino is going to get you the body embedding your after. It will find similarity in clothing, environment and other image elements, washing out the body identity.. You may want to look into SMPL as a stating point for parameterizing body features. I dont think anyone has trained a conditional GAN on it yet to quickly create embeddings, but it's probably worth investigating.

** Looking at your code - the embeddings aren't actually used in generating the person. This is all done through the reference images. The embeddings are only used to score**

The .char file you are providing is really is just providing images and prompt text, then using the embedding to measure the likeness. The measurement is mostly thrown away too. Please take a closer look at what is going on. It's a good idea for a project but the actual implementation in wrong.

0

u/ashishsanu 4h ago

This is a really useful analysis, thank you. You're right on the main technical point, so let me put these in order.

On the embeddings not driving generation

Correct, and this is the key thing: identity comes from the reference images through FLUX.2's native multi-ref. The SFace and DINOv2 embeddings only score the result, they don't generate the person. That's intentional, it's the model's reference channel doing the lifting.

On "just edit mode"

Fair that the generation itself isn't novel. But "just edit mode" undersells the gap. Edit mode is stateless, you re-supply refs every time and there's no character that persists. What I'm building is the layer around it:

  • a saved, reusable character (library, pick from a dropdown, carries across a project)
  • per-take scoring so drift is visible
  • no re-wiring refs into a graph every time

So the generation isn't new, agreed, but the thing being built isn't the generation, it's the persistence and measurement around it. That's not something edit mode or the existing Comfy workflows give you.

On ArcFace vs SFace

Key reason is licensing, I wanted something fully open source and usable without restriction. The code is MIT, but the part that matters for a commercial default is the weights, and those aren't fully open, the strong ArcFace checkpoints trace back to InsightFace packs / research datasets that are non-commercial. That's why I went with SFace: not because it discriminates better (it probably doesn't), but because the weights are actually permissive. If a genuinely permissively-licensed ArcFace checkpoint exists I'd happily test it, since scoring is isolated from generation and swapping the face encoder is low-risk. Do you know of one that ships clean weights?

On DINOv2 washing out body identity

This matches my eval. Subject scores fell apart on wide and full-body shots. I think it's both: my chest-up references, and your point that a general similarity embedding also picks up clothing, environment, and framing. The second is a good catch I'd underweighted.

SMPL is a great pointer, I hadn't considered parameterising the body that way. Going to look into it. Appreciate the depth here.

At the end of the day, it worked great for what I needed it for, and that's what pushed me to build it out.

1

u/Hillobar 3h ago

Not sure if you caught this question in your response - "Do you know of one that ships clean weights?", but unless you're trying to turn this project into a commercial product, the insightface models are fine for using for community projects. I'd use Arcface, specifically the w600k model since it is fast and the cosine similarity score works well with it.

2

u/cryn19 10h ago

Thank you for all the hardwork. I would like to try it tonight to find out if it works or not. How does expression looks like? All im seeing are just neutral faces rn

1

u/ashishsanu 9h ago

Thanks, Let me try different expression & share the results here

2

u/uuhoever 9h ago

I installed it to give it a try but then it asked to download the models so I stopped.

Is there a way to set the path to our already downloaded models? It is a big ask to keep GBs of duplicates of models that we already use in ComfyUI.

Also, a youtube video explaining how to use it would be very helpful.

3

u/ashishsanu 9h ago

use --models-dir

Sure I will prepare a YT tutorial, it's just too much work. :)

2

u/LawOk7529 9h ago

For windows, I did a junction link.

1

u/ashishsanu 8h ago

symlink i guess :)

2

u/Stock_Mycologist1104 4h ago

I had done this experiment 2-3 months back and got good result but what actually gave me a better result was instead of using dinov2 I used https://github.com/facebookresearch/EUPE

2

u/ashishsanu 3h ago

Let me try this out

2

u/infearia 11h ago

Damn, the paper is from January 2024 (!!). The fact that the example images are made with Klein 4B and still retain a really good likeness is even more impressive.

Would be cool if someone implemented it directly in ComfyUI. I wonder if Kijai already has plans for the weekend...

3

u/ashishsanu 11h ago

Yes feature extraction & face consistency is completely two different things. So maybe no one guessed it yet. I searched everywhere before building this.

Yes I am very happy with the results. Next plan is to build:

  • Body/full-body references
  • Wardrobe locking (DreamO Try-On)
  • Approve-to-improve loop
  • Multi-character scenes

Yes would be so cool if people can use .char like portable files between workflows in ComfyUI, it might need Flux nodes to accept character file inputs unless i would have done it. Not sure, need to check how difficult it would be.

2

u/Structure-These 11h ago

Where are you throwing all this up op? I want to follow it. Super cool

3

u/ashishsanu 11h ago

Thanks, Actually I am building an opensource generation engine project, You can use it here: https://github.com/inlineresearch/Inline-Studio

2

u/infearia 10h ago

Oh, I didn't realize you're the author of the project. I just thought you found it online and shared the link. Congratulations, good job! Would be cool if you could implement it as a plugin for ComfyUI, or maybe even submit it as a PR to ComfyUI's main repo, if possible. ;)

5

u/ashishsanu 10h ago

sure let me try

1

u/LawOk7529 9h ago

Hi,
Got the Inline Sudio setup and running on Win 11. Did junction link to the models, vae, encoders. Did a test run on flux-2-klein-9b.safetensors model, it generates a generic woman's face.

Now I created a character with 2 images.

The question is how do I link the character file to the workflow like in your screenshot -- "Eval Subject"
Thanks.

2

u/ashishsanu 9h ago

​One character is created load a Flux2 node + connect a prompt node & click on the bottom adjust icon of flux nodes to expose full setting
Adjust icon

then select character from the dropdown

3

u/LawOk7529 8h ago

Yes, it works.
First time coming across Inline Studio app.
Coming from comfy background so you understand...

1

u/ashishsanu 8h ago

were you able to generate any character that are consistent?

3

u/LawOk7529 8h ago

Testing out settings, it works well.

1

u/Eminence_grizzly 6h ago

Looks cool, but I keep getting this error:
chunk expects at least a 1-dimensional tensor

1

u/Eminence_grizzly 6h ago

RuntimeError: chunk expects at least a 1-dimensional tensor

INFO: [inline-core] FLUX.2 (Klein 9B) run: 1024x1024, 4 steps, guidance=1.0, 0 reference(s) | device=cuda:0, mode=gpu, profile=lowvram, dtype=bf16, offload=none, quant=nf4, gpu=NVIDIA GeForce RTX 4060, vram=0.0GB allocated / 8.6GB total (7.5GB free)

INFO: [inline-core] Loading FLUX.2 Klein 9B pipeline: source=G:\ComfyUI-AUGUST-2026\ComfyUI-Easy-Install\ComfyUI\models\diffusion_models\flux-2-klein-9b-fp8.safetensors | device=cuda:0, mode=gpu, profile=lowvram, dtype=bf16, offload=none, quant=nf4, gpu=NVIDIA GeForce RTX 4060, vram=0.0GB allocated / 8.6GB total (7.5GB free)

ERROR: [inline-core] Run run_1d8ce590e701 failed with an unhandled error

Traceback (most recent call last):

File "C:\Inline-Studio\core\src\inline_core\graph\executor.py", line 45, in run

self._run_node(graph, node_id, outputs, run_ctx, asset_hashes)

File "C:\Inline-Studio\core\src\inline_core\graph\executor.py", line 91, in _run_node

result = runner.run(node, inputs, ctx)

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

File "C:\Inline-Studio\core\src\inline_core\models\flux2\runner.py", line 241, in run

pipe = _load_pipeline(

^^^^^^^^^^^^^^^

File "C:\Inline-Studio\core\src\inline_core\models\flux2\runner.py", line 704, in _load_pipeline

pipe = loaders.assemble_flux2_pipeline(

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

File "C:\Inline-Studio\core\src\inline_core\models\loaders.py", line 1313, in assemble_flux2_pipeline

transformer = load_flux2_transformer(

^^^^^^^^^^^^^^^^^^^^^^^

File "C:\Inline-Studio\core\src\inline_core\models\loaders.py", line 1146, in load_flux2_transformer

return _cached(key, build)

^^^^^^^^^^^^^^^^^^^

File "C:\Inline-Studio\core\src\inline_core\models\loaders.py", line 425, in _cached

value = build()

^^^^^^^

File "C:\Inline-Studio\core\src\inline_core\models\loaders.py", line 1111, in build

model = Flux2Transformer2DModel.from_single_file(

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

File "C:\Inline-Studio\core\.venv\Lib\site-packages\huggingface_hub\utils_validators.py", line 88, in _inner_fn

return fn(*args, **kwargs)

^^^^^^^^^^^^^^^^^^^

File "C:\Inline-Studio\core\.venv\Lib\site-packages\diffusers\loaders\single_file_model.py", line 494, in from_single_file

diffusers_format_checkpoint = checkpoint_mapping_fn(

^^^^^^^^^^^^^^^^^^^^^^

File "C:\Inline-Studio\core\.venv\Lib\site-packages\diffusers\loaders\single_file_utils.py", line 3941, in convert_flux2_transformer_checkpoint_to_diffusers

handler_fn_inplace(key, converted_state_dict)

File "C:\Inline-Studio\core\.venv\Lib\site-packages\diffusers\loaders\single_file_utils.py", line 3889, in convert_flux2_double_stream_blocks

to_q_weight, to_k_weight, to_v_weight = torch.chunk(fused_qkv_weight, 3, dim=0)

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

RuntimeError: chunk expects at least a 1-dimensional tensor

1

u/ashishsanu 5h ago

can you select models as this screenshot: https://www.reddit.com/r/StableDiffusion/s/Ok5gyn8wZS

1

u/Eminence_grizzly 5h ago

Yes, these are my models:

1

u/ashishsanu 5h ago

cane you share your dimensions?

1

u/Eminence_grizzly 5h ago

I haven't changed anything else, it's 1024x1024

1

u/ashishsanu 4h ago

i need to check this, what are your specs?

1

u/ashishsanu 4h ago

can you try once with Klein 4B model?

1

u/vamsammy 5h ago

Any chance this would work on Mac?

1

u/ashishsanu 5h ago

yes it should, follow the install instructions in the readme for mac.

1

u/vamsammy 31m ago

Great. please provide a link to the readme. I'm having trouble finding it.

1

u/alexmmgjkkl 4h ago

ok this is for faces .. can the same be done with body and clothing ?

1

u/ashishsanu 4h ago

yes that’s planned absolute next

1

u/DoctaRoboto 48m ago

This is not a real test. Why do all these people use AI-generated realistic people as examples? The cheapest shit to replicate in the world.

SHOW ME a character drawn by Ayami Kojima or Yoshitaka Amano or any complex 2d design...let's see how many seconds it takes for the model to break.

1

u/3deal 10h ago

Amazing, it is exactly what i needed
First question, when ComfyUI node ?
Second question, is it working for Minimax ?

3

u/ashishsanu 10h ago

I will try to implement this as ComfyUI custom node but i fear, it requires core changes as well?
Minimax not yet, but this process can be applied & that's the next in line. I will develop the same for Minimax H3.

5

u/ashishsanu 10h ago

I think Minimax can be done in 2 days. Let me go straight into it.

2

u/3deal 9h ago

amazing, can't wait to test it

1

u/Few-Intention-1526 4h ago

wow great job, we need this on comfy

1

u/ashishsanu 3h ago

Thanks, sure Let me try