pipeline_runtime.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. """Pipeline 运行时配置 — 集中读取 settings,减少 pipeline 噪音。"""
  2. from __future__ import annotations
  3. from dataclasses import dataclass
  4. from typing import Any
  5. from .plan_helpers import effective_max_results, is_pinned_single_year
  6. from .search_plan import ResolvedSearchPlan
  7. @dataclass(frozen=True)
  8. class SearchRuntimeConfig:
  9. max_results: int
  10. recall_max: int
  11. recall_cap: int
  12. recall_wall: float
  13. rank_wall: float
  14. arxiv_fallback_wall: float
  15. proc_min: int
  16. proc_enabled: bool
  17. http_timeout_sec: float
  18. http_max_attempts: int
  19. openalex_timeout_sec: float
  20. dblp_timeout_sec: float | None = None
  21. @classmethod
  22. def from_settings(
  23. cls,
  24. settings: Any,
  25. plan: ResolvedSearchPlan,
  26. max_results: int | None = None,
  27. ) -> "SearchRuntimeConfig":
  28. mr = max(int(max_results or getattr(plan, "max_results", None) or 10), 5)
  29. mr = effective_max_results(plan, mr)
  30. recall_max = int(plan.recall_max_candidates or 24)
  31. try:
  32. recall_cap_setting = int(settings.papergraph_recall_max_candidates)
  33. except (TypeError, ValueError):
  34. recall_cap_setting = 24
  35. recall_cap = max(mr + 4, min(60, recall_cap_setting, recall_max))
  36. recall_wall = max(
  37. 10.0, min(180.0, float(getattr(settings, "papergraph_search_recall_wall_sec", 42.0)))
  38. )
  39. venue = (plan.venues[0] if plan.venues else None) or None
  40. if is_pinned_single_year(plan) and venue:
  41. recall_wall = max(recall_wall, 75.0)
  42. rank_wall = max(
  43. 10.0, min(120.0, float(getattr(settings, "papergraph_fine_rank_pipeline_wall_sec", 25.0)))
  44. )
  45. arxiv_fb_wall = max(
  46. 3.0,
  47. min(90.0, float(getattr(settings, "papergraph_search_arxiv_fallback_wall_sec", 15.0))),
  48. )
  49. try:
  50. proc_min = int(getattr(settings, "papergraph_proceedings_supplement_min_candidates", 8) or 8)
  51. except (TypeError, ValueError):
  52. proc_min = 8
  53. proc_enabled = bool(getattr(settings, "papergraph_proceedings_supplement_enabled", True))
  54. http_timeout = max(
  55. 2.0, min(60.0, float(getattr(settings, "papergraph_search_recall_http_timeout_sec", 12.0)))
  56. )
  57. try:
  58. http_max_attempts = int(settings.papergraph_search_http_max_attempts)
  59. except (TypeError, ValueError):
  60. http_max_attempts = 2
  61. http_max_attempts = max(1, min(3, http_max_attempts))
  62. openalex_timeout = 18.0
  63. dblp_timeout: float | None = None
  64. if is_pinned_single_year(plan) and venue:
  65. dblp_timeout = 55.0
  66. openalex_timeout = 45.0
  67. return cls(
  68. max_results=mr,
  69. recall_max=recall_max,
  70. recall_cap=recall_cap,
  71. recall_wall=recall_wall,
  72. rank_wall=rank_wall,
  73. arxiv_fallback_wall=arxiv_fb_wall,
  74. proc_min=proc_min,
  75. proc_enabled=proc_enabled,
  76. http_timeout_sec=http_timeout,
  77. http_max_attempts=http_max_attempts,
  78. openalex_timeout_sec=openalex_timeout,
  79. dblp_timeout_sec=dblp_timeout,
  80. )
  81. def execution_kwargs(self) -> dict[str, Any]:
  82. """HTTP/超时等执行参数,不混入用户约束。"""
  83. out: dict[str, Any] = {
  84. "http_timeout_sec": self.http_timeout_sec,
  85. "http_max_attempts": self.http_max_attempts,
  86. "openalex_timeout_sec": self.openalex_timeout_sec,
  87. }
  88. if self.dblp_timeout_sec is not None:
  89. out["dblp_timeout_sec"] = self.dblp_timeout_sec
  90. return out