최근에 MLOps를 공부하고 있어요.
Mlflow + FastAPI + CI/CD로 rest api를 만들기는 했는데 생각보다 손이 많이가더라고요.
Mlflow + bentoml을 많이 사용한다길래 bento 찍먹 해봤습니다.
1.x 버전이 나와서 따라해봤는데, 예전 버전과 코드가 좀 달라젹더라고요
+ 추가
mlflow는 파라미터 저장 및 관리로 사용하고
bentoml은 mlflow의 model을 배포하는 방식으로 사용할 예정입니다.
yatai/ yatai-deployment 사용하니까 신세계인 것 같아요.
UI로 다다닥 선택하면, 배포까지 되더라고요. scale out 옵션도 있고요
yatai로 배포한 내용
$ k get all -n yatai | grep iris
pod/iris-test2-7f685748f4-mzts4 2/2 Running 0 12h
pod/iris-test2-7f685748f4-stgsm 2/2 Running 0 12h
pod/iris-test2-runner-0-76fccf5c8f-ld75z 2/2 Running 0 12h
pod/iris-test2-runner-0-76fccf5c8f-twh85 2/2 Running 0 12h
service/iris-test2 ClusterIP 10.103.226.27 <none> 3000/TCP 12h
service/iris-test2-runner-dce7f9fc13e1812de63cdb66225d3777 ClusterIP 10.108.238.174 <none> 3000/TCP 12h
deployment.apps/iris-test2 2/2 2 2 12h
deployment.apps/iris-test2-runner-0 2/2 2 2 12h
replicaset.apps/iris-test2-7f685748f4 2 2 2 12h
replicaset.apps/iris-test2-runner-0-76fccf5c8f 2 2 2 12h
horizontalpodautoscaler.autoscaling/iris-test2 Deployment/iris-test2 1%/80% 2 10 2 12h
horizontalpodautoscaler.autoscaling/iris-test2-runner-0 Deployment/iris-test2-runner-0 0%/80% 2 10 2 12h
요약
- bentoml이란?
- Quickstart
- 모델 저장하기(save)
- 모델 불러오기(load_model)
- 배포 테스트(init_local)
- 배포 cli (bentoml serve)
- 이미지 빌드(bento build/containerize)
- 컨테이너 실행(docker run)
대상 독자
- bentoml 궁금하신 분
- 모델 서빙해보시려는 분
상세한 설명이 아니라 대충 이런게 있구나 스피드 5분 찍먹을 목표로 합니다.
친구한테 bentoml 설명해줄 용도로 쓴 글이거든요
1. bentoml이란?
> 한줄요약: 모델 배포를 쉽게 해주는 제품
flesxible, high-performance framework for serving,manaing, deploying
모델을 만들어도 실제 운영까지는 여러 단계를 거쳐야하는데
bentoml은 이걸 CLI로 쉽게 관리할 수 있게 해주고 있어요
2. QuickStart
공식문서와 git repo를 참고했습니다.
https://github.com/bentoml/BentoML/tree/main/examples/quickstart
https://docs.bentoml.org/en/latest/tutorial.html
그대로 따라면되서 편했어요.
2-1. 모델 저장(save)
모델을 쉽게 저장하고 불러올 수 있는데, 이건 mlflow와 비슷해요
예시를 보고 따라해보면 아래와 같이 특정 위치에 저장되고, cli로 조회할 수 있다는 것까지 MLflow와 비슷해요
bentoml.sklearn.save_model("iris_clf", clf)import bentoml
#모델 저장하기
기본적으로 모델은 로컬에 저장되요
$HOME/bentoml/models
# 모델 저장 위치
$ ls /home/bigdata/bentoml/models/iris_clf/lxoltybnrs2nu3vw
model.yaml saved_model.pkl
cli로 모델을 확인할 수도 있어요
# 모델 목록 cli$ bentoml models list | grep iris
iris_clf:lxoltybnrs2nu3vw bentoml.sklearn 5.78 KiB 2022-09-06 11:34:01
mlflow랑 크게 다른게 없는데 왜 사용하지?
왜 겹치는데 같이 사용하지?
이런 생각을 했어요.
2-2. 모델 불러오기(load_model)
모델을 저장했으면 이제 불러와야죠. load_model로 불러올 수 있어요.
mlflow 형식으로 저장하려면 bentoml.mlflow.load_model() 이런식으로 할 수있는데 이건 다른 포스팅에서 설명할게요
#모델 불러오기import bentoml
loaded_model = bentoml.sklearn.load_model("iris_clf:latest")loaded_model.predict([[5.9, 3.0, 5.1, 1.8]])
loaded_model
>> Model(tag="iris_clf:lxoltybnrs2nu3vw", path="/home/bigdata/bentoml/models/iris_clf/lxoltybnrs2nu3vw/")
기본적으로 모델은 로컬에 저장되요
2-3. 배포 테스트(init_local)
쉽게 api를 테스트하고 배포할 수 있어요.
이 부분에서는 mlfow 보다 bentoml이 더 강력한 것 같아요
아래 코드는 테스트용 코드로, api 배포하지 않고도 함수를 확인할 수 있어요. (굿!)
#runner 객체는 실제 배포 때도 사용해요
iris_clf_runner = bentoml.sklearn.get("iris_clf:latest").to_runner()
iris_clf_runner.init_local()
iris_clf_runner.predict.run([[5.9, 3.0, 5.1, 1.8]])
2-4. 배포 cli (bentoml serve)
문서보다 보면 갑자기 여기서부터 좀 머리아픈데, 배포를 위해서는 service.py 이 필요해요
%%writefile service.py
import numpy as np
import bentoml
from bentoml.io import NumpyNdarray
# 테스트할 때 사용한 runner 객체와 동일해요
iris_clf_runner = bentoml.sklearn.get("iris_clf:latest").to_runner()
svc = bentoml.Service("iris_classifier", runners=[iris_clf_runner])
@svc.api(input=NumpyNdarray(), output=NumpyNdarray())
def classify(input_series: np.ndarray) -> np.ndarray:
return iris_clf_runner.predict.run(input_series)
terminal 열고 api를 실행해줘요
$ bentoml serve service.py:svc --reload
cli로 실행하면 결과가 나오는걸 확인할 수 있어요
curl -X POST -H "content-type: application/json" --data "[[5.9, 3, 5.1, 1.8]]" http://127.0.0.1:3000/classify
# [2]
2-5. 이미지 빌드(bento build/containerize)
이제 운영 환경에서 사용할 이미지를 만들어야해요. 여기서 엄청 간단하고
mlflow 보다 더 따라하기 쉬워요. mlflow는 하다가 답답해서 그냥 ci/cd로 fastapi 만들었거든요
bento는 쉬워서 따라하기 좋아요
%%writefile bentofile.yaml
service: "service.py:svc"
labels:
owner: bentoml-team
project: gallery
include:
- "*.py"
python:
packages:
- scikit-learn
- pandas
build 명령어를 인력하면 끝
$ bentoml build
---
Building BentoML service "iris_classifier:24ncchbnrswxw3vw" from build context "/home/bigdata/github.com/bentoml/examples/quickstart"
Packing model "iris_clf:lxoltybnrs2nu3vw"
Locking PyPI package versions..
██████╗░███████╗███╗░░██╗████████╗░█████╗░███╗░░░███╗██╗░░░░░
██╔══██╗██╔════╝████╗░██║╚══██╔══╝██╔══██╗████╗░████║██║░░░░░
██████╦╝█████╗░░██╔██╗██║░░░██║░░░██║░░██║██╔████╔██║██║░░░░░
██╔══██╗██╔══╝░░██║╚████║░░░██║░░░██║░░██║██║╚██╔╝██║██║░░░░░
██████╦╝███████╗██║░╚███║░░░██║░░░╚█████╔╝██║░╚═╝░██║███████╗
╚═════╝░╚══════╝╚═╝░░╚══╝░░░╚═╝░░░░╚════╝░╚═╝░░░░░╚═╝╚══════╝
Successfully built Bento(tag="iris_classifier:24ncchbnrswxw3vw")
---
$ bentoml list | grep iris
iris_classifier:24ncchbnrswxw3vw 20.20 KiB 2022-09-06 11:37:27 ~/bentoml/bentos/iris_classifier/24ncchbnrswxw3vw
$ bentoml containerize iris_classifier:latest
---
$ docker images | grep iris
iris_classifier 24ncchbnrswxw3vw 162cbb24da63 5 hours ago 833MB
2-6. 컨테이너 실행(docker run)
docker run하면 swagger가 나와요.
docker run -p 3000:3000 iris_classifier:invwzzsw7li6zckb2ie5eubhd
크으으 이쁘네요. 막 아이콘도 있고, help도 있고 fastapi로 대충 만든 제거만 보다 보니 너무 이쁩니다.
헬스체크, 메트릭 같은 infra api도 있더라고요
다음 글은 mlflow와 어떻게 합칠지에 대해서 고민해야겠어요
참고
https://intrepidgeeks.com/tutorial/bentoml-inserter
https://velog.io/@perfitt/BentoML-%EC%82%BD%EC%A7%88%EA%B8%B0
https://blog.kubwa.co.kr/deploy-with-bentoml-yatai-bc7ad2f374b7