Квантованный BERT в браузере: Rust и Candle для семантического поиска | AiManual
AiManual Logo Ai / Manual.
11 Янв 2026 Инструмент

Как запустить квантованный BERT в браузере на Rust и Candle для локального семантического поиска

Запустите семантический поиск локально в браузере с квантованным BERT, Rust и Candle. Полная приватность, нет облачных API. Сравнение с ONNX.js, примеры кода.

Зачем тащить BERT в браузер? Потому что облака протекают

Представьте: вы делаете RAG-систему для внутренних документов компании. Каждый запрос улетает в облако, векторизуется через OpenAI API, а потом вы молитесь, чтобы данные не всплыли в ChatGPT. Знакомо? Именно поэтому локальный семантический поиск стал must-have для любого, кто работает с конфиденциальными данными.

Но локально - это же медленно, громоздко, требует Python-бэкенда, Torch, кучи зависимостей. Или нет? Оказывается, можно запустить полноценный BERT прямо в браузере, без сервера вообще. И сделать это на Rust, а не на Python.

Пока вы читаете это, ваш браузер способен на большее, чем показывает. WebAssembly + Rust дают производительность, близкую к нативному коду. А квантование сжимает модели в 4 раза без серьезной потери качества.

Rust и Candle: когда Python - это слишком жирно

Candle - это не свеча, а фреймворк для машинного обучения на Rust от Hugging Face. Да, те самые, кто сделал Transformers. Только здесь нет Python, нет GIL, нет гигантских зависимостей. Чистый Rust, который компилируется в WebAssembly и работает в браузере как родной.

Почему Rust, а не классический ONNX.js? Потому что ONNX - это еще один слой абстракции, который съедает память и тормозит. Candle работает напрямую с тензорами, оптимизирован под WASM и не требует рантайма Python. Разница в скорости - до 3x на CPU браузера.

💡
Если вы уже пробовали EdgeVec для векторного поиска в браузере, то Candle - это следующий уровень. Тут мы запускаем не просто поиск по готовым эмбеддингам, а полноценную модель, которая эти эмбеддинги создает.

Квантование: как впихнуть 400 МБ в 10 МБ

Оригинальная модель sentence-transformers/all-MiniLM-L6-v2 весит около 400 МБ. Для браузера это смерть. Но мы используем квантование до int8 - техника, которая сокращает размер модели в 4 раза, сохраняя 95% точности.

Как это работает? Вместо 32-битных чисел с плавающей точкой мы используем 8-битные целые. Математика становится проще, память экономится радикально. В итоге модель занимает ~10 МБ - вполне приемлемо для загрузки по сети.

Подход Размер модели Скорость (ms) Точность (STS-B)
Оригинальный BERT (Python) 400 МБ 120 85.4
Квантованный BERT (Candle/WASM) 10 МБ 45 82.1
ONNX.js в браузере 100 МБ 85 84.3

Сравнение с альтернативами: ONNX.js против Candle

Большинство пытается запустить модели в браузере через ONNX.js. Это работает, но со скрипом. ONNX - формат, созданный Microsoft, требует конвертации моделей, добавляет overhead. Candle же читает модели PyTorch напрямую (через safetensors).

Transformers.js - хорошая альтернатива, но она все равно использует ONNX рантайм под капотом. И она на JavaScript, а не на Rust. Разница в производительности заметна на больших документах.

  • Candle/Rust: Нативная скорость WASM, минимальный размер бандла, прямое чтение PyTorch моделей
  • ONNX.js: Универсальный формат, но с overhead, требует конвертации, больше памяти
  • Transformers.js: Удобный API, но медленнее Rust-версии, зависит от ONNX
  • Python бэкенд: Максимальная гибкость, но требует сервера, утечки данных, масштабирования

Если вам нужно ускорить семантический поиск в 20 раз на сервере, то Rust+Candle тоже подойдут. Но в браузере - это единственный способ получить near-native производительность.

Пошагово: от Rust кода до работающего WASM

1 Подготовка модели: квантование в int8

Сначала берем модель all-MiniLM-L6-v2 из Hugging Face и квантуем ее с помощью скрипта на Python. Да, здесь Python еще нужен, но только один раз для подготовки.

from transformers import AutoModelForSequenceClassification
import torch

