← Все статьи

WebGPU + Transformers.js: нейросети прямо в браузере

Как запускать ML в React без обязательного серверного GPU: WebGPU, Transformers.js, ONNX Runtime, OCR и компьютерное зрение, запасной путь на WASM и размер модели.

WebGPU + Transformers.js: нейросети прямо в браузере
Содержание

Классическое AI-приложение выглядит так: браузер шлёт картинку или текст на API, сервер гоняет модель на GPU, ответ едет обратно. Это работает — и дорого стоит: железо, сеть, приватность, масштаб. Другой путь: модель скачивается в браузер, вывод идёт на GPU пользователя через WebGPU, а сервер остаётся для данных и бизнес-логики. Ниже — как связаны WebGPU, Transformers.js и ONNX Runtime Web, где это уместно для OCR и компьютерного зрения, и почему React-сайт можно превратить в клиент AI-системы без иллюзии, что «большая языковая модель сама влезет во вкладку».

Ключевые выводы

WebGPU — не нейросеть. Это API GPU-вычислений в браузере: шейдеры вычислений и доступ к железу. Модель и среда исполнения живут выше.

Transformers.js — удобный слой над моделями. Под капотом — ONNX Runtime Web; ускорение на GPU включается через device: 'webgpu'.

Правильная лестница запасных путей: WebGPU → WASM → серверный вывод. Гарантировать GPU у всех пользователей нельзя (~85% поддержки по caniuse на март 2026).

ИИ в браузере силён на компактных моделях. Классификация, эмбеддинги, детект, OCR кропов — да. Гигантские языковые модели и тяжёлые модели зрения — чаще сервер.

Пайплайн из малых моделей часто лучше одной большой. YOLO находит «где», OCR читает «что» — как в инженерии детекции и компактной CRNN.

Зачем запускать AI в браузере

Серверный вывод решает контроль окружения и позволяет держать большие модели. Цена — аренда GPU, задержка сети, передача документов на чужой хост и масштабирование под пики. Для бланков, чеков и внутренних форм вопрос «куда ушла фотография» часто важнее «насколько умная модель».

Клиентский путь: первый визит качает веса (или берёт их из кеша), дальше вывод модели локально. Сервер хранит результаты, права доступа и оркестрацию — не обязан видеть сырое изображение. Главный вопрос статьи практический: можно ли превратить обычный React-сайт в клиент AI-системы? Да — если задача умещается в размер модели, холодный старт и поддержку WebGPU/WASM на устройствах аудитории.

WebGPU простыми словами

Нейросети — это массовые операции над матрицами. CPU хорош для разнородных последовательных задач. GPU — для тысяч однотипных параллельных шагов. Упрощённо: один исполнитель делает тысячу операций подряд против тысячи маленьких исполнителей, работающих одновременно.

До WebGPU в браузере были JavaScript на CPU, WebAssembly и WebGL. WebGL заточен под графику; для ML его приходится «ломать» через текстуры и шейдеры — неудобно и ограничено. WebGPU — преемник с более прямой моделью доступа к современному GPU и поддержкой вычислений общего назначения: как раз то, что нужно средам исполнения машинного обучения.

Важно развести слои:

JavaScript
   ↓
ML-каркас / среда исполнения
   ↓
WebGPU
   ↓
GPU API платформы
   ↓
GPU

WebGPU сам по себе не классифицирует изображения и не читает текст. Он даёт среде исполнения выполнить граф вычислений на железе пользователя.

Transformers.js и связка с ONNX

Transformers.js (пакет @huggingface/transformers) — JavaScript-библиотека экосистемы Hugging Face для запуска моделей в браузере и в Node. Через конвейеры задач доступны текстовая классификация, эмбеддинги, распознавание речи, классификация и детекция изображений, OCR-сценарии, генерация текста и другие задачи на базе Transformer-моделей и моделей зрения, экспортированных в ONNX.

Что такое ONNX (коротко)

ONNX (Open Neural Network Exchange) — открытый формат графа нейросети: узлы (операции), тензоры, константы. Это не «ещё один фреймворк обучения» и не замена PyTorch. Обучение обычно остаётся в PyTorch или другом каркасе; в ONNX модель экспортируют, чтобы один и тот же артефакт можно было гонять разными движками.

ONNX Runtime (ORT) — движок, который читает этот граф и исполняет его: на сервере (CPU / CUDA), в Node или в браузере (ONNX Runtime Web с бэкендами WASM / WebGPU). Transformers.js как раз опирается на ONNX Runtime Web: вы вызываете удобный pipeline, а под капотом крутится ONNX-граф.

