Skip to Content

ML Layer

The ML layer gives the Health AI Platform a clean boundary for Python-based analysis without forcing the rest of the repository to become Python-first.

In this repository snapshot:

  • apps/ml-service is a FastAPI service
  • packages/ml-client is the TypeScript client
  • the checked-in API surface is currently focused on service health

Why this boundary exists

Node and TypeScript are a good fit for apps, routing, and workflow orchestration. Python is a better fit for some numerical and scientific workloads.

The ML layer keeps those concerns separate.

TypeScript apps and packages | v @loop/ml-client | v FastAPI ML service

Current service shape

The FastAPI app mounts the health router:

from fastapi import FastAPI from app.routes.health import router as health_router app = FastAPI( title="Loop ML Service", description="Machine learning service for Loop Health AI Platform", version="0.1.0", ) app.include_router(health_router)

Health endpoint

The current route returns:

  • overall status
  • Python version
  • whether major dependencies are importable
  • installed versions for core packages
curl http://localhost:8000/health

Example response:

{ "status": "ok", "python_version": "3.11.8", "dependencies": { "pandas": true, "scikit_learn": true, "scipy": true }, "versions": { "fastapi": "0.115.0", "pandas": "2.2.2", "scikit_learn": "1.5.1", "scipy": "1.14.0" } }

Calling from TypeScript

The checked-in client is intentionally small:

import { MLClient } from '@loop/ml-client'; const ml = new MLClient({ baseUrl: 'http://localhost:8000', timeoutMs: 5000, }); const health = await ml.healthCheck(); console.log(health.status);

Local startup

cd apps/ml-service python3 -m venv .venv source .venv/bin/activate pip install -r requirements.txt uvicorn app.main:app --reload --port 8000

When to use the ML layer

Use the ML boundary when work is:

  • numerically heavy
  • scientific Python dependent
  • isolated enough to benefit from a service contract

Keep work in TypeScript when it is:

  • request orchestration
  • workflow evaluation
  • app routing
  • lightweight transformation

Example platform handshake

import { WorkflowEngine } from '@loop/workflow-engine'; import { MLClient } from '@loop/ml-client'; const workflow = WorkflowEngine.load({ id: 'ml-smoke-test', name: 'ML Smoke Test', version: '1.0.0', steps: [{ id: 'check', type: 'check_biomarker' }], }); const ml = new MLClient({ baseUrl: 'http://localhost:8000' }); const health = await ml.healthCheck(); console.log({ workflowRegistered: WorkflowEngine.get('ml-smoke-test') !== undefined, mlStatus: health.status, });

Current limits

The README describes the ML service as a place for pattern discovery, statistical tests, and outcome prediction, but those endpoints are not present in the checked-in service today.

That means docs should treat the ML layer as:

  • a real service boundary
  • a small current API
  • a clear place for future analytics endpoints