Spaces:
Running
Running
| import gradio as gr | |
| from df.PaperCentral import PaperCentral | |
| from gradio_calendar import Calendar | |
| from datetime import datetime, timedelta | |
| from typing import Union, List, Optional, Tuple | |
| from author_leaderboard_tab import author_leaderboard_tab | |
| from pr_paper_central_tab import pr_paper_central_tab | |
| from huggingface_hub import whoami | |
| import json | |
| import requests | |
| from bs4 import BeautifulSoup | |
| from author_leaderboard_contrib_tab import author_resource_leaderboard_tab | |
| from paper_chat_tab import paper_chat_tab | |
| from zoneinfo import ZoneInfo # Available in Python 3.9 and later | |
| # Initialize the PaperCentral class instance | |
| paper_central_df = PaperCentral() | |
| def logging_flow(oauth_token: Optional[gr.OAuthToken]): | |
| if oauth_token is None: | |
| # User is not logged in | |
| visibility_update = gr.update(visible=True) | |
| user_info_update = gr.update(value="", label="User") | |
| return visibility_update, user_info_update | |
| try: | |
| # Attempt to get user information | |
| user_info = whoami(oauth_token.token) | |
| visibility_update = gr.update(visible=False) | |
| except requests.exceptions.HTTPError as e: | |
| # If there's an error (e.g., token is invalid), treat as not logged in | |
| visibility_update = gr.update(visible=True) | |
| user_info_update = gr.update(value="", label="User") | |
| return visibility_update, user_info_update | |
| # Prepare user information for display | |
| avatar_url = user_info.get("avatarUrl", "") | |
| name = user_info.get("name", "") | |
| avatar_html = f''' | |
| <div style="display: flex; align-items: center;"> | |
| <img alt="Avatar" src="{avatar_url}" | |
| style="border: 2px solid rgb(245, 158, 11); border-radius: 50%; width: 1.38rem; height: 1.38rem; margin-right: 0.5rem;"> | |
| <span style="font-size: 1rem;">{name}</span> | |
| </div> | |
| Head to "Edit papers" tab to modify your paper! | |
| ''' | |
| user_info_update = gr.update(value=avatar_html, label="User") | |
| return visibility_update, user_info_update | |
| # Create the Gradio Blocks app with custom CSS | |
| with gr.Blocks(css_paths="style.css") as demo: | |
| gr.Markdown("# Paper Central") | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| login_button = gr.LoginButton(value="Add or edit your papers") | |
| user_info_md = gr.HTML() | |
| with gr.Column(scale=1): | |
| with gr.Accordion(label="⭐Release notes", open=False): | |
| gr.Markdown(""" | |
| - **November 21, 2024** – Neurips D&B 2024 proceedings added. | |
| - **November 20, 2024** – Neurips 2024 proceedings added. | |
| - **November 15, 2024** – EMNLP 2024 proceedings added. | |
| - **October 24, 2024** – CoRL 2024 proceedings added. | |
| - **October 20, 2024** – You can now add or edit papers. | |
| - **October 19, 2024** – Papers with github now have github stars. | |
| - **October 16, 2024** – Added functionality to filter papers by date ranges. | |
| - **October 11, 2024** – Introduced leaderboards feature. | |
| - **October 8, 2024** – MICCAI 2024 proceedings added. | |
| - **October 7, 2024** – COLM 2024 proceedings added. | |
| - **October 4, 2024** – Added functionality to filter papers by title. | |
| """) | |
| gr.Button(value="Use paper-central in datasets", | |
| icon="https://huggingface.co/front/assets/huggingface_logo-noborder.svg", | |
| size="sm", | |
| link="https://huggingface.co/datasets/huggingface/paper-central-data") | |
| with gr.Tabs() as tabs: | |
| with gr.Tab("Chat With Paper", id="tab-chat-with-paper", visible=True) as tab_chat_paper: | |
| gr.Markdown("## Chat with Paper") | |
| arxiv_id = gr.State(value=None) | |
| paper_from = gr.State(value=None) | |
| paper_chat_tab(arxiv_id, paper_from, paper_central_df) | |
| with gr.Tab("Paper-central", id="tab-paper-central"): | |
| # Create a row for navigation buttons and calendar | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| # Define the 'Next Day' and 'Previous Day' buttons | |
| next_day_btn = gr.Button("Next Day") | |
| prev_day_btn = gr.Button("Previous Day") | |
| with gr.Column(scale=4): | |
| # Define the calendar component for date selection | |
| calendar = Calendar( | |
| type="datetime", | |
| label="Select a date", | |
| info="Click the calendar icon to bring up the calendar.", | |
| value=datetime.now(ZoneInfo('America/Los_Angeles')).strftime('%Y-%m-%d') | |
| # Default to today's date in PST | |
| ) | |
| # Add Radio buttons for date ranges | |
| date_range_radio = gr.Radio( | |
| label="Date Range", | |
| choices=["This week", "This month", "This year", "All time"], | |
| value=None, | |
| ) | |
| # Create a row for Hugging Face options and Conference options | |
| with gr.Row(): | |
| with gr.Column(): | |
| # Define the checkbox group for Hugging Face options | |
| cat_options = gr.CheckboxGroup( | |
| label="Category", | |
| choices=[ | |
| '(ALL)', | |
| 'cs.*', | |
| 'eess.*', | |
| 'econ.*', | |
| 'math.*', | |
| 'astro-ph.*', | |
| 'cond-mat.*', | |
| 'gr-qc', | |
| 'hep-ex', | |
| 'hep-lat', | |
| 'hep-ph', | |
| 'hep-th', | |
| 'math-ph', | |
| 'nlin.*', | |
| 'nucl-ex', | |
| 'nucl-th', | |
| 'physics.*', | |
| 'quant-ph', | |
| 'q-bio.*', | |
| 'q-fin.*', | |
| 'stat.*', | |
| ], | |
| value=["(ALL)"] | |
| ) | |
| hf_options = gr.CheckboxGroup( | |
| label="Hugging Face options", | |
| choices=["🤗 artifacts", "datasets", "models", "spaces", "github", "project page"], | |
| value=[], | |
| elem_id="hf_options" | |
| ) | |
| with gr.Column(): | |
| # Define the checkbox group for Conference options | |
| conference_options = gr.CheckboxGroup( | |
| label="Conference options", | |
| choices=["ALL"] + PaperCentral.CONFERENCES | |
| ) | |
| with gr.Row(): | |
| # Define a Textbox for author search | |
| author_search = gr.Textbox( | |
| label="Search Authors", | |
| placeholder="Enter author name", | |
| ) | |
| title_search = gr.Textbox( | |
| label="Search Title", | |
| placeholder="Enter keywords", | |
| ) | |
| # Define the Dataframe component to display paper data | |
| # List of columns in your DataFrame | |
| columns = paper_central_df.COLUMNS_START_PAPER_PAGE | |
| paper_central_component = gr.Dataframe( | |
| label="Paper Data", | |
| value=paper_central_df.df_prettified[columns], | |
| datatype=[ | |
| paper_central_df.DATATYPES[column] | |
| for column in columns | |
| ], | |
| row_count=(0, "dynamic"), | |
| interactive=False, | |
| max_height=1000, | |
| elem_id="table", | |
| wrap=True, | |
| ) | |
| with gr.Tab("Edit papers", id="tab-pr"): | |
| pr_paper_central_tab(paper_central_df.df_raw) | |
| with gr.Tab("Leaderboards", id="tab-leaderboards"): | |
| with gr.Tab("Authors"): | |
| author_leaderboard_tab() | |
| with gr.Tab("Contributors"): | |
| author_resource_leaderboard_tab() | |
| # chat with paper | |
| def get_selected(evt: gr.SelectData, dataframe_origin): | |
| paper_id = gr.update(value=None) | |
| paper_from = gr.update(value=None) | |
| tab_chat_paper = gr.update(visible=True) | |
| selected_tab = gr.Tabs() | |
| try: | |
| # Parse the HTML content | |
| soup = BeautifulSoup(evt.value, "html.parser") | |
| # Find all <a> tags | |
| a_tags = soup.find_all('a') | |
| for a_tag in a_tags: | |
| # Check if 'action_id' attribute exists and equals 'chat-with-paper' | |
| if a_tag.get('action_id') == 'chat-with-paper': | |
| paper_id = a_tag.get("paper_id") | |
| paper_from = a_tag.get("paper_from") | |
| tab_chat_paper = gr.update(visible=True) | |
| selected_tab = gr.Tabs(selected="tab-chat-with-paper") | |
| except Exception as e: | |
| print("The content is not valid HTML or another error occurred:", str(e)) | |
| pass | |
| return paper_id, paper_from, tab_chat_paper, selected_tab | |
| paper_central_component.select(get_selected, inputs=[paper_central_component], | |
| outputs=[arxiv_id, paper_from, tab_chat_paper, tabs]) | |
| # Define function to move to the next day | |
| def go_to_next_day( | |
| date: Union[str, datetime], | |
| cat_options_list: List[str], | |
| hf_options_list: List[str], | |
| conference_options_list: List[str], | |
| author_search_input: str, | |
| title_search_input: str, | |
| date_range_option: Optional[str], | |
| ) -> tuple: | |
| """ | |
| Moves the selected date to the next day and updates the data. | |
| Returns: | |
| tuple: The new date as a string and the updated Dataframe component. | |
| """ | |
| date_range_update = gr.update(value=None) | |
| # Ensure the date is in string format | |
| if isinstance(date, datetime): | |
| date_str = date.strftime('%Y-%m-%d') | |
| else: | |
| date_str = date | |
| # Parse the date string and add one day | |
| new_date = datetime.strptime(date_str, '%Y-%m-%d') + timedelta(days=1) | |
| new_date_str = new_date.strftime('%Y-%m-%d') | |
| # Update the Dataframe | |
| updated_data = paper_central_df.filter( | |
| selected_date=new_date_str, | |
| cat_options=cat_options_list, | |
| hf_options=hf_options_list, | |
| conference_options=conference_options_list, | |
| author_search_input=author_search_input, | |
| title_search_input=title_search_input, | |
| date_range_option=date_range_option, | |
| ) | |
| # Return the new date and updated Dataframe | |
| return new_date_str, updated_data, date_range_update | |
| # Define function to move to the previous day | |
| def go_to_previous_day( | |
| date: Union[str, datetime], | |
| cat_options_list: List[str], | |
| hf_options_list: List[str], | |
| conference_options_list: List[str], | |
| author_search_input: str, | |
| title_search_input: str, | |
| date_range_option: Optional[str], | |
| ) -> tuple: | |
| """ | |
| Moves the selected date to the previous day and updates the data. | |
| Returns: | |
| tuple: The new date as a string and the updated Dataframe component. | |
| """ | |
| # If date_range_option is selected, do nothing | |
| date_range_update = gr.update(value=None) | |
| # Ensure the date is in string format | |
| if isinstance(date, datetime): | |
| date_str = date.strftime('%Y-%m-%d') | |
| else: | |
| date_str = date | |
| # Parse the date string and subtract one day | |
| new_date = datetime.strptime(date_str, '%Y-%m-%d') - timedelta(days=1) | |
| new_date_str = new_date.strftime('%Y-%m-%d') | |
| # Update the Dataframe | |
| updated_data = paper_central_df.filter( | |
| selected_date=new_date_str, | |
| cat_options=cat_options_list, | |
| hf_options=hf_options_list, | |
| conference_options=conference_options_list, | |
| author_search_input=author_search_input, | |
| title_search_input=title_search_input, | |
| date_range_option=date_range_option, | |
| ) | |
| # Return the new date and updated Dataframe | |
| return new_date_str, updated_data, date_range_update | |
| # Define function to update data when date or options change | |
| def update_data( | |
| date: Union[str, datetime], | |
| cat_options_list: List[str], | |
| hf_options_list: List[str], | |
| conference_options_list: List[str], | |
| author_search_input: str, | |
| title_search_input: str, | |
| date_range_option: Optional[str], | |
| ): | |
| """ | |
| Updates the data displayed in the Dataframe based on the selected date and options. | |
| """ | |
| return paper_central_df.filter( | |
| selected_date=date, | |
| cat_options=cat_options_list, | |
| hf_options=hf_options_list, | |
| conference_options=conference_options_list, | |
| author_search_input=author_search_input, | |
| title_search_input=title_search_input, | |
| date_range_option=date_range_option, | |
| ) | |
| # Function to handle conference options change | |
| def on_conference_options_change( | |
| date: Union[str, datetime], | |
| cat_options_list: List[str], | |
| hf_options_list: List[str], | |
| conference_options_list: List[str], | |
| author_search_input: str, | |
| title_search_input: str, | |
| date_range_option: Optional[str], | |
| ): | |
| cat_options_update = gr.update() | |
| paper_central_component_update = gr.update() | |
| visible = True | |
| # Some conference options are selected | |
| # Update cat_options to empty list | |
| if conference_options_list: | |
| cat_options_update = gr.update(value=[]) | |
| paper_central_component_update = update_data( | |
| date, | |
| [], | |
| hf_options_list, | |
| conference_options_list, | |
| author_search_input, | |
| title_search_input, | |
| None, | |
| ) | |
| visible = False | |
| calendar_update = gr.update(visible=visible) | |
| next_day_btn_update = gr.update(visible=visible) | |
| prev_day_btn_update = gr.update(visible=visible) | |
| date_range_option_update = gr.update(visible=visible, value=None) | |
| return paper_central_component_update, cat_options_update, calendar_update, next_day_btn_update, prev_day_btn_update, date_range_option_update | |
| # Function to handle category options change | |
| def on_cat_options_change( | |
| date: Union[str, datetime], | |
| cat_options_list: List[str], | |
| hf_options_list: List[str], | |
| conference_options_list: List[str], | |
| author_search_input: str, | |
| title_search_input: str, | |
| date_range_option: Optional[str], | |
| ): | |
| conference_options_update = gr.update() | |
| paper_central_component_update = gr.update() | |
| visible = False | |
| # Some category options are selected | |
| # Update conference_options to empty list | |
| if cat_options_list: | |
| conference_options_update = gr.update(value=[]) | |
| paper_central_component_update = update_data( | |
| date, | |
| cat_options_list, | |
| hf_options_list, | |
| [], | |
| author_search_input, | |
| title_search_input, | |
| date_range_option, | |
| ) | |
| visible = True | |
| calendar_update = gr.update(visible=visible) | |
| next_day_btn_update = gr.update(visible=visible) | |
| prev_day_btn_update = gr.update(visible=visible) | |
| date_range_option_update = gr.update(visible=visible) | |
| return paper_central_component_update, conference_options_update, calendar_update, next_day_btn_update, prev_day_btn_update, date_range_option_update | |
| # Include date_range_radio in the inputs | |
| inputs = [ | |
| calendar, | |
| cat_options, | |
| hf_options, | |
| conference_options, | |
| author_search, | |
| title_search, | |
| date_range_radio, | |
| ] | |
| # Set up the event listener for the author search | |
| author_search.submit( | |
| fn=update_data, | |
| inputs=inputs, | |
| outputs=paper_central_component, | |
| api_name=False | |
| ) | |
| title_search.submit( | |
| fn=update_data, | |
| inputs=inputs, | |
| outputs=paper_central_component, | |
| api_name=False | |
| ) | |
| # Set up the event listener for the 'Next Day' button | |
| next_day_btn.click( | |
| fn=go_to_next_day, | |
| inputs=inputs, | |
| outputs=[calendar, paper_central_component, date_range_radio], | |
| api_name=False | |
| ) | |
| # Set up the event listener for the 'Previous Day' button | |
| prev_day_btn.click( | |
| fn=go_to_previous_day, | |
| inputs=inputs, | |
| outputs=[calendar, paper_central_component, date_range_radio], | |
| api_name=False | |
| ) | |
| # Set up the event listener for the calendar date change | |
| calendar.change( | |
| fn=update_data, | |
| inputs=inputs, | |
| outputs=paper_central_component, | |
| api_name=False | |
| ) | |
| # Set up the event listener for the Hugging Face options change | |
| hf_options.change( | |
| fn=update_data, | |
| inputs=inputs, | |
| outputs=paper_central_component, | |
| api_name=False | |
| ) | |
| # Event chaining for conference options change | |
| conference_options.change( | |
| fn=on_conference_options_change, | |
| inputs=inputs, | |
| outputs=[paper_central_component, cat_options, calendar, next_day_btn, prev_day_btn, date_range_radio], | |
| api_name=False | |
| ) | |
| # Event chaining for category options change | |
| cat_options.change( | |
| fn=on_cat_options_change, | |
| inputs=inputs, | |
| outputs=[paper_central_component, conference_options, calendar, next_day_btn, prev_day_btn, date_range_radio], | |
| api_name=False | |
| ) | |
| # Set up the event listener for the date range radio button change | |
| date_range_radio.change( | |
| fn=update_data, | |
| inputs=inputs, | |
| outputs=paper_central_component, | |
| api_name=False | |
| ) | |
| # Load the initial data when the app starts | |
| request = gr.Request() | |
| def echo(request: gr.Request): | |
| """ | |
| Echoes the input text and prints request details. | |
| Args: | |
| text (str): The input text from the user. | |
| request (gr.Request): The HTTP request object. | |
| Returns: | |
| str: The echoed text. | |
| """ | |
| calendar = gr.update(datetime.today().strftime('%Y-%m-%d')) | |
| date_range = gr.update(value=None) | |
| conferences = gr.update(value=[]) | |
| hf_options = gr.update(value=[]) | |
| selected_tab = gr.Tabs() | |
| paper_id = gr.update(value=None) | |
| paper_from = gr.update(value=None) | |
| tab_chat_paper = gr.update(visible=True) | |
| if request: | |
| # print("Request headers dictionary:", dict(request.headers)) | |
| # print("IP address:", request.client.host) | |
| # print("Query parameters:", dict(request.query_params)) | |
| # print("Session hash:", request.session_hash) | |
| if 'date' in request.query_params: | |
| calendar = gr.update(value=request.query_params['date']) | |
| if 'date_range' in request.query_params: | |
| date_range = gr.update(value=request.query_params['date_range']) | |
| if 'conferences' in request.query_params: | |
| conferences = request.query_params['conferences'] | |
| try: | |
| conferences = [value for value in conferences.split(',')] | |
| except ValueError: | |
| conferences = [] | |
| conferences = gr.update(value=conferences) | |
| if "hf_options" in request.query_params: | |
| hf_options = request.query_params['hf_options'] | |
| try: | |
| hf_options = [value for value in hf_options.split(',')] | |
| except ValueError: | |
| hf_options = [] | |
| hf_options = gr.update(value=hf_options) | |
| if "paper_id" in request.query_params: | |
| paper_id = request.query_params['paper_id'] | |
| paper_from = request.query_params['paper_from'] | |
| # if "tab" in request.query_params: | |
| # tab = request.query_params['tab'] | |
| # if tab == "tab-leaderboards": | |
| # selected_tab = gr.Tabs(selected="tab-leaderboards") | |
| # elif tab == "tab-chat-with-paper": | |
| # selected_tab = gr.Tabs(selected="tab-chat-with-paper") | |
| # if "paper_id" in request.query_params: | |
| # paper_id = request.query_params['paper_id'] | |
| # tab_chat_paper = gr.update(visible=True) | |
| # paper_from = request.query_params['paper_from'] | |
| return calendar, date_range, conferences, hf_options, selected_tab, paper_id, paper_from, tab_chat_paper | |
| demo.load( | |
| fn=update_data, | |
| inputs=inputs, | |
| outputs=paper_central_component, | |
| api_name="update_data", | |
| ).then( | |
| fn=echo, | |
| outputs=[calendar, date_range_radio, conference_options, hf_options, tabs, arxiv_id, paper_from, | |
| tab_chat_paper], | |
| api_name=False, | |
| ).then( | |
| # New then to handle LoginButton and HTML components | |
| fn=logging_flow, | |
| outputs=[login_button, user_info_md], | |
| api_name=False, | |
| ) | |
| # Define the main function to launch the app | |
| def main(): | |
| """ | |
| Launches the Gradio app. | |
| """ | |
| demo.launch(ssr_mode=False, share=True) | |
| # Run the main function when the script is executed | |
| if __name__ == "__main__": | |
| main() | |