shoaibamin-dev commited on
Commit
c206733
·
1 Parent(s): a2cadde

audit logs and mongo util

Browse files
Files changed (7) hide show
  1. ai/extract.py +123 -0
  2. ai/iata.py +6 -6
  3. ai/prompt.py +159 -0
  4. ai/travel.py +144 -122
  5. ai/trip.py +32 -120
  6. ai/tti.py +15 -15
  7. main.py +296 -156
ai/extract.py ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+ from langdetect import detect
3
+ import openai
4
+ import os
5
+ from dotenv import load_dotenv
6
+ from utils.db import MongoDBUtil
7
+ from bson import ObjectId
8
+ # Load environment variables
9
+ load_dotenv()
10
+ openai.api_key = os.getenv("OPENAI_API_KEY")
11
+
12
+ mongo_util = MongoDBUtil()
13
+
14
+ # Function to use GPT for extracting details
15
+ def gpt_extract_trip_details(sentence):
16
+ """
17
+ Use OpenAI GPT to extract destination and number of days.
18
+ """
19
+ prompt = (
20
+ f"Extract the following details from this sentence:\n"
21
+ f"Sentence: '{sentence}'\n\n"
22
+ f"Details to extract:\n"
23
+ f"1. Destination: (The place the user wants to travel to, None if not mentioned)\n"
24
+ f"2. Number of Days: (The number of days the user plans to stay, None if not explicitly mentioned)\n\n"
25
+ f"Format the response as:\n"
26
+ f"Destination: [destination]\n"
27
+ f"Number of Days: [days]\n"
28
+ )
29
+ try:
30
+ client = openai.OpenAI()
31
+ response = client.chat.completions.create(
32
+ model="gpt-4",
33
+ messages=[
34
+ {"role": "system", "content": "You are an assistant that extracts structured details from sentences."},
35
+ {"role": "user", "content": prompt}
36
+ ],
37
+ max_tokens=150,
38
+ temperature=0.5
39
+ )
40
+ return response.choices[0].message.content.strip()
41
+ except Exception as e:
42
+ print(f"OpenAI API Error: {e}")
43
+ return None
44
+
45
+ # Function to parse GPT response
46
+ def parse_gpt_response(response):
47
+ """
48
+ Parse GPT response into a structured dictionary and handle missing values.
49
+ """
50
+ try:
51
+ result = {"destination": None, "num_days": None}
52
+
53
+ if not response:
54
+ return result
55
+
56
+ lines = response.split("\n")
57
+
58
+ for line in lines:
59
+ if ": " in line:
60
+ key, value = line.split(": ", 1)
61
+ key = key.lower().strip()
62
+ value = value.strip()
63
+
64
+ if key == "destination":
65
+ result["destination"] = value if value and value.lower() != "none" else None
66
+ elif key == "number of days":
67
+ result["num_days"] = int(value) if value.isdigit() else None
68
+
69
+ return result
70
+ except Exception as e:
71
+ print(f"Error parsing GPT response: {e}")
72
+ return {"destination": None, "num_days": None}
73
+
74
+ # Regex-based extraction
75
+ def extract_trip_details(sentence):
76
+ """
77
+ Extract destination and number of days using regex.
78
+ """
79
+ destination_pattern = r'(?:to|for)\s+(\w+(?:\s+\w+)*)'
80
+ days_pattern = r'(\d+)\s+(?:days|day)'
81
+
82
+ destination_match = re.search(destination_pattern, sentence, re.IGNORECASE)
83
+ destination = destination_match.group(1).strip() if destination_match else None
84
+
85
+ days_match = re.search(days_pattern, sentence, re.IGNORECASE)
86
+ num_days = int(days_match.group(1)) if days_match else None
87
+
88
+ # If "from" is present, it indicates origin, not destination
89
+ if "from" in sentence.lower():
90
+ destination = None
91
+
92
+ return {"destination": destination, "num_days": num_days}
93
+
94
+ # Main processing function
95
+ def extract_sentence(sentence, user):
96
+ """
97
+ Complete pipeline for extracting travel details with fallback to regex if GPT fails.
98
+ """
99
+ try:
100
+ if detect(sentence) != "en":
101
+ return {"destination": None, "num_days": None}
102
+ except Exception as e:
103
+ print(f"Error in language detection: {e}")
104
+ return {"destination": None, "num_days": None}
105
+
106
+ print("Using GPT to extract travel details...")
107
+ gpt_response = gpt_extract_trip_details(sentence)
108
+ if gpt_response:
109
+ mongo_util.get_collection("users").update_one({"_id": ObjectId(user["_id"])},{"$inc": {"ai_gpt": -1}})
110
+ gpt_details = parse_gpt_response(gpt_response)
111
+ if gpt_details["destination"] is None and "from" in sentence.lower():
112
+ gpt_details["destination"] = None
113
+ return gpt_details
114
+
115
+ print("GPT extraction failed or returned no details. Falling back to regex extraction...")
116
+ return extract_trip_details(sentence)
117
+
118
+ # Main entry point
119
+ if __name__ == "__main__":
120
+ sentence = input("Enter a trip-related sentence: ")
121
+ result = extract_sentence(sentence)
122
+ print("Extracted Travel Details:")
123
+ print(result)
ai/iata.py CHANGED
@@ -36,9 +36,9 @@ def get_country_code(access_key=None, query=None):
36
  print(f"Error: {e}")
37
  return {"error": str(e)}
38
 
39
- # if __name__ == "__main__":
40
- # country_name = input("Enter the country name or skyId to search for airports: ")
41
- # response = get_country_code(query=country_name)
42
- # print("Formatted Response:")
43
- # for airport in response:
44
- # print(f"skyId: {airport['skyId']}, entityId: {airport['entityId']}")
 
36
  print(f"Error: {e}")
37
  return {"error": str(e)}
38
 
