Завантаження та індексація документів для RAG у мобільних додатках

Завантаження та індексація документів для RAG у мобільних додатках Додаток вилітає при завантаженні PDF 50+ МБ — типова скарга на етапі QA. У 90% випадків пряме завантаження в пам'ять призводить до `OutOfMemoryError` на Android і низької продуктивності на iOS. Ми вирішили це потоковою передачею д

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

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

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

Послуги, які ми пропонуємо
Показано 1 з 1Усі 1734 послуг
Завантаження та індексація документів для RAG у мобільних додатках
Складний
~5 днів

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

Часті запитання

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

  • image_mobile-applications_feedme_467_0.webp
    Розробка мобільного додатка для компанії FEEDME
    897
  • image_mobile-applications_xoomer_471_0.webp
    Розробка мобільного додатку для компанії XOOMER
    783
  • image_mobile-applications_rhl_428_0.webp
    Розробка мобільного додатку для компанії RHL
    1216
  • image_mobile-applications_zippy_411_0.webp
    Розробка мобільного додатку для компанії ZIPPY
    1081
  • image_mobile-applications_affhome_429_0.webp
    Розробка мобільного додатку для компанії Affhome
    1004
  • image_mobile-applications_flavors_409_0.webp
    Розробка мобільного додатку для компанії FLAVORS
    598

Завантаження та індексація документів для RAG у мобільних додатках

Додаток вилітає при завантаженні PDF 50+ МБ — типова скарга на етапі QA. У 90% випадків пряме завантаження в пам'ять призводить до OutOfMemoryError на Android і низької продуктивності на iOS. Ми вирішили це потоковою передачею даних та асинхронним pipeline. Користувач прикріплює PDF із Files.app або галереї, натискає «Завантажити» — і через кілька секунд отримує можливість ставити запитання за документом. За цими секундами криється складний pipeline: завантаження файлу на сервер, парсинг, розбиття на чанки, генерація ембеддингів і запис у векторну БД. Кожен етап — потенційне джерело проблем: витік пам'яті на мобільному, обрив з'єднання, невірний чанкінг, втрата даних. Ми реалізували такий pipeline під ключ для 5 проєктів, включно з додатками з мільйонними базами документів. Наш досвід показує, що без правильної архітектури пайплайн може зруйнуватися під навантаженням. У цій статті детально розбираємо технічні рішення кожного етапу — від вибору API для завантаження до обробки помилок на сервері.

Як реалізувати завантаження файлів на мобільному пристрої?

Android: вибір правильного API

