Реклама
Перетяжка // Коробка 3.0

WebLLM запускает языковую модель в браузере без сервера за один вечер

Как запустить языковую модель прямо в браузере на WebGPU без сервера: команды из README, требования к видеопамяти, замеры скорости и честные ограничения.

Обложка: WebLLM запускает языковую модель в браузере без сервера за один вечер

WebLLM — открытый движок команды MLC AI, который выполняет языковую модель внутри браузера на WebGPU и отдаёт её через API в стиле OpenAI. Сервера для инференса нет: веса скачиваются один раз, дальше промпты и ответы не покидают вкладку. Проект живёт с 2023 года, но 2 сентября 2026 года снова поднялся на первую страницу Hacker News с 92 очками, а на GitHub у него 18 846 звёзд и 1 372 форка по данным API на 3 сентября.

Я разбираю WebLLM как рабочий инструмент: что нужно от железа и браузера, сколько весят модели, какой скоростью придётся заплатить за отказ от сервера и где проще остаться на облачном API. Все команды и фрагменты кода взяты из README репозитория, цифры производительности из статьи авторов на arXiv, требования к видеопамяти из файла конфигурации в исходниках.

Материал для фронтенд- и фулстек-разработчиков, которым нужен чат, классификатор или JSON-извлекатель на клиенте без счёта за токены и без передачи пользовательских данных третьей стороне.

Ключевые выводы
  • WebLLM выполняет модель в браузере на WebGPU, без сервера; API совместим с OpenAI Chat Completions: стриминг, JSON-режим, seed. Вызов функций помечен в README как незавершённый.
  • Актуальная версия пакета @mlc-ai/web-llm — 0.2.84 от 27 мая 2026 года; в 2025–2026 годах вышло всего 7 релизов против 63 за 2024 год по данным реестра npm.
  • По замерам авторов на MacBook Pro M3 Max WebLLM выдаёт 41,1 токена/с на Llama-3.1-8B и 71,1 токена/с на Phi-3.5-mini, то есть 71–80% от нативного MLC-LLM на том же железе.
  • Модели в 4-битной квантизации требуют от 0,7 ГБ видеопамяти (gemma3-1b) до 6,4 ГБ (Qwen3.5-9B) по значениям vram_required_MB в src/config.ts; первый запуск качает всё это с huggingface.co.
  • WebGPU по данным MDN есть в Chrome и Edge с версии 113, в Safari 26 с сентября 2025 года, в Firefox с 141 только частично: Linux и Intel-маки не поддерживаются.

Как WebLLM выполняет модель в браузере и при чём тут WebGPU?

Модель считается на видеокарте пользователя через WebGPU, а всё, что не ложится на GPU, крутится в WebAssembly. Авторы описывают схему так: родственный проект MLC LLM компилирует открытую модель заранее в два артефакта, конвертированные веса и WASM-библиотеку с WebGPU-ядрами и вспомогательными функциями. WebLLM в браузере загружает оба артефакта с хостинга, инициализирует WebGPU-устройство и дальше исполняет граф вычислений локально.

Everything runs inside the browser with no server support and is accelerated with WebGPU.
README репозитория mlc-ai/web-llmкоманда MLC AI (перевод: «Всё выполняется внутри браузера без участия сервера и ускоряется через WebGPU»)

Отсюда же и главное ограничение, о котором в статье авторы говорят прямо: в отличие от CUDA у WebGPU нет готовых ускоренных библиотек для типовых ядер, поэтому матричные умножения и внимание команде пришлось писать и оптимизировать самой. Цена этого видна в замерах: на Apple MacBook Pro M3 Max в Chrome Canary 133 WebLLM версии 0.2.75 выдавал 41,1 токена/с на 4-битной Llama-3.1-8B против 57,7 у нативного MLC-LLM с Metal-ядрами на той же машине, и 71,1 против 89,3 токена/с на Phi-3.5-mini. Это 71,2% и 79,6% нативной скорости соответственно, замер вендора, другого железа в статье нет.

WebLLM запускает языковую модель в браузере без сервера за один вечер_8
Скорость декодирования в браузере и нативно на одном MacBook Pro M3 Max, 4-битная квантизация. График: Tproger по данным статьи авторов WebLLM на arXiv 2412.15803