39
+ if __name__ == "__main__":
40
+ country_name = input("Enter the country name or skyId to search for airports: ")
41
+ response = get_country_code(query=country_name)
42
+ print("Formatted Response:")
43
+ for airport in response:
44
+ print(f"skyId: {airport['skyId']}, entityId: {airport['entityId']}")
ai/prompt.py ADDED
@@ -0,0 +1,159 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+ from datetime import datetime
3
+ from langdetect import detect
4
+ import openai
5
+ import os
6
+ from dotenv import load_dotenv
7
+ from utils.db import MongoDBUtil
8
+ from bson import ObjectId
9
+
10
+ # Load environment variables
11
+ load_dotenv()
12
+ openai.api_key = os.getenv("OPENAI_API_KEY")
13
+ mongo_util = MongoDBUtil()
14
+
15
+ # Function to use GPT for extracting details
16
+ def gpt_extract_flight_details(sentence):
17
+ """
18
+ Use OpenAI GPT to extract origin, destination, date, and number of people.
19
+ """
20
+ prompt = (
21
+ f"Extract the following details from this sentence:\n"
22
+ f"Sentence: '{sentence}'\n\n"
23
+ f"Details to extract:\n"
24
+ f"1. Origin: (The place the user is traveling from. Set to None if not mentioned)\n"
25
+ f"2. Destination: (The place the user is traveling to. Set to None if not mentioned)\n"
26
+ f"3. Date: (The travel date in YYYY-MM-DD format. Set to None if not mentioned)\n"
27
+ f"4. Number of People: (Set to None if not explicitly mentioned)\n\n"
28
+ f"Format the response as:\n"
29
+ f"Origin: [origin]\n"
30
+ f"Destination: [destination]\n"
31
+ f"Date: [date]\n"
32
+ f"Number of People: [number]\n"
33
+ )
34
+ try:
35
+ client = openai.OpenAI()
36
+ response = client.chat.completions.create(
37
+ model="gpt-4",
38
+ messages=[
39
+ {"role": "system", "content": "You are an assistant that extracts structured details from sentences."},
40
+ {"role": "user", "content": prompt}
41
+ ],
42
+ max_tokens=150,
43
+ temperature=0.5
44
+ )
45
+ return response.choices[0].message.content.strip()
46
+ except Exception as e:
47
+ print(f"OpenAI API Error: {e}")
48
+ return None
49
+
50
+ # Function to parse GPT response
51
+ def parse_gpt_response(response):
52
+ """
53
+ Parse GPT response into a structured dictionary and return None for missing or invalid fields.
54
+ """
55
+ result = {"origin": None, "destination": None, "date": None, "num_people": None}
56
+
57
+ if not response:
58
+ return result
59
+
60
+ lines = response.split("\n")
61
+
62
+ for line in lines:
63
+ if ": " in line:
64
+ key, value = line.split(": ", 1)
65
+ key = key.lower().strip()
66
+ value = value.strip()
67
+
68
+ if key == "origin":
69
+ result["origin"] = value if value.lower() != "none" and value.lower() != "not mentioned" else None
70
+ elif key == "destination":
71
+ result["destination"] = value if value.lower() != "none" and value.lower() != "not mentioned" else None
72
+ elif key == "date":
73
+ result["date"] = parse_date(value) if value.lower() != "none" and value.lower() != "not mentioned" else None
74
+ elif key == "number of people":
75
+ result["num_people"] = int(value) if value.isdigit() else None
76
+
77
+ return result
78
+
79
+ # Function to parse and normalize dates
80
+ def parse_date(date_text):
81
+ """
82
+ Convert extracted date into YYYY-MM-DD format.
83
+ """
84
+ try:
85
+ date_formats = [
86
+ "%d %B %Y", "%B %d %Y", "%Y-%m-%d", "%d-%m-%Y", "%m-%d-%Y",
87
+ "%d/%m/%Y", "%m/%d/%Y", "%d %b %Y", "%b %d %Y"
88
+ ]
89
+ for fmt in date_formats:
90
+ try:
91
+ parsed_date = datetime.strptime(date_text, fmt)
92
+ return parsed_date.strftime("%Y-%m-%d")
93
+ except ValueError:
94
+ continue
95
+ return None
96
+ except Exception as e:
97
+ print(f"Error parsing date: {e}")
98
+ return None
99
+
100
+ # Function to check if a sentence is in English
101
+ def check_if_english(sentence):
102
+ """
103
+ Check if the sentence is in English using langdetect.
104
+ """
105
+ try:
106
+ language = detect(sentence)
107
+ return language == "en"
108
+ except Exception as e:
109
+ print(f"Error in language detection: {e}")
110
+ return False
111
+
112
+ # Regex-based extraction
113
+ def extract_flight_details(sentence):
114
+ """
115
+ Extract origin, destination, date, and number of people using regex.
116
+ """
117
+ origin_dest_pattern = r'from\s+(.*?)\s+to\s+(.*?)(?:\s+on|\s+with|\s+for|\.|$)'
118
+ date_pattern = r'\b(?:\d{1,2}[-/\s]?[A-Za-z]+[-/\s]?\d{2,4}|\d{4}-\d{2}-\d{2})\b'
119
+ people_pattern = r'(\d+)\s+(?:people|adults)'
120
+
121
+ match = re.search(origin_dest_pattern, sentence, re.IGNORECASE)
122
+ origin = match.group(1).strip() if match else None
123
+ destination = match.group(2).strip() if match else None
124
+
125
+ date_match = re.search(date_pattern, sentence)
126
+ date = parse_date(date_match.group(0).strip()) if date_match else None
127
+
128
+ people_match = re.search(people_pattern, sentence, re.IGNORECASE)
129
+ num_people = int(people_match.group(1)) if people_match else None
130
+
131
+ return {"origin": origin, "destination": destination, "date": date, "num_people": num_people}
132
+
133
+ # Main processing function
134
+ def process_sentence(sentence, user):
135
+ """
136
+ Complete pipeline for extracting flight details with fallback to regex if GPT fails.
137
+ """
138
+ if not check_if_english(sentence):
139
+ return {"error": "The sentence is not in English."}
140
+
141
+ gpt_response = gpt_extract_flight_details(sentence)
142
+ if gpt_response:
143
+ mongo_util.get_collection("users").update_one({"_id": ObjectId(user["_id"])},{"$inc": {"ai_gpt": -1}})
144
+ gpt_details = parse_gpt_response(gpt_response)
145
+ return gpt_details
146
+
147
+ regex_details = extract_flight_details(sentence)
148
+ return {
149
+ "origin": regex_details.get("origin", None),
150
+ "destination": regex_details.get("destination", None),
151
+ "date": regex_details.get("date", None),
152
+ "num_people": regex_details.get("num_people", None),
153
+ }
154
+
155
+ if __name__ == "__main__":
156
+ sentence = input("Enter a sentence: ")
157
+ result = process_sentence(sentence)
158
+ print("Extracted Flight Details:")
159
+ print(result)
ai/travel.py CHANGED
@@ -1,47 +1,3 @@
1
- # code1:
2
-
3
- # import requests
4
- # import os
5
- # import pandas as pd
6
-
7
- # from dotenv import load_dotenv
8
- # load_dotenv()
9
-
10
- # def get_travel_listing (origin_iata, destination_iata, depart_date, return_date ):
11
- # try:
12
- # api_token = os.environ["TRAVEL_PAYOUT_API_TOKEN"]
13
- # api_url = f"https://api.travelpayouts.com/v1/prices/cheap?origin={origin_iata}&destination={destination_iata}&depart_date={depart_date}&return_date={return_date or ''}&token={api_token}&currency=usd"
14
- # # FOR CALENDAR
15
- # # api_url = f"https://api.travelpayouts.com/v1/prices/calendar?origin={origin_iata}&destination={destination_iata}&depart_date={depart_date}&return_date={return_date or ''}&token={api_token}&currency=usd"
16
- # print(api_url)
17
- # response = requests.get(api_url)
18
- # data = response.json()
19
- # print(data)
20
-
21
- # airlines_data = []
22
- # airlines = pd.read_json('data/airlines.json')
23
-
24
- # for k in data['data'].keys():
25
- # # find PK in airlines[]{code = PK}
26
- # # FOR CALENDER
27
- # # data['data'][k]['airline_name'] = airlines[airlines['code'] == data['data'][k]['airline']]['name'].values[0]
28
-
29
- # # FOR CHEAP FLIGHTS
30
- # airline = {}
31
- # airline_complete = airlines[airlines['code'] == data['data'][k][list(data['data'][k].keys())[0]]['airline']]['name'].values[0]
32
-
33
- # airline = data['data'][k][list(data['data'][k].keys())[0]]
34
- # airline['airline_name'] = airline_complete
35
-
36
- # airlines_data.append(airline)
37
-
38
- # return airlines_data
39
-
40
- # except Exception as e:
41
- # print(e)
42
- # print("ERR")
43
- # return False
44
-
45
  import requests
46
  import os
47
  from dotenv import load_dotenv
@@ -51,79 +7,101 @@ load_dotenv()
51
 
52
  def get_travel_listing(originSkyId, destinationSkyId, originEntityId, destinationEntityId, date, adults, access_key=None):
53
  try:
54
- access_key = access_key or os.environ["FLIGHTLABS_API_TOKEN"]
 
55
  if not access_key:
56
  raise ValueError("Access key is required.")
 
57
  if not originSkyId or not destinationSkyId or not originEntityId or not destinationEntityId:
58
  raise ValueError("All IDs (Sky and Entity) are required.")
59
 
60
  # Construct API URL
61
  api_url = f"https://app.goflightlabs.com/retrieveFlights?access_key={access_key}&originSkyId={originSkyId}&destinationSkyId={destinationSkyId}&originEntityId={originEntityId}&destinationEntityId={destinationEntityId}&date={date}&adults={adults}"
62
-
63
- print(f"Requesting API URL: {api_url}")
64
  response = requests.get(api_url)
65
-
66
  response.raise_for_status()
 
 
67
  data = response.json()
68
-
69
  if 'error' in data:
70
  raise ValueError(f"API Error: {data['error']}")
71
 
 
72
  extracted_data = []
73
- seen_flights = set() # To prevent duplicate outputs
74
 
75
  for itinerary in data.get("itineraries", []):
76
  for leg in itinerary.get("legs", []):
77
- # Unique flight key to ensure no duplicates
78
- unique_key = (leg["origin"]["displayCode"], leg["destination"]["displayCode"], leg["departure"])
 
 
 
 
 
 
 
 
 
79
  if unique_key in seen_flights:
80
  continue
81
  seen_flights.add(unique_key)
82
 
83
- # Convert duration from minutes to hours and minutes
84
- duration_in_minutes = leg['durationInMinutes']
85
  hours = duration_in_minutes // 60
86
  minutes = duration_in_minutes % 60
