File size: 5,468 Bytes
7bc7ddb
 
 
 
 
 
 
 
4564d70
 
7bc7ddb
 
 
 
 
4564d70
 
 
f79f78e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7bc7ddb
 
 
 
 
 
 
 
 
 
 
 
00a6f58
 
7bc7ddb
 
152241c
00a6f58
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a6e766c
 
 
00a6f58
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a6e766c
 
 
 
 
 
 
 
 
 
 
 
7bc7ddb
4564d70
7bc7ddb
 
 
 
 
4564d70
 
 
 
 
 
 
 
 
 
 
 
 
 
7bc7ddb
 
 
 
 
 
 
 
4564d70
 
 
 
 
 
 
 
 
7bc7ddb
 
 
4564d70
 
007a4cf
4564d70
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7bc7ddb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
from fastapi import FastAPI

from interface import PlanRequest, PlanResponse, TripPlan , YoutubeLinkRequest, YoutubeLinkResponse, ChatRequest
from data_importer import DataImporter
from utils.llm_caller import LLMCaller
import asyncio
import time
from datetime import datetime
from fastapi import FastAPI, HTTPException
import logging

app = FastAPI()
data_importer = DataImporter()
agent = LLMCaller()

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

@app.get("/")
def root():
    """Root endpoint - Hugging Face checks this"""
    return {
        "message": "PAN-SEA Travel Planning API is running",
        "status": "healthy",
        "timestamp": datetime.utcnow().isoformat()
    }

@app.get("/health")
def health_check():
    """Health check endpoint"""
    return {
        "status": "healthy",
        "timestamp": datetime.utcnow().isoformat(),
        "service": "PAN-SEA Travel Planning API"
    }

@app.get("/v1")
def greet_json():
    start_time = time.time()
    health_status = {
        "status": "healthy",
        "timestamp": datetime.utcnow().isoformat(),
        "service": "SealionAI Travel Planning Service",
        "version": "1.0.0",
        "checks": {}
    }
    return health_status
MAX_RETRIES = 3
RETRY_DELAY = 2  # seconds
@app.post("/v1/generateTripPlan", response_model=PlanResponse)
def generate_trip_plan(request: PlanRequest):
    data_importer.coldStartDatabase()
    
    for attempt in range(MAX_RETRIES):
        try:
            logger.info(f"Generating trip plan - attempt {attempt + 1}/{MAX_RETRIES}")
            trip_plan = asyncio.run(agent.query_with_rag(request))
            return PlanResponse(
                tripOverview=trip_plan.tripOverview,
                query_params=request,
                retrieved_data=trip_plan.retrieved_data,
                trip_plan=trip_plan.trip_plan,
                preparation=trip_plan.preparation,
                meta={
                    "status": "success", 
                    "timestamp": datetime.utcnow().isoformat(),
                    "attempt": attempt + 1
                }
            )
        except Exception as e:
            logger.warning(f"Error on attempt {attempt + 1}: {e}")

            # If this was the last attempt, raise the error
            if attempt == MAX_RETRIES - 1:
                logger.error(f"All {MAX_RETRIES} attempts failed due to timeout")
                raise HTTPException(
                    status_code=504,  # Gateway Timeout
                    detail={
                        "error": "Request timeout",
                        "message": f"Failed to generate trip plan after {MAX_RETRIES} attempts",
                        "details": "The service is experiencing high load. Please try again later."
                    }
                )
            
            # Wait before retrying
            logger.info(f"Retrying in {RETRY_DELAY} seconds...")
            time.sleep(RETRY_DELAY)
            
        # except Exception as e:
        #     # For non-timeout errors, don't retry
        #     logger.error(f"Non-timeout error in generate_trip_plan: {e}")
        #     raise HTTPException(
        #         status_code=500,
        #         detail={
        #             "error": "Internal server error",
        #             "message": "Failed to generate trip plan",
        #             "details": str(e),
        #             "attempt": attempt + 1
        #         }
        #     )


@app.post("/v1/addYoutubeLink", response_model=YoutubeLinkResponse)
def add_youtube_link(request: YoutubeLinkRequest):
    try:
        data_importer.insert_from_youtube(request.video_id)
        return YoutubeLinkResponse(
                    message="add successfully",
                    video_url=f"https://www.youtube.com/watch?v={request.video_id}"
                )
    except ValueError as e:
        raise HTTPException(status_code=400, detail=f"Invalid video ID: {str(e)}")
    except Exception as e:
        logger.error(f"Error adding YouTube link: {e}")
        raise HTTPException(
            status_code=500,
            detail={
                "error": "Internal server error",
                "message": "Failed to add YouTube link",
                "details": str(e)
            }
        )

@app.post("/v1/searchSimilar", response_model=list[dict])
def search_similar(request: YoutubeLinkRequest):
    try:
        results = data_importer.search_similar(query=request.video_id)
        return results
    except Exception as e:
        logger.error(f"Error during search: {e}")
        raise HTTPException(
            status_code=500,
            detail={
                "error": "Search failed",
                "message": "Unable to search similar content",
                "details": str(e)
            }
        )

@app.post("/v1/basicChat", response_model=str)
def basic_chat(request: ChatRequest):
    try:
        user_message = request.message
        print(f"User message: {user_message}")
        llm_response = asyncio.run(agent.basic_query(
            user_prompt=user_message
        ))
        return llm_response
    except Exception as e:
        logger.error(f"Error in basic_chat: {e}")
        raise HTTPException(
            status_code=500,
            detail={
                "error": "Internal server error",
                "message": "Failed to process chat request",
                "details": str(e)
            }
        )