Imagine: your service lets users create unique avatars in different styles, but without quality face generation, customers leave dissatisfied with the result. Standard diffusion models without personal tuning produce blurry features and low similarity — ID-score of just 0.3–0.6. In one frame, the nose is shorter, eyes are different colors. Our LoRA-based technology solves this: we train a personal LoRA on 10–20 user photos, then generate 8+ styles while preserving similarity (ID-score >0.85). Processing time per order is 30–40 minutes on GPU. Inference of one image requires minimal compute, making it 2x cheaper than full DreamBooth. Learn how to integrate avatars into your product — request an implementation example.
Problems and solutions
Face instability with direct prompting
Without LoRA, SDXL often changes face shape, especially in 3/4 view. Our system fixes the face via insightface and trains LoRA with low rank (dim=32), delivering stable ID.
Slow batch generation
Single-threaded inference of 32 images takes ~30 minutes. We use an async pipeline with Celery + cumulative LoRA loading — a batch of 8 styles processes in 10–15 minutes.
Quality with poor lighting
Photos with shadows on the face ruin LoRA. The preprocessor automatically rejects low-quality images (<0.9 detect_score) and calibrates color balance.
Why LoRA is better than DreamBooth full model
Compare: LoRA weights are only 3–5 MB vs 5–7 GB for the full model. Training 600 steps takes 15–25 minutes, and inference loads LoRA on top of the base model — no full network retraining. This gives 2–3x higher ID-scoring (by FaceNet metrics) compared to direct prompting in SDXL. Inference savings up to 60% while maintaining quality. As noted in Hugging Face documentation, LoRA significantly reduces the number of trainable parameters while preserving generation quality.
How we guarantee quality even with poor photos
Users may upload 10–20 photos, but some can be blurry or shadowed. Our preprocessor automatically discards images with detect_score <0.9, normalizes lighting, and crops the face via insightface. If high-quality photos are fewer than 10, we warn about possible similarity degradation. Up to 30% defects are tolerated — the system filters them out automatically.
Architecture and implementation
User uploads 10–20 photos
↓ Preprocessing (crop face, quality, filtering)
↓ DreamBooth LoRA training (~15–30 min, GPU)
↓ Generation in N styles (batch inference)
↓ Postprocessing (GFPGAN face enhance)
↓ Ready avatars to user
We use Stable Diffusion XL with LoRA rank 32 — this ensures high quality at moderate VRAM cost. For commercial projects, a switch to SD 3.5 or SDXL Turbo (2x speedup) is available.
Example code for training personal LoRA
import subprocess
import asyncio
from pathlib import Path
async def train_personal_avatar_lora(
user_id: str,
user_photos: list[bytes],
gpu_id: int = 0
) -> str:
work_dir = Path(f"/tmp/avatar/{user_id}")
work_dir.mkdir(parents=True, exist_ok=True)
# Save and preprocess photos
photos_dir = work_dir / "photos"
photos_dir.mkdir(exist_ok=True)
for i, photo_bytes in enumerate(user_photos):
from PIL import Image
import io
img = Image.open(io.BytesIO(photo_bytes)).convert("RGB")
# Crop face via insightface
face_crop = crop_face(img)
if face_crop:
face_crop.save(photos_dir / f"{i:03d}.jpg", quality=95)
# Auto-generate captions
for img_path in photos_dir.glob("*.jpg"):
caption = f"photo of {user_id} person, portrait"
txt_path = img_path.with_suffix(".txt")
txt_path.write_text(caption)
# Train LoRA
output_dir = work_dir / "lora"
output_dir.mkdir(exist_ok=True)
proc = await asyncio.create_subprocess_exec(
"accelerate", "launch", "train_network.py",
"--pretrained_model_name_or_path", "stabilityai/stable-diffusion-xl-base-1.0",
"--dataset_config", str(work_dir / "dataset.toml"),
"--output_dir", str(output_dir),
"--output_name", f"avatar_{user_id}",
"--network_module", "networks.lora",
"--network_dim", "32",
"--network_alpha", "16",
"--learning_rate", "1e-4",
"--max_train_steps", "600",
"--train_batch_size", "1",
"--mixed_precision", "fp16",
f"--cuda_ids={gpu_id}",
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE
)
await proc.wait()
return str(output_dir / f"avatar_{user_id}.safetensors")
Generating avatars in styles
from diffusers import StableDiffusionXLPipeline
import torch
AVATAR_STYLES = {
"anime": "anime portrait, Studio Ghibli style, cel shading, soft colors",
"oil_painting": "oil painting portrait, classical style, museum quality, dramatic lighting",
"cyberpunk": "cyberpunk portrait, neon lights, futuristic, digital art",
"fantasy": "fantasy portrait, epic illustration, magical background, detailed",
"pixar": "pixar 3D animation style, cute, cartoon, colorful",
"sketch": "pencil sketch portrait, detailed, artistic, black and white",
"watercolor": "watercolor portrait, soft edges, pastel colors, artistic",
"professional": "professional headshot, business attire, clean background, LinkedIn style",
}
async def generate_avatar_set(
user_id: str,
lora_path: str,
styles: list[str] = None
) -> dict[str, bytes]:
pipe = StableDiffusionXLPipeline.from_pretrained(
"stabilityai/stable-diffusion-xl-base-1.0",
torch_dtype=torch.float16
).to("cuda")
pipe.load_lora_weights(lora_path)
target_styles = styles or list(AVATAR_STYLES.keys())
results = {}
for style_name in target_styles:
style_desc = AVATAR_STYLES[style_name]
prompt = f"portrait of {user_id} person, {style_desc}, high quality, detailed face"
negative = "deformed, ugly, low quality, blurry, multiple faces"
image = pipe(
prompt=prompt,
negative_prompt=negative,
guidance_scale=7.5,
num_inference_steps=30
).images[0]
# Face enhancement
img_np = face_enhance(image)
import io
buf = io.BytesIO()
img_np.save(buf, format="PNG")
results[style_name] = buf.getvalue()
pipe.unload_lora_weights()
return results
Celery task for processing
from celery import Celery
celery_app = Celery("avatars", broker="redis://localhost:6379/0")
@celery_app.task(name="generate_avatars", bind=True, max_retries=2)
def generate_avatars_task(self, user_id: str, photo_paths: list[str]) -> dict:
try:
photos = [open(p, "rb").read() for p in photo_paths]
lora_path = asyncio.run(train_personal_avatar_lora(user_id, photos))
avatars = asyncio.run(generate_avatar_set(user_id, lora_path))
urls = {style: upload_to_cdn(f"{user_id}_{style}.png", img) for style, img in avatars.items()}
notify_user(user_id, urls)
return {"status": "done", "urls": urls}
except Exception as exc:
raise self.retry(exc=exc, countdown=60)
Method comparison and GPU requirements
| Parameter | LoRA (our approach) | DreamBooth full model | Generic SDXL prompt |
|---|---|---|---|
| Weights size | 3–5 MB | 5–7 GB | 0 |
| Training time | 15–25 min | 40–60 min | 0 |
| ID-scoring (FaceNet) | 0.85 | 0.90 | 0.50 |
| Overfitting risk | Low | High | None |
| Cost-efficiency | High | Medium | Low |
LoRA offers the best balance between quality and cost: ID-scoring nearly as high as full DreamBooth, but at half the inference cost and 2–3x faster training.
GPU requirements
| Task | Minimum GPU | Recommended GPU |
|---|---|---|
| LoRA training | RTX 3070 (8 GB) | RTX 4090 (24 GB) |
| Inference (batch) | RTX 3090 (24 GB) | A10G (24 GB) |
| Multi-user parallel | 2× RTX 4090 | 4× A100 (40 GB) |
Development process and timelines
- Analysis — define target styles, user volume, latency requirements.
- Design — pipeline schema, broker choice (Redis/RabbitMQ), database.
- Implementation — write pre-processing code, LoRA trainer, inference service, web interface.
- Testing — measure ID-scoring, A/B test on 1000 photos, load test the queue.
- Deployment — Docker containerization, Kubernetes orchestration, Prometheus/Grafana monitoring.
Estimated timelines: analysis and design 1–2 weeks, LoRA trainer and inference implementation 2–3 weeks, web interface and queue 1–2 weeks, testing and deployment 1 week. Total 5–8 weeks to launch.
What's included in the solution
- Documentation: API description, operation manual, GPU recommendations.
- Access: to repository (Git), documentation, monitoring.
- Training: 2–3 hour workshop for your team (how to add a new style, how to scale).
- Support: 1 month of warranty support after launch.
Over 15 AI projects delivered. Engineers with experience at NVIDIA and Hugging Face. Average p99 latency of generation — 2.1 sec per style at batch=4. All data stays on your servers (on-prem) or in isolated cloud segments.
We will evaluate your project: tell us how many styles you need and the expected load. Get a consultation on building an avatar service — contact us for a detailed discussion. We guarantee likeness to the original and fast generation.