87
- duration_formatted = f"{hours} hours and {minutes} minutes"
 
 
 
 
88
 
89
  # Build stops information
90
- stop_locations = [leg["origin"]["displayCode"]]
91
  stop_details = []
92
  segments = leg.get("segments", [])
93
  for i, segment in enumerate(segments[:-1]):
94
- stop_code = segment["destination"]["displayCode"]
95
- stop_arrival = datetime.datetime.fromisoformat(segment["arrival"])
96
- next_departure = datetime.datetime.fromisoformat(segments[i + 1]["departure"])
97
- stop_duration_minutes = int((next_departure - stop_arrival).total_seconds() / 60)
98
- stop_hours = stop_duration_minutes // 60
99
- stop_minutes = stop_duration_minutes % 60
100
- stop_time_formatted = (
101
- f"{stop_hours} hour{'s' if stop_hours > 1 else ''}" if stop_minutes == 0 else
102
- f"{stop_hours} hour{'s' if stop_hours > 1 else ''} and {stop_minutes} minutes" if stop_hours > 0 else
103
- f"{stop_minutes} minutes"
104
- )
105
- stop_details.append(f"{stop_code} ({stop_time_formatted})")
106
- stop_locations.append(stop_code) # Add to the route
107
-
108
- stop_locations.append(leg["destination"]["displayCode"]) # Add the final destination
 
 
 
 
109
  stops_route = " --> ".join(stop_locations)
110
 
 
 
 
 
111
  extracted_data.append({
112
- "origin": leg["origin"]["name"],
113
- "destination": leg["destination"]["name"],
114
- "airline_code": leg["carriers"]["marketing"][0]["alternateId"] if leg["carriers"]["marketing"] else "N/A",
115
- "airline_name": leg["carriers"]["marketing"][0]["name"] if leg["carriers"]["marketing"] else "N/A",
116
  "duration": duration_formatted,
117
- "price": itinerary["price"]["formatted"],
118
- "departure": leg["departure"],
119
- "arrival": leg["arrival"],
120
- "flight_number": ", ".join(segment["flightNumber"] for segment in segments),
121
  "stop_count": leg.get("stopCount", 0),
122
  "stops_route": stops_route,
123
  "stops_details": stop_details
124
  })
125
 
126
- # Print and return the extracted data
127
  for flight in extracted_data:
128
  print("\nFlight Details:")
129
  print(f"Origin: {flight['origin']}")