Второй компонент, о котором обычно забывают, это кэш. Веса и WASM-библиотека скачиваются при первом обращении и складываются в хранилище браузера. README перечисляет четыре бэкенда, которые задаются полем cacheBackend в AppConfig: Cache API по умолчанию, IndexedDB, Origin Private File System и экспериментальный cross-origin через расширение Chrome, чтобы одни и те же веса не качались заново для каждого сайта. Без расширения движок сам откатывается на Cache API.

			import { CreateMLCEngine, prebuiltAppConfig } from "@mlc-ai/web-llm";

const appConfig = { ...prebuiltAppConfig, cacheBackend: "cross-origin" };
const engine = await CreateMLCEngine("Llama-3.1-8B-Instruct-q4f32_1-MLC", {
  appConfig,
});
		

JSON-режим, который в серверных API обычно реализован на стороне провайдера, здесь тоже выполняется локально: по README структурированная генерация встроена в WebAssembly-часть библиотеки модели, а попробовать её со своей JSON-схемой можно в JSON Playground на Hugging Face. Про то, как WASM-рантаймы догоняют нативный код, мы писали в заметке про Wasmi 2.0.

Что нужно, чтобы запустить первый чат?

Достаточно npm-пакета, одного вызова фабрики и терпения на первую загрузку весов. README даёт три варианта установки и импорт через CDN для JSFiddle и CodePen без сборщика.

			# npm
npm install @mlc-ai/web-llm
# yarn
yarn add @mlc-ai/web-llm
# or pnpm
pnpm install @mlc-ai/web-llm
		

Движок создаётся функцией CreateMLCEngine: это асинхронная фабрика: она возвращает Promise, а готовый движок с загруженной моделью получают через await. Колбэк прогресса обязателен на практике, потому что без него пользователь смотрит на пустой экран, пока качаются гигабайты.

			import { CreateMLCEngine } from "@mlc-ai/web-llm";

// Callback function to update model loading progress
const initProgressCallback = (initProgress) => {
  console.log(initProgress);
};
const selectedModel = "Llama-3.1-8B-Instruct-q4f32_1-MLC";

const engine = await CreateMLCEngine(
  selectedModel,
  { initProgressCallback: initProgressCallback }, // engineConfig
);
		
loading models requires downloading and it can take a significant amount of time for the very first run without caching previously
README репозитория mlc-ai/web-llmкоманда MLC AI (перевод: «загрузка модели требует скачивания, и при самом первом запуске без кэша это может занять значительное время»)

Дальше интерфейс тот же, что у клиента OpenAI: engine.chat.completions.create({ messages }). Одна ловушка: параметр model в запросе игнорируется, модель выбирается при создании движка или через engine.reload(model). Стриминг включается флагом stream: true, а статистика по токенам приходит только в последнем чанке, если попросить её через stream_options.

			const messages = [
  { role: "system", content: "You are a helpful AI assistant." },
  { role: "user", content: "Hello!" },
];

// Chunks is an AsyncGenerator object
const chunks = await engine.chat.completions.create({
  messages,
  temperature: 1,
  stream: true, // <-- Enable streaming
  stream_options: { include_usage: true },
});

let reply = "";
for await (const chunk of chunks) {
  reply += chunk.choices[0]?.delta.content || "";
  console.log(reply);
  if (chunk.usage) {
    console.log(chunk.usage); // only last chunk has usage
  }
}

const fullReply = await engine.getMessage();
console.log(fullReply);
		

Готовый чат для проверки железа не нужно собирать самому: WebLLM Chat сделан на том же пакете, а его код открыт в отдельном репозитории.

Какие модели доступны и сколько видеопамяти им нужно?

В список prebuiltAppConfig.model_list в src/config.ts на 3 сентября входят 165 записей: это варианты квантизации и длины контекста для семейств Llama 3.x, Qwen 2.5, Qwen 3 и Qwen 3.5, Phi 3.5 и Phi 4 mini, Gemma 2 и Gemma 3, Mistral и Ministral 3, дистилляты DeepSeek-R1, SmolLM2, OLMo 2, а также две модели эмбеддингов snowflake-arctic-embed. README при этом всё ещё перечисляет старый набор с Llama 2 и Qwen2, так что актуальный набор виден только в коде.

