Реализация AI-генерации изображений (Stable Diffusion) в мобильном приложении
Stable Diffusion даёт больше контроля, чем DALL-E: negative prompts, ControlNet, LoRA, настройка шагов и CFG scale, SDXL vs SD 1.5. Но это и больше сложности: нужно выбрать провайдера (или хостить самому), разобраться с параметрами, которые напрямую влияют на качество, и правильно организовать асинхронный пайплайн — генерация занимает 10–30 секунд.
Варианты интеграции
Replicate — cloud-инференс через REST API. Поддерживает SDXL, SD 1.5, множество LoRA. Асинхронная модель: POST → получаешь prediction_id → polling или webhook для результата.
FAL.ai — быстрее Replicate по задержке, синхронный и асинхронный режим, поддерживает SDXL, SD3, Flux.
Stability AI API — официальный провайдер, стабильный но дороже.
Самохостинг — ComfyUI или AUTOMATIC1111 на GPU-сервере. Максимальный контроль, нет vendor lock-in, выгоднее при больших объёмах.
Для мобильного приложения с умеренной нагрузкой — Replicate или FAL, без инфраструктурных затрат.
Интеграция Replicate (SDXL)
Replicate использует асинхронную модель. Сначала создаёшь prediction, затем опрашиваешь статус:
class ReplicateSDXLService {
private let baseURL = "https://api.replicate.com/v1"
private let modelVersion = "7762fd07cf82c948538e41f63f77d685e02b063e0ccecb39397596b78813f88f" // SDXL
func generate(prompt: String, negativePrompt: String = "", steps: Int = 30) async throws -> URL {
// 1. Создаём prediction
let createBody: [String: Any] = [
"version": modelVersion,
"input": [
"prompt": prompt,
"negative_prompt": negativePrompt,
"num_inference_steps": steps,
"guidance_scale": 7.5,
"width": 1024,
"height": 1024
]
]
var createRequest = URLRequest(url: URL(string: "\(baseURL)/predictions")!)
createRequest.httpMethod = "POST"
createRequest.setValue("Token \(apiKey)", forHTTPHeaderField: "Authorization")
createRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
createRequest.httpBody = try JSONSerialization.data(withJSONObject: createBody)
let (createData, _) = try await URLSession.shared.data(for: createRequest)
let prediction = try JSONDecoder().decode(Prediction.self, from: createData)
// 2. Polling до завершения
return try await pollUntilComplete(predictionId: prediction.id)
}
private func pollUntilComplete(predictionId: String) async throws -> URL {
var attempts = 0
while attempts < 60 {
try await Task.sleep(nanoseconds: 2_000_000_000) // 2 секунды
let statusURL = URL(string: "\(baseURL)/predictions/\(predictionId)")!
var request = URLRequest(url: statusURL)
request.setValue("Token \(apiKey)", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
let status = try JSONDecoder().decode(PredictionStatus.self, from: data)
switch status.status {
case "succeeded":
return URL(string: status.output![0])!
case "failed":
throw SDError.generationFailed(status.error ?? "Unknown error")
default:
attempts += 1
}
}
throw SDError.timeout
}
}
Вместо polling можно использовать webhook ("webhook": "https://your-backend.com/webhook"), но для мобильного приложения polling с интервалом 2 секунды — проще.
Параметры, которые реально влияют на результат
num_inference_steps — количество шагов диффузии. 20–30 для продакшена (баланс скорость/качество). 50+ — заметного улучшения нет, только медленнее.
guidance_scale (CFG scale) — насколько точно следовать промпту. 7–8 для реалистичных изображений, 10–12 для стилизации. >15 — артефакты.
negative_prompt — что исключить. Стандартный набор: "blurry, low quality, distorted, deformed, ugly, duplicate, watermark". Это не магия, но работает.
Для портретов: "((best quality)), detailed face, sharp focus" в позитиве + "bad anatomy, distorted face, extra fingers, mutation" в негативе.
ControlNet для генерации по контуру/позе
ControlNet позволяет задать структуру изображения: позу тела (OpenPose), края (Canny), глубину. Это ключевое отличие от DALL-E:
let controlNetBody: [String: Any] = [
"version": "...", // ControlNet SDXL version
"input": [
"prompt": prompt,
"image": base64EncodedPoseImage, // OpenPose skeleton
"controlnet_conditioning_scale": 0.8,
"control_mode": "balanced"
]
]
Пользователь делает фото или выбирает позу → мы отправляем её как control image → модель генерирует персонажа в этой позе. Популярно в fashion, fitness, аватар-приложениях.
On-device: Core ML и ONNX
SDXL турбо-версии (SDXL-Turbo, LCM) с 4–8 шагами запускаются на iPhone 15 Pro через Core ML за 10–15 секунд. Apple публикует конвертированные Core ML модели SD на Hugging Face.
// Core ML SD через Apple's swift-coreml-diffusers
let pipeline = try StableDiffusionPipeline(
resourcesAt: modelURL,
controlNet: [],
configuration: config
)
let images = try pipeline.generateImages(
prompt: prompt,
imageCount: 1,
stepCount: 4, // SDXL-Turbo: 4 шага достаточно
seed: 42
)
На Android — ONNX Runtime с SD mobile-оптимизированными моделями (~400 МБ). 20–40 секунд на среднем устройстве 2024 года. Реально только для offline-сценариев.
Сроки
Интеграция Replicate SDXL с базовым UI (промпт + результат) — 3–5 дней. ControlNet, LoRA-выбор, параметры (CFG, шаги), история генераций, sharing — 2–3 недели.







