Spaces:
Sleeping
Sleeping
shoaibamin-dev
commited on
Commit
·
c206733
1
Parent(s):
a2cadde
audit logs and mongo util
Browse files- ai/extract.py +123 -0
- ai/iata.py +6 -6
- ai/prompt.py +159 -0
- ai/travel.py +144 -122
- ai/trip.py +32 -120
- ai/tti.py +15 -15
- 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 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
|
|
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}¤cy=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}¤cy=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 |
-
|
|
|
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()
|
74 |
|
75 |
for itinerary in data.get("itineraries", []):
|
76 |
for leg in itinerary.get("legs", []):
|
77 |
-
#
|
78 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
79 |
if unique_key in seen_flights:
|
80 |
continue
|
81 |
seen_flights.add(unique_key)
|
82 |
|
83 |
-
#
|
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
|
91 |
stop_details = []
|
92 |
segments = leg.get("segments", [])
|
93 |
for i, segment in enumerate(segments[:-1]):
|
94 |
-
stop_code = segment
|
95 |
-
stop_arrival =
|
96 |
-
next_departure =
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
|
|
|
|
|
|
|
|
109 |
stops_route = " --> ".join(stop_locations)
|
110 |
|
|
|
|
|
|
|
|
|
111 |
extracted_data.append({
|
112 |
-
"origin":
|
113 |
-
"destination":
|
114 |
-
"airline_code":
|
115 |
-
"airline_name":
|
116 |
"duration": duration_formatted,
|
117 |
-
"price":
|
118 |
-
"departure": leg
|
119 |
-
"arrival": leg
|
120 |
-
"flight_number": ", ".join(segment
|
121 |
"stop_count": leg.get("stopCount", 0),
|
122 |
"stops_route": stops_route,
|
123 |
"stops_details": stop_details
|
124 |
})
|
125 |
|
126 |
-
#
|
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 |
-
|
152 |
-
|
153 |
-
#
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
|
166 |
-
|
167 |
-
|
168 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
169 |
|
170 |
-
#
|
171 |
-
#
|
172 |
-
# raise ValueError("Travel date is required.")
|
173 |
|
174 |
-
#
|
175 |
-
|
176 |
-
#
|
177 |
-
#
|
178 |
-
|
179 |
-
#
|
180 |
-
#
|
181 |
-
|
182 |
-
|
183 |
-
#
|
184 |
-
#
|
185 |
-
|
186 |
-
#
|
187 |
-
|
188 |
-
#
|
189 |
-
|
190 |
-
#
|
191 |
-
# )
|
192 |
-
|
193 |
-
#
|
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}¤cy=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}¤cy=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 |
-
|
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 |
-
|
34 |
-
|
35 |
-
|
36 |
-
print("No trip plans found.")
|
37 |
return []
|
38 |
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
|
57 |
except Exception as e:
|
58 |
print(f"Error occurred: {e}")
|
59 |
-
return
|
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 |
-
|
72 |
|
73 |
-
if not
|
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 |
-
|
41 |
-
|
42 |
-
s3.Bucket(os.environ["S3_BUCKET_NAME"]).upload_file(path, s3_path)
|
43 |
-
url = s3.meta.client.generate_presigned_url(
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
)
|
50 |
-
os.remove(path)
|
51 |
|
52 |
|
53 |
-
print(
|
54 |
|
55 |
-
return
|
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
|
52 |
-
"Thank you for using Next Chat.
|
53 |
-
"
|
54 |
-
"
|
|
|
|
|
|
|
|
|
55 |
],
|
56 |
"destination": [
|
57 |
-
"Got it, can you tell me
|
58 |
-
"Great, and what is your destination?"
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
],
|
60 |
-
"
|
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 |
-
"
|
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(
|
213 |
-
user = request.state.user
|
214 |
-
print(user)
|
215 |
-
|
216 |
try:
|
217 |
-
|
218 |
-
|
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 |
-
|
238 |
-
|
|
|
|
|
|
|
|
|
239 |
|
240 |
-
|
241 |
-
|
242 |
-
|
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 |
-
|
248 |
-
"success": True,
|
249 |
-
"follow_question": "destination",
|
250 |
-
"data": body.data,
|
251 |
-
"question": random.choice(questions["travel"]["destination"]),
|
252 |
-
}
|
253 |
|
254 |
-
|
255 |
-
destination_response = get_country_code(query=body.query)
|
256 |
-
print("Destination Response:", destination_response)
|
257 |
|
258 |
-
|
259 |
-
|
|
|
260 |
|
261 |
-
|
262 |
-
|
263 |
-
|
|
|
|
|
|
|
|
|
264 |
|
265 |
-
|
266 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
267 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
268 |
return {
|
269 |
"success": True,
|
270 |
-
"follow_question":
|
271 |
"data": body.data,
|
272 |
-
"question": random.choice(questions["travel"][
|
273 |
}
|
274 |
|
275 |
-
|
276 |
-
|
277 |
-
print(f"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
278 |
|
279 |
-
|
280 |
-
|
|
|
|
|
|
|
|
|
|
|
281 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
282 |
return {
|
283 |
"success": True,
|
284 |
-
"follow_question":
|
285 |
"data": body.data,
|
286 |
-
"question": random.choice(questions["travel"][
|
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 |
-
|
332 |
-
|
333 |
-
|
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 |
-
|
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 |
-
|
346 |
-
|
347 |
-
"follow_question": "destination",
|
348 |
-
"data": body.data,
|
349 |
-
"question": random.choice(questions["trip"]["destination"]),
|
350 |
-
}
|
351 |
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
return {"success": False, "message": "Please provide a valid destination."}
|
356 |
|
357 |
-
print(
|
358 |
|
359 |
-
|
360 |
-
"
|
361 |
-
"follow_question": "days",
|
362 |
-
"data": body.data,
|
363 |
-
"question": random.choice(questions["trip"]["days"]),
|
364 |
-
}
|
365 |
|
366 |
-
|
367 |
-
|
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 |
-
|
373 |
-
except ValueError:
|
374 |
-
return {"success": False, "message": "Please provide a valid number of days."}
|
375 |
|
376 |
-
|
377 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
378 |
|
379 |
-
|
380 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
381 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
382 |
return {
|
383 |
"success": True,
|
384 |
-
"
|
385 |
-
"
|
|
|
386 |
}
|
387 |
|
388 |
-
|
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 |
|