Разработка систем AI-генерации изображений
AI-генерация изображений — создание пользовательских сервисов на базе Stable Diffusion, FLUX, DALL-E или Midjourney: аватары, баннеры, иллюстрации к статьям, product visualisation, NFT. Сложность проекта зависит от требований к кастомизации, скорости и стоимости инференса.
Выбор модели по задаче
| Модель | Сильные стороны | Стоимость инференса | Управляемость |
|---|---|---|---|
| DALL-E 3 | Понимание текста, следование инструкциям | $0.04–0.08/изображение | Высокая |
| FLUX.1 Dev | Фотореализм, детализация | $0.003–0.015 (Replicate) | Высокая |
| SDXL | Гибкость, LoRA/ControlNet | Self-hosted от $0.001 | Максимальная |
| Midjourney | Художественный стиль | $0.01–0.04 | Низкая (нет API) |
| Kandinsky 3 | Русскоязычные промпты | Self-hosted / $0.005 | Средняя |
DALL-E 3 интеграция
from openai import AsyncOpenAI
import base64
client = AsyncOpenAI()
async def generate_image_dalle(
prompt: str,
size: str = "1024x1024", # 1024x1024, 1792x1024, 1024x1792
quality: str = "standard", # standard, hd
style: str = "vivid" # vivid, natural
) -> bytes:
response = await client.images.generate(
model="dall-e-3",
prompt=prompt,
size=size,
quality=quality,
style=style,
n=1,
response_format="b64_json"
)
return base64.b64decode(response.data[0].b64_json)
FLUX через Replicate API
import replicate
import httpx
async def generate_image_flux(
prompt: str,
aspect_ratio: str = "1:1",
num_outputs: int = 1
) -> list[bytes]:
output = await replicate.async_run(
"black-forest-labs/flux-dev",
input={
"prompt": prompt,
"aspect_ratio": aspect_ratio,
"num_outputs": num_outputs,
"guidance": 3.5,
"num_inference_steps": 28,
"output_format": "webp",
"output_quality": 90
}
)
images = []
async with httpx.AsyncClient() as http:
for url in output:
resp = await http.get(str(url))
images.append(resp.content)
return images
Self-hosted через ComfyUI
import websocket
import json
import uuid
class ComfyUIClient:
def __init__(self, server_address: str = "127.0.0.1:8188"):
self.server_address = server_address
self.client_id = str(uuid.uuid4())
def queue_prompt(self, workflow: dict) -> str:
import urllib.request
data = json.dumps({"prompt": workflow, "client_id": self.client_id}).encode("utf-8")
req = urllib.request.Request(f"http://{self.server_address}/prompt", data=data)
return json.loads(urllib.request.urlopen(req).read())["prompt_id"]
def get_image(self, filename: str, subfolder: str, folder_type: str) -> bytes:
import urllib.parse
data = urllib.parse.urlencode({"filename": filename, "subfolder": subfolder, "type": folder_type})
url = f"http://{self.server_address}/view?{data}"
return urllib.request.urlopen(url).read()
Обработка очереди и масштабирование
from celery import Celery
import redis
app = Celery("image_gen", broker="redis://localhost:6379/0")
@app.task(bind=True, max_retries=3)
def generate_image_task(self, job_id: str, prompt: str, settings: dict):
try:
if settings.get("model") == "dalle":
image = asyncio.run(generate_image_dalle(prompt, **settings))
elif settings.get("model") == "flux":
images = asyncio.run(generate_image_flux(prompt, **settings))
image = images[0]
# Сохраняем в S3/MinIO
url = upload_to_storage(job_id, image)
# Уведомляем клиента
redis_client.publish(f"job:{job_id}", json.dumps({"status": "done", "url": url}))
return url
except Exception as exc:
raise self.retry(exc=exc, countdown=30)
Типовые архитектурные паттерны
Synchronous API (до 10 RPS): FastAPI → Replicate/OpenAI API → S3. Время ответа 3–15 сек.
Async с очередью (10–100 RPS): FastAPI → Redis → Celery workers → GPU сервер → S3. Webhook при готовности.
Self-hosted GPU кластер (100+ RPS): ComfyUI + Ray Serve + несколько GPU нод за балансировщиком.
Сроки: REST API с генерацией через DALL-E/FLUX — 1 неделя. Self-hosted SDXL с очередью — 2–3 недели. Полная платформа с кастомизацией и биллингом — 2–3 месяца.







