papers.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. """
  2. 论文相关API路由
  3. """
  4. from fastapi import APIRouter, HTTPException, Depends, Query, UploadFile, File
  5. from typing import List, Optional, Dict, Any
  6. from pydantic import BaseModel
  7. import logging
  8. import arxiv
  9. from datetime import datetime
  10. logger = logging.getLogger(__name__)
  11. router = APIRouter()
  12. # Pydantic模型
  13. class PaperSearchRequest(BaseModel):
  14. keywords: str
  15. source: str = "arxiv"
  16. limit: int = 10
  17. class PaperResponse(BaseModel):
  18. id: str
  19. title: str
  20. authors: List[str]
  21. abstract: str
  22. url: str
  23. published_date: str
  24. @router.post("/search", response_model=Dict[str, Any])
  25. async def search_papers(request: PaperSearchRequest):
  26. """搜索论文 - 使用真实的 ArXiv API"""
  27. try:
  28. papers = []
  29. if request.source == "arxiv" or request.source == "all":
  30. # 使用 ArXiv API 搜索
  31. logger.info(f"正在搜索 ArXiv: {request.keywords}")
  32. # 构建搜索查询
  33. search = arxiv.Search(
  34. query=request.keywords,
  35. max_results=request.limit,
  36. sort_by=arxiv.SortCriterion.SubmittedDate,
  37. sort_order=arxiv.SortOrder.Descending
  38. )
  39. # 获取搜索结果
  40. for result in search.results():
  41. paper = {
  42. "id": result.entry_id.split('/')[-1],
  43. "title": result.title,
  44. "authors": [author.name for author in result.authors],
  45. "abstract": result.summary.replace('\n', ' ').strip(),
  46. "url": result.entry_id,
  47. "published_date": result.published.strftime("%Y-%m-%d"),
  48. "pdf_url": result.pdf_url,
  49. "categories": result.categories,
  50. "primary_category": result.primary_category
  51. }
  52. papers.append(paper)
  53. logger.info(f"找到 {len(papers)} 篇论文")
  54. # 如果没有找到结果,返回提示
  55. if not papers:
  56. return {
  57. "success": True,
  58. "papers": [],
  59. "total_found": 0,
  60. "keywords": request.keywords,
  61. "source": request.source,
  62. "message": "未找到相关论文,请尝试其他关键词"
  63. }
  64. return {
  65. "success": True,
  66. "papers": papers,
  67. "total_found": len(papers),
  68. "keywords": request.keywords,
  69. "source": request.source
  70. }
  71. except Exception as e:
  72. logger.error(f"论文搜索失败: {str(e)}")
  73. raise HTTPException(status_code=500, detail=f"搜索失败: {str(e)}")
  74. @router.post("/upload", response_model=Dict[str, Any])
  75. async def upload_paper(file: UploadFile = File(...)):
  76. """上传论文PDF"""
  77. try:
  78. # 检查文件类型
  79. if not file.filename.endswith('.pdf'):
  80. raise HTTPException(status_code=400, detail="只支持PDF文件")
  81. # 模拟文件上传
  82. file_url = f"/uploads/{file.filename}"
  83. return {
  84. "success": True,
  85. "file_url": file_url,
  86. "filename": file.filename,
  87. "size": getattr(file, 'size', 0),
  88. "message": "文件上传成功"
  89. }
  90. except Exception as e:
  91. logger.error(f"文件上传失败: {str(e)}")
  92. raise HTTPException(status_code=500, detail=f"上传失败: {str(e)}")