sciverse 0.6.2__tar.gz → 0.7.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sciverse
3
- Version: 0.6.2
3
+ Version: 0.7.0
4
4
  Summary: Sciverse Agent Tools — OpenAI/Anthropic/LangChain compatible tool schema and async client for Sciverse retrieval APIs
5
5
  Project-URL: Homepage, https://github.com/opendatalab/Sciverse-Agent-Tools
6
6
  Project-URL: Repository, https://github.com/opendatalab/Sciverse-Agent-Tools.git
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "sciverse"
3
- version = "0.6.2"
3
+ version = "0.7.0"
4
4
  description = "Sciverse Agent Tools — OpenAI/Anthropic/LangChain compatible tool schema and async client for Sciverse retrieval APIs"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -142,6 +142,7 @@ def _cmd_search(args: argparse.Namespace) -> int:
142
142
  if args.title_contains: kwargs["title_contains"] = args.title_contains
143
143
  if args.abstract_contains: kwargs["abstract_contains"] = args.abstract_contains
144
144
  if args.sort_by_year != "none": kwargs["sort_by_year"] = args.sort_by_year
145
+ if args.freshness_boost != "NONE": kwargs["freshness_boost"] = args.freshness_boost
145
146
  kwargs["page"] = args.page
146
147
  kwargs["page_size"] = args.page_size
147
148
  r = await client.search_papers(**kwargs)
@@ -252,6 +253,9 @@ def _build_parser() -> argparse.ArgumentParser:
252
253
  search.add_argument("--abstract-contains", dest="abstract_contains", help="摘要包含关键词")
253
254
  search.add_argument("--sort-by-year", choices=["desc", "asc", "none"], default="desc",
254
255
  dest="sort_by_year", help="按年份排序,默认 desc;与 query 同传会冲突")
256
+ search.add_argument("--freshness-boost", choices=["NONE", "MILD", "STRONG"], default="NONE",
257
+ dest="freshness_boost",
258
+ help="模糊搜索新鲜度加权:MILD=近10年加权 / STRONG=近3年加权。仅 query 非空时生效;与 sort-by-year 互斥")
255
259
  search.add_argument("--page", type=int, default=1, help="页码,从 1 开始")
256
260
  search.add_argument("--page-size", type=int, default=10, dest="page_size",
257
261
  help="每页数量,默认 10,上限 50")
@@ -8,12 +8,13 @@ from typing import Any
8
8
 
9
9
  import httpx
10
10
 
11
- _SKILL_NAME = "sciverse"
12
11
  _CHANNEL = "python-sdk"
13
12
  _PLATFORM = platform.system().lower() # "linux" | "darwin" | "windows"
13
+ _SOURCE = f"{_PLATFORM}-{_CHANNEL}"
14
14
 
15
15
 
16
- _PASSTHROUGH = ("query", "page", "page_size", "fields")
16
+ _PASSTHROUGH = ("query", "page", "page_size", "fields", "freshness_boost")
17
+ _FRESHNESS_BOOST_VALUES = frozenset({"NONE", "MILD", "STRONG"})
17
18
 
18
19
 
19
20
  def _to_backend_payload(kwargs: dict[str, Any]) -> dict[str, Any]:
@@ -27,6 +28,13 @@ def _to_backend_payload(kwargs: dict[str, Any]) -> dict[str, Any]:
27
28
  if k in kwargs and kwargs[k] is not None:
28
29
  out[k] = kwargs[k]
29
30
 
31
+ # freshness_boost 校验:枚举值不合法直接报错(在打到后端前)。
32
+ if (boost := out.get("freshness_boost")) is not None:
33
+ if not isinstance(boost, str) or boost not in _FRESHNESS_BOOST_VALUES:
34
+ raise ValueError(
35
+ f"freshness_boost must be one of {sorted(_FRESHNESS_BOOST_VALUES)}, got {boost!r}"
36
+ )
37
+
30
38
  def _filter(field: str, op: str, value: Any) -> None:
31
39
  filters.append({"field": field, "operator": op, "value": value})
32
40
 
@@ -103,7 +111,8 @@ class AgentToolsClient:
103
111
 
104
112
  @staticmethod
105
113
  async def _inject_request_id(request: httpx.Request) -> None:
106
- request.headers["X-Request-Id"] = f"{_SKILL_NAME}-{_PLATFORM}-{_CHANNEL}-{uuid.uuid4()}"
114
+ request.headers["X-Request-Id"] = str(uuid.uuid4())
115
+ request.headers["X-Sciverse-Source"] = _SOURCE
107
116
 
108
117
  async def __aenter__(self) -> "AgentToolsClient":
109
118
  return self
@@ -126,6 +135,9 @@ class AgentToolsClient:
126
135
  - subjects → filter subjects IN
127
136
  - filters_advanced → 直接拼到 filters 列表
128
137
  - sort_by_year → sort publication_published_year DESC/ASC
138
+ - freshness_boost → 模糊搜索新鲜度加权(NONE/MILD/STRONG,默认 NONE)。
139
+ 仅 query 非空时生效;与 sort_by_year 互斥(boost 已在影响排序)。
140
+ MILD: 近 10 年加权,适合日常查文献;STRONG: 近 3 年,适合跟踪研究方向。
129
141
  """
130
142
  body = _to_backend_payload(kwargs)
131
143
  resp = await self._client.post("/meta-search", json=body)
@@ -1,7 +1,7 @@
1
1
  """Auto-generated. Do not edit. Run scripts/build.sh."""
2
2
  import json
3
3
 
4
- TOOLS_VERSION = "0.6.2"
4
+ TOOLS_VERSION = "0.7.0"
5
5
 
6
6
  OPENAI_TOOLS = json.loads(r"""
