Great for realistic images, accurate prompting, NSFW as well as SFW.
For the majority of my images, I use a simple workflow with the following:
er_sde / beta
8 to 10 steps
CFG 1
A single pass with 3MP latent, but that's down to your own preference and hardware capabilities...and that's it! Have fun and please post your images, with prompts, for us all to see.
Description
This is a merge of models and loras that I had been regularly using to get the best results.
FAQ
Comments (13)
Is it possible to download fp16/bf16 of your wonderful model somewhere? Unfortunately I can't use quantized versions on my setup yet.
I just had Claude create a script to convert it to BF16. It's uploading so should be available in about 1.5 hours. The results are not exactly the same, but I think they may actually be a little better! :)
@galaxytimemachine do you mean from int8 to BF16? It's useless because the data is already lost. It's like converting from one quantum to another. Always lossy. The pre-quantized version is needed because it can be converted into any variant.
@Unicom You said you can't use the quant version on your setup, so there's now a bf16 that you can use. It's not useless at all.
@galaxytimemachine Because I can quantize BF16 myself for my setup. If BF16 is already a quantized model, then nothing will work—the losses are already too great. You can't turn something smaller back into something larger—quantization is lossy compression. Here's an analogy: it's impossible to convert a compressed JPG back into a RAW image. If you convert a JPG to something else, the quality will never be better than the JPG, no matter what you convert it to.
@Unicom Have you tried it?
@galaxytimemachine converted int8 to bf16?
@Unicom The bf16 model I uploaded.
@galaxytimemachine The Bf16, if converted from int8/fp8, you uploaded can not be better quality than the quant you converted from. Converting the new bf16 to another 8-bit quant after that will be worse the the starting 8bit quant.
@galaxytimemachine I got your FP16 model working. Could you tell me which converter you used for dequantization?
@Unicom I used a python script to convert to BF16:
#!/usr/bin/env python3
"""
Dequantize an INT8-ConvRot safetensors file (produced by ComfyUI-INT8-Fast /
Comfy Quants) back into a BF16 safetensors file.
Format being reversed (per quantized Linear layer):
<layer>.weight int8, shape [out, in]
<layer>.weight_scale float32, shape [out, 1] (per-output-channel)
<layer>.comfy_quant uint8 JSON marker, e.g. {"convrot": true, "convrot_groupsize": 256, "per_row": true}
Reverse process:
w = int8_weight.float() * weight_scale # per-channel dequant
if convrot:
w = un-rotate w using the same normalized Hadamard matrix
(it's symmetric + orthogonal, so applying it again inverts it)
save as bf16
IMPORTANT: this recovers a valid BF16-precision file, but the numeric content
is still INT8-level precision -- you are not recovering the pre-quantization
weights bit-for-bit, just re-expressing the quantized values in BF16 storage.
Usage:
python dequant_convrot_to_bf16.py input_int8_convrot.safetensors output_bf16.safetensors
Requires: pip install torch safetensors
"""
import sys
import json
import math
import struct
import argparse
import torch
from safetensors import safe_open
from safetensors.torch import save_file
# Base 4x4 Hadamard matrix (symmetric, orthogonal after normalization)
_H4 = torch.tensor(
[
[1, 1, 1, -1],
[1, 1, -1, 1],
[1, -1, 1, 1],
[-1, 1, 1, 1],
],
dtype=torch.float64,
)
def build_hadamard(size: int) -> torch.Tensor:
"""
Build a normalized regular Hadamard matrix of the given size via
repeated Kronecker products of H4. size must be a power of 4
(64, 256, 1024, etc. -- matches ComfyUI-INT8-Fast's supported group sizes).
Result is symmetric and orthogonal (H @ H == I), so it's its own inverse.
"""
H = _H4.clone()
while H.shape[0] < size:
H = torch.kron(H, _H4)
if H.shape[0] != size:
raise ValueError(f"group size {size} is not a power of 4 -- can't build a matching Hadamard matrix")
return H / math.sqrt(size)
def read_header(path):
with open(path, "rb") as f:
header_size = struct.unpack("<Q", f.read(8))[0]
header_json = f.read(header_size)
return json.loads(header_json)
def decode_marker_tensor(tensor: torch.Tensor) -> dict:
raw = bytes(tensor.to(torch.uint8).numpy().tolist())
text = raw.decode("utf-8", errors="replace")
return json.loads(text)
def dequantize_file(input_path: str, output_path: str):
header = read_header(input_path)
all_keys = [k for k in header if k != "__metadata__"]
marker_keys = {k for k in all_keys if k.endswith(".comfy_quant")}
layer_bases = {k[: -len(".comfy_quant")] for k in marker_keys}
print(f"Total tensors : {len(all_keys)}")
print(f"Quantized layers : {len(layer_bases)}")
hadamard_cache = {}
out_tensors = {}
consumed = set()
with safe_open(input_path, framework="pt", device="cpu") as f:
for base in sorted(layer_bases):
weight_key = f"{base}.weight"
scale_key = f"{base}.weight_scale"
marker_key = f"{base}.comfy_quant"
if weight_key not in header or scale_key not in header:
print(f" SKIP (missing weight/scale tensor): {base}")
continue
q = f.get_tensor(weight_key) # int8 [out, in]
scale = f.get_tensor(scale_key) # float32 [out, 1]
marker = decode_marker_tensor(f.get_tensor(marker_key))
w = q.to(torch.float64) * scale.to(torch.float64)
if marker.get("convrot", False):
gs = marker["convrot_groupsize"]
out_f, in_f = w.shape
if in_f % gs != 0:
print(f" WARNING: {base} in_features {in_f} not divisible by group size {gs}, skipping un-rotation")
else:
if gs not in hadamard_cache:
hadamard_cache[gs] = build_hadamard(gs)
H = hadamard_cache[gs]
w = w.view(out_f, in_f // gs, gs)
w = torch.matmul(w, H) # H is its own inverse
w = w.reshape(out_f, in_f)
out_tensors[weight_key] = w.to(torch.bfloat16)
consumed.add(weight_key)
consumed.add(scale_key)
consumed.add(marker_key)
print(f" dequantized: {base} ({q.shape[0]}x{q.shape[1]}, convrot={marker.get('convrot', False)})")
# Copy through everything else unchanged (casting float tensors to bf16
# for a consistent output dtype; leave non-float tensors as-is)
for key in all_keys:
if key in consumed:
continue
tensor = f.get_tensor(key)
if tensor.is_floating_point():
out_tensors[key] = tensor.to(torch.bfloat16)
else:
out_tensors[key] = tensor
metadata = header.get("__metadata__", {})
save_file(out_tensors, output_path, metadata=metadata if metadata else None)
print(f"\nSaved BF16 file to: {output_path}")
print("Note: numeric precision is still INT8-level; this is not a bit-perfect")
print("recovery of the original pre-quantization weights.")
if name == "__main__":
parser = argparse.ArgumentParser(description="Dequantize an INT8-ConvRot safetensors file to BF16.")
parser.add_argument("input", help="Input INT8-ConvRot safetensors file")
parser.add_argument("output", help="Output BF16 safetensors file")
args = parser.parse_args()
dequantize_file(args.input, args.output)
Thank you for testing with my LoRA. Looking forward to see more of your content ♥
Amazing underrated model. Thanks for sharing!

