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.
- {sciverse-0.6.2 → sciverse-0.7.0}/PKG-INFO +1 -1
- {sciverse-0.6.2 → sciverse-0.7.0}/pyproject.toml +1 -1
- {sciverse-0.6.2 → sciverse-0.7.0}/src/sciverse/cli.py +4 -0
- {sciverse-0.6.2 → sciverse-0.7.0}/src/sciverse/client.py +15 -3
- {sciverse-0.6.2 → sciverse-0.7.0}/src/sciverse/tools.py +21 -1
- {sciverse-0.6.2 → sciverse-0.7.0}/src/sciverse/types.py +18 -0
- {sciverse-0.6.2 → sciverse-0.7.0}/tests/test_client.py +22 -0
- {sciverse-0.6.2 → sciverse-0.7.0}/uv.lock +1 -1
- {sciverse-0.6.2 → sciverse-0.7.0}/.gitignore +0 -0
- {sciverse-0.6.2 → sciverse-0.7.0}/README.md +0 -0
- {sciverse-0.6.2 → sciverse-0.7.0}/src/sciverse/__init__.py +0 -0
- {sciverse-0.6.2 → sciverse-0.7.0}/src/sciverse/credentials.py +0 -0
- {sciverse-0.6.2 → sciverse-0.7.0}/src/sciverse/py.typed +0 -0
- {sciverse-0.6.2 → sciverse-0.7.0}/tests/__init__.py +0 -0
- {sciverse-0.6.2 → sciverse-0.7.0}/tests/test_cli.py +0 -0
- {sciverse-0.6.2 → sciverse-0.7.0}/tests/test_contract.py +0 -0
- {sciverse-0.6.2 → sciverse-0.7.0}/tests/test_credentials.py +0 -0
- {sciverse-0.6.2 → sciverse-0.7.0}/tests/test_tools.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sciverse
|
|
3
|
-
Version: 0.
|
|
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
|
|
@@ -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"] =
|
|
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.
|
|
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")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|