Skip to content

Commit e6a56a3

Browse files
authored
배포 v1.12.1
배포 v1.12.1
2 parents 1c238fe + 41700d5 commit e6a56a3

File tree

6 files changed

+44
-86
lines changed

6 files changed

+44
-86
lines changed

.github/workflows/Deploy-ML-EC2.yml

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,17 @@ jobs:
4141
SIX_HOUR_MODEL_PATH: ${{ secrets.SIX_HOUR_MODEL_PATH }}
4242
TWELVE_HOUR_MODEL_PATH: ${{ secrets.TWELVE_HOUR_MODEL_PATH }}
4343

44-
PRED_PATH: ${{ secrets.PRED_PATH }}
44+
# PRED_PATH: ${{ secrets.PRED_PATH }}
45+
S3_BUCKET_NAME: ${{ secrets.S3_BUCKET_NAME }}
46+
S3_DIRECTORY_PATH: ${{ secrets.S3_DIRECTORY_PATH }}
47+
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
48+
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
4549
with:
4650
host: ${{ secrets.EC2_HOST_ML }}
4751
username: ${{ secrets.EC2_USER }}
4852
key: ${{ secrets.EC2_SSH_KEY }}
4953
port: 22
50-
envs: OPENAI_API_KEY,VECTORDB_PATH,DB_HOST,DB_PORT,DB_USER,DB_PASSWORD,DB_DATABASE,CLICK_LOG,DEEPFM_TRAIN_MODEL_PATH,DEEPFM_TRAIN_ENCODERS_PATH,DEEPFM_TRAIN_KEY2INDEX_PATH,SEOUL_API_KEY,PLACE_PATH,ONE_HOUR_MODEL_PATH,TWO_HOUR_MODEL_PATH,THREE_HOUR_MODEL_PATH,SIX_HOUR_MODEL_PATH,TWELVE_HOUR_MODEL_PATH,PRED_PATH
54+
envs: OPENAI_API_KEY,VECTORDB_PATH,DB_HOST,DB_PORT,DB_USER,DB_PASSWORD,DB_DATABASE,CLICK_LOG,DEEPFM_TRAIN_MODEL_PATH,DEEPFM_TRAIN_ENCODERS_PATH,DEEPFM_TRAIN_KEY2INDEX_PATH,SEOUL_API_KEY,PLACE_PATH,ONE_HOUR_MODEL_PATH,TWO_HOUR_MODEL_PATH,THREE_HOUR_MODEL_PATH,SIX_HOUR_MODEL_PATH,TWELVE_HOUR_MODEL_PATH,PRED_PATH,S3_BUCKET_NAME,AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY
5155
script: |
5256
# 프로젝트 디렉터리로 이동
5357
cd ~/MLOps
@@ -87,6 +91,11 @@ jobs:
8791
echo "SEOUL_API_KEY=$SEOUL_API_KEY" >> .env
8892
echo "PLACE_PATH=$PLACE_PATH" >> .env
8993
echo "PRED_PATH=$PRED_PATH" >> .env
94+
95+
echo "S3_BUCKET_NAME=$S3_BUCKET_NAME" >> .env
96+
echo "S3_DIRECTORY_PATH=$S3_DIRECTORY_PATH" >> .env
97+
echo "AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID" >> .env
98+
echo "AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY" >> .env
9099
91100
# Docker 컨테이너 재시작 (docker-compose가 있다면)
92101
if [ -f docker-compose.yml ]; then

.github/workflows/dvc-sync.yml

Lines changed: 0 additions & 50 deletions
This file was deleted.

MLOps/app/python_schedule/data/.gitignore

Lines changed: 0 additions & 1 deletion
This file was deleted.

MLOps/app/python_schedule/data/crowd_prediction.dvc

Lines changed: 0 additions & 6 deletions
This file was deleted.

MLOps/app/routers/crowd.py

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,6 @@
66

77
router = APIRouter(prefix="/api", tags=["crowdness"])
88

9-
# .env에서 PRED_PATH를 찾지 못할 경우를 대비한 기본 경로 설정
10-
PRED_PATH = os.getenv("PRED_PATH")
11-
if not PRED_PATH:
12-
print("PRED_PATH is not set")
13-
149
@router.get("/crowd", response_model=CrowdResponse)
1510
def get_crowd_prediction(hour: int, area: str = "all"):
1611
"""
@@ -19,18 +14,22 @@ def get_crowd_prediction(hour: int, area: str = "all"):
1914
- **area**: 조회할 지역 (all, 서울, 경기, 인천, 강원, 충청, 전라, 경상, 제주 중 하나)
2015
"""
2116
try:
22-
# 1. 대상 파일명 생성
17+
# 1. 대상 S3 경로 생성
2318
target_timestamp = (datetime.now()).strftime("%Y%m%d%H")
2419
filename = f"congestion_predictions_{target_timestamp}_{hour}.csv"
25-
file_path = os.path.join(PRED_PATH, filename)
26-
27-
print(f"Attempting to read: {file_path}")
2820

