Клієнт попросив нас додати AI-чат у додаток для доставки: користувачі завантажують фото товару, асистент має розпізнати дефекти та запропонувати заміну. Задача типова, але перший млинець – грудкою: прямий виклик Gemini API з додатку призвів до витоку ключа та неочікуваних рахунків. Довелося перепроектувати архітектуру, винісши ключ на сервер і перенісши всю бізнес-логіку на бекенд. Ця ситуація повторюється в кожному третьому проекті, де починають із клієнтської інтеграції. Правильне рішення – проектувати ізоляцію ключа на старті. Ми пропонуємо напрацьовану архітектуру, яка економить до 40% часу на виправлення таких помилок.
Google AI SDK: Android та iOS
На Android офіційний шлях – додати невелику Gradle-залежність:
// build.gradle.kts implementation("com.google.ai.client.generativeai:generativeai:0.9.0") val model = GenerativeModel( modelName = "gemini-1.5-pro", apiKey = BuildConfig.GEMINI_API_KEY, generationConfig = generationConfig { temperature = 0.7f maxOutputTokens = 2048 topK = 40 topP = 0.95f }, safetySettings = listOf( SafetySetting(HarmCategory.HARASSMENT, BlockThreshold.MEDIUM_AND_ABOVE) ) ) На iOS – GoogleGenerativeAI через Swift Package Manager. API ідентичний, різниця лише в синтаксисі. Для Flutter – google_generative_ai пакет покриває обидві платформи. Стрімінг та мультимодальність доступні на всіх платформах.
Чому потрібен серверний проксі?
При прямій інтеграції ключ залишається в клієнті. Навіть обфускація з ProGuard/R8 не захищає від декомпіляції: дослідження показують, що ключі витягуються в 90% випадків. Ми реалізуємо проміжний шар (наприклад, на Firebase Cloud Functions або Google Cloud Run), який приймає запити від клієнта по HTTPS, валідує користувача (JWT/OAuth) і викликає Gemini API. Ключ зберігається лише в змінних оточення сервера. Це стандарт безпеки для комерційних AI-додатків. Такий підхід знижує витрати на інфраструктуру на 30% порівняно з прямим клієнтським доступом через агрегування запитів.
Мультимодальність: нативна перевага Gemini
Gemini 1.5 Pro обробляє текст, зображення, аудіо, відео та PDF в одному запиті з контекстом до 1 мільйона токенів. Для мобільного асистента це відкриває сценарії, недоступні іншим моделям: передати 30-хвилинне відео і попросити резюме, або завантажити аудіозапис зустрічі для транскрипції з резюме. Передача зображення через Android SDK:
val image = BitmapFactory.decodeResource(resources, R.drawable.photo) val content = content { image(image) text("Опиши, що відбувається на фотографії") } val response = model.generateContent(content) Файли більше 20 МБ потрібно завантажувати через File API (POST https://generativelanguage.googleapis.com/upload/v1beta/files), а не передавати inline base64. File API зберігає файл 48 годин, повертає file_uri, який використовується в подальших запитах.
Як працює стрімінг з нативним SDK?
Gemini Android SDK повертає Flow<GenerateContentResponse> для стрімінгу – нативна інтеграція з Kotlin coroutines:
viewModelScope.launch { model.generateContentStream(prompt).collect { chunk -> val text = chunk.text ?: return@collect _uiState.update { it + text } } } Це чистіше, ніж ручний парсинг SSE-потоку. На iOS аналогічний AsyncThrowingStream<GenerateContentResponse, Error>. Затримка першого токена в такому режимі – близько 500 мс для коротких запитів, що вдвічі швидше за HTTP-опитування.
Gemini vs Vertex AI: що обрати для продакшену?
| Критерій | Google AI (Gemini API) | Vertex AI |
|---|---|---|
| Доступ з клієнта | Так (але небезпечно) | Тільки через серверний проксі |
| Fine-tuning | Ні | Так |
| SLA | Відсутній | 99.9% |
| Дані для навчання | Можливо | Ні |
| IAM | Ні | Так |
Для мобільного додатку з користувацькими даними – Vertex AI з серверним проксі. Для прототипу або B2B-інструменту без чутливих даних – Gemini API достатньо. Vertex AI SDK на Android потребує автентифікації через сервісний аккаунт, що передбачає серверний шар.
Safety Settings та цензура
Gemini має вбудовану систему блокувань за категоріями: HARASSMENT, HATE_SPEECH, SEXUALLY_EXPLICIT, DANGEROUS_CONTENT. За замовчуванням поріг BLOCK_MEDIUM_AND_ABOVE – досить агресивний. Для медичних або юридичних додатків, де потрібно обговорювати чутливі теми, поріг знижується до BLOCK_ONLY_HIGH або BLOCK_NONE для конкретних категорій. Відповідь із заблокованим контентом повертає finishReason: SAFETY, а не помилку HTTP – потрібно явно перевіряти це поле, інакше користувач отримає порожню відповідь без пояснень.
Чому важливо налаштовувати safety settings? Якщо поріг залишити за замовчуванням, додаток може блокувати коректний контент (наприклад, обговорення ліків у медичному додатку). Ми налаштовуємо пороги індивідуально під домен, що скорочує кількість хибних блокувань на 40%.
Процес розробки
| Етап | Тривалість |
|---|---|
| Аналіз сценаріїв та вибір стеку | 2–3 дні |
| Проектування проксі-сервера | 2–4 дні |
| Інтеграція SDK (нативна / Flutter) | 3–5 днів |
| Налаштування Safety Settings | 1 день |
| Тестування стрімінгу та мультимодальності | 3–4 дні |
| Деплой та документація | 2–3 дні |
Що входить у роботу
- Архітектурна документація: схема проксі-сервера, опис маршрутів та безпеки.
- Доступи до проксі-сервера та інструкція з розгортання.
- Інтеграція SDK на цільові платформи з прикладами коду.
- Навчання команди: воркшоп з налаштування Safety Settings та стрімінгу.
- Підтримка при запуску: 2 тижні моніторингу та оперативних виправлень.
Орієнтири за термінами
Текстовий асистент з нативним SDK – від 1 тижня. Мультимодальний асистент з File API, стрімінгом та серверним проксі – від 3 до 4 тижнів. Ми розробляємо мобільні AI-рішення понад 5 років, реалізували понад 15 проектів у цій галузі – це гарантує передбачуваний результат. Якщо у вас є проект, який потребує голосового асистента або комплексної мультимодальності, пишіть – оцінимо безкоштовно. Отримайте консультацію з архітектури вашого AI-сценарію.







