Реализация Smart Reply в мобильном приложении
Smart Reply — это автоматически предлагаемые ответы на сообщения: три кнопки под чатом с вариантами «Окей», «Буду в 18:00», «Не смогу». Google внедрил это в Gmail и Android Messages, Apple — в iMessage через iOS 17. Для кастомного приложения нужно либо использовать готовые SDK, либо реализовать собственную модель.
ML Kit Smart Reply: быстрый старт
Google ML Kit содержит готовую SmartReply модель — работает on-device, поддерживает английский язык. Для Android:
val smartReply = SmartReply.getClient()
val conversation = messages.takeLast(10).map { msg ->
if (msg.isFromUser) {
TextMessage.createForLocalUser(msg.text, msg.timestamp)
} else {
TextMessage.createForRemoteUser(msg.text, msg.timestamp, msg.senderId)
}
}
smartReply.suggestReplies(conversation)
.addOnSuccessListener { result ->
if (result.status == SmartReplySuggestionResult.STATUS_SUCCESS) {
val suggestions = result.suggestions.map { it.text }
showSuggestions(suggestions)
}
}
.addOnFailureListener { /* нет предложений — скрыть UI */ }
Модель не генерирует текст, а выбирает из заранее обученных шаблонов ответов. Плюс — очень быстро (< 20 мс). Минус — ограниченный набор шаблонов, не учитывает специфику приложения, только английский.
Для iOS — аналог через NaturalLanguage framework или Apple Intelligence API (iOS 18+), но уровень поддержки Smart Reply как отдельного use-case значительно скромнее.
Кастомный Smart Reply на базе LLM
Для русскоязычных приложений и специфичных доменов (поддержка, медицина, b2b) ML Kit не подходит. Нужен LLM с промптом.
func generateReplySuggestions(
lastMessages: [ChatMessage],
count: Int = 3
) async -> [String] {
let context = lastMessages.suffix(5)
.map { "\($0.role): \($0.text)" }
.joined(separator: "\n")
let prompt = """
Ты помогаешь пользователю быстро ответить на сообщение в чате.
История диалога:
\(context)
Предложи \(count) коротких варианта ответа пользователя.
Каждый ответ — одно предложение, максимум 10 слов.
Формат: JSON массив строк.
"""
let response = try await llmClient.complete(prompt: prompt, maxTokens: 100)
return parseJSONArray(response) ?? []
}
Latency — критичный параметр. GPT-4o mini отвечает за 1–2 секунды, что приемлемо. Предсказываете заранее, пока пользователь читает сообщение — к моменту когда он захочет ответить, варианты уже готовы.
UX: когда показывать и когда скрывать
Smart Reply должен появляться только при входящем сообщении, и исчезать как только пользователь начал печатать. Три предложения — оптимум (Google Research). Больше — перегружает, меньше — не даёт выбора.
// Android: переключение между Smart Reply и полем ввода
editText.addTextChangedListener(object : TextWatcher {
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
smartReplyChips.isVisible = s.isNullOrEmpty()
// Скрываем предложения как только пользователь печатает
}
override fun afterTextChanged(s: Editable?) {}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
})
Chips (горизонтальный скролл) — стандартный UI для предложений ответа. MaterialChip в Android, кастомные Button / Chip-компоненты в SwiftUI.
Адаптация к контексту
Стандартная ошибка — одинаковые предложения для всех типов сообщений. «Окей», «Понял», «Спасибо» — универсальные ответы, которые пользователь быстро перестаёт замечать. Контекстный Smart Reply должен разбираться:
- Вопрос → предложить прямой ответ
- Просьба о встрече → варианты «Да, удобно», «Нет, не смогу», «Предложи другое время»
- Благодарность → «Пожалуйста», «Не за что»
- Информационное сообщение → «Понял», «Принято», «Уточню»
Классификация типа сообщения (вопрос / просьба / информация) — отдельный лёгкий классификатор или часть промпта к LLM.
Процесс работы
Выбор подхода: ML Kit для английского vs LLM для кастомных сценариев. Реализация предзагрузки предложений при получении входящего сообщения. UI-компоненты: chips, анимации появления/скрытия. Логика скрытия при начале ввода. Аналитика: сколько % пользователей используют Smart Reply, какой вариант чаще.
Ориентиры по срокам
Smart Reply через ML Kit (Android, английский) — 1–2 дня. Кастомный Smart Reply на базе LLM с контекстной классификацией и аналитикой — 5–8 дней.







