import sys import os sys.path.append(os.path.abspath(os.path.join(os.getcwd(), ".."))) os.chdir(os.path.dirname(os.path.abspath(__file__))) import gradio as gr import json from tools.flights.apis import Flights from tools.accommodations.apis import Accommodations from tools.restaurants.apis import Restaurants from tools.googleDistanceMatrix.apis import GoogleDistanceMatrix from tools.attractions.apis import Attractions import pandas as pd from gradio.events import Changeable, Streamable, Submittable, on from src.utils import * from gradio.events import EventListenerMethod import math data = load_line_json_data('query.jsonl') query_dropdown_text = [f"Query {index}" for index in range(1, len(data)+1)] with open('assets/styles.css', 'r') as css_file: css_content = css_file.read() flight = Flights() accommodations = Accommodations() restaurants = Restaurants() googleDistanceMatrix = GoogleDistanceMatrix() attractions = Attractions() annotation_idx = 4 cost = 0 global_user_name = "" transportaion_val = "" accommodation_val = "" breakfast_val = "" lunch_val = "" dinner_val = "" attraction_val = "" def auto_update_current_cost(*components): global cost cost = 0 for i in range(7): # flight if judge_valid_info(components[7+i]): if components[7+i] != '-': if 'Flight Number' in components[7+i]: cost += flight.data[flight.data['Flight Number'] == components[7+i].split('Flight Number: ')[1].split(',')[0]]['Price'].values[0] * data[annotation_idx-1]['people_number'] elif 'Self-driving' in components[7+i] or 'Taxi' in components[7+i]: if 'Self-driving' in components[7+i]: cost += int(components[7+i].split('cost: ')[1]) * math.ceil(data[annotation_idx-1]['people_number'] * 1.0 / 5) else: cost += int(components[7+i].split('cost: ')[1]) * math.ceil(data[annotation_idx-1]['people_number'] * 1.0 / 4) # breakfast if judge_valid_info(components[7*2+i]): if components[7*2+i] != '-': name, city = get_valid_name_city(components[7*2+i]) cost += restaurants.data[(restaurants.data['Name'] == name) & (restaurants.data['City'] == city)]['Average Cost'].values[0] * data[annotation_idx-1]['people_number'] # attraction # lunch if judge_valid_info(components[7*4+i]): if components[7*4+i] != '-': name, city = get_valid_name_city(components[7*4+i]) cost += restaurants.data[(restaurants.data['Name'] == name) & (restaurants.data['City'] == city)]['Average Cost'].values[0] * data[annotation_idx-1]['people_number'] # dinner if judge_valid_info(components[7*5+i]): if components[7*5+i] != '-': name, city = get_valid_name_city(components[7*5+i]) cost += restaurants.data[(restaurants.data['Name'] == name) & (restaurants.data['City'] == city)]['Average Cost'].values[0] * data[annotation_idx-1]['people_number'] # accommodation if judge_valid_info(components[7*6+i]): if components[7*6+i] != '-': name, city = get_valid_name_city(components[7*6+i]) res = accommodations.data[(accommodations.data['NAME'] == name) & (accommodations.data['city'] == city)] cost += res['price'].values[0] * math.ceil(data[annotation_idx-1]['people_number'] * 1.0 / res['maximum occupancy'].values[0]) return gr.Number(label="Current Cost", value=cost, interactive=False,elem_classes="current_cost") def auto_update_current_cost_number(fn, input_components, output_components): events: list[EventListenerMethod] = [] for component in input_components: if isinstance(component, Streamable) and component.streaming: events.append(component.stream) elif isinstance(component, Changeable): events.append(component.change) on( events, fn, input_components, output_components ) def get_google_distance_matrix(mode,departure_city, destination_city): if mode == "Self-driving": return pd.DataFrame(googleDistanceMatrix.run_for_annotation(departure_city, destination_city,'driving'),index=[0]) elif mode == "Taxi": return pd.DataFrame(googleDistanceMatrix.run_for_annotation(departure_city, destination_city,'taxi'),index=[0]) def return_list_items(items): return items[0],items[1],items[2],items[3],items[4],items[5],items[6] def submit_update_options(query_candidate, *components): global query_dropdown_text ,cost global transportaion_val, accommodation_val, breakfast_val, lunch_val, dinner_val, attraction_val json_data = [{} for i in range(7)] new_components = [ None for i in range(len(components))] # write the annotation into the json file cuisine_set = set() for i in range(data[annotation_idx-1]['days']): json_data[i]['days'] = i+1 if judge_submit_info(components[i],i+1,'current city',data[annotation_idx-1]): json_data[i]['current_city'] = components[i] if judge_submit_info(components[7+i],i+1,'transportation',data[annotation_idx-1]): json_data[i]['transportation'] = components[7+i] if judge_submit_info(components[7*2+i],i+1,'breakfast',data[annotation_idx-1]): cuisine_set = judge_valid_cuisine(components[7*2+i],data[annotation_idx-1],restaurants.data, cuisine_set) json_data[i]['breakfast'] = components[7*2+i] if judge_submit_info(components[7*3+i],i+1,'attraction',data[annotation_idx-1]): json_data[i]['attraction'] = components[7*3+i] if judge_submit_info(components[7*4+i],i+1,'lunch',data[annotation_idx-1]): cuisine_set = judge_valid_cuisine(components[7*4+i],data[annotation_idx-1],restaurants.data, cuisine_set) json_data[i]['lunch'] = components[7*4+i] if judge_submit_info(components[7*5+i],i+1,'dinner',data[annotation_idx-1]): cuisine_set = judge_valid_cuisine(components[7*5+i],data[annotation_idx-1],restaurants.data, cuisine_set) json_data[i]['dinner'] = components[7*5+i] if judge_submit_info(components[7*6+i],i+1,'accommodation',data[annotation_idx-1],accommodations.data): json_data[i]['accommodation'] = components[7*6+i] if data[annotation_idx-1]['local_constraint']['cuisine'] and len(list(cuisine_set)) != len(data[annotation_idx-1]['local_constraint']['cuisine']): raise gr.Error("Please note the cuisine constraints.") consectutive_accommodation = count_consecutive_values(components[7*6:7*6+data[annotation_idx-1]['days']]) # print(consectutive_accommodation) # print("") for unit in consectutive_accommodation: # print(unit) if unit and unit[0] not in ['-',''] and unit!="You don't need to fill in the information for this or later days.": name, city = get_valid_name_city(unit[0]) if unit[1] < accommodations.data[(accommodations.data['NAME'] == name) & (accommodations.data['city'] == city)].iloc[0]['minimum nights']: raise gr.Error(f"Please note the minimum nights of {unit[0]}.") if cost > data[annotation_idx-1]['budget']: raise gr.Error("The current cost is higher than the budget, please modify the information.") # return [gr.Textbox(value="The current cost is higher than the budget, please modify the information.",interactive=False)]*6 + [gr.Dropdown(choices=query_dropdown_text)] # ['is_reasonalbe_visiting_city', 'is_valid_restaurants', 'is_valid_attractions', 'is_valid_transportation', 'is_valid_information_in_current_city', 'is_valid_information_in_sandbox'] for i in range(data[annotation_idx-1]['days']): new_components[i] = gr.Textbox(label="Current City", value=None,interactive=False) new_components[7+i] = gr.Textbox(label="Transportation", value="-",interactive=False) new_components[7*2+i] = gr.Textbox(label="Breakfast", value=None, interactive=False) new_components[7*3+i] = gr.Textbox(label="Attractions", value=None, interactive=False) new_components[7*4+i] = gr.Textbox(label="Lunch", value=None,interactive=False) new_components[7*5+i] = gr.Textbox(label="Dinner", value=None,interactive=False) new_components[7*6+i] = gr.Textbox(label="Accommodation", value=None,interactive=False) with open('../data/annotation/{}/annotation_{}.json'.format(global_user_name,annotation_idx), 'w') as f: json.dump(json_data, f) transportaion_val = "" accommodation_val = "" breakfast_val = "" lunch_val = "" dinner_val = "" attraction_val = "" new_options = query_dropdown_text new_options[annotation_idx-1] = f"Query {annotation_idx} --- Done" query_dropdown_text = new_options return [gr.Dropdown(choices=new_options)] + new_components + [gr.Textbox(value=None) for _ in range(14)] def update_gloabal_idx(selected_option): global annotation_idx,cost global transportaion_val, accommodation_val, breakfast_val, lunch_val, dinner_val, attraction_val transportaion_val = "" accommodation_val = "" breakfast_val = "" lunch_val = "" dinner_val = "" attraction_val = "" annotation_idx = extract_query_number(selected_option) new_components = [ gr.Textbox() for i in range(49)] city_list = get_city_list(data[annotation_idx-1]['days'], data[annotation_idx-1]['org'], data[annotation_idx-1]['dest']) city_drop_down = [None for i in range(63)] date_component_list = [gr.Textbox(value="", interactive=False) for i in range(7)] for i in range(data[annotation_idx-1]['days']): new_components[i] = gr.Textbox(label="Current City",value="",interactive=False) new_components[7+i] = gr.Textbox(label="Transportation",value="",interactive=False) new_components[7*2+i] = gr.Textbox(label="Breakfast", value="",interactive=False) new_components[7*3+i] = gr.Textbox(label="Attractions", value="",interactive=False) new_components[7*4+i] = gr.Textbox(label="Lunch", value="",interactive=False) new_components[7*5+i] = gr.Textbox(label="Dinner", value="",interactive=False) new_components[7*6+i] = gr.Textbox(label="Accommodation", value="",interactive=False) for i in range(63): if i % 9 in [0,2,4]: city_drop_down[i] = gr.Radio(label="Departure City",choices=city_list) elif i % 9 in [1,3,5]: city_drop_down[i] = gr.Radio(label="Destination City",choices=city_list) else: city_drop_down[i] = gr.Radio(label="City",choices=city_list) for i in range(data[annotation_idx-1]['days']): date_component_list[i] = gr.Textbox(label="Date", value=data[annotation_idx-1]['date'][i], interactive=False) return [create_data_display(css_content,data,annotation_idx),gr.update(visible=True)]+new_components+city_drop_down+date_component_list+[gr.Number(value=cost, interactive=False)] def Recommend_new(x): return x + ": Highest Cosine Similarity" def current_city_selection(departure_city, dest_city): final_city = "" if departure_city == dest_city: final_city = departure_city else: final_city = "from " + departure_city + " to " + dest_city return gr.Textbox(label="Current City", value=final_city, interactive=False) def tab_hint(current_city,transportaion,breakfast,attraction,lunch,dinner,accommodation,evt:gr.SelectData): global transportaion_val, accommodation_val, breakfast_val, lunch_val, dinner_val, attraction_val transportaion_val = "" accommodation_val = "" breakfast_val = breakfast lunch_val = lunch dinner_val = dinner attraction_val = attraction if data[annotation_idx-1]['days'] <= evt.index: return [gr.Textbox(value="You don't need to fill in the information for this or later days.",interactive=False)]*7 + [gr.Dropdown(choices=query_dropdown_text)] + [gr.Textbox(value="") for _ in range(2)] else: return current_city, transportaion,breakfast,attraction,lunch,dinner,accommodation, gr.Dropdown(choices=query_dropdown_text),gr.Textbox(value=""), gr.Textbox(value="") css = """ #submit_button {background: #00a1b8;} #clear_button {background: #ff8069;} """ with gr.Blocks(css=css) as demo: gr.HTML(f"""

