Spaces:
Running on Zero
Running on Zero
zhiyi commited on
Commit ·
ea4f5df
1
Parent(s): e10073b
Retry slow arXiv and PDF requests
Browse files
app.py
CHANGED
|
@@ -5,6 +5,7 @@ import io
|
|
| 5 |
import json
|
| 6 |
import os
|
| 7 |
import re
|
|
|
|
| 8 |
import uuid
|
| 9 |
import zipfile
|
| 10 |
from datetime import datetime, timezone
|
|
@@ -54,6 +55,33 @@ def safe_slug(value: str) -> str:
|
|
| 54 |
return (slug or "algorithm-topic")[:64]
|
| 55 |
|
| 56 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 57 |
def arxiv_search(topic: str, limit: int) -> list[dict[str, Any]]:
|
| 58 |
query = quote_plus(f'all:"{topic}"')
|
| 59 |
url = (
|
|
@@ -62,9 +90,7 @@ def arxiv_search(topic: str, limit: int) -> list[dict[str, Any]]:
|
|
| 62 |
"&sortBy=submittedDate&sortOrder=descending"
|
| 63 |
)
|
| 64 |
headers = {"User-Agent": f"algorithm-research-deck/1.0 ({os.getenv('CONTACT_EMAIL', 'contact-not-set')})"}
|
| 65 |
-
|
| 66 |
-
response = client.get(url)
|
| 67 |
-
response.raise_for_status()
|
| 68 |
ns = {"a": "http://www.w3.org/2005/Atom"}
|
| 69 |
root = ElementTree.fromstring(response.text)
|
| 70 |
papers = []
|
|
@@ -167,11 +193,9 @@ def select_papers(request: ResearchRequest, papers: list[dict[str, Any]], screen
|
|
| 167 |
|
| 168 |
|
| 169 |
def extract_pdf(paper: dict[str, Any], max_chars: int = 14000) -> str:
|
| 170 |
-
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
if len(response.content) > 20 * 1024 * 1024:
|
| 174 |
-
return "PDF omitted because it exceeds the 20 MB limit."
|
| 175 |
reader = PdfReader(io.BytesIO(response.content))
|
| 176 |
pages = []
|
| 177 |
indexes = list(range(min(8, len(reader.pages))))
|
|
@@ -304,7 +328,14 @@ def run_research_ui(
|
|
| 304 |
)
|
| 305 |
budget = DEPTHS[request.depth]
|
| 306 |
progress(0.08, desc="正在检索 arXiv")
|
| 307 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 308 |
if not papers:
|
| 309 |
raise gr.Error("没有检索到论文,请尝试英文关键词或提供 arXiv 链接。")
|
| 310 |
screen = papers[: budget["screen"]]
|
|
|
|
| 5 |
import json
|
| 6 |
import os
|
| 7 |
import re
|
| 8 |
+
import time
|
| 9 |
import uuid
|
| 10 |
import zipfile
|
| 11 |
from datetime import datetime, timezone
|
|
|
|
| 55 |
return (slug or "algorithm-topic")[:64]
|
| 56 |
|
| 57 |
|
| 58 |
+
def http_get_with_retries(
|
| 59 |
+
url: str,
|
| 60 |
+
*,
|
| 61 |
+
headers: dict[str, str] | None = None,
|
| 62 |
+
read_timeout: float = 90,
|
| 63 |
+
attempts: int = 3,
|
| 64 |
+
) -> httpx.Response:
|
| 65 |
+
last_error: Exception | None = None
|
| 66 |
+
timeout = httpx.Timeout(connect=20, read=read_timeout, write=30, pool=30)
|
| 67 |
+
for attempt in range(attempts):
|
| 68 |
+
try:
|
| 69 |
+
with httpx.Client(
|
| 70 |
+
timeout=timeout,
|
| 71 |
+
follow_redirects=True,
|
| 72 |
+
headers=headers,
|
| 73 |
+
http2=False,
|
| 74 |
+
) as client:
|
| 75 |
+
response = client.get(url)
|
| 76 |
+
response.raise_for_status()
|
| 77 |
+
return response
|
| 78 |
+
except (httpx.TimeoutException, httpx.NetworkError, httpx.RemoteProtocolError) as exc:
|
| 79 |
+
last_error = exc
|
| 80 |
+
if attempt + 1 < attempts:
|
| 81 |
+
time.sleep(2 + attempt * 3)
|
| 82 |
+
raise RuntimeError(f"External source did not respond after {attempts} attempts: {url}") from last_error
|
| 83 |
+
|
| 84 |
+
|
| 85 |
def arxiv_search(topic: str, limit: int) -> list[dict[str, Any]]:
|
| 86 |
query = quote_plus(f'all:"{topic}"')
|
| 87 |
url = (
|
|
|
|
| 90 |
"&sortBy=submittedDate&sortOrder=descending"
|
| 91 |
)
|
| 92 |
headers = {"User-Agent": f"algorithm-research-deck/1.0 ({os.getenv('CONTACT_EMAIL', 'contact-not-set')})"}
|
| 93 |
+
response = http_get_with_retries(url, headers=headers, read_timeout=90, attempts=3)
|
|
|
|
|
|
|
| 94 |
ns = {"a": "http://www.w3.org/2005/Atom"}
|
| 95 |
root = ElementTree.fromstring(response.text)
|
| 96 |
papers = []
|
|
|
|
| 193 |
|
| 194 |
|
| 195 |
def extract_pdf(paper: dict[str, Any], max_chars: int = 14000) -> str:
|
| 196 |
+
response = http_get_with_retries(paper["pdf_url"], read_timeout=120, attempts=3)
|
| 197 |
+
if len(response.content) > 20 * 1024 * 1024:
|
| 198 |
+
return "PDF omitted because it exceeds the 20 MB limit."
|
|
|
|
|
|
|
| 199 |
reader = PdfReader(io.BytesIO(response.content))
|
| 200 |
pages = []
|
| 201 |
indexes = list(range(min(8, len(reader.pages))))
|
|
|
|
| 328 |
)
|
| 329 |
budget = DEPTHS[request.depth]
|
| 330 |
progress(0.08, desc="正在检索 arXiv")
|
| 331 |
+
user_papers = normalize_user_papers(request.paper_urls)
|
| 332 |
+
try:
|
| 333 |
+
discovered_papers = arxiv_search(request.topic, budget["discover"])
|
| 334 |
+
except Exception as exc:
|
| 335 |
+
if not user_papers:
|
| 336 |
+
raise gr.Error(f"arXiv 连续三次请求超时。请稍后重试,或填写至少一个 arXiv 论文链接。详情:{exc}") from exc
|
| 337 |
+
discovered_papers = []
|
| 338 |
+
papers = deduplicate(user_papers + discovered_papers)
|
| 339 |
if not papers:
|
| 340 |
raise gr.Error("没有检索到论文,请尝试英文关键词或提供 arXiv 链接。")
|
| 341 |
screen = papers[: budget["screen"]]
|