release
This commit is contained in:
+61
-2
@@ -30,7 +30,7 @@ from contextlib import asynccontextmanager
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
import asyncio
|
||||
from fastapi import FastAPI, HTTPException, Depends
|
||||
from fastapi import FastAPI, HTTPException, Depends, Path
|
||||
from fastapi.responses import HTMLResponse, JSONResponse
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from pydantic import BaseModel, Field
|
||||
@@ -673,4 +673,63 @@ async def health_check():
|
||||
|
||||
if __name__ == "__main__":
|
||||
import uvicorn
|
||||
uvicorn.run(app, host=settings.HOST, port=settings.PORT)
|
||||
uvicorn.run(app, host=settings.HOST, port=settings.PORT)
|
||||
|
||||
@app.get(
|
||||
"/store/{store_id}",
|
||||
response_model=StoreInfoResponse,
|
||||
summary="매장 정보 조회",
|
||||
description="store_id를 이용하여 Vector DB에서 매장 기본정보와 리뷰 정보를 조회합니다"
|
||||
)
|
||||
async def get_store_info(
|
||||
store_id: str = Path(..., description="조회할 매장 ID", example="501745730"),
|
||||
vector_service: VectorService = Depends(get_vector_service)
|
||||
):
|
||||
"""🏪 store_id로 매장 정보 조회 API"""
|
||||
start_time = datetime.now()
|
||||
|
||||
try:
|
||||
logger.info(f"🔍 매장 정보 조회 요청: store_id={store_id}")
|
||||
|
||||
# Vector DB에서 매장 정보 조회
|
||||
store_data = vector_service.get_store_by_id(store_id)
|
||||
|
||||
execution_time = (datetime.now() - start_time).total_seconds()
|
||||
|
||||
if not store_data:
|
||||
return StoreInfoResponse(
|
||||
success=False,
|
||||
message=f"매장 정보를 찾을 수 없습니다: store_id={store_id}",
|
||||
store_id=store_id,
|
||||
execution_time=execution_time
|
||||
)
|
||||
|
||||
# 성공 응답
|
||||
store_info = store_data.get('store_info', {})
|
||||
reviews = store_data.get('reviews', [])
|
||||
review_summary = store_data.get('review_summary', {})
|
||||
metadata = store_data.get('metadata', {})
|
||||
|
||||
return StoreInfoResponse(
|
||||
success=True,
|
||||
message=f"매장 정보 조회 성공: {store_info.get('place_name', store_id)}",
|
||||
store_id=store_id,
|
||||
store_info=store_info,
|
||||
reviews=reviews,
|
||||
review_summary=review_summary,
|
||||
metadata=metadata,
|
||||
last_updated=store_data.get('combined_at'),
|
||||
total_reviews=len(reviews),
|
||||
execution_time=execution_time
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
execution_time = (datetime.now() - start_time).total_seconds()
|
||||
logger.error(f"❌ 매장 정보 조회 실패: store_id={store_id}, error={e}")
|
||||
|
||||
return StoreInfoResponse(
|
||||
success=False,
|
||||
message=f"매장 정보 조회 중 오류 발생: {str(e)}",
|
||||
store_id=store_id,
|
||||
execution_time=execution_time
|
||||
)
|
||||
@@ -108,4 +108,26 @@ class VectorDBStatusResponse(BaseModel):
|
||||
"""Vector DB 상태 조회 응답"""
|
||||
success: bool = Field(description="조회 성공 여부")
|
||||
status: VectorDBStatus = Field(description="DB 상태 정보")
|
||||
message: str = Field(description="응답 메시지")
|
||||
message: str = Field(description="응답 메시지")
|
||||
|
||||
class StoreInfoRequest(BaseModel):
|
||||
"""매장 정보 조회 요청 모델"""
|
||||
store_id: str = Field(
|
||||
...,
|
||||
description="조회할 매장 ID",
|
||||
example="501745730"
|
||||
)
|
||||
|
||||
class StoreInfoResponse(BaseModel):
|
||||
"""매장 정보 조회 응답 모델"""
|
||||
success: bool = Field(description="조회 성공 여부")
|
||||
message: str = Field(description="응답 메시지")
|
||||
store_id: str = Field(description="매장 ID")
|
||||
store_info: Optional[Dict[str, Any]] = Field(None, description="매장 기본 정보")
|
||||
reviews: Optional[List[Dict[str, Any]]] = Field(None, description="리뷰 목록")
|
||||
review_summary: Optional[Dict[str, Any]] = Field(None, description="리뷰 요약 정보")
|
||||
metadata: Optional[Dict[str, Any]] = Field(None, description="Vector DB 메타데이터")
|
||||
last_updated: Optional[str] = Field(None, description="마지막 업데이트 시간")
|
||||
total_reviews: int = Field(default=0, description="총 리뷰 수")
|
||||
execution_time: Optional[float] = Field(None, description="실행 시간(초)")
|
||||
|
||||
@@ -1178,4 +1178,64 @@ class VectorService:
|
||||
return {
|
||||
'added_count': added_count,
|
||||
'add_details': add_details
|
||||
}
|
||||
}
|
||||
|
||||
def get_store_by_id(self, store_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""
|
||||
store_id로 특정 매장의 정보를 조회합니다.
|
||||
|
||||
Args:
|
||||
store_id: 조회할 매장 ID
|
||||
|
||||
Returns:
|
||||
매장 정보 딕셔너리 또는 None
|
||||
"""
|
||||
try:
|
||||
if not self.is_ready():
|
||||
logger.warning("⚠️ VectorService가 준비되지 않음")
|
||||
return None
|
||||
|
||||
logger.info(f"🔍 매장 정보 조회 시작: store_id={store_id}")
|
||||
|
||||
# Vector DB에서 해당 store_id로 검색
|
||||
results = self.collection.get(
|
||||
where={"store_id": store_id},
|
||||
include=['documents', 'metadatas', 'ids']
|
||||
)
|
||||
|
||||
if not results or not results.get('metadatas') or not results['metadatas']:
|
||||
logger.warning(f"❌ 매장 정보를 찾을 수 없음: store_id={store_id}")
|
||||
return None
|
||||
|
||||
# 첫 번째 결과 사용 (store_id는 유니크해야 함)
|
||||
metadata = results['metadatas'][0]
|
||||
document = results['documents'][0] if results.get('documents') else None
|
||||
document_id = results['ids'][0] if results.get('ids') else None
|
||||
|
||||
logger.info(f"✅ 매장 정보 조회 성공: {metadata.get('store_name', 'Unknown')}")
|
||||
|
||||
# 문서에서 JSON 파싱 (combine_store_and_reviews 형태로 저장되어 있음)
|
||||
store_data = None
|
||||
if document:
|
||||
try:
|
||||
import json
|
||||
store_data = json.loads(document)
|
||||
except json.JSONDecodeError as e:
|
||||
logger.error(f"❌ JSON 파싱 실패: {e}")
|
||||
return None
|
||||
|
||||
# 응답 데이터 구성
|
||||
result = {
|
||||
"metadata": metadata,
|
||||
"document_id": document_id,
|
||||
"store_info": store_data.get('store_info') if store_data else None,
|
||||
"reviews": store_data.get('reviews', []) if store_data else [],
|
||||
"review_summary": store_data.get('review_summary', {}) if store_data else {},
|
||||
"combined_at": store_data.get('combined_at') if store_data else None
|
||||
}
|
||||
|
||||
return result
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"❌ 매장 정보 조회 실패: store_id={store_id}, error={e}")
|
||||
return None
|
||||
Reference in New Issue
Block a user