hyerimmy 910bd902b1
Some checks failed
HealthSync Intelligence CI / build-and-push (push) Has been cancelled
feat : initial commit
2025-06-20 05:28:30 +00:00

223 lines
7.7 KiB
Python

# app/main.py
"""
HealthSync AI - FastAPI 메인 애플리케이션 (MVC 패턴) - 벡터DB 및 Redis 연동 추가
"""
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import RedirectResponse, JSONResponse
from fastapi.exceptions import RequestValidationError
from fastapi.openapi.utils import get_openapi
from app.views.status_views import status_router
from app.views.mission_views import mission_router
from app.views.health_views import health_router
from app.views.chat_views import chat_router
from app.config.settings import settings
from app.models.base import ErrorResponse
from app.utils.vector_client import pinecone_client
from app.utils.redis_client import redis_client
import time
import logging
from datetime import datetime
# 로깅 설정
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s")
logger = logging.getLogger("HealthSync_AI")
# FastAPI 앱 생성
app = FastAPI(
title=settings.app_name,
description=f"""
{settings.app_description}
### 🚀 주요 기능
- **🎯 AI 미션 추천**: 개인 건강 데이터 기반 맞춤형 건강 미션 추천
- **🔬 AI 건강 진단**: 건강검진 데이터 3줄 요약 진단
- **💬 AI 건강 상담**: 개인 건강 데이터 기반 맞춤형 건강 상담 챗봇
- **🎉 미션 축하**: AI 기반 개인화된 미션 달성 축하 메시지
- **🔔 유사 미션 소식**: 벡터DB 기반 유사 사용자 미션 완료 소식
- **🏥 건강 상태 분석**: 건강검진 데이터 종합 분석
- **💡 개인화 서비스**: 직업군별 특화된 건강 관리 솔루션
### 🔧 기술 스택
- **Framework**: FastAPI {settings.app_version}
- **Pattern**: MVC (Model-View-Controller)
- **Language**: Python 3.11+
- **Database**: PostgreSQL
- **VectorDB**: Pinecone (유사도 검색)
- **Cache**: Redis (스마트 캐싱)
- **AI**: Claude API
- **Docs**: OpenAPI 3.0
---
💡 **Tip**: 왼쪽 사이드바에서 API 엔드포인트를 탐색해보세요!
""",
version=settings.app_version,
docs_url="/api/intelligence/docs",
redoc_url="/api/intelligence/redoc",
openapi_url="/api/intelligence/openapi.json"
)
# OpenAPI 스키마 커스터마이징
def custom_openapi():
if app.openapi_schema:
return app.openapi_schema
openapi_schema = get_openapi(
title=settings.app_name,
version=settings.app_version,
description=settings.app_description,
routes=app.routes,
)
# OpenAPI 3.1.0 명시적 설정
openapi_schema["openapi"] = "3.1.0"
# 서버 정보 추가
openapi_schema["servers"] = [
{
"url": f"http://{settings.host}:{settings.port}",
"description": "Development server"
}
]
# 태그 정보 추가
openapi_schema["tags"] = [
{
"name": "🏥 Status Check",
"description": "시스템 상태 확인 및 데이터베이스 연결 테스트"
},
{
"name": "🎯 Mission Management",
"description": "AI 기반 건강 미션 추천 및 축하 메시지"
},
{
"name": "🔬 Health Analysis",
"description": "건강검진 데이터 AI 분석 및 3줄 요약 진단"
},
{
"name": "💬 Chat Consultation",
"description": "개인 건강 데이터 기반 AI 건강 상담 챗봇"
}
]
app.openapi_schema = openapi_schema
return app.openapi_schema
app.openapi = custom_openapi
# CORS 미들웨어 설정
app.add_middleware(
CORSMiddleware,
allow_origins=settings.cors_origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# 요청 처리 시간 미들웨어
@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
start_time = time.time()
logger.info(f"📥 Request: {request.method} {request.url.path}")
response = await call_next(request)
process_time = time.time() - start_time
response.headers["X-Process-Time"] = str(round(process_time, 4))
response.headers["X-Service"] = settings.app_name
logger.info(
f"📤 Response: {request.method} {request.url.path} - Status: {response.status_code} - Time: {process_time:.4f}s")
return response
# API 라우터 등록
app.include_router(status_router, prefix=settings.api_v1_prefix)
app.include_router(mission_router, prefix=settings.api_v1_prefix)
app.include_router(health_router, prefix=settings.api_v1_prefix)
app.include_router(chat_router, prefix=settings.api_v1_prefix)
@app.get("/", include_in_schema=False)
async def root():
"""루트 경로 - API 문서로 리다이렉트"""
return RedirectResponse(url="/api/intelligence/docs")
@app.get("/docs", include_in_schema=False)
async def docs_redirect():
"""docs 경로 - API 문서로 리다이렉트"""
return RedirectResponse(url="/api/intelligence/docs")
# 예외 처리
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
error_response = ErrorResponse(
error_code="VALIDATION_ERROR",
message="입력 데이터 검증에 실패했습니다.",
details={"errors": exc.errors()},
timestamp=datetime.now()
)
return JSONResponse(
status_code=422,
content=error_response.model_dump(mode='json')
)
@app.on_event("startup")
async def startup_event():
logger.info(f"🚀 {settings.app_name} v{settings.app_version} 서비스 시작")
# 벡터DB 및 Redis 연결 초기화
try:
logger.info("🔗 외부 서비스 연결 초기화 중...")
# Pinecone 벡터DB 초기화
if settings.pinecone_api_key and settings.pinecone_api_key != "your_pinecone_api_key_here":
await pinecone_client.initialize()
logger.info("✅ Pinecone 벡터DB 연결 완료")
else:
logger.warning("⚠️ Pinecone API 키가 설정되지 않음 - 유사 미션 소식 기능 비활성화")
# Redis 캐시 연결
if settings.redis_host:
await redis_client.connect()
logger.info("✅ Redis 캐시 연결 완료")
else:
logger.warning("⚠️ Redis 설정이 없음 - 캐싱 기능 비활성화")
except Exception as e:
logger.error(f"❌ 외부 서비스 연결 실패: {str(e)}")
logger.warning("⚠️ 일부 기능이 제한될 수 있습니다.")
# API 엔드포인트 정보 출력
logger.info(f"📝 API 문서: http://{settings.host}:{settings.port}/api/missions/docs")
logger.info(f"🎯 미션 추천 API: http://{settings.host}:{settings.port}/api/missions/recommend")
logger.info(f"🎉 미션 축하 API: http://{settings.host}:{settings.port}/api/missions/celebrate")
logger.info(f"🔔 유사 미션 소식 API: http://{settings.host}:{settings.port}/api/missions/similar-news")
logger.info(f"📊 사용자 벡터 저장 API: http://{settings.host}:{settings.port}/api/missions/upsert-vector")
logger.info(f"🔬 건강 진단 API: http://{settings.host}:{settings.port}/api/health/diagnosis")
logger.info(f"💬 건강 상담 API: http://{settings.host}:{settings.port}/api/chat/consultation")
@app.on_event("shutdown")
async def shutdown_event():
logger.info("🛑 HealthSync AI 서비스 종료 중...")
# 외부 서비스 연결 해제
try:
if redis_client._connected:
await redis_client.disconnect()
logger.info("✅ Redis 연결 해제 완료")
except Exception as e:
logger.error(f"❌ Redis 연결 해제 실패: {str(e)}")
logger.info("🛑 HealthSync AI 서비스 종료 완료")