Skip to content

Commit

Permalink
feat: Add mlops serving pattern cookbook
Browse files Browse the repository at this point in the history
  • Loading branch information
YeonwooSung committed Nov 4, 2024
1 parent 9c6e165 commit 677c6b6
Show file tree
Hide file tree
Showing 508 changed files with 34,811 additions and 0 deletions.
15 changes: 15 additions & 0 deletions MLOps/serving_patterns/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Serving patterns

.</br>
├── [chapter 4. 추론 시스템 만들기](./)</br>
   ├── [web single pattern](./web_single_pattern)</br>
   ├── [synchronous inference pattern](./synchronous_pattern)</br>
   ├── [asynchronous inference pattern](./asynchronous_pattern)</br>
   ├── [batc inference pattern](./batch_pattern)</br>
   ├── [preprocess and prediction pattern](./prep_pred_pattern)</br>
   ├── [horizontal microservice pattern](./horizontal_microservice_pattern)</br>
   ├── [sync and async pattern](./sync_async_pattern)</br>
   ├── [pattern cache pattern](./prediction_cache_pattern)</br>
   ├── [data cache pattern](./data_cache_pattern)</br>
   ├── [prediction template pattern](./template_pattern)</br>
   └── [Edge AI pattern](./edge_ai_pattern)</br>
12 changes: 12 additions & 0 deletions MLOps/serving_patterns/asynchronous_pattern/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
dockerfile
Dockerfile
.dockerignore
log
tmp
*.sqlite3
*.sqlite3-journal
__pycache__
.pytest_cache
*.dvc
dvc.yaml
dvc.lock
19 changes: 19 additions & 0 deletions MLOps/serving_patterns/asynchronous_pattern/Dockerfile.backend
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
FROM python:3.8-slim

ENV MODEL_DIR imagenet_inception_v3
ENV PROJECT_DIR asynchronous_pattern
WORKDIR /${PROJECT_DIR}
ADD ./requirements_backend.txt /${PROJECT_DIR}/
RUN apt-get -y update && \
apt-get -y install apt-utils gcc && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* && \
pip install --no-cache-dir -r requirements_backend.txt

COPY ./src/ /${PROJECT_DIR}/src/
COPY ./${MODEL_DIR}/data/ /${PROJECT_DIR}/data/

ENV LOG_LEVEL DEBUG
ENV LOG_FORMAT TEXT

CMD [ "python", "-m", "src.app.backend.prediction_batch" ]
21 changes: 21 additions & 0 deletions MLOps/serving_patterns/asynchronous_pattern/Dockerfile.proxy
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
FROM python:3.8-slim

ENV MODEL_DIR imagenet_inception_v3
ENV PROJECT_DIR asynchronous_pattern
WORKDIR /${PROJECT_DIR}
ADD ./requirements_proxy.txt /${PROJECT_DIR}/
RUN apt-get -y update && \
apt-get -y install apt-utils gcc && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* && \
pip install --no-cache-dir -r requirements_proxy.txt

COPY ./src/ /${PROJECT_DIR}/src/
COPY ./${MODEL_DIR}/data/ /${PROJECT_DIR}/data/

ENV LOG_LEVEL DEBUG
ENV LOG_FORMAT TEXT

COPY ./run.sh /${PROJECT_DIR}/run.sh
RUN chmod +x /${PROJECT_DIR}/run.sh
CMD [ "./run.sh" ]
169 changes: 169 additions & 0 deletions MLOps/serving_patterns/asynchronous_pattern/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
# 비동기 추론 패턴

## 목적

비동기 추론 API 를 제공합니다.

## 전제

- Python 3.8 이상
- Docker
- Docker compose

## 사용법

0. 현재 디렉토리

```sh
$ pwd
~/ml-system-in-actions/chapter4_serving_patterns/asynchronous_pattern
```

1. 비동기 추론을 위한 Docker 이미지 빌드

```sh
$ make build_all
# 실행 커맨드
# docker build \
# -t shibui/ml-system-in-actions:asynchronous_pattern_asynchronous_proxy_0.0.1 \
# -f ./Dockerfile.proxy .
# docker build \
# -t shibui/ml-system-in-actions:asynchronous_pattern_imagenet_inception_v3_0.0.1 \
# -f ./imagenet_inception_v3/Dockerfile .
# docker build \
# -t shibui/ml-system-in-actions:asynchronous_pattern_asynchronous_backend_0.0.1 \
# -f ./Dockerfile.backend .
```

2. Docker compose 로 각 서비스 기동

```sh
$ make c_up
# 실행 커맨드
# docker-compose \
# -f ./docker-compose.yml \
# up -d
```

3. 기동한 API 에 요청

