diff --git a/.dockerignore b/.dockerignore index 2d8e515..4e9084e 100644 --- a/.dockerignore +++ b/.dockerignore @@ -2,6 +2,7 @@ .venv/ __pycache__/ .pytest_cache/ +.ruff_cache/ *.py[cod] .DS_Store .env diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index bd1b05b..420bec7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -20,8 +20,8 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - python -m pip install -r requirements.txt - python -m pip install -r requirements-dev.txt + python -m pip install -r requirements/base.txt + python -m pip install -r requirements/dev.txt - name: Lint run: python -m ruff check . diff --git a/.gitignore b/.gitignore index e854331..e66d57d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ .venv/ __pycache__/ .pytest_cache/ +.ruff_cache/ *.py[cod] .env .DS_Store diff --git a/Makefile b/Makefile index 881f2fb..05b509d 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,16 @@ -.PHONY: test train bench replay compose compose-prod smoke docker-build +.PHONY: lint compile test check train bench replay compose compose-prod smoke docker-build + +lint: + python -m ruff check . + +compile: + python -m compileall -q gateway worker training bench scripts tests test: python -m pytest -q +check: lint compile test + train: python training/train_text_model.py @@ -13,10 +21,10 @@ replay: python bench/replay_traffic.py --seconds-per-stage 8 --rps 18 compose: - docker compose up --build + docker compose -f deploy/compose/docker-compose.yml up --build compose-prod: - docker compose -f docker-compose.prod.yml up --build + docker compose -f deploy/compose/docker-compose.prod.yml up --build smoke: python scripts/smoke_check.py diff --git a/README.md b/README.md index f00ba22..5d23181 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ The first version runs a FastAPI gateway in front of a few model workers. The ga ```bash python3 -m venv .venv source .venv/bin/activate -pip install -r requirements.txt +pip install -r requirements/base.txt uvicorn worker.app.main:app --port 8011 WORKER_URLS=http://localhost:8011 uvicorn gateway.app.main:app --port 8000 @@ -45,7 +45,7 @@ python bench/replay_traffic.py --seconds-per-stage 8 --rps 18 ## Docker ```bash -docker compose up --build +make compose ``` That starts Redis, one gateway, and two workers. @@ -54,7 +54,7 @@ For a production-style local run: ```bash cp .env.example .env -docker compose -f docker-compose.prod.yml up --build +make compose-prod python scripts/smoke_check.py ``` @@ -69,6 +69,20 @@ keeps workers private and disables public worker failure controls. Deployment and validation steps are in `docs/hosted-demo.md`. +## Repository layout + +```text +gateway/ FastAPI gateway, routing, cache, metrics, dashboard +worker/ model worker service and exported model artifact +training/ MPS training and evaluation scripts +bench/ benchmark and replay scripts with saved results +scripts/ smoke checks and small operational helpers +tests/ unit tests for gateway, worker, model, and settings +docs/ architecture, deployment, report, and model card +deploy/compose/ local Docker Compose files +requirements/ runtime, development, and training dependency sets +``` + ## Benchmarks The scenario runner starts local gateway and worker processes, sends load, then writes JSON and markdown results. @@ -98,7 +112,7 @@ The worker can load a small trained text model artifact from `worker/app/artifac On Apple Silicon, the training script uses PyTorch MPS. It refuses to run on CPU by default so a slow accidental CPU run fails fast. ```bash -pip install -r requirements-train.txt +pip install -r requirements/train.txt python training/train_text_model.py ``` diff --git a/docker-compose.prod.yml b/deploy/compose/docker-compose.prod.yml similarity index 93% rename from docker-compose.prod.yml rename to deploy/compose/docker-compose.prod.yml index 886deb1..e8cc572 100644 --- a/docker-compose.prod.yml +++ b/deploy/compose/docker-compose.prod.yml @@ -6,7 +6,7 @@ services: worker-a: build: - context: . + context: ../.. dockerfile: worker/Dockerfile restart: unless-stopped environment: @@ -14,7 +14,7 @@ services: worker-b: build: - context: . + context: ../.. dockerfile: worker/Dockerfile restart: unless-stopped environment: @@ -22,7 +22,7 @@ services: gateway: build: - context: . + context: ../.. dockerfile: gateway/Dockerfile restart: unless-stopped environment: diff --git a/docker-compose.yml b/deploy/compose/docker-compose.yml similarity index 92% rename from docker-compose.yml rename to deploy/compose/docker-compose.yml index 6a79d1d..2b23080 100644 --- a/docker-compose.yml +++ b/deploy/compose/docker-compose.yml @@ -6,7 +6,7 @@ services: worker-a: build: - context: . + context: ../.. dockerfile: worker/Dockerfile environment: WORKER_ID: worker-a @@ -15,7 +15,7 @@ services: worker-b: build: - context: . + context: ../.. dockerfile: worker/Dockerfile environment: WORKER_ID: worker-b @@ -25,7 +25,7 @@ services: gateway: build: - context: . + context: ../.. dockerfile: gateway/Dockerfile environment: WORKER_URLS: http://worker-a:9000,http://worker-b:9000 diff --git a/docs/demo.md b/docs/demo.md index 59747e7..16ca08c 100644 --- a/docs/demo.md +++ b/docs/demo.md @@ -5,7 +5,7 @@ This is the local demo flow I use to show the system moving. Terminal 1: ```bash -docker compose up --build +make compose ``` Open: diff --git a/docs/deployment.md b/docs/deployment.md index 5831469..15404c3 100644 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -6,7 +6,7 @@ ModelMesh is still easiest to demo locally because the failure controls and traf ```bash cp .env.example .env -docker compose -f docker-compose.prod.yml up --build +make compose-prod python scripts/smoke_check.py ``` diff --git a/gateway/Dockerfile b/gateway/Dockerfile index d051e41..5761f07 100644 --- a/gateway/Dockerfile +++ b/gateway/Dockerfile @@ -4,7 +4,7 @@ ENV PYTHONDONTWRITEBYTECODE=1 ENV PYTHONUNBUFFERED=1 WORKDIR /app -COPY requirements.txt . +COPY requirements/base.txt ./requirements.txt RUN pip install --no-cache-dir -r requirements.txt COPY gateway ./gateway diff --git a/requirements.txt b/requirements/base.txt similarity index 100% rename from requirements.txt rename to requirements/base.txt diff --git a/requirements-dev.txt b/requirements/dev.txt similarity index 100% rename from requirements-dev.txt rename to requirements/dev.txt diff --git a/requirements-train.txt b/requirements/train.txt similarity index 100% rename from requirements-train.txt rename to requirements/train.txt diff --git a/worker/Dockerfile b/worker/Dockerfile index 5c03c31..5df1c03 100644 --- a/worker/Dockerfile +++ b/worker/Dockerfile @@ -4,7 +4,7 @@ ENV PYTHONDONTWRITEBYTECODE=1 ENV PYTHONUNBUFFERED=1 WORKDIR /app -COPY requirements.txt . +COPY requirements/base.txt ./requirements.txt RUN pip install --no-cache-dir -r requirements.txt COPY worker ./worker