This commit is contained in:
hiondal 2025-06-16 01:27:05 +00:00
parent a04b6c97aa
commit 1ba054db2a
3 changed files with 23 additions and 26 deletions

View File

@ -95,16 +95,6 @@ class RestaurantInfo(BaseModel):
x: str = Field(description="X 좌표값 (경도)") x: str = Field(description="X 좌표값 (경도)")
y: str = Field(description="Y 좌표값 (위도)") y: str = Field(description="Y 좌표값 (위도)")
class FindReviewsResponse(BaseModel):
"""리뷰 검색 응답 모델"""
success: bool = Field(description="검색 성공 여부")
message: str = Field(description="응답 메시지")
target_store: RestaurantInfo = Field(description="대상 가게 정보")
total_stores: int = Field(description="수집된 총 가게 수")
total_reviews: int = Field(description="수집된 총 리뷰 수")
food_category: str = Field(description="추출된 음식 카테고리")
region: str = Field(description="검색 지역")
@asynccontextmanager @asynccontextmanager
async def lifespan(app: FastAPI): async def lifespan(app: FastAPI):
"""🔧 애플리케이션 생명주기 관리 - 안전한 서비스 초기화""" """🔧 애플리케이션 생명주기 관리 - 안전한 서비스 초기화"""
@ -402,7 +392,13 @@ async def find_reviews(
logger.error(f"❌ 본인 가게를 찾을 수 없음: {request.store_name}") logger.error(f"❌ 본인 가게를 찾을 수 없음: {request.store_name}")
return FindReviewsResponse( return FindReviewsResponse(
success=False, success=False,
message=f"'{request.store_name}' 가게를 찾을 수 없습니다. 가게명과 지역을 정확히 입력해주세요." message=f"처리 중 오류가 발생했습니다: {str(e)}",
target_store=None,
food_category=None,
total_reviews=0,
total_stores=0,
execution_time=execution_time,
stored_data=None
) )
logger.info(f"✅ 본인 가게 찾기 성공: {target_restaurant.place_name}") logger.info(f"✅ 본인 가게 찾기 성공: {target_restaurant.place_name}")
@ -414,7 +410,7 @@ async def find_reviews(
# 3단계: 본인 가게 리뷰 수집 (우선순위 1) # 3단계: 본인 가게 리뷰 수집 (우선순위 1)
logger.info("3단계: 본인 가게 리뷰 수집 중...") logger.info("3단계: 본인 가게 리뷰 수집 중...")
target_store_info, target_reviews = await review_service.collect_store_reviews( target_store_info, target_reviews = await review_service.collect_store_reviews(
target_restaurant.id, max_reviews=100 target_restaurant.id, settings.MAX_REVIEWS_PER_RESTAURANT
) )
if not target_reviews: if not target_reviews:
@ -423,7 +419,9 @@ async def find_reviews(
# 4단계: 동종 업체 검색 # 4단계: 동종 업체 검색
logger.info("4단계: 동종 업체 검색 중...") logger.info("4단계: 동종 업체 검색 중...")
similar_stores = await restaurant_service.find_similar_stores( similar_stores = await restaurant_service.find_similar_stores(
request.region, food_category, max_count=50 request.region,
food_category,
max_count=settings.MAX_RESTAURANTS_PER_CATEGORY # 50 → 환경변수
) )
# 5단계: 동종 업체 리뷰 수집 # 5단계: 동종 업체 리뷰 수집
@ -436,14 +434,15 @@ async def find_reviews(
# 동종 업체 리뷰 수집 (본인 가게 제외) # 동종 업체 리뷰 수집 (본인 가게 제외)
similar_store_names = [] similar_store_names = []
for store in similar_stores[:10]: # 최대 10개 동종 업체 max_similar_reviews = min(settings.MAX_REVIEWS_PER_RESTAURANT // 2, 20) # 절반 또는 최대 20개
if store.id != target_restaurant.id: # 본인 가게 제외 for store in similar_stores[:settings.MAX_RESTAURANTS_PER_CATEGORY]: # 환경변수 활용
store_info, reviews = await review_service.collect_store_reviews( store_info, reviews = await review_service.collect_store_reviews(
store.id, max_reviews=50 store.id,
) max_reviews=max_similar_reviews # 동종업체는 더 적게
if store_info and reviews: )
review_results.append((store.id, store_info, reviews)) if store_info and reviews:
similar_store_names.append(store.place_name) review_results.append((store.id, store_info, reviews))
similar_store_names.append(store.place_name)
# 6단계: Vector DB 저장 및 저장 데이터 수집 # 6단계: Vector DB 저장 및 저장 데이터 수집
logger.info("6단계: Vector DB 저장 중...") logger.info("6단계: Vector DB 저장 중...")
@ -529,8 +528,7 @@ async def find_reviews(
total_reviews=total_reviews, total_reviews=total_reviews,
total_stores=len(review_results), total_stores=len(review_results),
execution_time=execution_time, execution_time=execution_time,
stored_data=stored_data, stored_data=stored_data
sample_similar_stores=similar_store_names[:5] # 상위 5개만 샘플로 제공
) )
except Exception as e: except Exception as e:

View File

@ -38,7 +38,6 @@ class FindReviewsResponse(BaseModel):
execution_time: Optional[float] = Field(None, description="실행 시간(초)") execution_time: Optional[float] = Field(None, description="실행 시간(초)")
# Vector DB 저장 데이터 # Vector DB 저장 데이터
stored_data: Optional[Dict[str, StoredDataInfo]] = Field(None, description="Vector DB에 저장된 데이터") stored_data: Optional[Dict[str, StoredDataInfo]] = Field(None, description="Vector DB에 저장된 데이터")
sample_similar_stores: List[str] = Field(default=[], description="동종 업체 샘플 목록")
class VectorBuildResponse(BaseModel): class VectorBuildResponse(BaseModel):
"""Vector DB 구축 응답 모델""" """Vector DB 구축 응답 모델"""

View File

@ -31,14 +31,14 @@ class ReviewService:
logger.info(f"🏪 가게 리뷰 수집 시작: store_id={store_id} (최대 {max_reviews}개)") logger.info(f"🏪 가게 리뷰 수집 시작: store_id={store_id} (최대 {max_reviews}개)")
# 본인 가게는 더 관대한 타임아웃 설정 # 본인 가게는 더 관대한 타임아웃 설정
timeout = aiohttp.ClientTimeout(total=900) # 15분 timeout = aiohttp.ClientTimeout(total=settings.REQUEST_TIMEOUT)
async with aiohttp.ClientSession(timeout=timeout) as session: async with aiohttp.ClientSession(timeout=timeout) as session:
url = f"{self.base_url}/analyze" url = f"{self.base_url}/analyze"
payload = { payload = {
"store_id": store_id, "store_id": store_id,
"days_limit": None, # 모든 날짜의 리뷰 수집 "days_limit": None, # 모든 날짜의 리뷰 수집
"max_time": min(600, max_reviews * 3) # 리뷰 수에 따라 시간 조정, 최대 10분 "max_time": settings.REQUEST_TIMEOUT
} }
logger.info(f"Review API 호출: {url} (타임아웃: {payload['max_time']}초)") logger.info(f"Review API 호출: {url} (타임아웃: {payload['max_time']}초)")