29-
# 2. 파일 존재 확인 및 데이터 로드
30-
if not os.path.exists(file_path):
31-
raise HTTPException(status_code=404, detail=f"Prediction file not found for T+{hour}h. It may not have been generated yet.")
21+
s3_bucket_name = os.getenv("S3_BUCKET_NAME")
22+
if not s3_bucket_name:
23+
raise ValueError("S3_BUCKET_NAME environment variable is not set.")
24+
25+
s3_directory = os.getenv("S3_DIRECTORY_PATH", "")
26+
s3_key = os.path.join(s3_directory, filename).replace("\\", "/") # S3는 /를 사용
27+
s3_path = f"s3://{s3_bucket_name}/{s3_key}"
28+
29+
print(f"Attempting to read from S3: {s3_path}")
3230

33-
df = pd.read_csv(file_path)
31+
# 2. S3에서 데이터 로드
32+
df = pd.read_csv(s3_path)
3433

3534
# 3. 'area' 파라미터에 따른 데이터 필터링
3635
if area != "all":
@@ -60,5 +59,7 @@ def get_crowd_prediction(hour: int, area: str = "all"):
6059
message=f"조회 성공!",
6160
crowdLevel=crowd_level
6261
)
62+
except FileNotFoundError:
63+
raise HTTPException(status_code=404, detail=f"Prediction file not found: {s3_path}. It may not have been generated yet.")
6364
except Exception as e:
6465
raise HTTPException(status_code=500, detail=f"An error occurred: {str(e)}")

MLOps/app/services/predict_cong_service.py

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from collections import defaultdict
99
import schedule
1010
import time
11+
import boto3
1112

1213
# --- 경로 설정 및 초기화 ---
1314
project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..'))
@@ -34,9 +35,6 @@
3435
# 파일명 접미사 매핑
3536
MODEL_FILE_SUFFIX = {"1-hour": 1, "2-hour": 2, "3-hour": 3, "6-hour": 6, "12-hour": 12}
3637

37-
38-
PRED_PATH = os.getenv("PRED_PATH")
39-
4038
# --- 전역 객체 및 모델 로드 ---
4139
preprocessor = CongestionDataPreprocessor()
4240
models = {}
@@ -112,14 +110,6 @@ def predict_and_save_all_locations():
112110
print("No predictions were made.")
113111
return
114112

115-
# PRED_PATH가 설정되지 않았을 경우에 대한 예외 처리
116-
if not PRED_PATH:
117-
print("❌ PRED_PATH environment variable is not set. Cannot save files.")
118-
return
119-
120-
# 저장 경로가 존재하는지 확인하고, 없으면 생성합니다.
121-
os.makedirs(PRED_PATH, exist_ok=True)
122-
123113
# 타임스탬프 (현재 시간 + 1시간)
124114
timestamp = (datetime.now() + timedelta(hours=1)).strftime("%Y%m%d%H")
125115

@@ -139,10 +129,25 @@ def predict_and_save_all_locations():
139129

140130
file_suffix = MODEL_FILE_SUFFIX.get(name)
141131
output_filename = f"congestion_predictions_{timestamp}_{file_suffix}.csv"
142-
output_path = os.path.join(PRED_PATH, output_filename)
143132

144-
final_df.to_csv(output_path, index=False, encoding='utf-8-sig')
145-
print(f"✅ Predictions for '{name}' saved to: {output_path}")
133+
# --- S3에 바로 저장 ---
134+
s3_bucket_name = os.getenv("S3_BUCKET_NAME")
135+
s3_directory = os.getenv("S3_DIRECTORY_PATH", "") # S3 내 디렉토리 경로 (옵션)
136+
137+
if s3_bucket_name:
138+
try:
139+
# S3 키는 디렉토리 경로와 파일명을 조합하여 만듭니다.
140+
s3_key = os.path.join(s3_directory, output_filename)
141+
s3_path = f"s3://{s3_bucket_name}/{s3_key}"
142+
143+
# EC2 인스턴스의 IAM 역할을 사용한 인증을 통해 S3에 직접 저장합니다.
144+
final_df.to_csv(s3_path, index=False, encoding='utf-8-sig')
145+
print(f"✅ Predictions for '{name}' successfully saved to: {s3_path}")
146+
147+
except Exception as e:
148+
print(f"❌ S3 save failed: {e}")
149+
else:
150+
print("⚠️ S3_BUCKET_NAME environment variable not set. Skipping S3 save.")
146151

147152
if __name__ == "__main__":
148153
print("Congestion prediction service started.")

0 commit comments

Comments
 (0)