Деплой на Cloudflare Workers и ограничения среды

ONNX Runtime Web (ORT Web) предоставляет возможность выполнять предобученные модели в формате ONNX в среде браузера и на серверной стороне с использованием Node.js или WebAssembly. При деплое на Cloudflare Workers важно учитывать специфику этой среды, ограничения по памяти, времени выполнения и доступным API.

Выбор среды исполнения

Cloudflare Workers используют V8 Isolate — легковесный контейнер для выполнения JavaScript. Это накладывает следующие особенности:

  • Отсутствие полноценного Node.js API. Многие модули, доступные в Node.js, недоступны. Использовать можно только Web API и предоставленные Worker API.
  • Ограничение на память. По умолчанию изолят ограничен несколькими сотнями мегабайт, что важно при работе с большими моделями ONNX.
  • Ограничение времени выполнения. Время одного запроса ограничено, поэтому обработка больших батчей данных должна быть оптимизирована.

Для использования ORT Web в Workers предпочтителен режим WebAssembly (wasm) или WebAssembly SIMD (wasm-simd) при поддержке SIMD инструкций. Это обеспечивает кросс-платформенность и совместимость с ограниченной средой Workers.

Инициализация ONNX Runtime Web в Worker

Используется стандартный импорт модуля через ESM:

import * as ort from "onnxruntime-web";

// Инициализация с выбором backend
const session = await ort.InferenceSession.create("model.onnx", {
    executionProviders: ['wasm'],
    graphOptimizationLevel: 'all'
});

Ключевые параметры:

  • executionProviders — массив поддерживаемых провайдеров ('wasm', 'webgl', 'webgpu').
  • graphOptimizationLevel — оптимизация графа модели ('all', 'basic', 'none').

В среде Workers доступен только wasm и частично webgpu при включении соответствующих флагов. Использование webgl невозможно.

Загрузка модели

Cloudflare Workers не имеют доступа к локальной файловой системе, поэтому модель следует загружать по URL или из KV/Asset Storage. Пример загрузки из внешнего источника:

async function loadModel(url) {
    const response = await fetch(url);
    const arrayBuffer = await response.arrayBuffer();
    return await ort.InferenceSession.create(arrayBuffer, { executionProviders: ['wasm'] });
}

const session = await loadModel("https://example.com/model.onnx");

Особенности:

  • fetch работает асинхронно, поэтому создание сессии модели также асинхронное.
  • Размер модели не должен превышать ограничение памяти Worker (обычно до 128–256 МБ без использования платных тарифов).

Подготовка входных данных

ORT Web требует подачи входов в формате TypedArray или Tensor. В Worker данные чаще всего приходят в виде JSON или бинарных payload’ов:

import { Tensor } from "onnxruntime-web";

const inputTensor = new Tensor('float32', new Float32Array([1.0, 2.0, 3.0, 4.0]), [2, 2]);
const feeds = { input: inputTensor };

Важно:

  • Размер тензора должен учитывать ограничение памяти.
  • Для больших батчей рекомендуется разделять данные на мини-батчи, чтобы избежать переполнения памяти.

Выполнение инференса

Инференс в Worker выполняется синхронно через метод run с передачей входных тензоров:

const output = await session.run(feeds);
console.log(output.output.data);

Оптимизация времени выполнения:

  • Использование graphOptimizationLevel: 'all' снижает количество промежуточных операций.
  • Минимизация копирования данных между массивами.
  • Предварительное выделение буферов памяти для тензоров, если инференс повторяется часто.

Ограничения и особенности среды

  1. Отсутствие доступа к файловой системе. Только загрузка через URL или KV Storage.
  2. Ограничение памяти. Модели размером >100–200 МБ могут вызвать сбой при стандартных тарифах Workers.
  3. Ограничение времени выполнения. Большие модели или сложные вычисления должны выполняться партиями или использовать платные тарифы с увеличенным лимитом времени.
  4. Нет поддержки Node.js специфичных модулей. Например, fs, child_process и нативные расширения не работают.
  5. WebGL недоступен. Доступны только wasm и webgpu (на экспериментальных тарифах).
  6. Асинхронность. Любая загрузка данных и инференс должны быть реализованы через async/await.

Рекомендации по оптимизации

  • Компактные модели ONNX предпочтительнее, особенно для Worker Free и Pro.
  • Использование формата float16 для весов снижает потребление памяти.
  • Разделение больших батчей на несколько запросов уменьшает риск превышения времени выполнения.
  • Кэширование моделей в KV Storage для ускорения повторных запросов.
  • Предварительная оптимизация модели через onnxruntime-tools (фьюжн операций, конвертация в float16) значительно ускоряет инференс в WebAssembly.

Пример полного потока в Cloudflare Worker

import * as ort from "onnxruntime-web";

addEventListener("fetch", event => {
  event.respondWith(handleRequest(event.request));
});

async function handleRequest(request) {
  const session = await ort.InferenceSession.create(
    await fetch("https://example.com/model.onnx").then(res => res.arrayBuffer()),
    { executionProviders: ['wasm'], graphOptimizationLevel: 'all' }
  );

  const inputTensor = new ort.Tensor('float32', new Float32Array([1,2,3,4]), [2,2]);
  const feeds = { input: inputTensor };

  const output = await session.run(feeds);
  return new Response(JSON.stringify(output.output.data));
}

Этот подход обеспечивает работу ONNX модели в ограниченной среде Cloudflare Workers, минимизируя риски переполнения памяти и превышения времени выполнения, при сохранении высокой производительности через оптимизацию графа и использование WebAssembly.