Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
de58741
๐Ÿ”€ Merge develop into infra/prometheus-grafana (#12)
simGPT Apr 23, 2026
2c0766e
:bug:Fix: cd ์‹œ์— ์ด๋ฏธ์ง€ ํƒœ๊ทธ ์—…๋ฐ์ดํŠธ ํ•˜๋„๋ก ์ˆ˜์ •(v1 -> ์ปค๋ฐ‹SHA) (#14)
simGPT Apr 23, 2026
663b1b2
โœจ Feat: MLflow ๊ธฐ๋ฐ˜ S3 ๋ชจ๋ธ ์ €์žฅ ๋ฐ ๋กœ๋“œ ํ™˜๊ฒฝ ๊ตฌ์ถ• (#17)
simGPT May 12, 2026
aaa9dce
:bug:Fix: volume mount ์ถ”๊ฐ€
simGPT May 12, 2026
edc1425
:bug:Fix: pvc.yaml(ํด๋Ÿฌ์Šคํ„ฐ์šฉ ์ €์žฅ์†Œ)๊ตฌ์ถ•์„ ์œ„ํ•œ ์„ค์ •ํŒŒ์ผ ์ถ”๊ฐ€
simGPT May 12, 2026
861bf16
๐Ÿ› Fix: mlflow-db ๋ฐ์ดํ„ฐ ์ดˆ๊ธฐํ™” ๋˜๋Š” ๋ฌธ์ œ (#20)
simGPT May 12, 2026
0568e8b
Merge branch 'develop' of https://github.com/simGPT/sw-mlops into devโ€ฆ
simGPT May 13, 2026
f467d73
Merge branch 'main' into develop
simGPT May 13, 2026
969359b
:twisted_rightwards_arrows:Merge: main<-develop pr ์ถฉ๋Œ ํ•ด๊ฒฐ
simGPT May 13, 2026
7492ca9
๐Ÿ› Fix: ๋ชจ๋ธ ์„œ๋น™ ์‹œ mlflow์˜ 403 ์—๋Ÿฌ ํ•ด๊ฒฐ (#23)
simGPT May 15, 2026
d34fc68
ci: trigger CI
simGPT May 15, 2026
261977c
:wrench:Settings: retrigger CI
simGPT May 15, 2026
ec12462
:wrench:Infra: ci ํŠธ๋ฆฌ๊ฑฐ์— pull_request ์ถ”๊ฐ€
simGPT May 15, 2026
9c5ccc7
:wrench:Settings: ci ํŠธ๋ฆฌ๊ฑฐ main push ์ œ๊ฑฐํ•˜๋„๋ก ์ˆ˜์ •
simGPT May 18, 2026
76ace0a
:wrench:Settings: aws๊ด€๋ จ secrets env๋กœ ์ถ”๊ฐ€
simGPT May 18, 2026
a6eaacd
:card_file_box:Comment: ์ฃผ์„ ์ˆ˜์ •
simGPT May 18, 2026
49224cc
:wrench:Settings: ์ด๋ฏธ์ง€ ํƒœ๊ทธ v1 -> latest๋กœ ์ˆ˜์ •
simGPT May 18, 2026
a6fbfb0
:wrench:Settings: localhost:5000 ํ—ˆ์šฉ ์„ค์ •
simGPT May 18, 2026
63604fd
๐Ÿ”ง Infra: EC2 k3s ์šด์˜ ํ™˜๊ฒฝ ๋ฐฐํฌ ํŒŒ์ดํ”„๋ผ์ธ ๊ตฌ์ถ• (#26)
simGPT May 20, 2026
4fdf761
:card_file_box:Comment: CI/CD ํŒŒ์ดํ”„๋ผ์ธ ํŠธ๋ฆฌ๊ฑฐ ํ™•์ธ์šฉ ์ฃผ์„ ์ถ”๊ฐ€
simGPT May 20, 2026
962b61c
:twisted_rightwards_arrows:Merge: merge origin main into develop
simGPT May 20, 2026
816bf5d
:bug:Fix: pull_request ์ค‘๋ณต ์‚ญ์ œ
simGPT May 20, 2026
b947c07
:sparkles:Feat: churn modeling test (#29)
simGPT May 27, 2026
94f20c9
โœจ Feat: ๊ณ ๊ฐ ์ดํƒˆ ์˜ˆ์ธก ๋ชจ๋ธ ํ•™์Šต ๋ฐ ์„œ๋น™ (#30)
simGPT May 27, 2026
88b75ab
โœจ Feat: ๋„๋ฉ”์ธ ๊ตฌ๋งค ๋ฐ ์„œ๋น„์Šค ์ธํ”„๋ผ ์—ฐ๊ฒฐ (#32)
simGPT May 30, 2026
ce3cabe
:twisted_rightwards_arrows:Merge: develop -> main ์ถฉ๋Œ ํ•ด๊ฒฐ
simGPT May 30, 2026
c29b709
:bug:Fix: ์ด๋ฏธ์ง€ ์ค‘๋ณต ์ œ๊ฑฐ
simGPT May 30, 2026
480bb89
:bug:Fix: ํ’€ DNS ์„ค์ • ํฌํŠธ ํฌํ•จ ๋ฐ ์ด๋ฏธ์ง€ ์ค‘๋ณต ์ œ๊ฑฐ
simGPT May 31, 2026
793764e
:recycle:Refactor: MLflow ๋ชจ๋ธ ๋ฒ„์ „ ๊ด€๋ฆฌ MLflow ๋‚ด์žฅ ๋ฒ„์ „์œผ๋กœ ๋ณ€๊ฒฝ (#37)
simGPT May 31, 2026
47a9aa4
โœจ Feat: ๋ชจ๋ธ ์„ฑ๋Šฅ ์ €ํ•˜ ์ž๋™ ๊ฐ์ง€ ๋ฐ ์žฌํ•™์Šต ํŒŒ์ดํ”„๋ผ์ธ ๊ตฌ์ถ• (#39)
simGPT Jun 2, 2026
430a16e
Merge branch 'main' into develop
simGPT Jun 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions .github/workflows/cd-production.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ on:
- main
paths:
- 'services/model-api/**'
- 'services/alert-bridge/**'

jobs:
deploy:
Expand All @@ -20,11 +21,17 @@ jobs:
mkdir -p $HOME/.kube
echo "${{ secrets.KUBECONFIG_PRODUCTION }}" | base64 -d > $HOME/.kube/config

- name: kubectl apply
- name: model-api kubectl apply
run: kubectl apply -k k8s/model-api/overlays/production/

- name: ํŒŒ๋“œ ์žฌ์‹œ์ž‘ # (์ด๋ฏธ์ง€ ํƒœ๊ทธ๊ฐ€ ๊ณ„์† latest์—ฌ๋„ ์ƒˆ ์ด๋ฏธ์ง€๋กœ ๋ฐฐํฌ๋˜๋„๋ก)
run: kubectl rollout restart deployment/model-api -n model-api # ๋„ค์ž„์ŠคํŽ˜์ด์Šค ์ง€์ •
- name: model-api ํŒŒ๋“œ ์žฌ์‹œ์ž‘
run: kubectl rollout restart deployment/model-api -n model-api

- name: ๋ฐฐํฌ ํ™•์ธ
run: kubectl rollout status deployment/model-api -n model-api # ๋„ค์ž„์ŠคํŽ˜์ด์Šค ์ง€์ •
- name: model-api ๋ฐฐํฌ ํ™•์ธ
run: kubectl rollout status deployment/model-api -n model-api

- name: alert-bridge ํŒŒ๋“œ ์žฌ์‹œ์ž‘
run: kubectl rollout restart deployment/alert-bridge -n monitoring

- name: alert-bridge ๋ฐฐํฌ ํ™•์ธ
run: kubectl rollout status deployment/alert-bridge -n monitoring
37 changes: 37 additions & 0 deletions .github/workflows/ci-alert-bridge.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: CI (alert-bridge)

on:
push:
branches:
- develop
paths:
- 'services/alert-bridge/**'
pull_request:
branches:
- main
- develop
paths:
- 'services/alert-bridge/**'

jobs:
build-and-push:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Docker Hub ๋กœ๊ทธ์ธ
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_TOKEN }}

- name: Docker ์ด๋ฏธ์ง€ ๋นŒ๋“œ & push
uses: docker/build-push-action@v5
with:
context: services/alert-bridge
push: true
tags: |
${{ secrets.DOCKER_USERNAME }}/alert-bridge:latest
${{ secrets.DOCKER_USERNAME }}/alert-bridge:${{ github.sha }}
43 changes: 43 additions & 0 deletions .github/workflows/retrain-churn.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: Retrain (churn)

on:
repository_dispatch:
types:
- model-retrain

jobs:
retrain:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Python ์„ค์น˜
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: ์˜์กด์„ฑ ์„ค์น˜
run: |
pip install -r services/model-api/requirements.txt

- name: ํŠธ๋ฆฌ๊ฑฐ๋œ ์•Œ๋ฆผ ์ถœ๋ ฅ
run: |
echo "Triggered by alerts: ${{ toJson(github.event.client_payload.alerts) }}"

- name: ๋ชจ๋ธ ์žฌํ•™์Šต & MLflow ๋“ฑ๋ก
working-directory: services/model-api
env:
MLFLOW_TRACKING_URI: https://mlflow.swmlops.site
run: |
python training/churn/train.py \
--mlflow_uri https://mlflow.swmlops.site \
--data_dir ../data/churn

- name: model-api ํŒŒ๋“œ ์žฌ์‹œ์ž‘
run: |
mkdir -p $HOME/.kube
echo "${{ secrets.KUBECONFIG_PRODUCTION }}" | base64 -d > $HOME/.kube/config
kubectl rollout restart deployment/model-api -n model-api
kubectl rollout status deployment/model-api -n model-api
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# ๋ฐ์ดํ„ฐ
data/
!services/data/churn/

# ๋ชจ๋ธ ๊ฐ€์ค‘์น˜ (v1์€ ์˜ˆ์™ธ์ ์œผ๋กœ ์ปค๋ฐ‹ํ•  ๊ฒฝ์šฐ ๋ณ„๋„ ์ฒ˜๋ฆฌ)
services/model-api/artifacts/*.pth
Expand Down
30 changes: 30 additions & 0 deletions k8s/alert-bridge/deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: alert-bridge
namespace: monitoring
spec:
replicas: 1
selector:
matchLabels:
app: alert-bridge
template:
metadata:
labels:
app: alert-bridge
spec:
containers:
- name: alert-bridge
image: simgpt/alert-bridge:latest
ports:
- containerPort: 8080
env:
- name: GITHUB_TOKEN
valueFrom:
secretKeyRef:
name: github-credentials
key: token
- name: GITHUB_REPO_OWNER
value: simGPT
- name: GITHUB_REPO_NAME
value: sw-mlops
12 changes: 12 additions & 0 deletions k8s/alert-bridge/service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
apiVersion: v1
kind: Service
metadata:
name: alert-bridge
namespace: monitoring
spec:
type: ClusterIP
selector:
app: alert-bridge
ports:
- port: 8080
targetPort: 8080
2 changes: 1 addition & 1 deletion k8s/mlflow/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,5 @@ spec:
- --port=5000
- --default-artifact-root=s3://kube-ml-bucket/mlflow-artifacts # ๋ชจ๋ธ ์ €์žฅ
- --backend-store-uri=postgresql://mlflow:1234@mlflow-db:5432/mlflow
- --allowed-hosts=mlflow.mlflow.svc.cluster.local,localhost,localhost:5000,mlflow.swmlops.site # ํ’€ DNS, localhost, ๋„๋ฉ”์ธ ํ—ˆ์šฉ
- --allowed-hosts=mlflow.mlflow.svc.cluster.local,mlflow.mlflow.svc.cluster.local:5000,localhost,localhost:5000,mlflow.swmlops.site # ํ’€ DNS, localhost, ๋„๋ฉ”์ธ ํ—ˆ์šฉ

60 changes: 60 additions & 0 deletions k8s/monitoring/alert-rules.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: churn-model-alerts
namespace: monitoring
labels:
release: monitoring
spec:
groups:
- name: churn-model
rules:
- alert: ChurnPredictionRatioHigh # ์ดํƒˆ ๋น„์œจ 10๋ถ„๋™์•ˆ 70% ์ดˆ๊ณผ
expr: |
sum(rate(churn_predictions_total{predicted="1"}[10m]))
/
sum(rate(churn_predictions_total[10m])) > 0.7
for: 10m
labels:
severity: warning
annotations:
summary: "์ดํƒˆ ์˜ˆ์ธก ๋น„์œจ ์ด์ƒ"
description: "์ดํƒˆ ์˜ˆ์ธก ๋น„์œจ์ด 10๋ถ„ ์ด์ƒ 70%๋ฅผ ์ดˆ๊ณผํ–ˆ์Šต๋‹ˆ๋‹ค."

- alert: ChurnConfidenceLow # ์˜ˆ์ธก ์‹ ๋ขฐ๋„ ์ €ํ•˜ 10๋ถ„๋™์•ˆ ํ‰๊ท  confidence๊ฐ€ 0.6 ๋ฏธ๋งŒ
expr: |
rate(churn_confidence_score_sum[10m])
/
rate(churn_confidence_score_count[10m]) < 0.6
for: 10m
labels:
severity: warning
annotations:
summary: "๋ชจ๋ธ ์‹ ๋ขฐ๋„ ์ €ํ•˜"
description: "ํ‰๊ท  confidence๊ฐ€ 10๋ถ„ ์ด์ƒ 0.6 ๋ฏธ๋งŒ์ž…๋‹ˆ๋‹ค."

- alert: ChurnInferenceLatencyHigh # ์ถ”๋ก  ์ง€์—ฐ ์‹œ๊ฐ„ 5๋ถ„๋™์•ˆ p99 ์ง€์—ฐ ์‹œ๊ฐ„์ด 0.1์ดˆ ์ดˆ๊ณผ
expr: |
histogram_quantile(0.99, rate(churn_inference_duration_seconds_bucket[5m])) > 0.1
for: 5m
labels:
severity: warning
annotations:
summary: "์ถ”๋ก  ์ง€์—ฐ ์‹œ๊ฐ„ ์ด์ƒ"
description: "์ถ”๋ก  p99 ์ง€์—ฐ ์‹œ๊ฐ„์ด 5๋ถ„ ์ด์ƒ 0.1์ดˆ๋ฅผ ์ดˆ๊ณผํ–ˆ์Šต๋‹ˆ๋‹ค."

- alert: ChurnFeatureDrift # ํ”ผ์ฒ˜ ํ‰๊ท ์ด 24์‹œ๊ฐ„ ์ „ ๋Œ€๋น„ 50% ์ด์ƒ ๋ณ€ํ™”
expr: |
abs(
avg_over_time(churn_feature_mean[1h])
-
avg_over_time(churn_feature_mean[1h] offset 24h)
)
/
avg_over_time(churn_feature_mean[1h] offset 24h) > 0.5
for: 10m
labels:
severity: warning
annotations:
summary: "์ž…๋ ฅ ํ”ผ์ฒ˜ ๋ถ„ํฌ ์ด์ƒ"
description: "ํ”ผ์ฒ˜ ํ‰๊ท ์ด 24์‹œ๊ฐ„ ์ „ ๋Œ€๋น„ 50% ์ด์ƒ ๋ณ€ํ™”ํ–ˆ์Šต๋‹ˆ๋‹ค."
20 changes: 20 additions & 0 deletions k8s/monitoring/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,26 @@ prometheus:
- targets:
- model-api.model-api.svc.cluster.local:8000 # ๋‹ค๋ฅธ ๋„ค์ž„์ŠคํŽ˜์ด์Šค์— ์žˆ๋Š” model-api์˜ ํด๋Ÿฌ์Šคํ„ฐ ๋‚ด๋ถ€ ์ฃผ์†Œ์™€ ํฌํŠธ

alertmanager:
config:
global:
resolve_timeout: 5m # ์•Œ๋ฆผ์ด ํ•ด๊ฒฐ๋œ ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผํ•˜๊ธฐ ์ „์— ๊ธฐ๋‹ค๋ฆฌ๋Š” ์‹œ๊ฐ„ 5๋ถ„
route:
group_by: ["alertname"] # ๊ฐ™์€ alertname์„ ๊ฐ€์ง„ ์•Œ๋ฆผ๋“ค์„ ๊ทธ๋ฃนํ™”
group_wait: 30s # ์ฒซ ๋ฒˆ์งธ ์•Œ๋ฆผ์ด ๋ฐœ์ƒํ•œ ํ›„ ๊ทธ๋ฃนํ™”๋œ ์•Œ๋ฆผ์„ ์ „์†กํ•˜๊ธฐ ์ „์— ๊ธฐ๋‹ค๋ฆฌ๋Š” ์‹œ๊ฐ„ 30์ดˆ
group_interval: 5m # ๊ทธ๋ฃนํ™”๋œ ์•Œ๋ฆผ์„ ์ „์†กํ•œ ํ›„ ๋‹ค์Œ ์•Œ๋ฆผ์„ ์ „์†กํ•˜๊ธฐ ์ „์— ๊ธฐ๋‹ค๋ฆฌ๋Š” ์‹œ๊ฐ„ 5๋ถ„
repeat_interval: 12h # ๊ฐ™์€ ์•Œ๋ฆผ์ด ๊ณ„์† ๋ฐœ์ƒํ•  ๋•Œ ์•Œ๋ฆผ์„ ๋ฐ˜๋ณตํ•ด์„œ ์ „์†กํ•˜๋Š” ๊ฐ„๊ฒฉ 12์‹œ๊ฐ„
receiver: alert-bridge # alert-bridge๋กœ ์•Œ๋ฆผ ์ „์†ก
routes:
- matchers:
- alertname =~ "ChurnPrediction.*|ChurnConfidence.*|ChurnInference.*|ChurnFeature.*"
receiver: alert-bridge
receivers:
- name: alert-bridge
webhook_configs:
- url: http://alert-bridge.monitoring.svc.cluster.local:8080/alert # alert-bridge์˜ ํด๋Ÿฌ์Šคํ„ฐ ๋‚ด๋ถ€ ์ฃผ์†Œ์™€ ํฌํŠธ
send_resolved: false # ์•Œ๋ฆผ์ด ํ•ด๊ฒฐ๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ์—๋งŒ ์•Œ๋ฆผ ์ „์†ก

grafana:
ingress:
enabled: true
Expand Down
10 changes: 10 additions & 0 deletions services/alert-bridge/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
FROM python:3.11-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY main.py .

CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]
36 changes: 36 additions & 0 deletions services/alert-bridge/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import os
import httpx
from fastapi import FastAPI, Request

app = FastAPI(title="Alert Bridge")

GITHUB_TOKEN = os.getenv("GITHUB_TOKEN")
GITHUB_REPO_OWNER = os.getenv("GITHUB_REPO_OWNER")
GITHUB_REPO_NAME = os.getenv("GITHUB_REPO_NAME")

# Alertmanager์—์„œ ์•Œ๋ฆผ์„ ๋ฐ›์•„์„œ GitHub Actions๋กœ ์ „๋‹ฌํ•˜๋Š” ์—ญํ• ์„ ํ•˜๋Š” api ์—”๋“œํฌ์ธํŠธ(Alertmanager๊ฐ€ ์š”์ฒญ์„ ๋ณด๋ƒ„)
@app.post("/alert")
async def receive_alert(request: Request):
payload = await request.json()

# alertmanager์—์„œ ๋ฐ›์€ ์•Œ๋ฆผ ์ค‘์—์„œ firing ์ƒํƒœ์ธ ์•Œ๋ฆผ๋งŒ ํ•„ํ„ฐ๋ง
firing_alerts = [a for a in payload.get("alerts", []) if a["status"] == "firing"]
if not firing_alerts:
return {"message": "no firing alerts"}

alert_names = [a["labels"].get("alertname", "") for a in firing_alerts]

async with httpx.AsyncClient() as client:
response = await client.post(
f"https://api.github.com/repos/{GITHUB_REPO_OWNER}/{GITHUB_REPO_NAME}/dispatches",
headers={
"Authorization": f"Bearer {GITHUB_TOKEN}",
"Accept": "application/vnd.github+json",
},
json={
"event_type": "model-retrain",
"client_payload": {"alerts": alert_names},
},
)

return {"status": response.status_code, "alerts": alert_names}
3 changes: 3 additions & 0 deletions services/alert-bridge/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fastapi
uvicorn
httpx
21 changes: 18 additions & 3 deletions services/model-api/app/models/loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,36 @@
_model_cache: dict = {}

# mlflow์—์„œ mnist ๋ชจ๋ธ ๋กœ๋“œํ•˜๋Š” ํ•จ์ˆ˜
def load_model(model_name: str, version: str):
cache_key = f"{model_name}_{version}"
def load_model(model_name: str):
cache_key = model_name
if cache_key in _model_cache:
return _model_cache[cache_key]

mlflow_uri = os.getenv("MLFLOW_TRACKING_URI", "http://mlflow:5000") # ํ™˜๊ฒฝ๋ณ€์ˆ˜์—์„œ mlflow tracking uri ๊ฐ€์ ธ์˜ค๊ธฐ, ์—†์œผ๋ฉด ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ http://mlflow:5000 ์‚ฌ์šฉ
mlflow.set_tracking_uri(mlflow_uri)

model_uri = f"models:/{model_name}-{version}/latest"
model_uri = f"models:/{model_name}/latest"
model = mlflow.pytorch.load_model(model_uri)
model.eval()

_model_cache[cache_key] = model
return model

# mlflow์—์„œ ๊ณ ๊ฐ ์ดํƒˆ ์˜ˆ์ธก ๋ชจ๋ธ ๋กœ๋“œํ•˜๋Š” ํ•จ์ˆ˜
def load_churn_model(model_name: str):
cache_key = f"{model_name}_sklearn"
if cache_key in _model_cache:
return _model_cache[cache_key]

mlflow_uri = os.getenv("MLFLOW_TRACKING_URI", "http://mlflow:5000") # ํ™˜๊ฒฝ๋ณ€์ˆ˜์—์„œ mlflow tracking uri ๊ฐ€์ ธ์˜ค๊ธฐ, ์—†์œผ๋ฉด ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ http://mlflow:5000 ์‚ฌ์šฉ
mlflow.set_tracking_uri(mlflow_uri)

model_uri = f"models:/{model_name}/latest"
model = mlflow.sklearn.load_model(model_uri)

_model_cache[cache_key] = model
return model

# mlflow์—์„œ ๊ณ ๊ฐ ์ดํƒˆ ์˜ˆ์ธก ๋ชจ๋ธ ๋กœ๋“œํ•˜๋Š” ํ•จ์ˆ˜
def load_churn_model(model_name: str, version: str):
cache_key = f"{model_name}_{version}_sklearn"
Expand Down
Loading
Loading