TravelPlanner Environment

""") gr.HTML("
") query_selection = gr.Dropdown(query_dropdown_text, label="Query") annotation_button = gr.ClearButton(value="Search") gr.HTML("
") transportaion_list = [] breakfast_list = [] attraction_list = [] lunch_list = [] dinner_list = [] accommodation_list = [] current_city_list = [] city_component_list = [] date_component_list = [] filtering_keyword_list = [] with gr.Column(visible=False) as component: query_display = gr.HTML(create_data_display(css_content,data,annotation_idx)) current_cost = gr.Number(label="Current Cost", value=0, interactive=False,elem_classes="current_cost") with gr.Row(): tabs = gr.Tabs() with tabs: for i in range(7): with gr.Tab(label=f"Day {i+1}", id=(i+1)) as tab: with gr.Row(): with gr.Column(): current_city = gr.Textbox(label="Current City", interactive=False,value="") transportaion = gr.Textbox(label="Transportation",interactive=False,value="") breakfast = gr.Textbox(label="Breakfast", interactive=False,value="") attraction = gr.Textbox(label="Attractions",interactive=False,value="") lunch = gr.Textbox(label="Lunch", interactive=False,value="") dinner = gr.Textbox(label="Dinner", interactive=False,value="") accommodation = gr.Textbox(label="Accommodation",interactive=False,value="") current_city_list.append(current_city) transportaion_list.append(transportaion) breakfast_list.append(breakfast) attraction_list.append(attraction) lunch_list.append(lunch) dinner_list.append(dinner) accommodation_list.append(accommodation) with gr.Column(): with gr.Tab(label=f'City Selection'): departure_city = gr.Radio(label="Departure City") destination_city = gr.Radio(label="Destination City") city_component_list += [departure_city,destination_city] btn = gr.Button("Done") # output = gr.HTML("") annotation_button.add(components=[departure_city,destination_city]) btn.click(current_city_selection,inputs=[departure_city,destination_city],outputs=current_city) # output.select(on_row_selected, inputs=[city],outputs=attraction) # btn_clear.click(clear,inputs=None,outputs=attraction) with gr.Tab(label=f'Flight'): transportaion_val = "" def on_row_selected(dep_city,dest_city,evt:gr.SelectData): global transportaion_val if evt.index[1] == 0: transportaion_val = "Flight Number: " + str(evt.value) + f", from {dep_city} to {dest_city}, Departure Time: {flight.data[flight.data['Flight Number']==evt.value].iloc[0]['DepTime']}, Arrival Time: {flight.data[flight.data['Flight Number']==evt.value].iloc[0]['ArrTime']}" return transportaion_val else: return transportaion_val departure_city = gr.Radio(label="Departure City") destination_city = gr.Radio(label="Destination City") city_component_list += [departure_city, destination_city] date = gr.Textbox(label="Date", interactive=False) date_component_list.append(date) btn = gr.Button("Search") clean_btn = gr.Button("Skip") output = gr.Dataframe(flight.run_for_annotation('','',''), interactive=False) annotation_button.add(components=[output]) btn.click(flight.run_for_annotation,inputs=[departure_city, destination_city, date],outputs=output) output.select(on_row_selected, inputs=[departure_city, destination_city],outputs=[transportaion]) clean_btn.click(lambda:"-",inputs=None,outputs=[transportaion]) with gr.Tab(label='Driving'): def on_row_selected(org, dest, mode,data, evt:gr.SelectData): global transportaion_val data_dict = data.to_dict(orient = 'split')['data'][0] transportaion_val = f"{mode}, from {org} to {dest}, duration: {data_dict[2]}, distance: {data_dict[1]}, cost: {data_dict[0]}" return transportaion_val transportation_mode = gr.Radio(["Self-driving", "Taxi"], label="Mode") departure_city = gr.Radio(label="Departure City") destination_city = gr.Radio(label="Destination City") city_component_list += [departure_city, destination_city] btn = gr.Button("Search") clean_btn = gr.Button("Skip") output = gr.Dataframe( headers=["duration", "distance", "cost"], datatype=["str", "str", "str"], value=["", "", ""], row_count=1, col_count=(3, "fixed"),interactive=False ) annotation_button.add(components=[output]) btn.click(get_google_distance_matrix, inputs=[transportation_mode, departure_city, destination_city],outputs=output) clean_btn.click(lambda:"-",inputs=None,outputs=[transportaion]) output.select(on_row_selected, inputs=[departure_city,destination_city,transportation_mode,output],outputs=transportaion) with gr.Tab(label='Accommodation'): accommodation_val = "" def on_row_selected(city,evt:gr.SelectData): global accommodation_val if evt.index[1] == 0: accommodation_val = str(evt.value) + f", {city}" return accommodation_val def search(city, filtering_keyword=None): # if filtering_keyword in [" ",""]: return accommodations.run_for_annotation(city) # else: # return_data = accommodations.run_for_annotation(city) # return return_data[~return_data['house_rules'].str.contains(filtering_keyword)] city = gr.Radio(label="City") # filtering_keyword = gr.Textbox(label="Forbidden keyword (only for hotel rule)",value="") # filtering_keyword_list.append(filtering_keyword) city_component_list += [city] btn = gr.Button("Search") skip_btn = gr.Button("Skip") output = gr.Dataframe(accommodations.run_for_annotation(''), interactive=False) annotation_button.add(components=[output]) btn.click(search,inputs=[city],outputs=output) output.select(on_row_selected, inputs=[city],outputs=accommodation) skip_btn.click(lambda:"-",inputs=None,outputs=accommodation) with gr.Tab(label='Restaurant'): breakfast_val = "" lunch_val = "" dinner_val = "" def on_row_selected(city, meal_type, evt: gr.SelectData): global breakfast_val, lunch_val, dinner_val if evt.index[1] == 0: if meal_type == "Breakfast": breakfast_val = str(evt.value) + f", {city}" elif meal_type == "Lunch": lunch_val = str(evt.value) + f", {city}" elif meal_type == "Dinner": dinner_val = str(evt.value) + f", {city}" return breakfast_val, lunch_val, dinner_val def skip(meal_type): global breakfast_val, lunch_val, dinner_val if meal_type == "Breakfast": breakfast_val = "-" elif meal_type == "Lunch": lunch_val = "-" elif meal_type == "Dinner": dinner_val = "-" return breakfast_val, lunch_val, dinner_val def search(city, filtering_keyword=None): # if filtering_keyword in [" ",""]: return restaurants.run_for_annotation(city) # else: # return_data = restaurants.run_for_annotation(city) # return return_data[return_data['Cuisines'].str.contains(filtering_keyword)] city = gr.Radio(label="City") # filtering_keyword = gr.Textbox(label="Contain keyword",value="") # filtering_keyword_list.append(filtering_keyword) city_component_list += [city] btn = gr.Button("Search") skip_btn = gr.Button("Skip") choice = gr.Radio(["Breakfast", "Lunch", "Dinner"], label="Meal Type") annotation_button.add(components=[choice]) output = gr.Dataframe(restaurants.run_for_annotation(''), interactive=False) annotation_button.add(components=[output]) btn.click(search,inputs=[city],outputs=output) # according to the meal type to select the outputs - breakfast, lunch, dinner output.select(on_row_selected, inputs=[city,choice],outputs=[breakfast, lunch, dinner]) skip_btn.click(skip,inputs=[choice],outputs=[breakfast, lunch, dinner]) with gr.Tab(label='Attraction'): attraction_val = "" def on_row_selected(city, evt:gr.SelectData): global attraction_val attraction_val = attraction_val.replace("-","") if evt.index[1] == 0: attraction_val += evt.value + ', '+ city + ";" return attraction_val def clear(): global attraction_val attraction_val = "" return attraction_val city = gr.Radio(label="City") city_component_list += [city] btn = gr.Button("Search") btn_clear = gr.Button("Clear") btn_skip = gr.Button("Skip") output = gr.Dataframe(attractions.run_for_annotation(''), interactive=False) annotation_button.add(components=[output]) btn.click(attractions.run_for_annotation,inputs=[city],outputs=output) output.select(on_row_selected, inputs=[city],outputs=attraction) btn_clear.click(clear,inputs=None,outputs=attraction) btn_skip.click(lambda:"-",inputs=None,outputs=attraction) tab.select(tab_hint, inputs=[current_city,transportaion,breakfast,attraction,lunch,dinner,accommodation],outputs=[current_city, transportaion,breakfast,attraction,lunch,dinner,accommodation, query_selection]+filtering_keyword_list[-2:]) component_list = current_city_list + transportaion_list + breakfast_list + attraction_list + lunch_list + dinner_list + accommodation_list # clear_button = gr.ClearButton(components=component_list,value="Clear") input_args = [query_selection] + component_list auto_update_current_cost_number(auto_update_current_cost, component_list, [current_cost]) # b3.click(Recommend_new, inputs=query_selection, outputs=new_title) annotation_button.add(components=city_component_list) annotation_button.click(update_gloabal_idx, inputs=[query_selection], outputs=[query_display,component]+component_list+city_component_list+date_component_list+[current_cost]) if __name__ == "__main__": demo.launch(debug=True)