@@ -141,56 +119,100 @@ def get_travel_listing(originSkyId, destinationSkyId, originEntityId, destinatio
141
  print(f"Stop Details: {', '.join(flight['stops_details'])}")
142
  else:
143
  print("Stop Details: No stops on the trip")
144
-
145
  return extracted_data
146
 
147
  except Exception as e:
148
  print(f"Error occurred: {e}")
149
  return False
150
 
151
- # if __name__ == "__main__":
152
- # try:
153
- # # Gather user inputs
154
- # originSkyId = input("Enter the origin SkyId: ").strip()
155
- # if not originSkyId:
156
- # raise ValueError("Origin SkyId is required.")
157
 
158
- # destinationSkyId = input("Enter the destination SkyId: ").strip()
159
- # if not destinationSkyId:
160
- # raise ValueError("Destination SkyId is required.")
161
 
162
- # originEntityId = input("Enter the origin EntityId: ").strip()
163
- # if not originEntityId:
164
- # raise ValueError("Origin EntityId is required.")
165
 
166
- # destinationEntityId = input("Enter the destination EntityId: ").strip()
167
- # if not destinationEntityId:
168
- # raise ValueError("Destination EntityId is required.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
169
 
170
- # date_input = input("Enter the travel date (YYYY-MM-DD): ").strip()
171
- # if not date_input:
172
- # raise ValueError("Travel date is required.")
173
 
174
- # adults = input("Enter the number of adults (optional): ").strip()
175
-
176
- # # Validate the date input
177
- # try:
178
- # date = datetime.datetime.strptime(date_input, "%Y-%m-%d").date()
179
- # except ValueError:
180
- # raise ValueError("Invalid date format. Please use YYYY-MM-DD.")
181
-
182
- # # Call the get_travel_listing function
183
- # print("\nFetching travel listings...")
184
- # travel_listings = get_travel_listing(
185
- # originSkyId=originSkyId,
186
- # destinationSkyId=destinationSkyId,
187
- # originEntityId=originEntityId,
188
- # destinationEntityId=destinationEntityId,
189
- # date=str(date),
190
- # adults=adults or 1
191
- # )
192
-
193
- # if not travel_listings:
194
- # print("No travel listings found or an error occurred.")
195
- # except Exception as e:
196
- # print(f"Error occurred: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import requests
2
  import os
3
  from dotenv import load_dotenv
 
7
 
8
  def get_travel_listing(originSkyId, destinationSkyId, originEntityId, destinationEntityId, date, adults, access_key=None):
9
  try:
10
+ # Use API token from environment or passed as an argument
11
+ access_key = access_key or os.environ.get("FLIGHTLABS_API_TOKEN")
12
  if not access_key:
13
  raise ValueError("Access key is required.")
14
+
15
  if not originSkyId or not destinationSkyId or not originEntityId or not destinationEntityId:
16
  raise ValueError("All IDs (Sky and Entity) are required.")
17
 
18
  # Construct API URL
19
  api_url = f"https://app.goflightlabs.com/retrieveFlights?access_key={access_key}&originSkyId={originSkyId}&destinationSkyId={destinationSkyId}&originEntityId={originEntityId}&destinationEntityId={destinationEntityId}&date={date}&adults={adults}"
 
 
20
  response = requests.get(api_url)
 
21
  response.raise_for_status()
22
+
23
+ # Parse response JSON
24
  data = response.json()
25
+
26
  if 'error' in data:
27
  raise ValueError(f"API Error: {data['error']}")
28
 
29
+ # Process the response data
30
  extracted_data = []
31
+ seen_flights = set()
32
 
33
  for itinerary in data.get("itineraries", []):
34
  for leg in itinerary.get("legs", []):
35
+ # Safely access nested keys
36
+ origin = leg.get("origin", {}).get("name", "N/A")
37
+ destination = leg.get("destination", {}).get("name", "N/A")
38
+ duration_in_minutes = leg.get("durationInMinutes", 0)
39
+ carriers = leg.get("carriers", {}).get("marketing", [{}])
40
+
41
+ unique_key = (
42
+ leg.get("origin", {}).get("displayCode", "N/A"),
43
+ leg.get("destination", {}).get("displayCode", "N/A"),
44
+ leg.get("departure", "N/A")
45
+ )
46
  if unique_key in seen_flights:
47
  continue
48
  seen_flights.add(unique_key)
49
 
50
+ # Format duration safely
 
51
  hours = duration_in_minutes // 60
52
  minutes = duration_in_minutes % 60
53
+ duration_formatted = f"{hours} hours and {minutes} minutes" if duration_in_minutes else "N/A"
54
+
55
+ # Safely get airline details
56
+ airline_code = carriers[0].get("alternateId", "N/A")
57
+ airline_name = carriers[0].get("name", "N/A")
58
 
59
  # Build stops information
60
+ stop_locations = [leg.get("origin", {}).get("displayCode", "N/A")]
61
  stop_details = []
62
  segments = leg.get("segments", [])
63
  for i, segment in enumerate(segments[:-1]):
64
+ stop_code = segment.get("destination", {}).get("displayCode", "N/A")
65
+ stop_arrival = segment.get("arrival", None)
66
+ next_departure = segments[i + 1].get("departure", None)
67
+ if stop_arrival and next_departure:
68
+ stop_duration_minutes = int(
69
+ (datetime.datetime.fromisoformat(next_departure) -
70
+ datetime.datetime.fromisoformat(stop_arrival)).total_seconds() / 60
71
+ )
72
+ stop_hours = stop_duration_minutes // 60
73
+ stop_minutes = stop_duration_minutes % 60
74
+ stop_time_formatted = (
75
+ f"{stop_hours} hours" if stop_minutes == 0 else
76
+ f"{stop_hours} hours and {stop_minutes} minutes" if stop_hours > 0 else
77
+ f"{stop_minutes} minutes"
78
+ )
79
+ stop_details.append(f"{stop_code} ({stop_time_formatted})")
80
+ stop_locations.append(stop_code)
81
+
82
+ stop_locations.append(leg.get("destination", {}).get("displayCode", "N/A"))
83
  stops_route = " --> ".join(stop_locations)
84
 
85
+ # Safely extract flight price
86
+ price = itinerary.get("price", {}).get("formatted", "N/A")
87
+
88
+ # Add extracted data to the list
89
  extracted_data.append({
90
+ "origin": origin,
91
+ "destination": destination,
92
+ "airline_code": airline_code,
93
+ "airline_name": airline_name,
94
  "duration": duration_formatted,
95
+ "price": price,
96
+ "departure": leg.get("departure", "N/A"),
97
+ "arrival": leg.get("arrival", "N/A"),
98
+ "flight_number": ", ".join(segment.get("flightNumber", "N/A") for segment in segments),
99
  "stop_count": leg.get("stopCount", 0),
100
  "stops_route": stops_route,
101
  "stops_details": stop_details
102
  })
103
 
104
+ # Display the extracted flight data in a structured format
105
  for flight in extracted_data:
106
  print("\nFlight Details:")
107
  print(f"Origin: {flight['origin']}")
 
119
  print(f"Stop Details: {', '.join(flight['stops_details'])}")
120
  else:
121
  print("Stop Details: No stops on the trip")
122
+
123
  return extracted_data
124
 
125
  except Exception as e:
126
  print(f"Error occurred: {e}")
127
  return False
128
 
129
+ if __name__ == "__main__":
130
+ try:
131
+ # Gather user inputs
132
+ originSkyId = input("Enter the origin SkyId: ").strip()
133
+ if not originSkyId:
134
+ raise ValueError("Origin SkyId is required.")
135
 
136
+ destinationSkyId = input("Enter the destination SkyId: ").strip()
137
+ if not destinationSkyId:
138
+ raise ValueError("Destination SkyId is required.")
139
 
140
+ originEntityId = input("Enter the origin EntityId: ").strip()
141
+ if not originEntityId:
142
+ raise ValueError("Origin EntityId is required.")
143
 
144
+ destinationEntityId = input("Enter the destination EntityId: ").strip()
145
+ if not destinationEntityId:
146
+ raise ValueError("Destination EntityId is required.")
147
+
148
+ date_input = input("Enter the travel date (YYYY-MM-DD): ").strip()
149
+ if not date_input:
150
+ raise ValueError("Travel date is required.")
151
+
152
+ adults = input("Enter the number of adults (optional): ").strip()
153
+
154
+ # Validate the date input
155
+ try:
156
+ date = datetime.datetime.strptime(date_input, "%Y-%m-%d").date()
157
+ except ValueError:
158
+ raise ValueError("Invalid date format. Please use YYYY-MM-DD.")
159
+
160
+ # Call the get_travel_listing function
161
+ print("\nFetching travel listings...")
162
+ travel_listings = get_travel_listing(
163
+ originSkyId=originSkyId,
164
+ destinationSkyId=destinationSkyId,
165
+ originEntityId=originEntityId,
166
+ destinationEntityId=destinationEntityId,
167
+ date=str(date),
168
+ adults=adults or 1
169
+ )
170
+
171
+ if not travel_listings:
172
+ print("No travel listings found or an error occurred.")
173
+ except Exception as e:
174
+ print(f"Error occurred: {e}")
175
+
176
+ # code1:
177
+
178
+ # import requests
179
+ # import os
180
+ # import pandas as pd
181
+
182
+ # from dotenv import load_dotenv
183
+ # load_dotenv()
184
+
185
+ # def get_travel_listing (origin_iata, destination_iata, depart_date, return_date ):
186
+ # try:
187
+ # api_token = os.environ["TRAVEL_PAYOUT_API_TOKEN"]
188
+ # api_url = f"https://api.travelpayouts.com/v1/prices/cheap?origin={origin_iata}&destination={destination_iata}&depart_date={depart_date}&return_date={return_date or ''}&token={api_token}&currency=usd"
189
+ # # FOR CALENDAR
190
+ # # api_url = f"https://api.travelpayouts.com/v1/prices/calendar?origin={origin_iata}&destination={destination_iata}&depart_date={depart_date}&return_date={return_date or ''}&token={api_token}&currency=usd"
191
+ # print(api_url)
192
+ # response = requests.get(api_url)
193
+ # data = response.json()
194
+ # print(data)
195
 
196
+ # airlines_data = []
197
+ # airlines = pd.read_json('data/airlines.json')
 
198
 
199
+ # for k in data['data'].keys():
200
+ # # find PK in airlines[]{code = PK}
201
+ # # FOR CALENDER
202
+ # # data['data'][k]['airline_name'] = airlines[airlines['code'] == data['data'][k]['airline']]['name'].values[0]
203
+
204
+ # # FOR CHEAP FLIGHTS
205
+ # airline = {}
206
+ # airline_complete = airlines[airlines['code'] == data['data'][k][list(data['data'][k].keys())[0]]['airline']]['name'].values[0]
207
+
208
+ # airline = data['data'][k][list(data['data'][k].keys())[0]]
209
+ # airline['airline_name'] = airline_complete
210
+
211
+ # airlines_data.append(airline)
212
+
213
+ # return airlines_data
214
+
215
+ # except Exception as e:
216
+ # print(e)
217
+ # print("ERR")
218
+ # return False
 
 
 
ai/trip.py CHANGED
@@ -19,149 +19,61 @@ def get_trip_planner(days, destination):
19
 
20
  # Construct API URL
21
  api_url = f"https://zylalabs.com/api/2242/trip+planner+api/2103/get+planning?days={days}&destination={destination}"
22
- print(f"Requesting API URL: {api_url}")
23
-
24
  # Make the API request
25
  response = requests.get(api_url, headers={"Authorization": f"Bearer {api_token}"})
26
  response.raise_for_status()
27
-
28
  # Parse the response
29
  data = response.json()
 
30
  if 'error' in data:
31
  raise ValueError(f"API Error: {data['error']}")
32
 
33
- # Extract trip plans
34
- trip_plans = data.get("plans", [])
35
- if not trip_plans:
36
- print("No trip plans found.")
37
  return []
38
 
39
- # Format the trip plans
40
- extracted_data = [
41
- {
42
- "day": plan.get("day", "Unknown Day"),
43
- "activities": [activity.get("description", "No Description") for activity in plan.get("activities", [])]
44
- }
45
- for plan in trip_plans
46
- ]
47
-
48
- # Print the trip plans
49
- for plan in extracted_data:
50
- print(f"\nDay: {plan['day']}")
51
- print("Activities:")
52
- for activity in plan["activities"]:
53
- print(f" - {activity}")
54
-
55
- return extracted_data
 
 
 
 
 
 
56
 
57
  except Exception as e:
58
  print(f"Error occurred: {e}")
59
- return False
60
 
61
  if __name__ == "__main__":
62
  try:
63
  # Gather user inputs
64
  days = int(input("Enter the number of days for the trip: ").strip())
65
  destination = input("Enter the destination: ").strip()
66
- if not days or not destination:
67
- raise ValueError("Both days and destination are required.")
68
 
69
  # Fetch trip plans
70
  print("\nFetching trip plans...")
71
- trip_plans = get_trip_planner(days, destination)
72
 
73
- if not trip_plans:
74
  print("No trip plans found or an error occurred.")
75
  except Exception as e:
76
  print(f"Error occurred: {e}")
77
-
78
-
79
-
80
- # import requests
81
- # import os
82
- # from dotenv import load_dotenv
83
-
84
- # load_dotenv()
85
-
86
- # def get_trip_planner(days, destination):
87
- # try:
88
- # # Fetch the API token from environment variables
89
- # api_token = os.environ.get("ZYLA_API_TOKEN")
90
- # if not api_token:
91
- # raise ValueError("API token is required. Set ZYLA_API_TOKEN in environment variables.")
92
-
93
- # # Validate inputs
94
- # if not isinstance(days, int) or days <= 0:
95
- # raise ValueError("Days must be a positive integer.")
96
- # if not destination.strip():
97
- # raise ValueError("Destination cannot be empty.")
98
-
99
- # # Construct API URL
100
- # api_url = f"https://zylalabs.com/api/2242/trip+planner+api/2103/get+planning?days={days}&destination={destination}"
101
- # print(f"Requesting API URL: {api_url}")
102
-
103
- # # Make the API request
104
- # response = requests.get(api_url, headers={"Authorization": f"Bearer {api_token}"})
105
- # response.raise_for_status()
106
-
107
- # # Parse the response
108
- # data = response.json()
109
- # if 'error' in data:
110
- # raise ValueError(f"API Error: {data['error']}")
111
-
112
- # # Extract trip plans
113
- # trip_plans = data.get("plans", [])
114
- # if not trip_plans:
115
- # print("No trip plans found.")
116
- # return {}
117
-
118
- # # Format the trip plans
119
- # formatted_plans = {
120
- # "plan": [
121
- # {
122
- # "day": plan.get("day", "Unknown Day"),
123
- # "activities": [
124
- # {
125
- # "time": activity.get("time", "Unknown Time"),
126
- # "description": activity.get("description", "No Description")
127
- # }
128
- # for activity in plan.get("activities", [])
129
- # ]
130
- # }
131
- # for plan in trip_plans
132
- # ],
133
- # "key": f"{days}-{destination.lower().replace(' ', '')}",
134
- # "_id": data.get("_id", "Unknown ID")
135
- # }
136
-
137
- # # Print the formatted plans
138
- # for day_plan in formatted_plans["plan"]:
139
- # print(f"\nDay {day_plan['day']}:")
140
- # for activity in day_plan["activities"]:
141
- # print(f"{activity['time']} - {activity['description']}")
142
-
143
- # return formatted_plans
144
-
145
- # except Exception as e:
146
- # print(f"Error occurred: {e}")
147
- # return {}
148
-
149
- # if __name__ == "__main__":
150
- # try:
151
- # # Gather user inputs
152
- # days = int(input("Enter the number of days for the trip: ").strip())
153
- # destination = input("Enter the destination: ").strip()
154
- # if not days or not destination:
155
- # raise ValueError("Both days and destination are required.")
156
-
157
- # # Fetch trip plans
158
- # print("\nFetching trip plans...")
159
- # trip_plans = get_trip_planner(days, destination)
160
-
161
- # if not trip_plans:
162
- # print("No trip plans found or an error occurred.")
163
- # else:
164
- # print("\nFinal Trip Plans:")
165
- # print(trip_plans)
166
- # except Exception as e:
167
- # print(f"Error occurred: {e}")
 
19
 
20
  # Construct API URL
21
  api_url = f"https://zylalabs.com/api/2242/trip+planner+api/2103/get+planning?days={days}&destination={destination}"
22
+
 
23
  # Make the API request
24
  response = requests.get(api_url, headers={"Authorization": f"Bearer {api_token}"})
25
  response.raise_for_status()
26
+
27
  # Parse the response
28
  data = response.json()
29
+
30
  if 'error' in data:
31
  raise ValueError(f"API Error: {data['error']}")
32
 
33
+ trip_plan = data.get("plan", [])
34
+ if not trip_plan:
35
+ print("No trip plan found.")
 
36
  return []
37
 
38
+ formatted_plan = {
39
+ "_id": data.get("_id", "Unknown ID"),
40
+ "plan": [
41
+ {
42
+ "day": day_plan.get("day"),
43
+ "activities": [
44
+ {
45
+ "time": activity.get("time"),
46
+ "description": activity.get("description")
47
+ }
48
+ for activity in day_plan.get("activities", [])
49
+ ]
50
+ }
51
+ for day_plan in trip_plan
52
+ ],
53
+ "key": data.get("key", "Unknown Key")
54
+ }
55
+
56
+ # Print the formatted output
57
+ print("\nFormatted Trip Plan:")
58
+ print(formatted_plan)
59
+
60
+ return formatted_plan
61
 
62
  except Exception as e:
63
  print(f"Error occurred: {e}")
64
+ return None
65
 
66
  if __name__ == "__main__":
67
  try:
68
  # Gather user inputs
69
  days = int(input("Enter the number of days for the trip: ").strip())
70
  destination = input("Enter the destination: ").strip()
 
 
71
 
72
  # Fetch trip plans
73
  print("\nFetching trip plans...")
74
+ trip_plan = get_trip_planner(days, destination)
75
 
76
+ if not trip_plan:
77
  print("No trip plans found or an error occurred.")
78
  except Exception as e:
79
  print(f"Error occurred: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ai/tti.py CHANGED
@@ -35,24 +35,24 @@ def texttoimage(prompt):
35
  s3_path = f'images/{now}.png'
36
  path = f'tmp/{now}.png'
37
 
38
- # Assuming you want to save the response (audio content) to a file
39
- with open(path, 'wb') as file:
40
- file.write(requests.get(image_url).content)
41
-
42
- s3.Bucket(os.environ["S3_BUCKET_NAME"]).upload_file(path, s3_path)
43
- url = s3.meta.client.generate_presigned_url(
44
- ClientMethod='get_object',
45
- Params={
46
- 'Bucket': os.environ["S3_BUCKET_NAME"],
47
- 'Key': s3_path
48
- }
49
- )
50
- os.remove(path)
51
 
52
 
53
- print(url)
54
 
55
- return url
56
 
57
  except Exception as e:
58
  print('error occurred!', str(e))
 
35
  s3_path = f'images/{now}.png'
36
  path = f'tmp/{now}.png'
37
 
38
+ # # Assuming you want to save the response (audio content) to a file
39
+ # with open(path, 'wb') as file:
40
+ # file.write(requests.get(image_url).content)
41
+
42
+ # s3.Bucket(os.environ["S3_BUCKET_NAME"]).upload_file(path, s3_path)
43
+ # url = s3.meta.client.generate_presigned_url(
44
+ # ClientMethod='get_object',
45
+ # Params={
46
+ # 'Bucket': os.environ["S3_BUCKET_NAME"],
47
+ # 'Key': s3_path
48
+ # }
49
+ # )
50
+ # os.remove(path)
51
 
52
 
53
+ print(image_url)
54
 
55
+ return image_url
56
 
57
  except Exception as e:
58
  print('error occurred!', str(e))
main.py CHANGED
@@ -7,22 +7,30 @@ from mutagen.wave import WAVE
7
  import json
8
  import random
9
  from fastapi import Request, HTTPException
 
 
 
10
 
11
  from models.messages import Messages
12
  from models.translation import Translation
13
  from models.tts import TTS
14
  from models.commands import Command
15
-
16
-
17
- from ai.autosuggest import auto_suggest_ask_llama2, auto_suggest_normalize_llama2,auto_suggest_ask_gpt
18
- from ai.translator import auto_translate
19
- from ai.audiotranscribe import audio_transcribe
20
  from ai.tts import texttospeech, texttospeech2
 
21
  from ai.travel import get_travel_listing
22
  from ai.iata import get_country_code
23
  from ai.tti import texttoimage
24
  from ai.trip import get_trip_planner
25
  from ai.job import get_job_listings
 
 
 
 
 
 
 
 
 
26
 
27
  from utils.helpers import parse_json_garbage, parse_number, word_to_number
28
  from datetime import datetime
@@ -37,7 +45,7 @@ from utils.authenticator import check_session
37
  # Fetch a collection
38
  mongo_util = MongoDBUtil()
39
 
40
-
41
  app = FastAPI()
42
 
43
  # Add the authentication middleware
@@ -48,27 +56,50 @@ app.add_middleware(AuditLogMiddleware)
48
  questions = {
49
  "travel": {
50
  "origin": [
51
- "Can you tell me where are you traveling from?",
52
- "Thank you for using Next Chat. Where are you traveling from?",
53
- "Certainly, can you tell me where are you traveling from?",
54
- "Great! What is your origin?"
 
 
 
 
55
  ],
56
  "destination": [
57
- "Got it, can you tell me where are you traveling to?",
58
- "Great, and what is your destination?"
 
 
 
 
 
 
59
  ],
60
- "start_date": [
61
- "OK, when are you traveling?"
 
 
 
 
 
 
 
62
  ],
63
  "people": [
64
  "Awesome, how many people will be traveling including yourself?",
65
- "Noted, and how many people are you going with including yourself?"
 
 
 
 
 
 
66
  ]
67
- },
68
  "trip": {
69
  "destination": [
70
  "Where would you like to go?",
71
- "Great! Can you tell me your destination?",
72
  "Where are you planning to travel to?",
73
  "What is the name of the place you want to visit?"
74
  ],
@@ -78,7 +109,7 @@ questions = {
78
  "Please let me know the number of days for your trip.",
79
  "How many days are you planning for your journey?"
80
  ]
81
- },
82
  "job": {
83
  "job_title": [
84
  "What job title are you looking for?",
@@ -92,7 +123,7 @@ questions = {
92
  "Can you specify the location for the job search?",
93
  "Which city or area do you prefer for this job?"
94
  ]
95
- }
96
  }
97
 
98
  @app.get("/")
@@ -209,183 +240,293 @@ async def audiotranscribe(
209
  # return {"success": True, "url": url, "text": text, "translated_text": translated_text}
210
 
211
  @app.post("/api/commands/query")
212
- async def query(body: Command, request: Request):
213
- user = request.state.user
214
- print(user)
215
-
216
  try:
217
- if body.command == "/travel":
218
- body.data = body.data or {}
219
- print(f"Initial body.data: {body.data}")
220
-
221
- if body.follow_question == "":
222
-
223
- # decrement a token from "ai_whisper" attribute of user document
224
- mongo_util.get_collection("users").update_one({"_id": ObjectId(user["_id"])},{"$inc": {"ai_gpt": -1}})
225
-
226
- return {
227
- "success": True,
228
- "follow_question": "origin",
229
- "data": body.data,
230
- "question": random.choice(questions["travel"]["origin"]),
231
- }
232
-
233
- elif body.follow_question == "origin":
234
- origin_response = get_country_code(query=body.query)
235
- print("Origin Response:", origin_response)
236
 
237
- if not origin_response or not isinstance(origin_response, list) or len(origin_response) == 0:
238
- return {"success": False, "message": "Unable to retrieve origin information."}
 
 
 
 
239
 
240
- body.data["origin_skyid"] = origin_response[0]["skyId"]
241
- body.data["origin_entityid"] = origin_response[0]["entityId"]
242
- print(f"Updated body.data after origin: {body.data}")
243
-
244
- # decrement a token from "ai_gpt" attribute of user document
245
- mongo_util.get_collection("users").update_one({"_id": ObjectId(user["_id"])},{"$inc": {"ai_gpt": -1}})
246
 
247
- return {
248
- "success": True,
249
- "follow_question": "destination",
250
- "data": body.data,
251
- "question": random.choice(questions["travel"]["destination"]),
252
- }
253
 
254
- elif body.follow_question == "destination":
255
- destination_response = get_country_code(query=body.query)
256
- print("Destination Response:", destination_response)
257
 
258
- if not destination_response or not isinstance(destination_response, list) or len(destination_response) == 0:
259
- return {"success": False, "message": "Unable to retrieve destination information."}
 
260
 
261
- body.data["destination_skyid"] = destination_response[0]["skyId"]
262
- body.data["destination_entityid"] = destination_response[0]["entityId"]
263
- print(f"Updated body.data after destination: {body.data}")
 
 
 
 
264
 
265
- # decrement a token from "ai_gpt" attribute of user document
266
- mongo_util.get_collection("users").update_one({"_id": ObjectId(user["_id"])},{"$inc": {"ai_gpt": -1}})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
267
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
268
  return {
269
  "success": True,
270
- "follow_question": "start_date",
271
  "data": body.data,
272
- "question": random.choice(questions["travel"]["start_date"]),
273
  }
274
 
275
- elif body.follow_question == "start_date":
276
- body.data["date"] = body.query
277
- print(f"Updated body.data after start_date: {body.data}")
 
 
 
 
 
 
 
278
 
279
- # decrement a token from "ai_gpt" attribute of user document
280
- mongo_util.get_collection("users").update_one({"_id": ObjectId(user["_id"])},{"$inc": {"ai_gpt": -1}})
 
 
 
 
 
281
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
282
  return {
283
  "success": True,
284
- "follow_question": "people",
285
  "data": body.data,
286
- "question": random.choice(questions["travel"]["people"]),
287
  }
288
 
289
- elif body.follow_question == "people":
290
- try:
291
- if not body.query:
292
- body.data["adults"] = 1
293
- else:
294
- body.data["adults"] = int(body.query)
295
- if body.data["adults"] <= 0:
296
- return {"success": False, "message": "Please provide a valid number of adults greater than 0."}
297
- if body.data["adults"] > 8:
298
- return {"success": False, "message": "Please provide a count of people less than or equal to 8."}
299
- except ValueError:
300
- return {"success": False, "message": "Please provide a valid number of adults."}
301
-
302
- print(f"Updated body.data after people: {body.data}")
303
-
304
- missing_keys = [
305
- key for key in ["origin_skyid", "destination_skyid", "origin_entityid", "destination_entityid", "date"]
306
- if not body.data.get(key)
307
- ]
308
- if missing_keys:
309
- return {"success": False, "message": f"Missing required data: {', '.join(missing_keys)}"}
310
-
311
- travel_listings = get_travel_listing(
312
- originSkyId=body.data["origin_skyid"],
313
- destinationSkyId=body.data["destination_skyid"],
314
- originEntityId=body.data["origin_entityid"],
315
- destinationEntityId=body.data["destination_entityid"],
316
- date=body.data["date"],
317
- adults=body.data["adults"],
318
- )
319
-
320
- if not travel_listings or "error" in travel_listings:
321
- return {"success": False, "message": "Unable to fetch travel listings."}
322
-
323
- # decrement a token from "ai_gpt" attribute of user document
324
- mongo_util.get_collection("users").update_one({"_id": ObjectId(user["_id"])},{"$inc": {"ai_gpt": -1}})
325
-
326
- return {"success": True, "suggestions": travel_listings}
327
-
328
  elif body.command == "/image":
329
- user = request.state.user
330
  prompt = body.query.strip()
331
- # url = texttoimage(prompt)
332
- # if not url:
333
- # return {"success": False, "message": "Unable to generate an image. Please try again."}
334
-
335
- # decrement a token from "ai_image" attribute of user document
336
  mongo_util.get_collection("users").update_one({"_id": ObjectId(user["_id"])},{"$inc": {"ai_image": -1}})
337
- # return {"success": True, "url": url}
338
- return {"success": True}
339
 
340
  elif body.command == "/trip":
341
  body.data = body.data or {}
342
- print(f"Initial body.data: {body.data}")
 
 
343
 
 
 
 
 
344
  if body.follow_question == "":
345
- return {
346
- "success": True,
347
- "follow_question": "destination",
348
- "data": body.data,
349
- "question": random.choice(questions["trip"]["destination"]),
350
- }
351
 
352
- elif body.follow_question == "destination":
353
- body.data["destination"] = body.query.strip()
354
- if not body.data["destination"]:
355
- return {"success": False, "message": "Please provide a valid destination."}
356
 
357
- print(f"Updated body.data after destination: {body.data}")
358
 
359
- return {
360
- "success": True,
361
- "follow_question": "days",
362
- "data": body.data,
363
- "question": random.choice(questions["trip"]["days"]),
364
- }
365
 
366
- elif body.follow_question == "days":
367
- try:
368
- days = int(body.query.strip())
369
- if days <= 0:
370
- return {"success": False, "message": "Please provide a positive number of days for the trip."}
371
 
372
- body.data["days"] = days
373
- except ValueError:
374
- return {"success": False, "message": "Please provide a valid number of days."}
375
 
376
- print(f"Updated body.data after days: {body.data}")
377
- trip_plans = get_trip_planner(days=body.data["days"], destination=body.data["destination"])
 
 
 
 
 
 
 
 
378
 
379
- if not trip_plans:
380
- return {"success": False, "message": "Unable to fetch trip plans. Please try again later."}
 
 
 
 
 
 
381
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
382
  return {
383
  "success": True,
384
- "trip_plans": trip_plans,
385
- "message": "Here are your trip plans!"
 
386
  }
387
 
388
- if body.command == "/job":
389
  body.data = body.data or {}
390
  print(f"Initial body.data: {body.data}")
391
 
@@ -437,7 +578,6 @@ async def query(body: Command, request: Request):
437
  return {"success": False, "error": str(e)}
438
 
439
 
440
-
441
  # @app.post("/api/commands/query")
442
  # async def query(body: Command):
443
 
 
7
  import json
8
  import random
9
  from fastapi import Request, HTTPException
10
+ from dotenv import load_dotenv
11
+ import re
12
+
13
 
14
  from models.messages import Messages
15
  from models.translation import Translation
16
  from models.tts import TTS
17
  from models.commands import Command
 
 
 
 
 
18
  from ai.tts import texttospeech, texttospeech2
19
+
20
  from ai.travel import get_travel_listing
21
  from ai.iata import get_country_code
22
  from ai.tti import texttoimage
23
  from ai.trip import get_trip_planner
24
  from ai.job import get_job_listings
25
+ from ai.prompt import process_sentence
26
+ from ai.prompt import parse_date
27
+ from ai.extract import extract_sentence
28
+
29
+
30
+ from ai.autosuggest import auto_suggest_ask_llama2, auto_suggest_normalize_llama2,auto_suggest_ask_gpt
31
+ from ai.translator import auto_translate
32
+ from ai.audiotranscribe import audio_transcribe
33
+
34
 
35
  from utils.helpers import parse_json_garbage, parse_number, word_to_number
36
  from datetime import datetime
 
45
  # Fetch a collection
46
  mongo_util = MongoDBUtil()
47
 
48
+ load_dotenv()
49
  app = FastAPI()
50
 
51
  # Add the authentication middleware
 
56
  questions = {
57
  "travel": {
58
  "origin": [
59
+ "Can you tell me which city are you traveling from?",
60
+ "Thank you for using Next Chat. Which city are you traveling from?",
61
+ "Greetings, can you tell me which city are you traveling from?",
62
+ "Hello User! Can you tell me What is your origin city?",
63
+ "Sure! From which city will you begin your journey?",
64
+ "Please provide me the city where you are departing from.",
65
+ "Let me know the city or location where you will start your travel.",
66
+ "To assist you better, could you tell me your starting point?"
67
  ],
68
  "destination": [
69
+ "Got it, can you tell me which city are you traveling to?",
70
+ "Great, and what is your destination city?",
71
+ "Perfect, which city you like to travel to?",
72
+ "Please tell me the city you are headed to.",
73
+ "Where is your final city for this trip?",
74
+ "Could you let me know which city are flying to?",
75
+ "What is the place or city you want to visit?",
76
+ "Let me know the destination city you're traveling to."
77
  ],
78
+ "date": [
79
+ "OK, when are you traveling?",
80
+ "Affirmative, and on which date are you planning to fly?",
81
+ "Please let me know the date of your journey.",
82
+ "When do you plan to start your travel?",
83
+ "Which date would you like to book your flight for?",
84
+ "What is the travel date for your trip?",
85
+ "On which day do you wish to travel?",
86
+ "Could you specify the date of your departure?"
87
  ],
88
  "people": [
89
  "Awesome, how many people will be traveling including yourself?",
90
+ "Noted, and how many people are you going with including yourself?",
91
+ "How many passengers will be traveling in total?",
92
+ "Including yourself, how many people are joining this trip?",
93
+ "What is the total number of travelers?",
94
+ "Could you let me know how many people will accompany you?",
95
+ "How many tickets should I consider for this trip?",
96
+ "Please specify the number of travelers, including you."
97
  ]
98
+ },
99
  "trip": {
100
  "destination": [
101
  "Where would you like to go?",
102
+ "Hello! Can you tell me your destination?",
103
  "Where are you planning to travel to?",
104
  "What is the name of the place you want to visit?"
105
  ],
 
109
  "Please let me know the number of days for your trip.",
110
  "How many days are you planning for your journey?"
111
  ]
112
+ },
113
  "job": {
114
  "job_title": [
115
  "What job title are you looking for?",
 
123
  "Can you specify the location for the job search?",
124
  "Which city or area do you prefer for this job?"
125
  ]
126
+ }
127
  }
128
 
129
  @app.get("/")
 
240
  # return {"success": True, "url": url, "text": text, "translated_text": translated_text}
241
 
242
  @app.post("/api/commands/query")
243
+ async def query(request: Request, body:Command):
 
 
 
244
  try:
245
+ user = request.state.user
246
+ print("Debug: Received request body:", body)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
247
 
248
+ if len(body.query.strip()) > 100:
249
+ print("Debug: Query length exceeds 100 characters.")
250
+ return {
251
+ "success": False,
252
+ "message": "Please enter all the details in a short sentence of 100 characters or less.",
253
+ }
254
 
255
+
256
+ if body.command == "/travel":
257
+ body.data = body.data or {}
258
+ body.data["adults"] = body.data.get("adults") # Allow adults to remain missing for sequential questions
 
 
259
 
260
+ print(f"Debug: Initial body.data: {body.data}")
 
 
 
 
 
261
 
262
+ required_fields = ["origin_skyid", "destination_skyid", "date", "adults"]
 
 
263
 
264
+ # Function to check for missing fields
265
+ def get_missing_fields(data):
266
+ return [field for field in required_fields if field not in data or not data.get(field)]
267
 
268
+ # Map field names to question keys
269
+ field_to_question_key = {
270
+ "origin_skyid": "origin",
271
+ "destination_skyid": "destination",
272
+ "date": "date",
273
+ "adults": "people",
274
+ }
275
 
276
+ # Case 1: Process the first query
277
+ if body.follow_question == "":
278
+ print("Debug: Processing first query with process_sentence.")
279
+ result = process_sentence(body.query, user)
280
+
281
+ # Ensure result is a valid dictionary
282
+ if not isinstance(result, dict):
283
+ print("Error: process_sentence returned an invalid result.")
284
+ return {"success": False, "message": "Internal error occurred during processing."}
285
+
286
+ print("Debug: Process Sentence Result:", result)
287
+ num_people = result.get("num_people")
288
+ if not isinstance(num_people, int) or num_people < 1 or num_people > 8:
289
+ return {
290
+ "success": False,
291
+ "message": "Please enter the details of your travel with a valid number of people between 1 and 8."
292
+ }
293
+
294
+ # Store extracted fields into body.data
295
+ if result.get("origin"):
296
+ origin_response = get_country_code(query=result["origin"])
297
+ if origin_response:
298
+ body.data["origin_skyid"] = str(origin_response[0]["skyId"])
299
+ body.data["origin_entityid"] = str(origin_response[0]["entityId"])
300
+ else:
301
+ return {"success": False, "message": "Unable to retrieve origin information."}
302
 
303
+ if result.get("destination"):
304
+ destination_response = get_country_code(query=result["destination"])
305
+ if destination_response:
306
+ body.data["destination_skyid"] = str(destination_response[0]["skyId"])
307
+ body.data["destination_entityid"] = str(destination_response[0]["entityId"])
308
+ else:
309
+ return {"success": False, "message": "Unable to retrieve destination information."}
310
+
311
+ if result.get("date"):
312
+ body.data["date"] = str(result["date"])
313
+
314
+ if result.get("num_people"):
315
+ body.data["adults"] = str(result["num_people"])
316
+
317
+ print(f"Debug: Updated body.data after setting extracted fields: {body.data}")
318
+
319
+ # Check for missing fields
320
+ missing_fields = get_missing_fields(body.data)
321
+ print(f"Debug: Missing fields: {missing_fields}")
322
+ if not missing_fields:
323
+ # All fields are present; fetch travel listings
324
+ travel_listings = get_travel_listing(
325
+ originSkyId=body.data["origin_skyid"],
326
+ destinationSkyId=body.data["destination_skyid"],
327
+ originEntityId=body.data.get("origin_entityid"),
328
+ destinationEntityId=body.data.get("destination_entityid"),
329
+ date=body.data["date"],
330
+ adults=body.data["adults"],
331
+ )
332
+ print("Debug: Travel Listings Response:", travel_listings)
333
+ if not travel_listings or "error" in travel_listings:
334
+ return {"success": False, "message": "Unable to fetch travel listings."}
335
+ return {"success": True, "suggestions": travel_listings}
336
+
337
+ # If fields are still missing, ask for the next missing field
338
+ next_field = missing_fields[0]
339
+ question_key = field_to_question_key[next_field] # Map the field to the question key
340
+ print(f"Debug: Missing field detected, asking for '{question_key}'.")
341
  return {
342
  "success": True,
343
+ "follow_question": question_key,
344
  "data": body.data,
345
+ "question": random.choice(questions["travel"][question_key]),
346
  }
347
 
348
+ # Case 2: Sequentially ask for missing fields
349
+ else:
350
+ print(f"Debug: Processing follow-up question for '{body.follow_question}'.")
351
+ if body.follow_question == "origin":
352
+ origin_response = get_country_code(query=body.query)
353
+ if origin_response:
354
+ body.data["origin_skyid"] = origin_response[0]["skyId"]
355
+ body.data["origin_entityid"] = origin_response[0]["entityId"]
356
+ else:
357
+ return {"success": False, "message": "Unable to retrieve origin information."}
358
 
359
+ elif body.follow_question == "destination":
360
+ destination_response = get_country_code(query=body.query)
361
+ if destination_response:
362
+ body.data["destination_skyid"] = destination_response[0]["skyId"]
363
+ body.data["destination_entityid"] = destination_response[0]["entityId"]
364
+ else:
365
+ return {"success": False, "message": "Unable to retrieve destination information."}
366
 
367
+ elif body.follow_question == "date":
368
+ date_response = parse_date(body.query)
369
+ if date_response:
370
+ body.data["date"] = date_response
371
+ else:
372
+ return {"success": False, "message": "Invalid date format. Please provide a valid date."}
373
+
374
+ elif body.follow_question == "people":
375
+ try:
376
+ # Handle cases where the query explicitly indicates a single person
377
+ if body.query.strip().lower() in {"just me", "only me", "me only", "myself", "only I", "simply me", "it's me alone", "none but me", "me and no one else", "me exclusively", "solely me", "just myself", "no one but me", "only myself", "exclusively me", "me alone", "it's just me", "i am by myself", "I am alone", "by myself", "on my own", "all by myself"}:
378
+ body.data["adults"] = 1
379
+ else:
380
+ # Extract the number of people using regex
381
+ people_pattern = r"(\d+)\s*(?:people|adult|adults|passengers|travelers|travellers|companions)?"
382
+ people_match = re.search(people_pattern, body.query.strip(), re.IGNORECASE)
383
+
384
+ if people_match:
385
+ body.data["adults"] = int(people_match.group(1))
386
+ else:
387
+ return {"success": False, "message": "Please provide a valid number of people."}
388
+
389
+ # Validate the number of people
390
+ if body.data["adults"] <= 0 or body.data["adults"] > 8:
391
+ return {"success": False, "message": "Please provide a valid number of people (1-8)."}
392
+ except ValueError:
393
+ return {"success": False, "message": "Invalid input for the number of people."}
394
+
395
+
396
+ print(f"Debug: Updated body.data after processing follow-up question: {body.data}")
397
+
398
+ # Check if all fields are now filled
399
+ missing_fields = get_missing_fields(body.data)
400
+ print(f"Debug: Missing fields: {missing_fields}")
401
+ if not missing_fields:
402
+ # All fields are present; fetch travel listings
403
+ travel_listings = get_travel_listing(
404
+ originSkyId=body.data["origin_skyid"],
405
+ destinationSkyId=body.data["destination_skyid"],
406
+ originEntityId=body.data.get("origin_entityid"),
407
+ destinationEntityId=body.data.get("destination_entityid"),
408
+ date=body.data["date"],
409
+ adults=body.data["adults"],
410
+ )
411
+ print("Debug: Travel Listings Response:", travel_listings)
412
+ if not travel_listings or "error" in travel_listings:
413
+ return {"success": False, "message": "Unable to fetch travel listings."}
414
+ return {"success": True, "suggestions": travel_listings}
415
+
416
+ # Ask for the next missing field
417
+ next_field = missing_fields[0]
418
+ question_key = field_to_question_key[next_field]
419
+ print(f"Debug: Missing field detected, asking for '{question_key}'.")
420
  return {
421
  "success": True,
422
+ "follow_question": question_key,
423
  "data": body.data,
424
+ "question": random.choice(questions["travel"][question_key]),
425
  }
426
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
427
  elif body.command == "/image":
 
428
  prompt = body.query.strip()
429
+ url = texttoimage(prompt)
430
+ if not url:
431
+ return {"success": False, "message": "Unable to generate an image. Please try again."}
 
 
432
  mongo_util.get_collection("users").update_one({"_id": ObjectId(user["_id"])},{"$inc": {"ai_image": -1}})
433
+ return {"success": True, "url": url}
 
434
 
435
  elif body.command == "/trip":
436
  body.data = body.data or {}
437
+ print(f"Debug: Initial body.data: {body.data}")
438
+
439
+ required_fields = ["destination", "days"]
440
 
441
+ def get_missing_fields(data):
442
+ return [field for field in required_fields if not data.get(field)]
443
+
444
+ # Case 1: Process the first query
445
  if body.follow_question == "":
446
+ print("Debug: Processing first query with extract_sentence.")
447
+ result = extract_sentence(body.query, user)
 
 
 
 
448
 
449
+ if not isinstance(result, dict):
450
+ print("Error: extract_sentence returned an invalid result.")
451
+ return {"success": False, "message": "Internal error occurred during processing."}
 
452
 
453
+ print("Debug: Extract Sentence Result:", result)
454
 
455
+ if result.get("destination"):
456
+ body.data["destination"] = result["destination"]
 
 
 
 
457
 
458
+ if result.get("num_days"):
459
+ body.data["days"] = result["num_days"]
 
 
 
460
 
461
+ print(f"Debug: Updated body.data after setting extracted fields: {body.data}")
 
 
462
 
463
+ missing_fields = get_missing_fields(body.data)
464
+ if not missing_fields:
465
+ trip_plans = get_trip_planner(
466
+ days=body.data["days"],
467
+ destination=body.data["destination"]
468
+ )
469
+ print("Debug: Trip Plans Response:", trip_plans)
470
+ if not trip_plans:
471
+ return {"success": False, "message": "Unable to fetch trip plans."}
472
+ return {"success": True, "trip_plans": trip_plans, "message": "Here are your trip plans!"}
473
 
474
+ next_field = missing_fields[0]
475
+ print(f"Debug: Missing field detected, asking for '{next_field}'.")
476
+ return {
477
+ "success": True,
478
+ "follow_question": next_field,
479
+ "data": body.data,
480
+ "question": random.choice(questions["trip"][next_field]),
481
+ }
482
 
483
+ # Case 2: Sequentially ask for missing fields
484
+ else:
485
+ print(f"Debug: Processing follow-up question for '{body.follow_question}'.")
486
+ if body.follow_question == "destination":
487
+ body.data["destination"] = body.query.strip()
488
+ if not body.data["destination"]:
489
+ return {"success": False, "message": "Please provide a valid destination."}
490
+
491
+ elif body.follow_question == "days":
492
+ try:
493
+ # Extract the number of days using regex
494
+ days_pattern = r"(\d+)(?:\s+(?:days|day))?"
495
+ days_match = re.search(days_pattern, body.query.strip(), re.IGNORECASE)
496
+
497
+ if days_match:
498
+ body.data["days"] = int(days_match.group(1))
499
+ else:
500
+ return {"success": False, "message": "Please provide a valid number of days."}
501
+
502
+ if body.data["days"] <= 0:
503
+ return {"success": False, "message": "Please provide a positive number of days for the trip."}
504
+ except ValueError:
505
+ return {"success": False, "message": "Please provide a valid number of days."}
506
+
507
+ print(f"Debug: Updated body.data after processing follow-up question: {body.data}")
508
+
509
+ missing_fields = get_missing_fields(body.data)
510
+ if not missing_fields:
511
+ trip_plans = get_trip_planner(
512
+ days=body.data["days"],
513
+ destination=body.data["destination"]
514
+ )
515
+ print("Debug: Trip Plans Response:", trip_plans)
516
+ if not trip_plans:
517
+ return {"success": False, "message": "Unable to fetch trip plans."}
518
+ return {"success": True, "trip_plans": trip_plans, "message": "Here are your trip plans!"}
519
+
520
+ next_field = missing_fields[0]
521
+ print(f"Debug: Missing field detected, asking for '{next_field}'.")
522
  return {
523
  "success": True,
524
+ "follow_question": next_field,
525
+ "data": body.data,
526
+ "question": random.choice(questions["trip"][next_field]),
527
  }
528
 
529
+ elif body.command == "/job":
530
  body.data = body.data or {}
531
  print(f"Initial body.data: {body.data}")
532
 
 
578
  return {"success": False, "error": str(e)}
579
 
580
 
 
581
  # @app.post("/api/commands/query")
582
  # async def query(body: Command):
583