Реалізація AI-чат-бота у мобільному додатку
Інтегрувати GPT-4o або Claude у мобільний чат — це не «підключити SDK та готово». Справжня складність починається після першого робочого запиту: керування контекстом діалогу, відображення потокової генерації без стрибків UI, обробка мережі при поганому сигналі, зберігання історії чатів між сесіями без витоку персональних даних.
Керування контекстом діалогу
Усі LLM — без стану. Кожен запит до OpenAI, Anthropic, GigaChat або YandexGPT надсилає повну історію діалогу. Це означає: зберігання та усічення контексту — ваше завдання. При наївній реалізації після 20 повідомлень вартість токенів зростає в 3–4 рази, а при контексті 128k можна отримати відповідь за 30+ секунд.
Практичне рішення — ковзне вікно з резюме:
class ConversationManager {
private var messages: [ChatMessage] = []
private let maxMessages = 20
private let summaryThreshold = 15
func addMessage(_ message: ChatMessage) {
messages.append(message)
if messages.count > summaryThreshold {
Task { await compressSummary() }
}
}
private func compressSummary() async {
// Беремо повідомлення до порога, резюмуємо окремим запитом до LLM
let toCompress = Array(messages.prefix(10))
let summary = try? await llmClient.summarize(messages: toCompress)
if let summary {
messages = [ChatMessage(role: .system, content: "Контекст: \(summary)")] +
Array(messages.suffix(10))
}
}
}
Системний промпт — окремо. Він повинен залишатися першим повідомленням завжди. При стисненні контексту не змінюйте його.
Потокова генерація та UI
Користувачі не повинні чекати повної відповіді. Streaming через SSE — стандарт для всіх сучасних LLM API. На iOS:
// Оновлення SwiftUI View через @Published
class ChatViewModel: ObservableObject {
@Published var streamingText = ""
func streamResponse(for prompt: String) {
streamingText = ""
Task {
for try await chunk in llmClient.stream(prompt: prompt) {
await MainActor.run {
streamingText += chunk
}
}
}
}
}
На Android з Compose — StateFlow<String>, оновлюваний з collectAsState(). Типова помилка: виклик notifyDataSetChanged() або пересоздання Adapter RecyclerView на кожен чанк — дає видиме мигання. Оновлюйте тільки текст останнього повідомлення, не весь список.
Offline-режим та локальні моделі
Для базових сценаріїв (FAQ-бот, форматування даних) — розгляньте on-device моделі. Apple Intelligence API (iOS 18+) дає доступ до локальної мовної моделі через FoundationModels framework без мережевих запитів. Google ML Kit на Android надає SmartReply та EntityExtraction без інтернету.
Для складніших: llama.cpp через Metal/CoreML на iOS або NNAPI на Android — запускає Llama 3 8B int4 прямо на пристрої. На iPhone 15 Pro швидкість генерації ~15 токенів/сек, що прийнятно для допоміжних функцій.
Зберігання історії
Історія чатів — персональні дані. SQLite/Core Data з шифруванням через SQLCipher або iOS Data Protection. Не зберігайте в UserDefaults — синхронізується в iCloud без шифрування. На Android — Room з EncryptedSharedPreferences для ключів шифрування.
Стратегія очистки: автоудалення діалогів старших за N днів, або явне видалення за запитом користувача — вимога GDPR/CCPA.
Типові проблеми виробництва
Повторювані відповіді. GPT інколи циклюється на паттерні. Параметр presence_penalty: 0.6 та frequency_penalty: 0.3 зменшують ймовірність. Якщо циклюється — клієнтська логіка виявлення: якщо останніх 3 повідомлень бота містять > 60% однакових n-грам, скинути контекст.
Timeout при поганій мережі. LLM може генерувати довго. URLSession таймаут за замовчуванням — 60 секунд, замало для довгих потокових відповідей. Встановіть timeoutIntervalForResource: 120 та додайте індикатор прогресу «думаю...» після 5 секунд очікування першого чанка.
Модерація. OpenAI Moderation API перед відправкою користувацького вводу — обов'язково для додатків користувачів. Один POST /v1/moderations коштує дешевше, ніж обробка скарги в App Store Review.
Процес реалізації
Проектування архітектури: вибір LLM-провайдера, on-device vs хмара, схема авторизації. Розробка backend-proxy з обмеженням швидкості. Реалізація ConversationManager із керуванням контекстом. Чат-UI з streaming, bubble-layout, typing indicator. Зашифрована історія чатів. Тестування edge-cases: втрата мережі під час генерації, дуже довгі відповіді, паралельні запити.
Орієнтири за часом
Простий чат з одним LLM-провайдером без історії — 5–7 днів. Повнофункціональний чат-бот з історією, стисненням контексту, offline-режимом та модерацією — 3–5 тижнів.







