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