7
7
  [
@@ -95,6 +95,16 @@ OPENAI_TOOLS = json.loads(r"""
95
95
  ],
96
96
  "default": "desc"
97
97
  },
98
+ "freshness_boost": {
99
+ "type": "string",
100
+ "enum": [
101
+ "NONE",
102
+ "MILD",
103
+ "STRONG"
104
+ ],
105
+ "default": "NONE",
106
+ "description": "模糊搜索新鲜度加权(仅 query 非空时生效;与 sort_by_year 互斥)。\nMILD: 近 10 年加权,适合日常查文献;STRONG: 近 3 年加权,适合跟踪\n研究方向 / 追最新进展。底层为 function_score + gauss decay over\npublication_published_date。\n"
107
+ },
98
108
  "page": {
99
109
  "type": "integer",
100
110
  "default": 1,
@@ -317,6 +327,16 @@ ANTHROPIC_TOOLS = json.loads(r"""
317
327
  ],
318
328
  "default": "desc"
319
329
  },
330
+ "freshness_boost": {
331
+ "type": "string",
332
+ "enum": [
333
+ "NONE",
334
+ "MILD",
335
+ "STRONG"
336
+ ],
337
+ "default": "NONE",
338
+ "description": "模糊搜索新鲜度加权(仅 query 非空时生效;与 sort_by_year 互斥)。\nMILD: 近 10 年加权,适合日常查文献;STRONG: 近 3 年加权,适合跟踪\n研究方向 / 追最新进展。底层为 function_score + gauss decay over\npublication_published_date。\n"
339
+ },
320
340
  "page": {
321
341
  "type": "integer",
322
342
  "default": 1,
@@ -33,6 +33,20 @@ class SortByYear(Enum):
33
33
  none = "none"
34
34
 
35
35
 
36
+ class FreshnessBoost(Enum):
37
+ """
38
+ 模糊搜索新鲜度加权(仅 query 非空时生效;与 sort_by_year 互斥)。
39
+ MILD: 近 10 年加权,适合日常查文献;STRONG: 近 3 年加权,适合跟踪
40
+ 研究方向 / 追最新进展。底层为 function_score + gauss decay over
41
+ publication_published_date。
42
+
43
+ """
44
+
45
+ NONE = "NONE"
46
+ MILD = "MILD"
47
+ STRONG = "STRONG"
48
+
49
+
36
50
  class SearchPapersRequest(BaseModel):
37
51
  query: str | None = Field(
38
52
  None,
@@ -61,6 +75,10 @@ class SearchPapersRequest(BaseModel):
61
75
  None, description="高级过滤逃生舱(仅当上述字段不够用时使用)。"
62
76
  )
63
77
  sort_by_year: SortByYear | None = "desc"
78
+ freshness_boost: FreshnessBoost | None = Field(
79
+ "NONE",
80
+ description="模糊搜索新鲜度加权(仅 query 非空时生效;与 sort_by_year 互斥)。\nMILD: 近 10 年加权,适合日常查文献;STRONG: 近 3 年加权,适合跟踪\n研究方向 / 追最新进展。底层为 function_score + gauss decay over\npublication_published_date。\n",
81
+ )
64
82
  page: int | None = Field(1, ge=1)
65
83
  page_size: int | None = Field(10, ge=1, le=50)
66
84
 
@@ -159,3 +159,25 @@ async def test_search_papers_passthrough_keeps_only_canonical_fields():
159
159
  import json as _json
160
160
  parsed = _json.loads(route.calls.last.request.read())
161
161
  assert set(parsed.keys()) == {"query", "page", "page_size", "fields"}
162
+
163
+
164
+ @pytest.mark.asyncio
165
+ @respx.mock
166
+ async def test_search_papers_freshness_boost_passthrough():
167
+ """freshness_boost 直接透传到 /meta-search payload。"""
168
+ route = respx.post("https://api.example/meta-search").mock(
169
+ return_value=Response(200, json={"hits": [], "total": 0, "page": 1, "page_size": 10})
170
+ )
171
+ async with AgentToolsClient(base_url="https://api.example", token="t") as c:
172
+ await c.search_papers(query="transformer", freshness_boost="STRONG")
173
+ import json as _json
174
+ parsed = _json.loads(route.calls.last.request.read())
175
+ assert parsed["freshness_boost"] == "STRONG"
176
+
177
+
178
+ @pytest.mark.asyncio
179
+ async def test_search_papers_freshness_boost_invalid_value_rejected():
180
+ """非法 freshness_boost 值在 SDK 层校验阶段就被拒(不打到后端)。"""
181
+ async with AgentToolsClient(base_url="https://api.example", token="t") as c:
182
+ with pytest.raises(ValueError, match="freshness_boost"):
183
+ await c.search_papers(query="x", freshness_boost="EXTREME")
@@ -323,7 +323,7 @@ wheels = [
323
323
 
324
324
  [[package]]
325
325
  name = "sciverse"
326
- version = "0.6.1"
326
+ version = "0.6.3"
327
327
  source = { editable = "." }
328
328
  dependencies = [
329
329
  { name = "httpx" },
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes