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-serviceis a FastAPI servicepackages/ml-clientis 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 serviceCurrent 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/healthExample 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 8000When 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