paper_reader.py 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. """论文阅读助手 API 路由 —— PDF 打开、AI 导读、对话问答与阅读历史."""
  2. import logging
  3. from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException, Query
  4. from ...models.schemas import (
  5. PaperReaderChatRequest,
  6. PaperReaderChatResponse,
  7. PaperReaderHistoryItem,
  8. PaperReaderHistoryResponse,
  9. PaperReaderOpeningRequest,
  10. PaperReaderOpeningResponse,
  11. )
  12. from ..dependencies import get_database
  13. from ...utils.common import safe_http_500
  14. from ...services.reader.paper_reader_service import PaperReaderService
  15. logger = logging.getLogger(__name__)
  16. router = APIRouter(prefix="/ai", tags=["AI 分析"])
  17. def get_paper_reader_service() -> PaperReaderService:
  18. db = get_database()
  19. return PaperReaderService(db=db)
  20. # 首次打开论文 → 生成 AI 导读和结构化摘要
  21. @router.post("/paper-reader/opening", response_model=PaperReaderOpeningResponse)
  22. async def paper_reader_opening(
  23. body: PaperReaderOpeningRequest,
  24. background_tasks: BackgroundTasks,
  25. service: PaperReaderService = Depends(get_paper_reader_service),
  26. ):
  27. try:
  28. result = await service.get_opening(paper_id=int(body.paper_id), background_tasks=background_tasks)
  29. return PaperReaderOpeningResponse(success=True, **result)
  30. except HTTPException:
  31. raise
  32. except Exception as e:
  33. raise safe_http_500("paper_reader_opening", e)
  34. # 论文对话:基于 PDF 全文 + 参考文献上下文的问答
  35. @router.post("/paper-reader/chat", response_model=PaperReaderChatResponse)
  36. async def paper_reader_chat(
  37. body: PaperReaderChatRequest,
  38. background_tasks: BackgroundTasks,
  39. service: PaperReaderService = Depends(get_paper_reader_service),
  40. ):
  41. try:
  42. out = await service.process_chat(
  43. paper_id=int(body.paper_id),
  44. messages=list(body.messages or []),
  45. user_message=body.user_message,
  46. background_tasks=background_tasks,
  47. )
  48. return PaperReaderChatResponse(
  49. success=True,
  50. reply=str(out.get("reply") or "").strip(),
  51. pdf_parsing=bool(out.get("pdf_parsing", False)),
  52. related_papers=list(out.get("related_papers") or []),
  53. related_hints=list(out.get("related_hints") or []),
  54. kg_edges=list(out.get("kg_edges") or []),
  55. )
  56. except HTTPException:
  57. raise
  58. except Exception as e:
  59. raise safe_http_500("paper_reader_chat", e)
  60. @router.get("/paper-reader/history", response_model=PaperReaderHistoryResponse)
  61. async def paper_reader_history(
  62. paper_id: int = Query(..., ge=1),
  63. limit: int = Query(default=200, ge=1, le=1000),
  64. service: PaperReaderService = Depends(get_paper_reader_service),
  65. ):
  66. try:
  67. turns = await service.get_history(paper_id=int(paper_id), limit=int(limit))
  68. return PaperReaderHistoryResponse(
  69. success=True,
  70. paper_id=int(paper_id),
  71. turns=[PaperReaderHistoryItem(**t) for t in turns],
  72. )
  73. except HTTPException:
  74. raise
  75. except Exception as e:
  76. raise safe_http_500("paper_reader_history", e)