Реалізація AI-асистента для написання текстів (Writing Assistant) у мобільному додатку

TRUETECH займається розробкою, підтримкою та обслуговуванням мобільних додатків iOS, Android, PWA. Маємо великий досвід та експертизу для публікації мобільних додатків до популярних маркетів Google Play, App Store, Amazon, AppGallery та інші.

Розробка та підтримка будь-яких видів мобільних додатків:

Інформаційні та розважальні мобільні програми
Новинки, ігри, довідники, онлайн-каталоги, погодні, фітнес та здоров'я, туристичні, освітні, соціальні мережі та месенджери, квіз, блоги та подкасти, форуми, агрегатори
Мобільні програми електронної комерції
Інтернет-магазини, B2B-додатки, маркетплейси, онлайн-обмінники, кешбек-сервіси, біржі, дропшиппінг-платформи, програми лояльності, доставка їжі та товарів, платіжні системи
Мобільні програми для управління бізнес-процесами
CRM-системи, ERP-системи, управління проектами, інструменти для команди продажів, облік фінансів, управління виробництвом, логістика та доставка, управління персоналом, системи моніторингу даних
Мобільні програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, платформи надання електронних послуг, платформи кешбеку, відеохостинги, тематичні портали, платформи онлайн-бронювання та запису, платформи онлайн-торгівлі

Це лише деякі з типів мобільних додатків, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 1735 послуг
Реалізація AI-асистента для написання текстів (Writing Assistant) у мобільному додатку
Середній
~3-5 днів
Часті запитання

Наші компетенції:

Етапи розробки

Останні роботи

  • image_mobile-applications_feedme_467_0.webp
    Розробка мобільного додатка для компанії FEEDME
    792
  • image_mobile-applications_xoomer_471_0.webp
    Розробка мобільного додатку для компанії XOOMER
    671
  • image_mobile-applications_rhl_428_0.webp
    Розробка мобільного додатку для компанії RHL
    1097
  • image_mobile-applications_zippy_411_0.webp
    Розробка мобільного додатку для компанії ZIPPY
    969
  • image_mobile-applications_affhome_429_0.webp
    Розробка мобільного додатку для компанії Affhome
    914
  • image_mobile-applications_flavors_409_0.webp
    Розробка мобільного додатку для компанії FLAVORS
    495

Реалізація AI-асистента для написання текстів (Writing Assistant) в мобільному додатку

Writing Assistant у мобільному додатку — це не просто поле введення з кнопкою «поліпшити». Це редактор, який працює в контексті: розуміє тип документа (лист, пост, звіт), підтримує стрімінг, не скидає курсор при вставці, та пережує фоновий режим без втрати стану.

Саме на цих деталях ламаються 80% реалізацій.

Архітектура редактора з AI

Перший вибір — використовувати нативний UITextView/EditText або кастомний редактор. Для більшості випадків нативний компонент — правильний вибір, але з AI-функціями з'являється нетривіальне завдання: вставка сгенерованого тексту без руйнування позиції курсору та виділення.

// iOS: вставка AI-тексту через NSTextStorage без скидання курсору
func insertAIText(_ text: String, at range: NSRange) {
    guard let textView = self.textView else { return }
    let storage = textView.textStorage

    // Зберігаємо позицію курсору
    let cursorOffset = textView.selectedRange.location

    storage.beginEditing()
    storage.replaceCharacters(
        in: range,
        with: NSAttributedString(string: text, attributes: defaultTypingAttributes)
    )
    storage.endEditing()

    // Відновлюємо курсор після вставки
    let newOffset = cursorOffset + (text.count - range.length)
    textView.selectedRange = NSRange(location: max(0, newOffset), length: 0)
}

На Android аналог через Editable.replace() + збереження SelectionStart/SelectionEnd через android.text.Selection.

Стрімінг та прогресивна вставка

Writing Assistant обов'язково мусить стримити текст — користувач бачить, як AI пише. Технічно це AsyncStream<String> (iOS) або Flow<String> (Android), кожний чанк додається до кінця активного параграфа.