У каждой записи есть поле vram_required_MB, и это честнее любого «весит N гигабайт»: оно включает не только веса, но и память под KV-кэш при заданном контексте. Для 4-битных вариантов с половинной точностью (суффикс q4f16_1) разброс такой:

WebLLM запускает языковую модель в браузере без сервера за один вечер_24
Значение vram_required_MB для вариантов q4f16_1 с контекстом по умолчанию. График: Tproger по данным src/config.ts репозитория mlc-ai/web-llm, 3 сентября 2026
  • gemma3-1b-it — 0,71 ГБ; Llama-3.2-1B-Instruct — 0,88 ГБ; Qwen2.5-0.5B-Instruct — 0,94 ГБ. Помечены флагом low_resource_required, это кандидаты для встроенной графики и ноутбуков.
  • Qwen3-0.6B — 1,40 ГБ; gemma-2-2b-it — 1,90 ГБ; Llama-3.2-3B-Instruct — 2,26 ГБ.
  • Qwen3-4B — 3,43 ГБ; Phi-3.5-mini-instruct — 3,67 ГБ; Llama-3.1-8B-Instruct — 5,00 ГБ; Qwen3-8B — 5,70 ГБ; Qwen3.5-9B — 6,43 ГБ.
  • Есть и Llama-3.1-70B-Instruct в 3-битной квантизации с требованием 31,15 ГБ; на потребительской видеокарте это не запустится.

Варианты с суффиксом «-1k» урезают контекст до одной тысячи токенов и экономят память: у Llama-3.1-8B это 4,60 ГБ вместо 5,00, у Phi-3.5-mini 2,52 ГБ вместо 3,67. Все эти гигабайты приезжают с huggingface.co/mlc-ai, поэтому доступность и скорость этого хоста в вашей сети стоит проверить до того, как обещать пользователям «работает без сервера». Свою модель в формате MLC подключают через appConfig.model_list, указав URL весов и WASM-библиотеки. Какие небольшие открытые модели вышли в августе и на чём их запускать дома, мы собирали в обзоре открытых нейросетей.

Полный каталог собранных моделей лежит на mlc.ai/models. Номер совместимой сборки библиотек зашит в пакет: для 0.2.84 это константа modelVersion со значением «v0_2_84/base», так что после обновления npm-пакета кэшированные WASM-библиотеки могут потребовать перезагрузки.

Как не заморозить интерфейс: Web Worker или Service Worker?

Для обычного приложения хватает выделенного Web Worker, а Service Worker нужен, когда модель должна переживать переходы между страницами. Оба варианта в README оформлены одинаково: в потоке живёт обработчик, в основном скрипте создаётся движок-прокси с тем же интерфейсом MLCEngineInterface.

			// worker.ts
import { WebWorkerMLCEngineHandler } from "@mlc-ai/web-llm";

// A handler that resides in the worker thread
const handler = new WebWorkerMLCEngineHandler();
self.onmessage = (msg: MessageEvent) => {
  handler.onmessage(msg);
};

// main.ts
import { CreateWebWorkerMLCEngine } from "@mlc-ai/web-llm";

const engine = await CreateWebWorkerMLCEngine(
  new Worker(new URL("./worker.ts", import.meta.url), {
    type: "module",
  }),
  selectedModel,
  { initProgressCallback }, // engineConfig
);
		

С Service Worker сложнее. Его жизненным циклом управляет браузер и может убить поток без предупреждения; движок шлёт heartbeat каждые 10 секунд по умолчанию (значение keepAliveMs в src/service_worker.ts), но авторы просят закладывать обработку ошибок и в приложении. README отдельно требует создавать ServiceWorkerMLCEngineHandler на верхнем уровне скрипта и запрещает делать это внутри обработчиков activate или message: браузер перезапускает уже активный воркер без повторного события activate.