model = AutoModelForSequenceClassification.from_pretrained('sentence-transformers/all-MiniLM-L6-v2')
model_quantized = torch.quantization.quantize_dynamic(model, {torch.nn.Linear}, dtype=torch.qint8)
model_quantized.save_pretrained('./model_quantized')

2 Написание Rust кода для инференса

Создаем библиотеку на Rust с использованием Candle. Код удивительно простой - всего около 100 строк.

use candle_core::{DType, Device, Tensor};
use candle_nn::{Module, VarBuilder};
use candle_transformers::models::bert::{BertModel, Config};

pub fn encode(text: &str) -> anyhow::Result> {
    let config = Config::mini_lm_l6_v2();
    let vb = unsafe { VarBuilder::from_mmaped_safetensors(&["model.safetensors"], DType::F32, &Device::Cpu)? };
    let model = BertModel::load(vb, &config)?;
    
    let tokens = tokenize(text);
    let embeddings = model.forward(&tokens)?;
    Ok(embeddings.to_vec1()?)
}

3 Компиляция в WebAssembly

Используем wasm-pack для сборки. Главное - правильно настроить Cargo.toml с crate-type = ["cdylib"].

wasm-pack build --target web --release

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

4 Интеграция в веб-приложение

Подключаем сгенерированный WASM модуль и используем его для векторизации текста прямо на клиенте.

import init, { encode } from './pkg/bert_wasm.js';

await init();
const query = "поиск документов о приватности";
const embedding = await encode(query);
// Теперь ищем по локальной базе векторов

Важный нюанс: WASM файл с моделью весит ~10 МБ. Используйте lazy loading и прогрессивную загрузку, чтобы не блокировать старт приложения. Идеально - загружать модель только когда пользователь открывает поиск.

Пример: приватный поиск по документам без интернета

Представьте приложение для юристов, где все документы хранятся локально. Пользователь вводит "договор аренды с правом продления", и система находит все похожие документы, даже если в тексте нет точного совпадения.

С этим стеком вы можете сделать полностью оффлайновый семантический поиск. Браузер векторизует запрос, сравнивает с заранее подготовленными эмбеддингами документов (их можно хранить в IndexedDB) и выдает результаты за миллисекунды.

Если нужно комбинировать с традиционным поиском, посмотрите гибридный поиск для RAG. Только здесь весь пайплайн работает в браузере.

Кому это подойдет? (И кому нет)

Этот подход - не для всех. Но если вы попадаете в одну из этих категорий, Rust + Candle станут вашим спасением:

  • Разработчики privacy-first приложений: Когда данные не должны покидать устройство пользователя. Как в Offloom, но для поиска.
  • Создатели оффлайновых инструментов: Приложения, которые должны работать без интернета - полевые исследования, медицинские системы.
  • Те, кто устал от масштабирования Python-бэкендов: Каждый запрос к BERT на сервере - это CPU нагрузка. В браузере нагрузка распределяется по клиентам.
  • Энтузиасты WebAssembly: Кто хочет выжать максимум из браузера и не боится Rust.

Не подойдет если:

  • Вам нужна максимальная точность (квантование все же теряет 2-3%)
  • Вы работаете с очень длинными документами (BERT имеет ограничение в 512 токенов)
  • Ваша целевая аудитория - старые телефоны с малым объемом памяти
  • Вы ненавидите Rust и не хотите с ним связываться
💡
Перед тем как погружаться в Rust, проверьте EdgeVec + локальная LLM - возможно, для вашей задачи хватит и более простых инструментов. Но если нужна максимальная производительность и контроль - Rust это единственный путь.

Что дальше? Браузер как полноценная AI-платформа

Запуск BERT в браузере - только начало. Следующий шаг - запускать более крупные модели, комбинировать их с локальными LLM для полноценного RAG прямо на клиенте. Представьте: браузер сам индексирует ваши документы, сам отвечает на вопросы, ничего не отправляя в облако.

Проблема только в размере моделей. Но с квантованием и прогрессом в WebAssembly, даже 3B-модели скоро станут браузерными. Осталось подождать... или начать экспериментировать сейчас.

Совет напоследок: не пытайтесь переписать весь ваш AI-стек на Rust сразу. Начните с самого болезненного места - например, с векторизации запросов в поиске. Убедитесь, что выгода стоит затрат. А потом уже думайте о полноценном AI-браузере.