Использование onnxruntime-node для отладки на сервере

Библиотека onnxruntime-node является серверной версией ONNX Runtime для Node.js. Она позволяет выполнять модели, созданные в формате ONNX, с высокой производительностью, используя нативные бинарные зависимости, что особенно важно для отладки и тестирования сложных моделей на сервере.

Для установки используется стандартный пакет npm:

npm install onnxruntime-node

После установки рекомендуется проверить доступные устройства выполнения (CPU и, при поддержке, GPU). Это позволяет определить, какие оптимизации доступны для конкретного окружения:

const ort = require('onnxruntime-node');

console.log('Доступные Execution Providers:', ort.getAvailableExecutionProviders());

Загрузка модели и подготовка сессии

Сессия выполнения модели создаётся с помощью метода InferenceSession.create, которому передаётся путь к файлу модели ONNX. Для серверной отладки можно явно указать устройство выполнения через параметр executionProviders:

const session = await ort.InferenceSession.create('model.onnx', {
  executionProviders: ['cpu']  // или ['cuda'] при наличии GPU
});

Параметр executionProviders управляет тем, какие вычислительные движки будут использоваться. CPU-провайдер подходит для отладки и тестирования, GPU — для ускоренной инференции.

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

Модель ONNX ожидает вход в виде тензора, поэтому необходимо преобразовать данные в формат ort.Tensor. Для этого используются типы данных float32, int32 и другие, соответствующие определению модели.

Пример создания тензора:

const inputData = new Float32Array([1.0, 2.0, 3.0, 4.0]);
const inputTensor = new ort.Tensor('float32', inputData, [2, 2]); // форма [2,2]

Важно точно указывать форму и тип данных, иначе сессия вызовет ошибку на этапе инференции.

Выполнение инференции

Для выполнения инференции используется метод session.run, которому передаётся объект с именами входов и соответствующими тензорами:

const feeds = { input: inputTensor };
const results = await session.run(feeds);

console.log(results.output.data);

Ключевые моменты:

  • Имена входов и выходов должны строго соответствовать определению модели.
  • Метод run возвращает объект, где ключи — имена выходов, а значения — тензоры.

Отладка и профилирование

Для диагностики производительности и поиска узких мест используется включение логирования и профилирования сессии:

const session = await ort.InferenceSession.create('model.onnx', {
  executionProviders: ['cpu'],
  logSeverityLevel: 0, // 0 — подробное логирование
  enableProfiling: true
});

// После инференции можно получить профиль
console.log(session.endProfiling());

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

Работа с большими моделями

Для больших моделей следует учитывать управление памятью и размер батча. ONNX Runtime позволяет:

  • Использовать пакетную обработку (batching) для повышения производительности.
  • Загружать модели частично через опции graphOptimizationLevel:
const session = await ort.InferenceSession.create('large_model.onnx', {
  executionProviders: ['cpu'],
  graphOptimizationLevel: 'all' // базовая, расширенная или все оптимизации
});

Уровень оптимизации управляет компромиссом между скоростью инференции и временем загрузки модели. Для отладки рекомендуется включать все оптимизации, чтобы тестировать модель в максимально приближенном к боевому режиме виде.

Интеграция с Node.js сервером

onnxruntime-node легко интегрируется с серверными фреймворками:

const express = require('express');
const app = express();

app.use(express.json());

app.post('/predict', async (req, res) => {
  const inputArray = Float32Array.from(req.body.input);
  const inputTensor = new ort.Tensor('float32', inputArray, [1, inputArray.length]);
  
  const results = await session.run({ input: inputTensor });
  res.json({ output: Array.from(results.output.data) });
});

app.listen(3000, () => console.log('Server started on port 3000'));

Такой подход позволяет протестировать инференцию на сервере и выявлять ошибки до переноса модели в браузер или на клиентское устройство.

Обработка ошибок и исключений

onnxruntime-node генерирует исключения при:

  • Несоответствии типов данных или форм входов.
  • Ошибках при загрузке модели.
  • Превышении доступной памяти.

Рекомендуется использовать конструкцию try-catch для отладки:

try {
  const results = await session.run({ input: inputTensor });
} catch (err) {
  console.error('Ошибка инференции:', err.message);
}

Это позволяет детально логировать проблемы и отслеживать причину падений модели.