AI Avatar Generation Service with Personal LoRA

We design and deploy artificial intelligence systems: from prototype to production-ready solutions. Our team combines expertise in machine learning, data engineering and MLOps to make AI work not in the lab, but in real business.
Showing 1 of 1All 1566 services
AI Avatar Generation Service with Personal LoRA
Medium
~3-5 days
Frequently Asked Questions

AI Development Areas

AI Solution Development Stages

Latest works

  • image_website-b2b-advance_0.webp
    B2B ADVANCE company website development
    1317
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1226
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    925
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1156
  • image_logo-advance_0.webp
    B2B Advance company logo design
    620
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    894

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

  1. Analysis — define target styles, user volume, latency requirements.
  2. Design — pipeline schema, broker choice (Redis/RabbitMQ), database.
  3. Implementation — write pre-processing code, LoRA trainer, inference service, web interface.
  4. Testing — measure ID-scoring, A/B test on 1000 photos, load test the queue.
  5. 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.