151 слов | 1 минута

Node.js + ONNX: ML-микросервис для Bitrix

Архитектура интеграции ML-модели с проектом на Bitrix (PHP) через Node.js-микросервис без Python.

Архитектура

Bitrix (PHP)
      ↓ HTTP POST
Node.js (Express + ONNX Runtime)
      ↓
ONNX-модель (model.onnx)

Bitrix отправляет данные → Node.js выполняет модель → возвращает результат в JSON.

Поддерживаемые типы моделей

Тип задачи Модели
Классификация текста BERT, DistilBERT, RoBERTa, ALBERT
Генерация текста GPT-2 small, DistilGPT2
Классификация изображений MobileNetV2, EfficientNet-Lite, ResNet50
Детекция объектов YOLOv5/YOLOv8 (ONNX), SSD MobileNet
Табличные данные CatBoost, LightGBM, XGBoost, sklearn
Аудио Whisper Tiny (ONNX), Wav2Vec2

Не запускать через ONNX Runtime:

  • Большие LLM (GPT-J, LLaMA 13B+)
  • Модели весом более 3 ГБ
  • GPU-зависимые модели

Установка Node.js

curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs

Создание ML-сервиса

mkdir ml-service
cd ml-service
npm init -y
npm install express onnxruntime-node

server.js

const express = require("express");
const ort = require("onnxruntime-node");

const app = express();
app.use(express.json());

let session;

async function loadModel() {
    session = await ort.InferenceSession.create("model.onnx");
    console.log("ONNX model loaded");
}

app.post("/predict", async (req, res) => {
    try {
        const input = Float32Array.from(req.body.input);

        const feeds = {
            input: new ort.Tensor("float32", input, [1, input.length])
        };

        const results = await session.run(feeds);

        res.json({
            result: results[Object.keys(results)[0]].data
        });

    } catch (error) {
        res.status(500).json({ error: error.message });
    }
});

loadModel();
app.listen(8000, () => console.log("ML API running on port 8000"));

Автозапуск через systemd

Файл /etc/systemd/system/ml-service.service:

[Unit]
Description=ML Node.js Service
After=network.target

[Service]
ExecStart=/usr/bin/node server.js
WorkingDirectory=/var/www/ml-service
Restart=always
User=root

[Install]
WantedBy=multi-user.target

Вызов из Bitrix (PHP)

function ml_predict($data)
{
    $url = "http://127.0.0.1:8000/predict";

    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(["input" => $data]));

    $response = curl_exec($ch);
    curl_close($ch);

    return json_decode($response, true);
}

$result = ml_predict([1.0, 2.0, 3.0]);
print_r($result);

Преимущества подхода

  • Bitrix остаётся на чистом PHP — без изменения архитектуры.
  • Модель загружается в память один раз при старте сервиса.
  • Ошибка в ML-сервисе не уронит PHP-процесс Битрикса.
  • Работает на любом VPS без GPU.
  • Обновление модели не требует изменений на сайте.