from fastapi import FastAPI, HTTPException from fastapi.middleware.cors import CORSMiddleware from pydantic import BaseModel from typing import List, Dict, Any # utils 폴더 확인 필수 from utils import tarot, calculations, prompts, llm import os import traceback app = FastAPI(title="AI Pantheon API") app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # --- 1. 요청 모델 --- class TarotRequest(BaseModel): cards: List[str] topic: str query: str lang: str = "한국어" class FengShuiRequest(BaseModel): year: int gender: str door_dir: str head_dir: str query: str lang: str = "한국어" class SajuRequest(BaseModel): year: int month: int day: int hour: int minute: int calendar_type: str query: str lang: str = "한국어" # --- 2. 페르소나 생성기 (🔥 다국어 완벽 지원 수정!) --- def get_dynamic_persona(role_type: str, lang: str) -> Dict[str, str]: # 언어값이 비어있으면 기본값 영어 target_lang = lang if lang else "English" # 한국어 특화 처리 (한국어는 뉘앙스가 중요해서 따로 뺌) is_korean = any(k in target_lang for k in ["한국", "Korean", "ko"]) prompt_text = "" if role_type == "tarot": if is_korean: prompt_text = """ 당신은 타로 리더 '에밀리'입니다. 사용자의 고민에 대해 따뜻하고 직관적인 통찰력을 제공하세요. 말투: 부드럽고 신비로운 존댓말 (해요체). """ else: # 🔥 [수정] 영어가 아니라 {target_lang}으로 답변하라고 지시 prompt_text = f""" You are 'Emily', a mysterious Tarot Reader. CRITICAL INSTRUCTION: You must ANSWER STRICTLY IN {target_lang}. Even if the user input is in another language, TRANSLATE your reading to {target_lang}. Tone: Mystical, soft, empathetic. """ elif role_type == "fengshui": if is_korean: prompt_text = """ 당신은 풍수지리 전문가입니다. 논리적이고 전문적으로 한국어로 답변하세요. """ else: # 🔥 [수정] {target_lang} 사용 prompt_text = f""" You are a Feng Shui Master. CRITICAL INSTRUCTION: You must ANSWER STRICTLY IN {target_lang}. Do NOT mention translation. Speak with authority as a Master in {target_lang}. Tone: Professional, logical, wise. """ elif role_type == "shaman": if is_korean: prompt_text = """ 당신은 무당 '천명'입니다. 거친 반말(~해라, ~구나)을 쓰며 한국어로 답변하세요. """ else: # 🔥 [수정] {target_lang} 사용 prompt_text = f""" You are 'Shaman Cheon-Myeong'. CRITICAL INSTRUCTION: You must ANSWER STRICTLY IN {target_lang}. Speak directly to the user's soul in {target_lang}. Tone: Mystical, Charismatic, slightly archaic style. """ else: prompt_text = f"Answer strictly in {target_lang}." return {"system_prompt": prompt_text} # --- 3. 엔드포인트 --- @app.get("/") def read_root(): return {"message": "Server is Running!"} @app.get("/tarot/deck") def get_tarot_deck(): return tarot.MAJOR_ARCANA @app.post("/tarot/read") def read_tarot(req: TarotRequest): try: selected_cards = [card for card in tarot.MAJOR_ARCANA if card["name"] in req.cards] persona = get_dynamic_persona("tarot", req.lang) card_infos = [] # 카드 설명은 한국어 아니면 일단 영어로 나감 (추후 베트남어 DB 있으면 여기도 분기 가능) is_kor = "한국" in req.lang or "Korean" in req.lang for c in selected_cards: desc = c.get('desc_kor') if is_kor else c.get('desc_eng') or c.get('desc') if not desc: desc = "No description" card_infos.append(f"- {c['name']}: {desc}") card_str = "\n".join(card_infos) full_query = f""" Topic: {req.topic} User Question: {req.query} Selected Cards: {card_str} """ response = llm.get_ai_response(full_query, persona) return {"result": response} except Exception as e: print(traceback.format_exc()) return {"result": f"Server Error: {str(e)}"} @app.post("/fengshui/analyze") def analyze_fengshui(req: FengShuiRequest): try: gender_kor = "남성" if req.gender in ["Male", "남성"] else "여성" fs_data = calculations.get_fengshui_advanced(req.year, gender_kor, req.door_dir, req.head_dir) persona = get_dynamic_persona("fengshui", req.lang) full_query = f"[FengShui Data]: {fs_data}\nUser Query: {req.query}" response = llm.get_ai_response(full_query, persona) return {"data": fs_data, "result": response} except Exception as e: return {"result": f"Error: {str(e)}"} @app.post("/shaman/read") def read_saju(req: SajuRequest): try: import datetime b_date = datetime.date(req.year, req.month, req.day) b_time = datetime.time(req.hour, req.minute) saju_data = calculations.get_ganji_full(b_date, b_time, req.calendar_type) persona = get_dynamic_persona("shaman", req.lang) full_query = f"[Saju Data]: {saju_data}\nUser Query: {req.query}" response = llm.get_ai_response(full_query, persona) return {"data": saju_data, "result": response} except Exception as e: return {"result": f"Error: {str(e)}"}