Skip to content

Commit 69764e1

Browse files
committed
♻️ 🎨 more projest structure for use in repo template
1 parent 95317f4 commit 69764e1

File tree

19 files changed

+282
-1
lines changed

19 files changed

+282
-1
lines changed

.DS_Store

6 KB
Binary file not shown.

Dockerfile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
FROM python:3.7-stretch
2+
RUN pip install pipenv
3+
COPY Pipfile* /tmp
4+
RUN cd /tmp && pipenv lock --requirements > requirements.txt
5+
RUN pip install -r /tmp/requirements.txt
6+
COPY . /tmp/myapp
7+
RUN pip install /tmp/myapp
8+
CMD ["uvicorn", "fastapi_scaffolding.main:app", "host='0.0.0.0'", "port=3000"]

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
1-
# fastapi-ml-scaffolding
1+
# FastAPI Model Serving Scaffolding
2+
23
Scaffolding for serving ml model APIs using FastAPI
4+
5+
This repo contains the scaffolding which can be used to speed up your next machine learning project.
6+

docker-compose.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
version: '3'
2+
services:
3+
python1:
4+
container_name: ml-api-service-1
5+
restart: always
6+
build:
7+
context: .
8+
dockerfile: Dockerfile
9+
ports:
10+
- "3000:3000"
11+
volumes:
12+
- ./app1:/app
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
2+
from fastapi import APIRouter
3+
4+
from fastapi_scaffolding.models.heartbeat import HearbeatResult
5+
6+
router = APIRouter()
7+
8+
9+
@router.get("/heartbeat", response_model=HearbeatResult, name="heartbeat")
10+
def get_hearbeat() -> HearbeatResult:
11+
heartbeat = HearbeatResult(is_alive=True)
12+
return heartbeat
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
from fastapi import APIRouter, Depends
2+
from starlette.requests import Request
3+
4+
from fastapi_scaffolding.core import security
5+
from fastapi_scaffolding.models.payload import HousePredictionPayload # Incoming payload data model
6+
from fastapi_scaffolding.models.prediction import HousePredictionResult # Outbound prediction result data model
7+
from fastapi_scaffolding.services.models import HousePriceModel # ML Model itself
8+
9+
router = APIRouter()
10+
11+
12+
@router.post("/predict", response_model=HousePredictionResult, name="predict")
13+
def post_predict(
14+
request: Request,
15+
authenticated: bool = Depends(security.validate_request),
16+
block_data: HousePredictionPayload = None
17+
) -> HousePredictionResult:
18+
19+
model: HousePriceModel = request.app.state.model
20+
prediction: HousePredictionResult = model.predict(block_data)
21+
22+
return prediction
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
2+
3+
from fastapi import APIRouter
4+
5+
from fastapi_scaffolding.api.routes import heartbeat, prediction
6+
7+
api_router = APIRouter()
8+
api_router.include_router(heartbeat.router, tags=["health"], prefix="/health")
9+
api_router.include_router(prediction.router, tags=[
10+
"prediction"], prefix="/model")

fastapi_scaffolding/core/config.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
2+
3+
from starlette.config import Config
4+
from starlette.datastructures import Secret
5+
6+
APP_VERSION = "0.0.1"
7+
APP_NAME = "Machine Learning Prediction Example"
8+
API_PREFIX = "/api"
9+
10+
config = Config(".env")
11+
12+
API_KEY: Secret = config("API_KEY", cast=Secret)
13+
IS_DEBUG: bool = config("IS_DEBUG", cast=bool, default=False)
14+
15+
DEFAULT_MODEL_PATH: str = config("DEFAULT_MODEL_PATH")
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
2+
3+
from typing import Callable
4+
5+
from fastapi import FastAPI
6+
from loguru import logger
7+
8+
from fastapi_scaffolding.core.config import DEFAULT_MODEL_PATH
9+
from fastapi_scaffolding.services.models import HousePriceModel
10+
11+
12+
def _startup_model(app: FastAPI) -> None:
13+
model_path = DEFAULT_MODEL_PATH
14+
model_instance = HousePriceModel(model_path)
15+
app.state.model = model_instance
16+
17+
18+
def _shutdown_model(app: FastAPI) -> None:
19+
app.state.model = None
20+
21+
22+
def start_app_handler(app: FastAPI) -> Callable:
23+
def startup() -> None:
24+
logger.info("Running app start handler.")
25+
_startup_model(app)
26+
return startup
27+
28+
29+
def stop_app_handler(app: FastAPI) -> Callable:
30+
def shutdown() -> None:
31+
logger.info("Running app shutdown handler.")
32+
_shutdown_model(app)
33+
return shutdown
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
NO_API_KEY = "No API key provided."
2+
AUTH_REQ = "Authentication required."
3+
HTTP_500_DETAIL = "Internal server error."
4+
5+
# templates
6+
NO_VALID_PAYLOAD = "{} is not a valid payload."

0 commit comments

Comments
 (0)