```sh
# 헬스 체크
$ curl localhost:8000/health
# 출력
# {"health":"ok"}

# 메타 데이터
$ curl localhost:8000/metadata
# 출력
# {
# "model_spec": {
# "name": "inception_v3",
# "signature_name": "",
# "version": "0"
# },
# "metadata": {
# "signature_def": {
# "signature_def": {
# "serving_default": {
# "inputs": {
# "image": {
# "dtype": "DT_STRING",
# "tensor_shape": {
# "dim": [
# {
# "size": "-1",
# "name": ""
# }
# ],
# "unknown_rank": false
# },
# "name": "serving_default_image:0"
# }
# },
# "outputs": {
# "output_0": {
# "dtype": "DT_STRING",
# "tensor_shape": {
# "dim": [],
# "unknown_rank": true
# },
# "name": "StatefulPartitionedCall:0"
# }
# },
# "method_name": "tensorflow/serving/predict"
# },
# "__saved_model_init_op": {
# "inputs": {},
# "outputs": {
# "__saved_model_init_op": {
# "dtype": "DT_INVALID",
# "tensor_shape": {
# "dim": [],
# "unknown_rank": true
# },
# "name": "NoOp"
# }
# },
# "method_name": ""
# }
# }
# }
# }
# }

# 라벨 목록
$ curl localhost:8000/label
# 출력
# [
# "background",
# "tench",
# "goldfish",
# ...
# "bolete",
# "ear",
# "toilet tissue"
# ]

# 테스트 데이터로 추론 요청
$ curl localhost:8000/predict/test
# 출력
# {
# "job_id": "f22689"
# }


# 이미지를 요청
$ (echo \
-n '{"image_data": "'; \
base64 imagenet_inception_v3/data/cat.jpg; \
echo '"}') | \
curl \
-X POST \
-H "Content-Type: application/json" \
-d @- \
localhost:8000/predict
# 출력
# {
# "job_id":"2f49aa"
# }

# 이미지 요청의 작업 ID 로부터 추론 결과를 요청
$ curl localhost:8000/job/2f49aa
# 출력
# {
# "2f49aa": {
# "prediction": "Siamese cat"
# }
# }
```

4. Docker compose 정지

```sh
$ make c_down
# 실행 커맨드
# docker-compose \
# -f ./docker-compose.yml \
# down
```
Empty file.
48 changes: 48 additions & 0 deletions MLOps/serving_patterns/asynchronous_pattern/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
version: "3"

services:
asynchronous_proxy:
container_name: asynchronous_proxy
image: shibui/ml-system-in-actions:asynchronous_pattern_asynchronous_proxy_0.0.1
restart: always
environment:
- PLATFORM=docker_compose
- QUEUE_NAME=tfs_queue
- API_ADDRESS=imagenet_inception_v3
ports:
- "8000:8000"
command: ./run.sh
depends_on:
- redis
- imagenet_inception_v3
- asynchronous_backend

imagenet_inception_v3:
container_name: imagenet_inception_v3
image: shibui/ml-system-in-actions:asynchronous_pattern_imagenet_inception_v3_0.0.1
restart: always
environment:
- PORT=8500
- REST_API_PORT=8501
ports:
- "8500:8500"
- "8501:8501"
entrypoint: ["/usr/bin/tf_serving_entrypoint.sh"]

asynchronous_backend:
container_name: asynchronous_backend
image: shibui/ml-system-in-actions:asynchronous_pattern_asynchronous_backend_0.0.1
restart: always
environment:
- PLATFORM=docker_compose
- QUEUE_NAME=tfs_queue
- API_ADDRESS=imagenet_inception_v3
entrypoint: ["python", "-m", "src.app.backend.prediction_batch"]
depends_on:
- redis

redis:
container_name: asynchronous_redis
image: "redis:latest"
ports:
- "6379:6379"
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
FROM tensorflow/tensorflow:2.5.1 as builder

ARG SERVER_DIR=imagenet_inception_v3
ENV PROJECT_DIR asynchronous_pattern
WORKDIR /${PROJECT_DIR}
ADD ./${SERVER_DIR}/requirements.txt /${PROJECT_DIR}/

COPY ./${SERVER_DIR}/extract_inception_v3.py /${PROJECT_DIR}/extract_inception_v3.py
COPY ./${SERVER_DIR}/data/image_net_labels.json /${PROJECT_DIR}/data/image_net_labels.json

RUN apt-get -y update && \
apt-get -y install apt-utils gcc && \
pip install --no-cache-dir -r requirements.txt && \
touch __init__.py && \
python -m extract_inception_v3


FROM tensorflow/serving:2.5.2

ARG SERVER_DIR=imagenet_inception_v3
ENV PROJECT_DIR asynchronous_pattern
ENV MODEL_BASE_PATH /${PROJECT_DIR}/saved_model/inception_v3
ENV MODEL_NAME inception_v3

COPY --from=builder /${PROJECT_DIR}/saved_model/inception_v3 ${MODEL_BASE_PATH}
EXPOSE 8500
EXPOSE 8501

COPY ./${SERVER_DIR}/tf_serving_entrypoint.sh /usr/bin/tf_serving_entrypoint.sh
RUN chmod +x /usr/bin/tf_serving_entrypoint.sh
ENTRYPOINT ["/usr/bin/tf_serving_entrypoint.sh"]
Empty file.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 677c6b6

Please sign in to comment.