Реалізація передбачуваного вводу тексту у мобільному додатку
Передбачуваний текст — це не просто автодоповнення слів. У контексті мобільного додатку це може бути автозаповнення форм на основі історії, передбачення наступної дії користувача, розумні підказки в пошуку або smart-compose у чаті. Реалізація залежить від того, що саме потрібно передбачати.
Вбудовані API платформ
Найшвидший шлях — використовувати те, що вже є в OS.
На iOS UITextInputTraits та UITextField.autocorrectionType дають базову коррекцію. Для передбачення слів у користувацькій клавіатурі — UILexicon та UITextDocumentProxy.documentContextBeforeInput. Apple не відкриває свою передбачувальну модель прямо розробникам, але KeyboardExtension отримує доступ до контексту документа.
NSSpellChecker на iOS 16+ вміє працювати з checkedString(with:range:types:options:inSpellDocumentWithTag:orthography:wordCount:) — повертає контекстно-залежні поради щодо заміни.
На Android TextServicesManager та SpellCheckerSession надають аналогічний доступ. InputMethodService для користувацьких IME. SuggestionSpan показує підказки прямо в тексті.
Користувацький передбачувач на TFLite
Коли платформені API не підходять (спеціалізована лексика, корпоративний жаргон, нестандартний контекст), потрібна своя модель.
Архітектура для next-word prediction: LSTM або невеликий Transformer (GPT-2 small, 117M параметрів у fp16 = ~240 МБ). Для мобіля — квантизована до int8, ~60 МБ. На iPhone 14+ інференс < 50 мс на 1 передбачення.
class PredictiveTextEngine {
private var interpreter: Interpreter
private let tokenizer: WordpieceTokenizer
private let vocabSize = 30522
func predict(context: String, topK: Int = 3) -> [WordSuggestion] {
let tokens = tokenizer.encode(context.suffix(128)) // останніх 128 токенів
var inputTensor = tokens.map { Int32($0) }
// Вхід → отримуємо логіти над словником
try interpreter.copy(&inputTensor, toInputAt: 0)
try interpreter.invoke()
let outputTensor = try interpreter.output(at: 0)
let logits = outputTensor.data.withUnsafeBytes {
Array(UnsafeBufferPointer<Float>(
start: $0.baseAddress!.assumingMemoryBound(to: Float.self),
count: vocabSize
))
}
return topKIndices(logits, k: topK).map { idx in
WordSuggestion(word: tokenizer.decode(idx), score: logits[idx])
}
}
}
Токенізатор — окреме завдання. WordPiece добре працює для англійської, для російської використовуйте SentencePiece з BPE-моделлю, навченою на російському корпусі. Розмір словника впливає на швидкість: 32k токенів vs 64k.
Автодоповнення в пошуку: Trie vs ML
Для пошуку за фіксованим каталогом (товари, міста, користувачі) — Trie на клієнті швидший та передбачуваніший, ніж ML. Prefix match за O(k) де k — довжина запиту. SQLite FTS5 (MATCH "query*") — хороший варіант для каталогів до 1M записів з нечітким пошуком через spellfix1 extension.
ML потрібна там, де ранжування за особистою релевантністю важливо, а не просто текстове збігання.
Кешування та затримка
Передбачуваний ввід повинен відповідати менше 100 мс — інакше користувач уже надрукував наступний символ. Кешуйте останніх N передбачень у пам'яті, інвальдуйте при зміні контексту. На iOS DispatchQueue з qos: .userInteractive, на Android Dispatchers.Main.immediate в корутині.
Debounce: не викликайте передбачувач на кожен символ, чекайте 150–200 мс після останнього введення. Знижує навантаження без впливу на UX.
Процес реалізації
Аналізуйте домен: який текст, який контекст, потрібна персоналізація? Виберіть підхід: платформні API, Trie + FTS, або ML модель. Підготуйте дані для навчання (якщо користувацька модель). Квантизуйте та оптимізуйте для мобільного інференсу. Інтегруйте в UI з правильним debounce та кешем. Тестуйте на різних класах пристроїв.
Орієнтири за часом
Автодоповнення пошуку через Trie/FTS — 2–4 дні. Користувацька ML-модель для next-word prediction з квантизацією та CoreML/TFLite-інференсом — 3–5 тижнів (включно з підготовкою даних).







