from pathlib import Path import gradio as gr from datetime import datetime, timedelta from fetch_paper import fetch_papers_with_daterange from sorter import sort_by_upvotes, sort_by_comments, sort_by_date from date import Date import assets def format_author(author): """Format author information""" if not author: return "" hidden_status = " (hidden)" if author.hidden else "" if author.name: return f"<a href='https://scholar.google.com/citations?view_op=search_authors&mauthors={author.name.replace(' ', '+')}' target='_blank'>{author.name}</a>" return "Anonymous author" # 底部论文介绍 def format_paper_info(article): """Generate HTML content for paper display""" if not article.paper: return "Paper information missing" info = [] # Title section info.append(f"<h2 class='sf-paper-title' id='sf-flag'>{article.title or 'Untitled Paper'}</h2>") info.append(f"<p style='text-align: center'>") info.append(f"<a href='https://huggingface.co/papers/{article.paper.id}' target='_blank' class='sf-button'>Hugging Face{assets.SVG_LINK}</a>") info.append(f"<a href='https://arxiv.org/abs/{article.paper.id}' target='_blank' class='sf-button'>arXiv{assets.SVG_LINK}</a>") info.append(f"<a href='https://arxiv.org/pdf/{article.paper.id}' target='_blank' class='sf-button'>PDF{assets.SVG_LINK}</a>") info.append(f"</p>") # Thumbnail if article.thumbnail: info.append(f"<p><img src='{article.thumbnail}' style='max-width: 30em; width: 100%; margin: auto'/></p>") # Basic information info.append( f"<p><strong>Paper ID</strong>: <a href='https://huggingface.co/papers/{article.paper.id}' target='_blank'>{article.paper.id or 'Unknown'}</a></p>") info.append( f"<p><strong>Published At</strong>: {article.paper.publishedAt.strftime('%Y-%m-%d %H:%M') if article.paper.publishedAt else 'Unknown'}</p>") # Author information authors = ", ".join([format_author(a) for a in article.paper.authors]) if article.paper.authors else "Author information not available" info.append(f"<p><strong>Authors</strong>: {authors}</p>") # Summary if article.paper.summary: summary = article.paper.summary.replace('{{', '{').replace('}}', '}').replace('\n', ' ') info.append(f"<h3>Summary</h3><p>{summary}</p>") # Discussion information info.append(f"<p><strong>Upvotes</strong>: {article.paper.upvotes or 0}<span style='margin-left: .5rem'></span>") info.append(f"<strong>Comments</strong>: {article.numComments or 0}</p>") if article.paper.discussionId: info.append( f"<a href='https://huggingface.co/papers/{article.paper.id}#community' target='_blank' class='sf-button'>Join Discussion{assets.SVG_LINK}</a></p>") # Submitter information if article.submittedBy: submitter = article.submittedBy info.append(f"<hr><p><strong>Submitter</strong>: ") avatar_url = submitter.avatarUrl if submitter.avatarUrl.startswith("http") else f"https://huggingface.co{submitter.avatarUrl}" profile_url = f"https://huggingface.co/{submitter.name}" info.append( f"<span><img src='{avatar_url}' class='sf-author' /></span>{submitter.fullname}(<a href='{profile_url}' target='_blank'>@{submitter.name}</a>) ") info.append(f"Followers: {submitter.followerCount or 0}</p>") return "".join(info) def generate_table_html(papers): """Generate table HTML with clickable titles and an extra column for arXiv abs link""" html = ['<table class="paper-table"><thead><tr>' '<th>Title</th>' '<th>👍 Upvotes</th>' '<th>💬 Comments</th>' '<th>📅 Date</th>' # '<th>Label</th>' '<th></th>' '</tr></thead><tbody>'] for article in papers: title = article.title or "Untitled" upvotes = article.paper.upvotes or 0 comments = article.numComments or 0 date = article.paper.publishedAt.strftime("%Y-%m-%d") if article.paper.publishedAt else "Unknown" paper_id = article.paper.id # label = ", ".join(article.paper.label) or "" # 构造 arXiv abs 链接 arxiv_abs_link = f"https://huggingface.co/papers/{paper_id}" row = f""" <tr> <td><a class="paper-title" href="{arxiv_abs_link}" target="_blank">{title}{assets.SVG_LINK}</a></td> <td>{upvotes}</td> <td>{comments}</td> <td>{date}</td> <td><a href="javascript:void(0)" onclick="showDetail('{paper_id}')" class="sf-button" style="margin: 0">Details{assets.SVG_LINK}</a></td> </tr> """ # <td>{label}</td> html.append(row) html.append("</tbody></table>") return "".join(html) def build_html(papers): # Convert all papers to an HTML string, each paper wrapped in a div, with the div containing the paper's information, and the div's id being the paper's id html = "" for index, article in enumerate(papers): article_html = format_paper_info(article) html += f"<div id='smartflow-paper-{article.paper.id.replace('.', '-')}' style='{'' if index == 0 else 'display: none'}'>{article_html}</div>" return html def query_papers(start_date_str: str, end_date_str: str, sort_method: str): # Added sort_method parameter """Handle date range query""" try: start_date = Date(start_date_str) end_date = Date(end_date_str) papers = fetch_papers_with_daterange(start_date, end_date) # Sort papers based on the selected sorting method if sort_method == "Sort by upvotes ascending": papers = sort_by_upvotes(papers, reverse=False) elif sort_method == "Sort by upvotes descending": papers = sort_by_upvotes(papers, reverse=True) elif sort_method == "Sort by comments ascending": papers = sort_by_comments(papers, reverse=False) elif sort_method == "Sort by comments descending": papers = sort_by_comments(papers, reverse=True) elif sort_method == "Sort by date ascending": papers = sort_by_date(papers, reverse=False) elif sort_method == "Sort by date descending": papers = sort_by_date(papers, reverse=True) # elif sort_method == "Sort by label": # papers = sorted(papers, key=lambda x: ", ".join(x.paper.label)) return generate_table_html(papers), build_html(papers) except Exception as e: print(f"Query error: {e}") return "<p>⚠️ Query failed, please check the date format (YYYY-MM-DD)</p>", "<p>⚠️ Query failed, please check the date format (YYYY-MM-DD)</p>" # CSS 样式(可放入单独文件) custom_css = """ .detail-area { margin-top: 20px; padding: 20px; border: 1px solid #ddd; border-radius: 5px; } .sf-paper-title { text-align: center; } img.sf-author { height: 1.3rem; border: 1px solid #000; vertical-align: middle; border-radius: 50%; display: inline; margin: 0 0.1rem; } #paper-detail-area { display: none; } #paper-detail-area:has(#sf-flag) { display: block; } #query-results-html { min-height: 100px; } """ # 遍历./css文件夹下的所有文件,将文件内容作为CSS样式添加到页面中 for css_file in Path("./css").glob("*.css"): with open(css_file, "r") as f: custom_css += "\n" + f.read() + "\n" custom_js = """""" # 遍历./css文件夹下的所有文件,将文件内容作为CSS样式添加到页面中 for js_file in Path("./js").glob("*.js"): with open(js_file, "r") as f: custom_js += "\n" + f.read() + "\n" def create_interface(): """Create a new interface layout""" with gr.Blocks(title="Hugging Face Daily Paper", css=custom_css, head=f"<script>{custom_js}</script>") as app: # Main interface gr.HTML("<div style='text-align: center'><h1>📚 Hugging Face Weekly Paper</h1></div>") gr.HTML("""<div style='text-align: center'> <span style=""> 🔗 <a href='https://larkcommunity.feishu.cn/wiki/HSSTwsq7JiDur0kJrvjcnFZfnTe'>Contribute to this project</a> </span> <span style="margin-left: 1rem"> Sponsor: <a href='https://internlm.intern-ai.org.cn/api/document'>InternLM</a> </span> </div>""") # Query control area with gr.Row(): with gr.Column(): with gr.Row(): start_date = gr.Textbox(elem_id="start_date", label="Start Date", placeholder="YYYY-MM-DD", value=str(Date() + (-7))) end_date = gr.Textbox(elem_id="end_date", label="End Date", placeholder="YYYY-MM-DD", value=str(Date())) with gr.Column(): with gr.Row(): today_btn = gr.Button("Today") last_week_btn = gr.Button("Last Week") last_month_btn = gr.Button("Last Month") query_btn = gr.Button("🔍 Query", variant="primary", elem_id="query_button") with gr.Row(): # Add sorting method selection sort_method = gr.Radio( label="Sort Method", choices=[ "Sort by upvotes descending", "Sort by comments descending", "Sort by date descending", "Sort by upvotes ascending", "Sort by comments ascending", "Sort by date ascending", # "Sort by label", ], value="Sort by upvotes descending", ) # Results display area with gr.Column(visible=True): results_html = gr.HTML(label="Query Results", elem_id="query-results-html") # Paper details area with gr.Column(visible=True, elem_classes="detail-area", elem_id="paper-detail-area"): gr.Markdown("## Paper Details") detail_html = gr.HTML(elem_id="detail-html") # Event handling query_btn.click( fn=query_papers, inputs=[start_date, end_date, sort_method], outputs=[results_html, detail_html] ) sort_method.change( fn=query_papers, inputs=[start_date, end_date, sort_method], outputs=[results_html, detail_html] ) # Add button event handling today_btn.click( fn=lambda: (str(Date()), str(Date())), outputs=[start_date, end_date] ).then( fn=query_papers, inputs=[start_date, end_date, sort_method], outputs=[results_html, detail_html] ) last_week_btn.click( fn=lambda: (str(Date() + (-7)), str(Date())), outputs=[start_date, end_date] ).then( fn=query_papers, inputs=[start_date, end_date, sort_method], outputs=[results_html, detail_html] ) last_month_btn.click( fn=lambda: (str(Date() + (-30)), str(Date())), outputs=[start_date, end_date] ).then( fn=query_papers, inputs=[start_date, end_date, sort_method], outputs=[results_html, detail_html] ) return app