diff --git a/.gitignore b/.gitignore index 4dbc92f..2a4a0d1 100644 --- a/.gitignore +++ b/.gitignore @@ -84,7 +84,6 @@ vector_db/ *.pkl *.model *.bin -models/ embeddings/ checkpoints/ @@ -117,4 +116,4 @@ yarn-error.log* # Backup files *.bak -*.backup \ No newline at end of file +*.backup diff --git a/vector/app/models/restaurant_models.py b/vector/app/models/restaurant_models.py new file mode 100644 index 0000000..cf532b5 --- /dev/null +++ b/vector/app/models/restaurant_models.py @@ -0,0 +1,70 @@ +# app/models/restaurant_models.py +from pydantic import BaseModel, Field +from typing import List, Optional, Dict, Any + +class RestaurantSearchRequest(BaseModel): + """음식점 검색 요청 모델""" + region: str = Field( + ..., + description="지역 (시군구 + 읍면동)", + example="서울특별시 강남구 역삼동" + ) + store_name: str = Field( + ..., + description="가게명", + example="맛있는 한식당" + ) + +class RestaurantInfo(BaseModel): + """음식점 정보 모델""" + id: str = Field(description="카카오 장소 ID") + place_name: str = Field(description="장소명") + category_name: str = Field(description="카테고리명") + category_group_code: str = Field(description="카테고리 그룹 코드") + category_group_name: str = Field(description="카테고리 그룹명") + phone: str = Field(description="전화번호") + address_name: str = Field(description="전체 지번 주소") + road_address_name: str = Field(description="전체 도로명 주소") + place_url: str = Field(description="장소 상세페이지 URL") + distance: str = Field(description="중심좌표까지의 거리 (meter)") + x: str = Field(description="X 좌표값, 경위도인 경우 longitude") + y: str = Field(description="Y 좌표값, 경위도인 경우 latitude") + +class SimilarRestaurantsRequest(BaseModel): + """동종 업체 검색 요청 모델""" + region: str = Field( + ..., + description="지역", + example="서울특별시 강남구" + ) + food_category: str = Field( + ..., + description="음식 종류", + example="육류,고기" + ) + max_count: int = Field( + default=50, + description="최대 검색 개수", + example=50 + ) + +class RestaurantSearchResponse(BaseModel): + """음식점 검색 응답 모델""" + success: bool = Field(description="검색 성공 여부") + message: str = Field(description="응답 메시지") + restaurant: Optional[RestaurantInfo] = Field(description="찾은 음식점 정보") + +class SimilarRestaurantsResponse(BaseModel): + """동종 업체 검색 응답 모델""" + success: bool = Field(description="검색 성공 여부") + message: str = Field(description="응답 메시지") + restaurants: List[RestaurantInfo] = Field(description="동종 업체 목록") + total_count: int = Field(description="총 검색된 업체 수") + +class ErrorResponse(BaseModel): + """에러 응답 모델""" + success: bool = False + error: str = Field(description="에러 코드") + message: str = Field(description="에러 메시지") + timestamp: str = Field(description="에러 발생 시간") + diff --git a/vector/app/models/review_models.py b/vector/app/models/review_models.py new file mode 100644 index 0000000..823b652 --- /dev/null +++ b/vector/app/models/review_models.py @@ -0,0 +1,68 @@ +# app/models/review_models.py +from pydantic import BaseModel, Field +from typing import List, Optional, Dict, Any + +class ReviewerStats(BaseModel): + """리뷰어 통계 정보""" + reviews: Optional[int] = Field(None, description="작성한 리뷰 수") + average_rating: Optional[float] = Field(None, description="평균 별점") + followers: Optional[int] = Field(None, description="팔로워 수") + +class ReviewData(BaseModel): + """개별 리뷰 데이터""" + reviewer_name: str = Field(description="리뷰어 이름") + reviewer_level: str = Field(description="리뷰어 레벨") + reviewer_stats: ReviewerStats = Field(description="리뷰어 통계") + rating: int = Field(description="별점") + date: str = Field(description="작성 날짜") + content: str = Field(description="리뷰 내용") + badges: List[str] = Field(description="태그/배지 목록") + likes: int = Field(description="좋아요 수") + photo_count: int = Field(description="사진 개수") + has_photos: bool = Field(description="사진 포함 여부") + +class StoreInfo(BaseModel): + """가게 정보""" + id: str = Field(description="가게 ID") + name: str = Field(description="가게명") + category: str = Field(description="카테고리") + rating: str = Field(description="평균 별점") + review_count: str = Field(description="리뷰 수") + status: str = Field(description="영업 상태") + address: str = Field(description="주소") + +class DateFilter(BaseModel): + """날짜 필터 정보""" + cutoff_date: Optional[str] = Field(None, description="기준 날짜") + filtered: bool = Field(description="필터 적용 여부") + +class ReviewAnalysisRequest(BaseModel): + """리뷰 분석 요청 모델""" + store_id: str = Field( + ..., + description="카카오맵 가게 ID", + example="501745730" + ) + days_limit: Optional[int] = Field( + None, + description="며칠 이후의 리뷰만 수집할지 (None이면 모든 날짜)", + example=30 + ) + max_time: int = Field( + 300, + description="최대 스크롤 시간(초)", + example=300 + ) + +class ReviewAnalysisResponse(BaseModel): + """리뷰 분석 응답 모델""" + success: bool = Field(description="분석 성공 여부") + message: str = Field(description="응답 메시지") + store_info: Optional[StoreInfo] = Field(None, description="가게 정보") + reviews: List[ReviewData] = Field(description="리뷰 목록") + analysis_date: str = Field(description="분석 수행 날짜시간") + total_reviews: int = Field(description="수집된 총 리뷰 수") + analysis_method: str = Field(description="분석 방법") + date_filter: DateFilter = Field(description="날짜 필터 정보") + execution_time: float = Field(description="실행 시간(초)") + diff --git a/vector/app/models/vector_models.py b/vector/app/models/vector_models.py new file mode 100644 index 0000000..1cf028b --- /dev/null +++ b/vector/app/models/vector_models.py @@ -0,0 +1,84 @@ +# app/models/vector_models.py +from pydantic import BaseModel, Field +from typing import List, Optional, Dict, Any + +class VectorBuildRequest(BaseModel): + """Vector DB 구축 요청 모델""" + region: str = Field( + ..., + description="지역 (시군구 + 읍면동)", + example="서울특별시 강남구 역삼동" + ) + store_name: str = Field( + ..., + description="가게명", + example="맛있는 한식당" + ) + force_rebuild: bool = Field( + False, + description="강제 재구축 여부", + example=False + ) + +class VectorBuildResponse(BaseModel): + """Vector DB 구축 응답 모델""" + success: bool = Field(description="구축 성공 여부") + message: str = Field(description="응답 메시지") + store_info: Dict[str, Any] = Field(description="대상 가게 정보") + similar_stores_count: int = Field(description="동종 업체 수") + total_reviews_processed: int = Field(description="처리된 총 리뷰 수") + vector_db_status: str = Field(description="Vector DB 상태") + execution_time: float = Field(description="실행 시간(초)") + food_category: str = Field(description="추출된 음식 카테고리") + +class ActionRecommendationRequest(BaseModel): + """액션 추천 요청 모델""" + store_id: str = Field( + ..., + description="가게 ID", + example="12345" + ) + context: Optional[str] = Field( + None, + description="추가 컨텍스트", + example="매출이 감소하고 있어서 개선 방안이 필요합니다." + ) + +class ActionRecommendationResponse(BaseModel): + """액션 추천 응답 모델""" + success: bool = Field(description="추천 성공 여부") + message: str = Field(description="응답 메시지") + claude_input: str = Field(description="Claude API에 전달한 프롬프트") + claude_response: Optional[str] = Field(None, description="Claude AI 원본 응답") + parsed_response: Optional[Dict[str, Any]] = Field(None, description="파싱된 JSON 응답") # 새로 추가 + store_name: str = Field(description="가게명") + food_category: str = Field(description="음식 카테고리") + similar_stores_count: int = Field(description="분석된 동종 업체 수") + execution_time: Optional[float] = Field(None, description="Claude API 응답 시간(초)") + json_parse_success: Optional[bool] = Field(None, description="JSON 파싱 성공 여부") # 새로 추가 + +class VectorStoreDocument(BaseModel): + """Vector Store에 저장될 문서 구조""" + store_id: str = Field(description="가게 ID") + store_name: str = Field(description="가게명") + food_category: str = Field(description="음식 카테고리") + region: str = Field(description="지역") + store_info: Dict[str, Any] = Field(description="가게 정보") + reviews: List[Dict[str, Any]] = Field(description="리뷰 목록") + review_summary: Dict[str, Any] = Field(description="리뷰 요약 정보") + last_updated: str = Field(description="마지막 업데이트 시간") + +class VectorDBStatus(BaseModel): + """Vector DB 상태 정보""" + collection_name: str = Field(description="컬렉션명") + total_documents: int = Field(description="총 문서 수") + total_stores: int = Field(description="총 가게 수") + db_path: str = Field(description="DB 경로") + last_updated: Optional[str] = Field(None, description="마지막 업데이트 시간") + +class VectorDBStatusResponse(BaseModel): + """Vector DB 상태 조회 응답""" + success: bool = Field(description="조회 성공 여부") + status: VectorDBStatus = Field(description="DB 상태 정보") + message: str = Field(description="응답 메시지") +