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() | |