Для Android 13+ використовуємо ActivityResultContracts.GetContent() з MIME-типом application/pdf або */*. Отримуємо Uri типу content://. Щоб прочитати дані без OutOfMemoryError для великих файлів, не завантажуємо все в ByteArray — передаємо InputStream напряму через кастомний RequestBody в OkHttp. Приклад:

val uri: Uri = // з ActivityResult val requestBody = object : RequestBody() { override fun contentType() = "application/octet-stream".toMediaType() override fun contentLength() = -1 // unknown override fun writeTo(sink: BufferedSink) { contentResolver.openInputStream(uri)?.use { input -> sink.writeAll(input.source()) } } } 

Для файлів понад 50 МБ — чанковане завантаження через MultipartBody з викликом writeTo по частинах. Це дозволяє уникнути перевантаження оперативної пам'яті та підвищити стабільність додатка.

iOS: UIDocumentPicker і потокове завантаження

На iOS використовуємо UIDocumentPickerViewController з UTType.pdf тощо. Отримуємо URL типу file://. Читання через Data(contentsOf:) для файлів >20 МБ небезпечне — краще використовувати URLSession.uploadTask(with:fromFile:), який читає файл напряму з файлової системи, не завантажуючи в пам'ять.

let request = URLRequest(url: uploadEndpoint) let (_, response) = try await URLSession.shared.upload(for: request, fromFile: fileURL) 

Детальніше про URLSession – стандартна документація Apple (Apple URLSession documentation).

Прогрес завантаження

Прогрес-бар обов'язковий: на Android — через CountingOutputStream в OkHttp, на iOS — через URLSession у властивості uploadProgress. Користувач повинен бачити, скільки залишилося. Без прогресу великі файли створюють враження «зависання». Типовий час завантаження 20-30 МБ файлу — близько 5 секунд на хорошому з'єднанні.

Серверний pipeline: від файлу до векторів

Процес включає наступні кроки: 1) завантаження файлу, 2) вилучення тексту, 3) розбиття на чанки, 4) генерація ембеддингів, 5) завантаження у векторну БД. Після завантаження файлу на сервер запускаємо асинхронний pipeline через Celery (або аналогічну чергу). Клієнту одразу повертаємо {"job_id": "abc", "status": "processing"}, а статус відстежується через polling або WebSocket.

@celery.task def process_document(file_path: str, user_id: str, content_type: str): text = extract_text(file_path, content_type) chunks = split_into_chunks(text, chunk_size=500, overlap=50) embeddings = create_embeddings_batch(chunks) upsert_to_vector_store(chunks, embeddings, user_id) update_document_status(file_path, "completed") 

Парсинг документів — таблиця:

Формат Інструмент Особливості
PDF (текст) PyMuPDF (fitz) Швидкий, зберігає структуру, в 10 разів швидше PyPDF2
PDF (скан) Tesseract + pdf2image Повільно, потрібен OCR; скани до 2 хвилин
DOCX python-docx Без зображень
TXT / MD Нативно Тривіально
HTML BeautifulSoup Потрібне очищення від тегів
XLSX openpyxl Таблиці → текст рядково

PyMuPDF — наш вибір для PDF: коректно обробляє кирилицю, зберігає інформацію про шрифти (корисно для визначення заголовків). Джерело: PyMuPDF. Детальніше — PyMuPDF.

Які чанки вибирати: фіксований розмір vs семантичний?

Стратегія Розмір Перекриття Застосування
Фіксований 500 токенів 50 токенів Універсально, просто
Семантичний За реченнями/абзацами 1-2 речення Краще для запитань, точніше

Фіксований чанкінг швидший і передбачуваніший, але може розривати смислові блоки. Семантичний довший, але підвищує якість відповідей RAG на 15–20% за нашими вимірами. Розмір чанка залежить від моделі ембеддингів: для text-embedding-3-small оптимально 512 токенів. Якщо документ містить таблиці або код, збільшуйте перекриття до 100 токенів.

Чому важливий прогрес і статус індексації?

Поки документ обробляється, клієнт повинен бачити актуальний стан. Два підходи:

  • Polling — кожні 2–3 секунди запитуємо /api/documents/{job_id}/status. Просто, працює скрізь, але створює зайві запити (до 20-30 за хвилину).
  • WebSocket / SSE — клієнт підписується на події для job_id. Бекенд надсилає оновлення: {"step": "chunking", "progress": 0.3}{"step": "embedding", "progress": 0.7}{"step": "completed"}. Найкращий UX, але складніше реалізувати при фоновій роботі.

Ми використовуємо SSE як баланс між складністю та досвідом користувача. Після завершення індексації — push-сповіщення через APNs/FCM. Час індексації одного документа скоротили на 40% за рахунок паралельної обробки чанків.

Управління документами користувача

Користувач може видаляти документи. При видаленні:

  1. Видаляємо файл зі сховища.
  2. Видаляємо всі чанки з векторної БД (по user_id + document_id).
  3. Оновлюємо запис у реляційній БД.

У Pinecone: index.delete(filter={"document_id": "xyz"}, namespace=user_id). У pgvector: DELETE FROM documents WHERE document_id = $1 AND user_id = $2.

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

Що входить у нашу роботу з впровадження RAG-пайплайна

Ми надаємо:

  • Проектування архітектури пайплайна під ваші сценарії
  • Реалізацію завантаження з прогресом на iOS/Android
  • Серверну частину: парсинг, чанкінг, ембеддинги, векторне зберігання
  • Інтеграцію з Firebase Cloud Messaging для сповіщень
  • Документацію за API та інструкції з деплою
  • Навчання команди роботі з системою
  • Гарантію стабільності: покриваємо код unit-тестами та проводимо навантажувальне тестування

Наша команда має понад 5 років досвіду в мобільній розробці та успішно впровадила RAG-пайплайни для 5+ проєктів. Отримайте консультацію з архітектури пайплайна.

Терміни та вартість

MVP з підтримкою PDF і TXT, базовим чанкінгом і pgvector — 3–4 тижні. Повний pipeline з OCR, кількома форматами, асинхронною чергою та WebSocket-статусом — 6–8 тижнів. Вартість розраховується індивідуально після аналізу вимог.

Зв'яжіться з нами для оцінки вашого проєкту. Замовте впровадження під ключ.