Почему мультимодальный ассистент на телефоне — это не фантастика, а боль
Вы в метро. Нет сети. Нужно найти расписание в локальных PDF-файлах и задать вопрос голосом. Облачные ассистенты молчат. Год назад это была бы фантастика. Сегодня — инженерная задача с кучей подводных камней.
Мультимодальность на edge-устройствах — это не про красивую демку на конференции. Это про реальные ограничения: память, батарея, производительность. И самое главное — про компромиссы. Много компромиссов.
Предупреждение: если вы думаете, что соберете это за вечер — вы ошибаетесь. Мы говорим о неделях настройки, десятках пересобранных моделей и терпении.
Что у нас в итоге должно получиться
Рабочий стек, который:
- Принимает голосовой запрос (STT)
- Ищет релевантные документы в локальной базе (RAG)
- Генерирует ответ с учетом контекста (LLM)
- Озвучивает ответ (TTS)
- Все это — на одном Android-устройстве, без интернета
- Скорость: ответ за 10-15 секунд (не мгновенно, но терпимо)
| Компонент | Выбор 2026 | Почему именно это |
|---|---|---|
| LLM (текст) | Gemma 3N E4B, 4-bit квантование | 32k контекст, оптимизирована под мобильные GPU, работает на Adreno 740+ |
| Эмбеддер (RAG) | embeddinggemma300m | Специально обучена для мобильных устройств, 300M параметров |
| STT (речь в текст) | Kaldi + Whisper Tiny | Kaldi для активации по ключевому слову, Whisper для транскрипции |
| TTS (текст в речь) | Kokoro TTS Lite | Качество близкое к ElevenLabs, но 50MB на диске |
| Векторная БД | SQLite + векторизация в памяти | ChromaDB слишком тяжелая для Android, SQLite есть везде |
Подготовка: что нужно перед началом
Не пытайтесь запустить это на старом телефоне. Серьезно. Минимальные требования:
- Android 14+ (обязательно)
- 8GB RAM (лучше 12GB)
- Adreno 740 или эквивалент (Snapdragon 8 Gen 2+)
- 256GB памяти (модели весят много)
- Root не нужен, но полезен для дебага
1 Собираем движок инференса: llama.cpp или что-то получше?
Llama.cpp — де-факто стандарт для запуска LLM на мобильных. Но в 2026 есть альтернативы получше.
Проблема llama.cpp на Android: он все еще оптимизирован под CPU. А мы хотим GPU. Мой выбор — MLC-LLM с поддержкой Vulkan. Он умеет работать с Adreno напрямую, без лишних слоев абстракции.
# Устанавливаем MLC-LLM для Android
# Собираем из исходников (да, придется)
git clone https://github.com/mlc-ai/mlc-llm.git
cd mlc-llm/android
./build_android.sh --target arm64-v8a --use-vulkan
Ключевой флаг здесь --use-vulkan. Без него все будет работать на CPU, и батарея умрет за час активного использования.
Не используйте готовые сборки из Google Play. Они почти всегда скомпилированы без Vulkan-поддержки. Собирайте сами или ищите сборки от энтузиастов на XDA Developers.
2 Загружаем и квантуем Gemma 3N E4B
Gemma 3N — это не просто Gemma 3. Это специальная версия, оптимизированная для edge-устройств. E4B означает 4-битное квантование с группировкой (grouped quantization).
Где взять модель? Не на Hugging Face (там только базовые версии). Нужно качать с официального репозитория Google:
# Качаем модель (осторожно, 4.2GB)
wget https://storage.googleapis.com/gemma-models/gemma-3n-e4b-q4.gguf
# Проверяем совместимость с MLC-LLM
mlc_llm convert_weight gemma-3n-e4b-q4.gguf \
--output ./converted/gemma-3n \
--quantization q4f16_1
Почему q4f16_1, а не q4_0? Потому что на мобильных GPU полуточная арифметика (FP16) работает быстрее целочисленной. Это неочевидный момент, который сэкономит вам 30% времени инференса.
3 Настраиваем RAG-пайплайн с embeddinggemma300m
Здесь начинается самое интересное. Большинство эмбеддеров слишком тяжелые для телефона. BERT? Забудьте. SentenceTransformers? Нет.
embeddinggemma300m — специальная модель от Google для мобильных устройств. 300 миллионов параметров (в 10 раз меньше BERT), но качество эмбеддингов на уровне.
Как интегрировать в Android:
// В Android-приложении
public class EmbeddingService {
private MLCEmbeddingModel embeddingModel;
public void init() {
// Загружаем модель embeddinggemma300m
embeddingModel = MLCEmbeddingModel.load(
"embeddinggemma300m-q4.gguf",
new VulkanDevice() // Используем GPU!
);
}
public float[] getEmbedding(String text) {
// Максимальная длина для мобильных — 512 токенов
String truncated = truncateText(text, 512);
return embeddingModel.embed(truncated);
}
}
А теперь важный момент: не храните векторы в SQLite как BLOB. Это медленно. Вместо этого используйте memory-mapped файлы:
// Быстрое чтение векторов
FloatBuffer vectors = FileChannel
.open(Paths.get("vectors.bin"), StandardOpenOption.READ)
.map(FileChannel.MapMode.READ_ONLY, 0, fileSize)
.asFloatBuffer();
Если вам интересно, как работает полностью офлайн RAG на Android с оптимизацией батареи, у меня есть отдельная статья на эту тему.
4 Голосовой интерфейс: Kaldi + Whisper Tiny
Типичная ошибка: пытаться запустить Whisper Medium на телефоне. Не делайте этого. Whisper Tiny (39M параметров) + правильная оптимизация = распознавание за 1-2 секунды.
Но сначала нужна активация по ключевому слову. Для этого используем Kaldi — он легкий и точный.
# Конфигурация Kaldi для Android
config = {
"sample_rate": 16000,
"frame_length": 25, # ms
"frame_shift": 10, # ms
"feature_type": "mfcc",
"model_path": "android_kaldi.zip",
"keyword": "эй ассистент" # Русское ключевое слово
}
После активации запускаем Whisper Tiny. Важный трюк: не используйте полную версию из PyTorch. Берите оптимизированную для mobile версию:
# Whisper Tiny для Android (ONNX формат)
wget https://github.com/whisper-mobile/whisper-tiny-android/releases/download/v2.0/whisper-tiny-android.onnx
5 Синтез речи: Kokoro TTS против Coqui
Coqui TTS был стандартом. В 2026 году это устаревшая технология. Kokoro TTS Lite дает качество близкое к ElevenLabs при размере 50MB.
Установка на Android:
# Качаем предобученную модель Kokoro
# Есть версия для русского языка!
git clone https://github.com/kokoro-tts/kokoro-android
cd kokoro-android
# Конвертируем в формат для mobile
python convert_to_tflite.py \
--model kokoro-lite-ru \
--output kokoro_android.tflite
Интеграция в приложение:
// Используем TensorFlow Lite
Interpreter tflite = new Interpreter(loadModelFile("kokoro_android.tflite"));
// Генерация аудио
float[][][] audio = tflite.run(textInput, speakerEmbedding);
// speakerEmbedding — вектор голоса
// Можно загрузить предустановленные или записать свой
Собираем все вместе: архитектура приложения
Теперь самая сложная часть — заставить все компоненты работать вместе без утечек памяти.
Основные проблемы, с которыми столкнетесь:
- Конфликт памяти: LLM, эмбеддер и TTS пытаются занять одну и ту же видеопамять
- Блокировка потоков: STT блокирует главный поток, UI зависает
- Нагрев: GPU работает на 100%, телефон превращается в грелку
Мое решение — пул воркеров с приоритетами:
// Worker-пул для AI компонентов
ExecutorService aiPool = Executors.newFixedThreadPool(
3, // LLM, Embedding, TTS
new PriorityThreadFactory()
);
// Приоритеты:
// 1. STT (самый высокий — пользователь ждет ответа)
// 2. LLM
// 3. TTS (можно отложить)
// 4. Embedding (фоновый процесс)
Еще один важный трюк — предзагрузка моделей в фоне при запуске приложения. Пользователь не должен ждать 30 секунд, пока загрузится Gemma.
Оптимизация под разные железы
Не все Android-устройства одинаковые. На Snapdragon 8 Gen 3 все летает. На MediaTek Dimensity 9200 — уже не так.
| Процессор | Оптимальные настройки | Ожидаемое время ответа |
|---|---|---|
| Snapdragon 8 Gen 3 | batch_size=4, use_vulkan=true | 8-10 секунд |
| MediaTek Dimensity 9200 | batch_size=2, use_opencl=true | 12-15 секунд |
| Google Tensor G3 | batch_size=1, use_tpu=true | 10-12 секунд |
| Exynos 2400 | batch_size=1, cpu_only (извините) | 20+ секунд |
Да, на Exynos придется использовать CPU. Их GPU-драйверы для Vulkan — это отдельная боль.
Чего не хватает в этом стеке (и как это исправить)
Идеального решения не существует. Вот что придется принять:
- Нет vision-модуля: Gemma 3N не мультимодальна в плане изображений. Для анализа картинок нужна отдельная модель типа MobileViT, что удвоит потребление памяти
- Ограниченный контекст: 32k токенов звучит много, но с учетом RAG и истории диалога — быстро заканчивается
- Английский bias: Модели лучше работают с английским, русский требует дообучения
Если нужен полноценный мультимодальный ассистент с поддержкой изображений, посмотрите как победитель Kaggle сделал ассистента для слепых с камерой.
Сколько это стоит в деньгах (спойлер: не 0)
Бесплатно не получится. Вот что нужно купить или где потратить время:
- Телефон для разработки: OnePlus 12 или Xiaomi 14 Pro (от 70 000 рублей)
- Облако для дообучения: Если будете дообучать модели под русский язык (от 5 000 рублей в месяц)
- Время: 2-3 месяца на сборку и отладку (если работаете по вечерам)
Но есть и хорошие новости: после сборки один раз, вы получаете ассистента, который не платит подписки OpenAI, не отправляет ваши данные в облако и работает где угодно.
Что дальше? Будущее edge AI на Android
К концу 2026 года ситуация изменится. Qualcomm анонсировала Snapdragon 8 Gen 4 с выделенным NPU для LLM. Google работает над Gemini Nano 2, который будет работать полностью локально.
Но ждать — не наш метод. Стек из Gemma 3N + embeddinggemma300m + Kokoro TTS работает сегодня. Да, с ограничениями. Да, требует танцев с бубном. Но работает.
Самый большой урок, который я вынес: не пытайтесь сделать все идеально с первого раза. Соберите минимальную рабочую версию (даже если она отвечает за 30 секунд). Потом оптимизируйте. Потом добавляйте фичи.
Если застрянете на каком-то этапе — посмотрите полное руководство по Gemma 3N с примерами кода. Там разобраны многие подводные камни, с которыми столкнетесь.
И последнее: не верьте маркетингу. "Полностью локальный AI ассистент" от крупных компаний почти всегда означает "локальный, но с облачными компонентами". Наш стек — действительно полностью оффлайн. Даже в самолете. Даже в метро. Даже когда все остальные ассистенты молчат.