npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@memberjunction/predictive-studio-sidecar

v5.47.0

Published

Self-managing TypeScript wrapper for the Predictive Studio Python ML sidecar. Spawns a bundled FastAPI microservice as a child process (managed mode) or connects to a remote/containerized instance, exposing a typed /train + /predict + /health client.

Readme

@memberjunction/predictive-studio-sidecar

A self-managing TypeScript wrapper for Predictive Studio's Python ML sidecarnew MLSidecar(); await s.start() and you have a live training/inference service. No Docker required.

WhatMLSidecar, a TypeScript class fronting a CPU-only FastAPI service (bundled in src/python/) that trains and serves tabular ML models over the contract defined in @memberjunction/predictive-studio-core.

Why — Node is poor at ML training; Python is excellent. So MJ (TypeScript) assembles the feature matrix and orchestrates, and this sidecar does the CPU-bound fitting (/train) and inference (/predict). Keeping it self-managing means a developer needs zero infrastructure to train a model locally.

How it fits — in the four-layer Predictive Studio architecture (data → feature → model → inference) this is the model/inference compute tier. It follows the @memberjunction/sqlglot-ts bundled-microservice pattern: the Python service ships inside this npm package (src/python/) and MLSidecar spawns it as a child process on demand. Managed spawn is the default and needs no Docker — it just works once the bundled venv exists (npm run setup:python). A remote/containerized topology is opt-in, not a prerequisite.

For the full architecture, read the Predictive Studio Guide (§2 covers this package); for the design record, plans/predictive-studio.md.

Two topologies

| Mode | When | What start() does | |------|------|---------------------| | Managed (default) | nothing configured | Spawns the bundled FastAPI service on 127.0.0.1 with an ephemeral port, reads PREDICTIVE_STUDIO_SIDECAR_PORT=<n> from its stdout, polls /health until ready, registers SIGINT/SIGTERM/exit cleanup. | | Remote | url option or PREDICTIVE_STUDIO_SIDECAR_URL env set | Connects only — no child process — and just verifies /health. Use for a containerized/scaled sidecar. |

Quick start (managed mode)

import { MLSidecar } from '@memberjunction/predictive-studio-sidecar';

const s = new MLSidecar();          // managed mode by default
await s.start();                    // spawns the bundled Python service

const trained = await s.train({
  algorithm: 'xgboost',
  problem_type: 'classification',
  hyperparameters: {},
  validation: { strategy: 'train_test_split', test_size: 0.25 },
  feature_schema: [{ Name: 'x0', Kind: 'numeric' }, { Name: 'x1', Kind: 'numeric' }],
  preprocessing: [{ op: 'standardize', cols: ['x0', 'x1'] }],
  target: 'label',
  data: { columns: ['x0', 'x1', 'label'], rows: [/* ... */] },
});

const { predictions } = await s.predict({
  artifact_b64: trained.artifact_b64,
  fitted_preprocessing: trained.fitted_preprocessing,
  feature_schema: [{ Name: 'x0', Kind: 'numeric' }, { Name: 'x1', Kind: 'numeric' }],
  rows: [{ x0: 1.2, x1: -0.4 }],
});

await s.stop();                     // shut the child down

Remote mode

const s = new MLSidecar({ url: 'http://predictive-studio-sidecar:8000' });
await s.start();                    // just verifies /health — no spawn
// ... train / predict / health ...
// stop() is a no-op (this client never owned the process)

MLSidecar API

new MLSidecar(options?: {
  url?: string;                 // remote-mode base URL (also via PREDICTIVE_STUDIO_SIDECAR_URL)
  pythonPath?: string;          // managed-mode interpreter; defaults to bundled .venv python, else python3
  startupTimeoutMs?: number;    // default 30000
  requestTimeoutMs?: number;    // default 300000 (training can be slow)
});

await s.start(): Promise<void>;                       // spawn (managed) or verify /health (remote)
await s.stop(): Promise<void>;                        // SIGTERM the child (no-op in remote mode)
await s.train(req: TrainRequest): Promise<TrainResponse>;
await s.predict(req: PredictRequest): Promise<PredictResponse>;
await s.health(): Promise<SidecarHealthResponse>;

s.IsRunning: boolean;   // remote always true; managed needs a live child
s.IsRemote:  boolean;
s.Port:      number | null;   // ephemeral port in managed mode, null in remote

TrainRequest / TrainResponse / PredictRequest / PredictResponse are imported from @memberjunction/predictive-studio-core — import them from there, not from this package.

Setting up the bundled Python environment

The managed mode spawns a Python interpreter. Create the bundled venv + install the pinned requirements once:

cd packages/AI/PredictiveStudio/Sidecar
npm run setup:python      # creates .venv and pip-installs src/python/requirements.txt

macOS: xgboost / lightgbm need an OpenMP runtime. Install it once:

brew install libomp

MLSidecar automatically appends DYLD_LIBRARY_PATH=/opt/homebrew/opt/libomp/lib to the spawn environment on darwin, so the venv finds libomp at runtime. On Linux the OpenMP runtime is libgomp1 (install via your distro's package manager).

If you prefer your own interpreter, pass pythonPath or set PREDICTIVE_STUDIO_SIDECAR_URL and run the service yourself.

Running the Python tests

npm run setup:python
npm run test:python       # runs pytest (19 tests) against the bundled venv

The anti-skew core (why this exists)

Stateful transforms — impute, standardize, onehot, bin — are fit once at /train and returned as fitted_preprocessing; /predict only applies those frozen parameters, never re-fits. This fit-once / apply-everywhere split prevents train/serve skew and is locked down by src/python/tests/test_preprocessing_golden.py.

Remote / scaled deployment (optional)

Managed in-process spawn is the default and needs no extra infrastructure. For a scaled or isolated deployment, run the bundled service yourself (any process manager / host) and point MJAPI at it via PREDICTIVE_STUDIO_SIDECAR_URL — then MLSidecar connects to that URL instead of spawning a child process.

Tests

  • src/python/tests/test_train_predict.py — trains + predicts each algorithm on a synthetic make_classification / make_regression fixture, asserts sane metrics, and round-trips /predict via both the artifact and the warm-cache model_id.
  • src/python/tests/test_preprocessing_golden.py — the anti-skew golden tests.
  • src/__tests__/ml-sidecar.test.ts — TypeScript unit tests (spawn + HTTP mocked, no live process).

How it fits the whole

predictive-studio-core  → the /train + /predict contract (TrainRequest, PredictRequest, …)
        │ implemented by
this package (MLSidecar) → TS wrapper + bundled Python FastAPI service (app/main.py)
        │ used by
predictive-studio (Engine) → MJSidecarTrainer (training) · MJSidecarPredictor (scoring)

MJ (TypeScript) assembles the feature matrix and orchestrates; this sidecar does the CPU-bound fitting (/train) and inference (/predict). The fit-once preprocessing (§ "The anti-skew core" above) and the warm LRU model cache are what let the engine train in seconds-to-minutes and serve interactive single-record scores fast.