Минимальная цепочка:

Обученная модель (PyTorch и т.п.)
        ↓
   экспорт в ONNX
        ↓
ONNX Runtime (Web / сервер)
        ↓
   WebGPU / WASM / CUDA …

Без этого звена «своя CRNN в браузере» не склеивается: React не исполняет .pt напрямую. Разбор экспорта, opset, динамических осей и паритета с Python — в отдельной статье ONNX: от PyTorch до Runtime.

Жизненный цикл модели:

Первый запуск → загрузка файлов → кеш браузера → локальный вывод

Размер весов бьёт по холодному старту: сотни мегабайт на мобильном — уже продуктовое решение, а не «мелочь для демо».

Роли в стеке:

Слой Задача
Transformers.js Удобные конвейеры, загрузка и предобработка
ONNX Runtime Web Исполнение графа модели
WebGPU GPU-бэкенд
WASM запасной путь на CPU, когда GPU недоступен

Схема целиком:

React / JavaScript
        ↓
Transformers.js
        ↓
`ONNX Runtime Web`
        ↓
   WebGPU или WASM
        ↓
     GPU / CPU

WebGPU, WASM и сервер: что выбрать

Подход Где крутится Плюсы Минусы
WASM CPU Широкая совместимость Часто медленнее
WebGPU GPU клиента Выше скорость на подходящем железе Нужна поддержка браузера и драйвера
GPU сервера Сервер Мощное железо, большие модели Стоимость, сеть, приватность

Рабочая лестница для продукта:

WebGPU → если нет → WASM → если модель слишком тяжёлая / медленная → вывод на сервере

Не выбирайте бэкенд «по моде». Выбирайте по задаче, 95-го перцентиля времени на реальных устройствах аудитории и политике данных.

Первая модель и device: 'webgpu'

Установка (актуальный пакет):

npm install @huggingface/transformers

Минимальный пример классификации текста:

import { pipeline } from '@huggingface/transformers';

const classifier = await pipeline(
  'text-classification',
  'Xenova/distilbert-base-uncased-finetuned-sst-2-english',
);

const result = await classifier('Hello world');

После pipeline библиотека находит карточку модели, качает ONNX-файлы, готовит среду исполнения, выбирает бэкенд, выполняет вывод и возвращает результат. Чтобы явно взять GPU:

const pipe = await pipeline(
  'image-classification',
  'onnx-community/mobilenetv4_conv_small.e2400_r224_in1k',
  { device: 'webgpu' },
);

Так же включают эмбеддинги и распознавание речи — в гайде Hugging Face по WebGPU. device: 'webgpu' не гарантирует успех: нужна поддержка API, рабочий драйвер и модель, чьи операторы среда исполнения умеет на этом бэкенде. Оборачивайте инициализацию в проверку и запасной путь на WASM (или на сервер).

React: где держать модель и зачем рабочий поток

Не создавайте pipeline внутри каждого рендера. Нужны ленивая инициализация, сервис-одиночка или React-хук useAIModel(), который грузит модель один раз и отдаёт статус: idle → loading → ready → error. Пока идёт загрузка, UI показывает прогресс и не блокирует остальную страницу. Повторный вход на экран OCR должен брать уже тёплый экземпляр из модуля-сервиса, а не качать веса снова.

Для UI удобна схема:

React UI → useAIModel() → Model Service → Transformers.js → ORT → WebGPU

Вывод модели и разбор больших тензоров на главном потоке могут заморозить интерфейс: прокрутка останавливается, клики «теряются», пользователь думает, что вкладка зависла. Выносите загрузку и вывод в Web Worker: главный поток шлёт сообщение с ArrayBuffer изображения или OffscreenCanvas, рабочий поток отвечает результатом, метриками времени и кодом ошибки. Паттерн близок к другим тяжёлым клиентским задачам — см. также Web Worker для клиентских вычислений.

Отдельно продумайте отмену: пользователь выбрал другое фото, пока крутится вывод. Рабочий поток должен уметь игнорировать устаревший requestId, иначе в UI приедет результат от предыдущего файла.

Компьютерное зрение и OCR в браузере

Технология интересна не только для обработки текста. Типичный конвейер зрения:

Изображение → preprocessing → детект / кроп → классификация или OCR → результат

Сценарии: документы, чеки, бланки, схемы, технические формы. Классический серверный OCR шлёт файл на API. Браузерный путь держит изображение на устройстве:

Браузер → изображение → предобработка → модель → текст

Плюсы: данные не уезжают, ниже сетевая задержка, нет стоимости GPU-инстанса, возможен офлайн после кеширования. Минусы: размер модели, требования к устройству, ограничения песочницы браузера, сложнее катать очень тяжёлые веса.

Для бланков с замерами выгоднее цепочка «найти таблицу → найти ячейку → кроп → компактная OCR», чем слать весь скан в большую языковую модель. Это та же дисциплина, что в практике CRNN на замерах УЗТ и разборе рукописных цифр — только среда исполнения смещается ближе к клиенту.

Своя CRNN, YOLO и зрение по документам

Собственную модель из PyTorch можно вести в браузер так:

PyTorch → обученная CRNN → export ONNX → `ONNX Runtime Web` → (Transformers.js или прямой ORT) → WebGPU

Проверяйте: все операторы есть в целевом провайдер исполнения; предварительная обработка в браузере совпадает с Python (нормализация, порядок каналов, размер); постобработка (CTC, argmax) даёт те же строки на контрольном наборе. Расхождение «в Colab 0.98, во вкладке мусор» почти всегда в препроцессе или в другой версии квантования — не в «магии WebGPU».

Сценарий с детектором:

Image → YOLO → bounding boxes → crop → OCR

YOLO отвечает «где объект», OCR — «что внутри». Обе модели могут жить локально, если ужаты по размеру. Конвейер зрения по документам на клиенте — реалистичная цель для внутренних инструментов, где документы не должны покидать рабочую станцию. Инженерная логика детектора разобрана в опорный разбор про YOLO.

Когда полезно, размер модели и квантование

Хорошие кандидаты: OCR небольших кропов, классификация, детекция объектов, эмбеддинги, компактные модели зрения, речь, локальные инструменты, приложения «сначала офлайн».

Плохие: очень большие языковые модели, огромные сети зрения, задачи с большим объёмом оперативной и видеопамяти, операторы вне поддержки ONNX Runtime, модели с невыносимым холодным стартом.

Парадокс поставки:

Server:  10 MB JS + 5 GB модель на сервере
Browser: 10 MB JS + 500 MB модель у пользователя

Пользователь платит трафиком и диском. Смягчают: квантование, сжатие, кеш (Cache Storage / IndexedDB), ленивая подгрузка, CDN, несколько малых моделей вместо одной огромной.

Квантование упрощённо:

FP32 → FP16 → INT8 → меньше размер и память → часто быстрее

Это компромисс размера, скорости и качества — не бесплатное «сжать без потерь». Меряйте точность на своём валидационном наборе после каждого шага.

Приватность, режим «сначала офлайн» и сравнение с сервером

Локальный вывод снижает утечку сырых документов на сервер вывода. Это не абсолютная безопасность: модель и зависимости всё равно скачиваются, песочница браузера ограничивает, но не отменяет цепочки поставок; вредоносный или подменённый артефакт модели — отдельный риск. Контролируйте источники весов и целостность (хеши, свой CDN).

Режим «сначала офлайн» после прогрева кеша:

React → Local AI Model → WebGPU → GPU
(интернет может быть отключён)

PWA, Cache Storage и IndexedDB держат UI и веса. Сравнение с сервером:

Характеристика ИИ в браузере ИИ на сервере
GPU пользователя сервера
Данные локально уходят на сервер
Задержка потенциально низкая после прогрева зависит от сети
Стоимость вывода ниже для владельца сервиса платит владелец
Размер модели ограничен устройством можно крупные
Офлайн возможен обычно нет
Контроль окружения ниже выше

Как мерить и какие ошибки ломают проект

Считайте не только «заработало». Фиксируйте: размер модели (MB на диске и в памяти), время загрузки по сети и из кеша, холодный старт первого вывода, тёплый вывод, долю времени предварительной и постобработки, пик памяти вкладки, долю устройств с успешным WebGPU. Без разреза «первый визит vs повторный» вы оптимизируете не тот путь: у повторных пользователей модель уже в Cache Storage, а у новых — ещё нет.

Пример отчёта для стенда:

Загрузка модели (холодная сеть):  2.8 s
Загрузка модели (попадание в кеш):     0.4 s
Первый вывод:               450 ms
Тёплый вывод:                 85 ms
Размер модели:                    120 MB
Успех WebGPU (стенд):      9/10 devices

