John Jomi
All Projects
In Development/Case Study

SkinAIBot — Medical AI Diagnosis Platform

A medical AI platform for skin disease diagnosis and analysis, built on a deliberately separated two-team architecture that splits the full-stack application from the AI/ML platform so the two can evolve independently.

The Problem

Medical imaging products fail in a particular way: the model and the application get entangled, so retraining a classifier means redeploying the whole product, and the application team ends up blocked on ML work they cannot do. Splitting the two along a stable contract lets the application ship against a mock while the real model is still being trained.

Two-team architecture

The system is split into an Application team owning the full-stack product and an AI/ML team owning the inference service. The AI service runs behind its own interface, and the application talks to it over HTTP — during local development that endpoint is a mock, so the frontend and backend are never blocked on model availability.

Layered backend

The FastAPI backend enforces strict layering with explicit dependency rules, so business logic never reaches directly for the database or the model.

LayerResponsibility
api/HTTP handling, routing and request validation
schemas/Pydantic request and response contracts
services/Business logic, use cases and orchestration
repositories/Database access
models/SQLAlchemy domain models
ai/Model adapters, providers and prompt templates
storage/File storage abstractions over Azure Blob

Inference pipeline

An uploaded image is preprocessed — resized and normalized — then classified, producing top-K predictions with confidence scores alongside an explainability heatmap. The explainability output matters clinically: a prediction a physician cannot interrogate is a prediction they cannot act on.

ComponentTechnology
Image classifierAzure Custom Vision / PyTorch
ExplainabilityGrad-CAM and LIME heatmaps via Captum
Patient chatbotAzure OpenAI / Llama
Prompt templatesJinja2 / LangChain

Provider abstraction

Models sit behind an adapter interface rather than being called directly, so the platform can move between Azure Custom Vision, ONNX Runtime and PyTorch without the services layer changing. The same abstraction covers storage, which targets Azure Blob through a generic interface.

Operational setup

The whole stack runs under Docker Compose, and the boot sequence is designed to fail fast rather than start in a broken state.

  • The backend refuses to start without a JWT signing secret, and Compose fails fast if it is absent from the environment
  • A one-shot migrate service runs alembic upgrade head once Postgres is healthy
  • The backend only starts after migrations complete, so a fresh volume is always at head on first boot
  • PostgreSQL is kept inside the Docker network and never published to the host