Service Worker's life cycle is managed by the browser and can be killed any time without notifying the webapp. ServiceWorkerMLCEngine will try to keep the service worker thread alive by periodically sending heartbeat events, but your application should also include proper error handling.
README репозитория mlc-ai/web-llmкоманда MLC AI (перевод: «Жизненным циклом Service Worker управляет браузер, и он может быть убит в любой момент без уведомления веб-приложения. ServiceWorkerMLCEngine будет пытаться удержать поток живым периодическими heartbeat-событиями, но ваше приложение тоже должно корректно обрабатывать ошибки»)

Отдельная ветка применения — расширения Chrome: в репозитории есть примеры базового расширения и расширения на Service Worker с WebGPU, которое держит модель в фоне. По данным MDN, в Firefox WebGPU недоступен именно в контексте Service Worker, так что этот сценарий пока привязан к Chromium.

Где WebLLM выигрывает у серверного API, а где проигрывает?

Выигрывает там, где важны приватность промптов и нулевая стоимость токена, проигрывает там, где нельзя выбирать пользователю железо. Разложу по пунктам, отделяя проверяемое от обещаний.

  • Деньги. Инференс идёт на GPU пользователя, счёт за токены равен нулю. Платите трафиком: каждый новый пользователь качает от 0,7 до 6,4 ГБ весов с Hugging Face; свой CDN нужен только тем, кто перехостит артефакты сам.
  • Приватность. Промпты и ответы на сервер не уходят, это следует из архитектуры. Но сетевые запросы есть: веса и WASM скачиваются с huggingface.co и jsdelivr, поэтому формулировка «данные никогда не покидают устройство» некорректна, и в политике приватности так писать нельзя.
  • Скорость. 71–80% от нативного инференса по замеру авторов на M3 Max. На ноутбуке с встроенной графикой цифр в статье нет, и обещать «десятки токенов в секунду» без своего замера нельзя.
  • Первый запуск. Минуты загрузки против миллисекунд первого ответа у API. Кэш спасает повторные визиты, но не первый.
  • Браузеры. По данным MDN, WebGPU есть в Chrome и Edge с версии 113 (полная поддержка на Linux только с 144 и только на Intel Gen12 и новее), в Safari 26 на macOS и iOS с 15 сентября 2025 года, в Firefox с 141 частично: есть Windows и Apple Silicon, нет Linux и Intel-маков. Проверка navigator.gpu обязательна.
  • Управление моделью. Серверный API даёт одну версию модели для всех и мгновенную замену. В WebLLM версия модели живёт в кэше каждого браузера, а обновление пакета может потребовать перекачки библиотек.
  • Функции. Вызов инструментов через tools и tool_choice в README помечен как WIP с предварительной поддержкой. Для агентских сценариев это стоп-фактор; про выбор стека для агентов у нас есть отдельный разбор.

Есть и организационный риск. По реестру npm пакет обновлялся 19 раз в 2023 году, 63 раза в 2024-м, 3 раза в 2025-м и 4 раза с начала 2026 года; последний релиз 0.2.84 вышел 27 мая. Код в репозитории при этом продолжает меняться, последний push был 3 сентября. Для продакшена это означает, что свежие модели из config.ts могут ждать релиза месяцами.

WebLLM запускает языковую модель в браузере без сервера за один вечер_38
Релизы пакета @mlc-ai/web-llm по годам, 2026 год по 3 сентября. График: Tproger по данным реестра npm
Evaluations show that WebLLM can retain up to 80% native performance on the same device with room to close the gap further.
Чарли Руан и соавторыстатья «WebLLM: A High-Performance In-Browser LLM Inference Engine», arXiv 2412.15803 (перевод: «Замеры показывают, что WebLLM сохраняет до 80% нативной производительности на том же устройстве, и разрыв ещё есть куда сокращать»)

Что делать по шагам, чтобы собрать чат на WebLLM за вечер