Типичные ошибки: путать Transformers.js с «нейросетью» и WebGPU с ML-фреймворком; тащить слишком большую модель «потому что на сервере тянет»; крутить вывод на потоке интерфейса; не иметь запасного пути на WASM; игнорировать холодный старт; слать всю фотографию, когда нужен кроп; звать языковую модель там, где хватает детектора и OCR; сравнивать качество браузерного вывода с Python без фиксации версии квантования.

Скелет для промышленного контура:

React → AI Service → рабочий поток → Transformers.js → `ONNX Runtime Web` → WebGPU
Fallback: WebGPU → WASM → серверный API

Большая языковая модель ≠ любой ИИ. Для документов часто выигрывает:

YOLO → OCR → Classifier → Rules

вместо «картинка → огромная языковая модель → JSON». Место серверной языковой модели остаётся там, где нужна широкая рассуждающая модель — рядом с клиентским контуром, а не вместо него. Про слои LLM-стека см. три слоя стека LLM.

Будущее: зрелее WebGPU, API вроде WebNN, SIMD в WASM, квантованные и мультимодальные модели, сценарии с сохранением приватности. Отделяйте уже доступное (device: 'webgpu' сегодня) от дорожной карты браузеров, иначе план превращается в слайд-шоу без даты поставки.

Мини-проект: AI OCR во вкладке

Соберите черновик приложения:

  1. Загрузка изображения и предпросмотр.
  2. Проверка navigator.gpu / попытка device: 'webgpu'.
  3. Загрузка компактной модели с индикатором прогресса.
  4. Предобработка и (по возможности) поиск области документа.
  5. OCR → JSON в UI.
  6. Печать времени загрузки и тёплого вывода.
  7. Переключатель запасного пути на WASM.

Архитектура цели:

Image → React → рабочий поток → Model → WebGPU → OCR → JSON → UI

Так вы проверяете гипотезу на своих устройствах раньше, чем обещать заказчику «весь AI в браузере».

Частые вопросы

Нужен ли сервер, если есть WebGPU?

Часто да — для авторизации, хранения результатов, обновления моделей и тяжёлого вывода. Клиент закрывает чувствительный и частый путь; сервер — контроль и запасной контур.

Чем Transformers.js отличается от ONNX Runtime?

Transformers.js даёт конвейеры задач и загрузку моделей Hugging Face. ONNX Runtime Web исполняет граф. Можно звать ONNX Runtime напрямую для своей ONNX-модели без API Transformers.js.

Всегда ли WebGPU быстрее WASM?

Обычно на подходящем GPU — да для вычислительно тяжёлых сетей. На слабом устройстве или при огромных накладных расходах загрузки выигрыш может съесться. Меряйте тёплый вывод на целевых машинах.

Можно ли запускать свою CRNN из PyTorch?

Да через экспорт в ONNX и проверку операторов + паритет препроцесса. Не каждый слой и кастомный op переживёт экспорт без доработки.

Безопасно ли обрабатывать паспорта и меддокументы в браузере?

Локальный путь снижает передачу на сервер вывода, но не отменяет межсайтовый скриптинг, вредоносные расширения и политику хранения на диске. Это часть угрозной модели, не волшебная кнопка «безопасно».

Покроет ли WebGPU всех пользователей в 2026?

Нет. Ориентир поддержки высокий, но не 100%. Без WASM или сервера вы сознательно режете аудиторию.

Дальше по теме

Идеи следующих материалов серии: ONNX: от PyTorch до Runtime, ML-фреймворки, YOLO в браузере, CRNN на WebGPU, квантование без магии, ИИ «сначала офлайн».

Отдельно стоит зафиксировать ожидания заказчика: «ИИ в браузере» не значит «без инфраструктуры». Вам всё равно нужны хостинг статических весов или CDN, политика обновления моделей, телеметрия ошибок на клиенте и план, что делать, когда на слабом ноутбуке тёплый вывод выходит за бюджет времени. Именно эти договорённости отличают демо от продукта.

Заключение

WebGPU даёт браузеру GPU-вычисления. Transformers.js упрощает запуск моделей. ONNX Runtime Web связывает веса с провайдерами исполнения. Вместе они позволяют держать OCR, детект и компактное зрение на устройстве пользователя — с честным запасным путём, бюджетом размера модели и рабочим потоком вокруг интерфейса. Будущее веб-ИИ выглядит не как «всё только в браузере» или «всё только на сервере», а как сочетание клиентского вывода для чувствительных и частых задач с серверным контуром для тяжёлых моделей и контроля.

Комментарии

Загрузка комментариев…