release
This commit is contained in:
parent
c737cd8210
commit
c06d453cf4
@ -633,116 +633,67 @@ def _extract_store_id_from_place_url(place_url: str) -> Optional[str]:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
@app.post(
|
@app.post(
|
||||||
"/action-recommendation",
|
"/action-recommendation-simple",
|
||||||
response_model=ActionRecommendationResponse,
|
response_model=ActionRecommendationSimpleResponse,
|
||||||
summary="액션 추천 요청",
|
summary="간소화된 액션 추천 요청",
|
||||||
description="점주가 Claude AI에게 액션 추천을 요청합니다."
|
description="JSON 추천 결과만 반환하는 최적화된 엔드포인트"
|
||||||
)
|
)
|
||||||
async def action_recommendation(
|
async def action_recommendation_simple(
|
||||||
request: ActionRecommendationRequest,
|
request: ActionRecommendationRequest,
|
||||||
claude_service: ClaudeService = Depends(get_claude_service),
|
claude_service: ClaudeService = Depends(get_claude_service),
|
||||||
vector_service: VectorService = Depends(get_vector_service)
|
vector_service: VectorService = Depends(get_vector_service)
|
||||||
):
|
):
|
||||||
"""🧠 Claude AI 액션 추천 API"""
|
"""🧠 최적화된 Claude AI 액션 추천 API - JSON만 반환"""
|
||||||
try:
|
try:
|
||||||
logger.info(f"액션 추천 요청: store_id={request.store_id}")
|
logger.info(f"간소화된 액션 추천 요청: store_id={request.store_id}")
|
||||||
|
|
||||||
start_time = datetime.now()
|
# 1단계: Vector DB에서 최적화된 컨텍스트 조회
|
||||||
|
|
||||||
# 1단계: Vector DB에서 컨텍스트 조회
|
|
||||||
try:
|
|
||||||
db_status = vector_service.get_db_status()
|
|
||||||
|
|
||||||
if db_status.get('total_documents', 0) == 0:
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=404,
|
|
||||||
detail={
|
|
||||||
"success": False,
|
|
||||||
"error": "NO_VECTOR_DATA",
|
|
||||||
"message": "Vector DB에 데이터가 없습니다. 먼저 /build-vector API를 호출하여 데이터를 구축해주세요.",
|
|
||||||
"timestamp": datetime.now().isoformat()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
# Vector DB에서 유사한 케이스 검색
|
|
||||||
context_data = vector_service.search_similar_cases(request.store_id, request.context)
|
|
||||||
|
|
||||||
except HTTPException:
|
|
||||||
raise
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Vector DB 조회 실패: {e}")
|
|
||||||
# Vector DB 조회 실패해도 일반적인 추천은 제공
|
|
||||||
context_data = None
|
context_data = None
|
||||||
|
try:
|
||||||
|
# 개선된 검색 메소드 사용
|
||||||
|
context_data = vector_service.search_similar_cases_improved(
|
||||||
|
request.store_id,
|
||||||
|
request.context
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"Vector DB 조회 실패 (계속 진행): {e}")
|
||||||
|
|
||||||
# 2단계: Claude AI 호출 (프롬프트 구성부터 파싱까지 모두 포함)
|
# 2단계: Claude AI 호출 - JSON만 추출
|
||||||
try:
|
try:
|
||||||
# 컨텍스트 구성
|
# 컨텍스트 구성
|
||||||
full_context = f"가게 ID: {request.store_id}\n점주 요청: {request.context}"
|
full_context = f"가게 ID: {request.store_id}\n점주 요청: {request.context}"
|
||||||
additional_context = context_data if context_data else None
|
|
||||||
|
|
||||||
# Claude AI 액션 추천 생성 (완전한 처리)
|
# Claude AI 호출
|
||||||
claude_response, parsed_response = await claude_service.generate_action_recommendations(
|
claude_response, parsed_json = await claude_service.generate_action_recommendations(
|
||||||
context=full_context,
|
context=full_context,
|
||||||
additional_context=additional_context
|
additional_context=context_data
|
||||||
)
|
)
|
||||||
|
|
||||||
if not claude_response:
|
if not parsed_json:
|
||||||
raise Exception("Claude AI로부터 응답을 받지 못했습니다")
|
# JSON 파싱 실패시 재시도
|
||||||
|
logger.warning("JSON 파싱 실패 - 재시도")
|
||||||
|
parsed_json = claude_service.parse_recommendation_response(claude_response)
|
||||||
|
|
||||||
logger.info(f"Claude 응답 길이: {len(claude_response)} 문자")
|
if not parsed_json:
|
||||||
json_parse_success = parsed_response is not None
|
raise Exception("Claude AI 응답을 JSON으로 파싱할 수 없습니다")
|
||||||
|
|
||||||
|
return ActionRecommendationSimpleResponse(
|
||||||
|
success=True,
|
||||||
|
recommendation=parsed_json
|
||||||
|
)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Claude AI 호출 실패: {e}")
|
logger.error(f"Claude AI 호출 실패: {e}")
|
||||||
raise HTTPException(
|
return ActionRecommendationSimpleResponse(
|
||||||
status_code=500,
|
success=False,
|
||||||
detail=f"AI 추천 생성 중 오류: {str(e)}"
|
error_message=f"AI 추천 생성 중 오류: {str(e)}"
|
||||||
)
|
)
|
||||||
|
|
||||||
# 3단계: 응답 구성
|
|
||||||
claude_execution_time = (datetime.now() - start_time).total_seconds()
|
|
||||||
|
|
||||||
# 가게 정보 추출 (Vector DB에서)
|
|
||||||
store_name = request.store_id # 기본값
|
|
||||||
food_category = "기타" # 기본값
|
|
||||||
|
|
||||||
try:
|
|
||||||
store_context = vector_service.get_store_context(request.store_id)
|
|
||||||
if store_context:
|
|
||||||
store_name = store_context.get('store_name', request.store_id)
|
|
||||||
food_category = store_context.get('food_category', '기타')
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"가게 정보 추출 실패: {e}")
|
logger.error(f"액션 추천 처리 실패: {e}")
|
||||||
|
return ActionRecommendationSimpleResponse(
|
||||||
response = ActionRecommendationResponse(
|
success=False,
|
||||||
success=True,
|
error_message=f"서버 내부 오류: {str(e)}"
|
||||||
message=f"액션 추천이 완료되었습니다. (실행시간: {claude_execution_time:.1f}초, JSON 파싱: {'성공' if json_parse_success else '실패'})",
|
|
||||||
claude_input=full_context + (f"\n--- 동종 업체 분석 데이터 ---\n{additional_context}" if additional_context else ""),
|
|
||||||
claude_response=claude_response,
|
|
||||||
parsed_response=parsed_response,
|
|
||||||
store_name=store_name,
|
|
||||||
food_category=food_category,
|
|
||||||
similar_stores_count=len(context_data.split("---")) if context_data else 0,
|
|
||||||
execution_time=claude_execution_time,
|
|
||||||
json_parse_success=json_parse_success
|
|
||||||
)
|
|
||||||
|
|
||||||
logger.info(f"✅ 액션 추천 완료: Claude 응답 {len(claude_response) if claude_response else 0} 문자, JSON 파싱 {'성공' if json_parse_success else '실패'}, {claude_execution_time:.1f}초 소요")
|
|
||||||
return response
|
|
||||||
|
|
||||||
except HTTPException:
|
|
||||||
raise
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"❌ 액션 추천 요청 실패: {str(e)}")
|
|
||||||
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=500,
|
|
||||||
detail={
|
|
||||||
"success": False,
|
|
||||||
"error": "RECOMMENDATION_FAILED",
|
|
||||||
"message": f"액션 추천 중 오류가 발생했습니다: {str(e)}",
|
|
||||||
"timestamp": datetime.now().isoformat()
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@app.get(
|
@app.get(
|
||||||
|
|||||||
@ -57,6 +57,12 @@ class ActionRecommendationResponse(BaseModel):
|
|||||||
execution_time: Optional[float] = Field(None, description="Claude API 응답 시간(초)")
|
execution_time: Optional[float] = Field(None, description="Claude API 응답 시간(초)")
|
||||||
json_parse_success: Optional[bool] = Field(None, description="JSON 파싱 성공 여부") # 새로 추가
|
json_parse_success: Optional[bool] = Field(None, description="JSON 파싱 성공 여부") # 새로 추가
|
||||||
|
|
||||||
|
class ActionRecommendationSimpleResponse(BaseModel):
|
||||||
|
"""단순화된 액션 추천 응답 - JSON만 반환"""
|
||||||
|
success: bool = Field(description="추천 성공 여부")
|
||||||
|
recommendation: Optional[Dict[str, Any]] = Field(None, description="추천 결과 JSON")
|
||||||
|
error_message: Optional[str] = Field(None, description="오류 메시지 (실패시에만)")
|
||||||
|
|
||||||
class VectorStoreDocument(BaseModel):
|
class VectorStoreDocument(BaseModel):
|
||||||
"""Vector Store에 저장될 문서 구조"""
|
"""Vector Store에 저장될 문서 구조"""
|
||||||
store_id: str = Field(description="가게 ID")
|
store_id: str = Field(description="가게 ID")
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user