План ниже покрывает путь от проверки железа до защиты артефактов; команды и имена функций взяты из README для версии 0.2.84.

  1. Проверьте, что в браузере есть navigator.gpu, и покажите понятную заглушку тем, у кого его нет. По MDN это Chrome и Edge 113+, Safari 26+, Firefox 141+ с оговорками по ОС.
  2. Установите пакет: npm install @mlc-ai/web-llm (версия 0.2.84). Для прототипа без сборки подойдёт импорт с https://esm.run/@mlc-ai/web-llm.
  3. Выберите модель из prebuiltAppConfig.model_list по полю vram_required_MB. Для широкой аудитории начните с моделей с флагом low_resource_required: Llama-3.2-1B, Qwen2.5-0.5B, gemma3-1b.
  4. Создайте движок через CreateMLCEngine с initProgressCallback и выведите прогресс загрузки на экран.
  5. Перенесите инференс в Web Worker через CreateWebWorkerMLCEngine, чтобы интерфейс не замирал во время генерации.
  6. Включите стриминг флагом stream: true; для извлечения структурированных данных используйте JSON-режим из раздела Full OpenAI Compatibility.
  7. Если артефакты лежат на своём хостинге, добавьте в запись модели поле integrity с SRI-хэшами для конфига, WASM и токенизатора; хэш генерируется командой openssl из README.

При несовпадении хэша движок бросает IntegrityError, либо пишет предупреждение и продолжает работу, если задать onFailure: "warn". Без поля integrity проверка не выполняется вовсе, как и в прежних версиях.

Что дальше: чего нет в WebLLM и за чем следить

Первое, за чем стоит следить, это релиз после 0.2.84: в src/config.ts уже есть Qwen3.5 и Ministral 3, и вопрос в том, когда они попадут в опубликованный пакет. Второе — статус вызова функций, который держится в README как WIP. Третье — cross-origin хранилище: сейчас это расширение Chrome и экспериментальный API, а без него каждый сайт качает свою копию весов.

Мы не проверяли скорость на встроенной графике и на Windows-ноутбуках; единственные опубликованные цифры относятся к MacBook Pro M3 Max. Доступность huggingface.co и esm.run из конкретной сети мы тоже не измеряли: перед запуском продукта на WebLLM стоит замерить время первой загрузки у своей аудитории или перехостить артефакты.

Частые вопросы
1
Работает ли WebLLM в Firefox и Safari?

Зависит от WebGPU. По данным MDN, Safari 26 на macOS и iOS поддерживает WebGPU с 15 сентября 2025 года. Firefox поддерживает его с версии 141 частично: на Windows и на Apple Silicon, но не на Linux, не на Intel-маках и не в Service Worker. Полная поддержка на Linux есть только в Chrome и Edge с версии 144 и только на GPU Intel Gen12 и новее.

2
Сколько места занимает модель на диске?

Порядка требуемой видеопамяти из поля vram_required_MB: от 0,71 ГБ для gemma3-1b до 6,43 ГБ для Qwen3.5-9B в 4-битной квантизации. Веса лежат в Cache API браузера по умолчанию, можно переключить на IndexedDB или OPFS.

3
Уходит ли что-то на сервер во время диалога?

Промпты и ответы обрабатываются локально и на сервер не отправляются. Сетевые запросы есть при первой загрузке: веса и WASM-библиотека скачиваются с huggingface.co и CDN, поэтому полностью «без сети» это не работает.

4
Можно ли пользоваться офлайн?

После того как веса и библиотека попали в кэш браузера, да. README предлагает для этого Service Worker, который не перезагружает модель при каждом визите; в Firefox WebGPU в Service Worker недоступен.

5
Можно ли подключить свою модель?

Да, если она сконвертирована в формат MLC: в appConfig.model_list указываются URL весов и WASM-библиотеки. Инструкция по компиляции есть в документации MLC LLM.

Источники: GitHub: mlc-ai/web-llm (README, лицензия Apache-2.0), src/config.ts: prebuiltAppConfig.model_list с vram_required_MB, src/service_worker.ts: keepAliveMs и heartbeat, arXiv 2412.15803: WebLLM: A High-Performance In-Browser LLM Inference Engine, Блог MLC: WebLLM, 13 июня 2024, Документация WebLLM, Реестр npm: @mlc-ai/web-llm (версии и даты), Hacker News: обсуждение WebLLM 2 сентября 2026, MDN: WebGPU API, совместимость браузеров, Hugging Face: модели mlc-ai, WebLLM JSON Playground, WebLLM Chat, Каталог моделей MLC, GitHub: mlc-ai/mlc-llm

Изображение на обложке: Скриншот: chat.webllm.ai

Рекомендуем