Типова проблема: при швидкому стрімінгу (> 20 символів/сек) UITextView починає лагати на довгих текстах. Причина — textStorage тригерить layout pass на кожній зміні. Рішення — батчинг апдейтів:

private var streamBuffer = ""
private var streamTimer: Timer?

func appendStreamChunk(_ chunk: String) {
    streamBuffer += chunk

    if streamTimer == nil {
        streamTimer = Timer.scheduledTimer(withTimeInterval: 0.05, repeats: false) { [weak self] _ in
            guard let self else { return }
            self.textView.textStorage.beginEditing()
            self.textView.textStorage.append(NSAttributedString(string: self.streamBuffer))
            self.textView.textStorage.endEditing()
            self.streamBuffer = ""
            self.streamTimer = nil
        }
    }
}

Кожні 50 мс — один layout pass замість 20. На iPhone SE 2nd gen різниця видна невеликим оком.

Режими асистента: як не захламити UI

Writing Assistant зазвичай пропонує кілька дій: продовжити текст, переписати виділене, змінити тон, скоротити, розширити. Якщо показувати всі кнопки одразу — UI перетворюється на хаос.

Правильна схема: контекстне меню з'являється тільки при наявності виділення (для «переписати», «змінити тон»), floating action button з'являється у кінці параграфа (для «продовжити»). Два різних триггери — два різних UX-паттерни.

// Android Compose - floating assistant button
@Composable
fun WritingAssistantOverlay(
    textFieldState: TextFieldState,
    onContinue: () -> Unit,
    onRewrite: (String) -> Unit
) {
    val hasSelection = textFieldState.selection.length > 0

    AnimatedVisibility(visible = !hasSelection) {
        FloatingActionButton(
            onClick = onContinue,
            modifier = Modifier.align(Alignment.BottomEnd)
        ) {
            Icon(Icons.Default.AutoAwesome, "Продовжити")
        }
    }

    AnimatedVisibility(visible = hasSelection) {
        ContextualMenu(
            items = listOf("Переписати", "Змінити тон", "Скоротити"),
            onSelect = { action ->
                val selected = textFieldState.text.substring(textFieldState.selection)
                onRewrite("$action: $selected")
            }
        )
    }
}

Промпти для різних дій

Кожна дія асистента — окремий промпт. їх не можна узагальнити в один універсальний. Кілька робочих шаблонів:

Продовження тексту:

Continue the following text naturally, maintaining the same style, language, and tone.
Write 1-3 sentences only. Do not repeat what was already written.
Text: {last_500_chars}

Переписати виділене:

Rewrite the following text. Keep the core meaning but improve clarity and flow.
Language: {detected_language}. Style: {business|casual|formal}.
Text: {selected_text}

Змінити тон:

Rewrite this text in a {formal|casual|empathetic|assertive} tone.
Preserve all key information. Output only the rewritten text.
Text: {selected_text}

Визначення мови — через NLLanguageRecognizer (iOS) або TextClassifier з ML Kit (Android). Не покладайтеся на Locale.current — користувач може писати на іншій мові.

Стан при фоновому режимі

Якщо користувач згорнув додаток у процесі генерації, iOS відправить задачу в URLSession з background конфігурацією або просто скасує запрос. Потрібно зберегти промпт та статус у UserDefaults/SharedPreferences та відновити при поверненні.

При довгих генераціях (> 15 секунд для великих текстів) переходимо на Background Tasks API на iOS або WorkManager на Android — стрімінг у фоні неможливий, але можна отримати кінцевий результат через push notification.

Орієнтири за часом

Базовий асистент з кнопкою «поліпшити» через OpenAI — 3–5 днів. Повноцінний редактор зі стрімінгом, контекстним меню, режимами та збереженням стану — 3–4 тижні. Підтримка офлайн-режиму з on-device моделлю (через CoreML/TFLite) — окремо від 2 тижнів.