Впровадження генерування зображень з штучним інтелектом (Kandinsky) в мобільному додатку
Kandinsky — російська модель від Sber AI (KANDINSKY 3.1 на момент написання). Основна практична перевага для продуктів, які працюють з російськомовною аудиторією: нативне розуміння російських промптів без перекладу. «Захід сонця над березовим лісом» на Kandinsky працює так само, як англійські промпти працюють на західних моделях — без втрати якості при трансляції.
Доступні способи інтеграції
Fusionbrain API (api.fusionbrain.ai) — офіційний API від розробників Kandinsky. Безплатний рівень, REST, відносно стабільний. Більшість інтеграцій використовують це.
Replicate — Kandinsky 2.2 і 3 доступні як community models. Стабільний API, але може бути старша версія моделі.
HuggingFace Inference API — kandinsky-community/kandinsky-3. Достатньо для прототипів.
Для продакшену — Fusionbrain API з власним бекенд-проксі.
Fusionbrain API: особливості протоколу
API використовує двоетапну модель: спочатку створюєш task, потім опитуєш статус.
class KandinskyService(private val apiKey: String, private val secretKey: String) {
// Крок 1: отримати ID моделі
suspend fun getModelId(): String {
val response = httpClient.get("https://api-key.fusionbrain.ai/key/api/v1/models") {
header("X-Key", "Key $apiKey")
header("X-Secret", "Secret $secretKey")
}
val models = response.body<List<FusionBrainModel>>()
return models.first { it.name == "Kandinsky" }.id.toString()
}
// Крок 2: створити задачу генерування
suspend fun createTask(modelId: String, prompt: String, width: Int = 1024, height: Int = 1024): String {
val params = JSONObject().apply {
put("type", "GENERATE")
put("numImages", 1)
put("width", width)
put("height", height)
put("generateParams", JSONObject().apply {
put("query", prompt)
})
}
// Multipart запит
val requestBody = MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("model_id", modelId)
.addFormDataPart(
"params",
"params.json",
params.toString().toRequestBody("application/json".toMediaType())
)
.build()
val response = OkHttpClient().newCall(
Request.Builder()
.url("https://api-key.fusionbrain.ai/key/api/v1/text2image/run")
.header("X-Key", "Key $apiKey")
.header("X-Secret", "Secret $secretKey")
.post(requestBody)
.build()
).execute()
return JSONObject(response.body!!.string()).getString("uuid")
}
// Крок 3: polling
suspend fun pollResult(taskUuid: String): Bitmap? {
repeat(30) {
delay(3000)
val response = OkHttpClient().newCall(
Request.Builder()
.url("https://api-key.fusionbrain.ai/key/api/v1/text2image/status/$taskUuid")
.header("X-Key", "Key $apiKey")
.header("X-Secret", "Secret $secretKey")
.get()
.build()
).execute()
val json = JSONObject(response.body!!.string())
if (json.getString("status") == "DONE") {
val images = json.getJSONArray("images")
val base64 = images.getString(0)
val bytes = Base64.decode(base64, Base64.DEFAULT)
return BitmapFactory.decodeByteArray(bytes, 0, bytes.size)
}
}
return null
}
}
Відповідь приходить як base64-рядок у полі images — не URL. Декодуєш у Bitmap / UIImage безпосередньо на клієнті. Зберігаєш у внутрішнє сховище, якщо потрібна історія.
Параметри генерування
Kandinsky підтримує:
-
width/height: від 256 до 1024, кратно 64. Оптимально: 768x768 або 1024x1024 -
style:DEFAULT,ANIME,PORTRAIT,NATURE,REALISTIC(доступність залежить від версії моделі) -
negativePromptDecoder: негативний промпт — список того, чого не повинно бути
val params = JSONObject().apply {
put("type", "GENERATE")
put("numImages", 1)
put("width", 768)
put("height", 1024)
put("style", "PORTRAIT")
put("generateParams", JSONObject().apply {
put("query", "портрет молодої жінки в традиційному російському костюмі, детальний, реалізм")
})
put("negativePromptDecoder", "розмитість, артефакти, деформація, текст, водяний знак")
}
Російський промпт проти англійського
Kandinsky розуміє російський без деградації якості. Але на практиці для технічних описів (архітектура, механізми) англійський промпт дає більш точний результат — модель навчена на змішаному корпусі, технічні терміни краще представлені англійською. Для художніх, пейзажних, портретних сценаріїв — російський працює чудово.
Для максимальної якості — промпт на обох мовах (якщо UI дозволяє), Kandinsky обробить обидва.
Інтеграція через Replicate (альтернатива)
let replicateBody: [String: Any] = [
"version": "ai-forever/kandinsky-3:...",
"input": [
"prompt": prompt,
"negative_prompt": negativePrompt,
"num_steps": 50,
"guidance_scale": 4.0,
"scheduler": "DDPMScheduler",
"width": 1024,
"height": 1024
]
]
Replicate забезпечує більш передбачуване час відповіді (8–20 сек), ніж Fusionbrain у пікові години.
Типові помилки
FAIL статус без пояснень від Fusionbrain — звичайно промпт порушує content policy або надто короткий (менше 3 слів). Мінімальний промпт для стабільної роботи — 5–10 слів опису.
Декодування base64 на основному потоці — блокування UI. Завжди фоновий потік: DispatchQueue.global().async (iOS) або Dispatchers.Default (Android).
Терміни
Базова інтеграція Fusionbrain API з UI — 3–4 дні. Стилі, історія генерування, збереження в галерею, обробка помилок content policy — 8–12 днів.







