import gradio as gr
import requests
from datetime import datetime, timezone
API_URL = "https://huggingface.co/api/daily_papers"
class PaperManager:
def __init__(self, papers_per_page=10):
self.papers_per_page = papers_per_page
def fetch_papers(self, page=1):
try:
response = requests.get(f"{API_URL}?page={page}&limit={self.papers_per_page}")
response.raise_for_status()
data = response.json()
papers = sorted(data, key=lambda x: x.get('paper', {}).get('upvotes', 0), reverse=True)
# Update total_pages based on the 'X-Total-Pages' header if available
total_pages = int(response.headers.get('X-Total-Pages', 1))
return papers, total_pages
except requests.RequestException as e:
print(f"Error fetching papers: {e}")
return None, 1
def format_paper(self, paper):
title = paper.get('title', 'No title')
url = f"https://huggingface.co/papers/{paper['paper'].get('id', '')}"
authors = ', '.join([author.get('name', '') for author in paper['paper'].get('authors', [])])
upvotes = paper.get('paper', {}).get('upvotes', 0)
comments = paper.get('numComments', 0)
published_time = datetime.fromisoformat(
paper.get('publishedAt', datetime.now(timezone.utc).isoformat()).replace('Z', '+00:00')
)
time_ago = (datetime.now(timezone.utc) - published_time).days
return f"""
{title}
{upvotes} upvotes | by {authors} | {time_ago} days ago | {comments} comments
"""
def render_papers(self, papers):
if not papers:
return "No papers available for this page.
"
return "".join([self.format_paper(paper) for paper in papers])
def search_papers(self, papers, query):
if not query:
return self.render_papers(papers)
filtered_papers = [paper for paper in papers if query.lower() in paper.get('title', '').lower()]
return self.render_papers(filtered_papers)
css = """
html, body {
height: 100%;
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
background-color: #f0f0f0;
}
.container {
font-family: Arial, sans-serif;
max-width: 800px;
width: 100%;
background-color: white;
padding: 20px;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
}
.paper-list {
max-height: 400px;
overflow-y: auto;
border: 1px solid #eee;
border-radius: 5px;
padding: 10px;
margin-bottom: 10px;
}
.search-row {
display: flex;
gap: 10px;
margin-bottom: 20px;
}
.title {
text-align: center;
color: #333;
}
.footer {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 10px;
}
"""
paper_manager = PaperManager()
def initialize():
papers, total_pages = paper_manager.fetch_papers(page=1)
html = paper_manager.render_papers(papers)
return html, 1, total_pages, papers # paper_list, current_page, total_pages, papers
def refresh_papers(current_page, query):
papers, total_pages = paper_manager.fetch_papers(page=1)
if query:
html = paper_manager.search_papers(papers, query)
else:
html = paper_manager.render_papers(papers)
return html, 1, total_pages, papers
def search_papers(query, papers):
html = paper_manager.search_papers(papers, query)
return html
def change_page(direction, current_page, total_pages, papers, query):
if direction == "next" and current_page < total_pages:
new_page = current_page + 1
elif direction == "prev" and current_page > 1:
new_page = current_page - 1
else:
new_page = current_page # No change if limits are reached
papers, total_pages = paper_manager.fetch_papers(page=new_page)
if query:
html = paper_manager.search_papers(papers, query)
else:
html = paper_manager.render_papers(papers)
return html, new_page, total_pages, papers
demo = gr.Blocks(css=css)
with demo:
with gr.Column(elem_classes=["container"]):
gr.Markdown("# Daily Papers - HackerNews Style", elem_classes=["title"])
with gr.Row(elem_classes=["search-row"]):
search_input = gr.Textbox(label="Search papers", placeholder="Enter search term...")
refresh_button = gr.Button("Refresh")
paper_list = gr.HTML(elem_classes=["paper-list"])
with gr.Row(elem_classes=["footer"]):
prev_button = gr.Button("Previous Page")
page_info = gr.Markdown("Page 1 of 1")
next_button = gr.Button("Next Page")
# Hidden states
current_page_state = gr.State(1)
total_pages_state = gr.State(1)
papers_state = gr.State([])
# Initialize the app
demo.load(initialize, outputs=[paper_list, current_page_state, total_pages_state, papers_state])
# Search functionality
search_input.submit(search_papers, inputs=[search_input, papers_state], outputs=[paper_list])
search_input.change(search_papers, inputs=[search_input, papers_state], outputs=[paper_list])
# Refresh functionality
refresh_button.click(refresh_papers,
inputs=[current_page_state, search_input],
outputs=[paper_list, current_page_state, total_pages_state, papers_state])
# Previous Page
prev_button.click(change_page,
inputs=["prev", current_page_state, total_pages_state, papers_state, search_input],
outputs=[paper_list, current_page_state, total_pages_state, papers_state])
# Next Page
next_button.click(change_page,
inputs=["next", current_page_state, total_pages_state, papers_state, search_input],
outputs=[paper_list, current_page_state, total_pages_state, papers_state])
demo.launch()