aiagents4pharma 1.20.0__py3-none-any.whl → 1.21.0__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- aiagents4pharma/talk2biomodels/configs/config.yaml +5 -0
- aiagents4pharma/talk2scholars/agents/main_agent.py +90 -91
- aiagents4pharma/talk2scholars/agents/s2_agent.py +61 -17
- aiagents4pharma/talk2scholars/configs/agents/talk2scholars/main_agent/default.yaml +31 -10
- aiagents4pharma/talk2scholars/configs/agents/talk2scholars/s2_agent/default.yaml +8 -16
- aiagents4pharma/talk2scholars/configs/app/frontend/default.yaml +11 -9
- aiagents4pharma/talk2scholars/configs/config.yaml +1 -0
- aiagents4pharma/talk2scholars/configs/tools/multi_paper_recommendation/default.yaml +2 -0
- aiagents4pharma/talk2scholars/configs/tools/retrieve_semantic_scholar_paper_id/__init__.py +3 -0
- aiagents4pharma/talk2scholars/configs/tools/search/default.yaml +1 -0
- aiagents4pharma/talk2scholars/configs/tools/single_paper_recommendation/default.yaml +1 -0
- aiagents4pharma/talk2scholars/state/state_talk2scholars.py +36 -7
- aiagents4pharma/talk2scholars/tests/test_llm_main_integration.py +58 -0
- aiagents4pharma/talk2scholars/tests/test_main_agent.py +98 -122
- aiagents4pharma/talk2scholars/tests/test_s2_agent.py +95 -29
- aiagents4pharma/talk2scholars/tests/test_s2_tools.py +158 -22
- aiagents4pharma/talk2scholars/tools/s2/__init__.py +4 -2
- aiagents4pharma/talk2scholars/tools/s2/display_results.py +60 -21
- aiagents4pharma/talk2scholars/tools/s2/multi_paper_rec.py +35 -8
- aiagents4pharma/talk2scholars/tools/s2/query_results.py +61 -0
- aiagents4pharma/talk2scholars/tools/s2/retrieve_semantic_scholar_paper_id.py +79 -0
- aiagents4pharma/talk2scholars/tools/s2/search.py +34 -10
- aiagents4pharma/talk2scholars/tools/s2/single_paper_rec.py +39 -9
- {aiagents4pharma-1.20.0.dist-info → aiagents4pharma-1.21.0.dist-info}/METADATA +2 -2
- {aiagents4pharma-1.20.0.dist-info → aiagents4pharma-1.21.0.dist-info}/RECORD +28 -24
- aiagents4pharma/talk2scholars/tests/test_integration.py +0 -237
- {aiagents4pharma-1.20.0.dist-info → aiagents4pharma-1.21.0.dist-info}/LICENSE +0 -0
- {aiagents4pharma-1.20.0.dist-info → aiagents4pharma-1.21.0.dist-info}/WHEEL +0 -0
- {aiagents4pharma-1.20.0.dist-info → aiagents4pharma-1.21.0.dist-info}/top_level.txt +0 -0
@@ -5,7 +5,7 @@ This tool is used to search for academic papers on Semantic Scholar.
|
|
5
5
|
"""
|
6
6
|
|
7
7
|
import logging
|
8
|
-
from typing import Annotated, Any,
|
8
|
+
from typing import Annotated, Any, Optional
|
9
9
|
import hydra
|
10
10
|
import requests
|
11
11
|
from langchain_core.messages import ToolMessage
|
@@ -14,7 +14,6 @@ from langchain_core.tools.base import InjectedToolCallId
|
|
14
14
|
from langgraph.types import Command
|
15
15
|
from pydantic import BaseModel, Field
|
16
16
|
|
17
|
-
|
18
17
|
# Configure logging
|
19
18
|
logging.basicConfig(level=logging.INFO)
|
20
19
|
logger = logging.getLogger(__name__)
|
@@ -28,7 +27,7 @@ class SearchInput(BaseModel):
|
|
28
27
|
"Be specific and include relevant academic terms."
|
29
28
|
)
|
30
29
|
limit: int = Field(
|
31
|
-
default=
|
30
|
+
default=5, description="Maximum number of results to return", ge=1, le=100
|
32
31
|
)
|
33
32
|
year: Optional[str] = Field(
|
34
33
|
default=None,
|
@@ -44,13 +43,13 @@ with hydra.initialize(version_base=None, config_path="../../configs"):
|
|
44
43
|
cfg = cfg.tools.search
|
45
44
|
|
46
45
|
|
47
|
-
@tool(args_schema=SearchInput)
|
46
|
+
@tool("search_tool", args_schema=SearchInput, parse_docstring=True)
|
48
47
|
def search_tool(
|
49
48
|
query: str,
|
50
49
|
tool_call_id: Annotated[str, InjectedToolCallId],
|
51
|
-
limit: int =
|
50
|
+
limit: int = 5,
|
52
51
|
year: Optional[str] = None,
|
53
|
-
) ->
|
52
|
+
) -> Command[Any]:
|
54
53
|
"""
|
55
54
|
Search for academic papers on Semantic Scholar.
|
56
55
|
|
@@ -62,9 +61,9 @@ def search_tool(
|
|
62
61
|
Supports formats like "2024-", "-2024", "2024:2025". Defaults to None.
|
63
62
|
|
64
63
|
Returns:
|
65
|
-
|
64
|
+
The number of papers found on Semantic Scholar.
|
66
65
|
"""
|
67
|
-
|
66
|
+
logger.info("Searching for papers on %s", query)
|
68
67
|
endpoint = cfg.api_endpoint
|
69
68
|
params = {
|
70
69
|
"query": query,
|
@@ -80,26 +79,51 @@ def search_tool(
|
|
80
79
|
data = response.json()
|
81
80
|
papers = data.get("data", [])
|
82
81
|
logger.info("Received %d papers", len(papers))
|
82
|
+
if not papers:
|
83
|
+
return Command(
|
84
|
+
update={ # Place 'messages' inside 'update'
|
85
|
+
"messages": [
|
86
|
+
ToolMessage(
|
87
|
+
content="No papers found. Please try a different search query.",
|
88
|
+
tool_call_id=tool_call_id,
|
89
|
+
)
|
90
|
+
]
|
91
|
+
}
|
92
|
+
)
|
83
93
|
# Create a dictionary to store the papers
|
84
94
|
filtered_papers = {
|
85
95
|
paper["paperId"]: {
|
96
|
+
# "semantic_scholar_id": paper["paperId"], # Store Semantic Scholar ID
|
86
97
|
"Title": paper.get("title", "N/A"),
|
87
98
|
"Abstract": paper.get("abstract", "N/A"),
|
88
99
|
"Year": paper.get("year", "N/A"),
|
89
100
|
"Citation Count": paper.get("citationCount", "N/A"),
|
90
101
|
"URL": paper.get("url", "N/A"),
|
102
|
+
# "arXiv_ID": paper.get("externalIds", {}).get(
|
103
|
+
# "ArXiv", "N/A"
|
104
|
+
# ), # Extract arXiv ID
|
91
105
|
}
|
92
106
|
for paper in papers
|
93
107
|
if paper.get("title") and paper.get("authors")
|
94
108
|
}
|
95
109
|
|
110
|
+
logger.info("Filtered %d papers", len(filtered_papers))
|
111
|
+
|
112
|
+
content = "Search was successful."
|
113
|
+
content += " Here is a summary of the search results:"
|
114
|
+
content += f"Number of papers found: {len(filtered_papers)}\n"
|
115
|
+
content += f"Query: {query}\n"
|
116
|
+
content += f"Year: {year}\n" if year else ""
|
117
|
+
|
96
118
|
return Command(
|
97
119
|
update={
|
98
120
|
"papers": filtered_papers, # Now sending the dictionary directly
|
121
|
+
"last_displayed_papers": "papers",
|
99
122
|
"messages": [
|
100
123
|
ToolMessage(
|
101
|
-
content=
|
102
|
-
tool_call_id=tool_call_id
|
124
|
+
content=content,
|
125
|
+
tool_call_id=tool_call_id,
|
126
|
+
artifact=filtered_papers,
|
103
127
|
)
|
104
128
|
],
|
105
129
|
}
|
@@ -5,7 +5,7 @@ This tool is used to return recommendations for a single paper.
|
|
5
5
|
"""
|
6
6
|
|
7
7
|
import logging
|
8
|
-
from typing import Annotated, Any,
|
8
|
+
from typing import Annotated, Any, Optional
|
9
9
|
import hydra
|
10
10
|
import requests
|
11
11
|
from langchain_core.messages import ToolMessage
|
@@ -26,7 +26,7 @@ class SinglePaperRecInput(BaseModel):
|
|
26
26
|
description="Semantic Scholar Paper ID to get recommendations for (40-character string)"
|
27
27
|
)
|
28
28
|
limit: int = Field(
|
29
|
-
default=
|
29
|
+
default=5,
|
30
30
|
description="Maximum number of recommendations to return",
|
31
31
|
ge=1,
|
32
32
|
le=500,
|
@@ -48,15 +48,16 @@ with hydra.initialize(version_base=None, config_path="../../configs"):
|
|
48
48
|
cfg = cfg.tools.single_paper_recommendation
|
49
49
|
|
50
50
|
|
51
|
-
@tool(args_schema=SinglePaperRecInput)
|
51
|
+
@tool(args_schema=SinglePaperRecInput, parse_docstring=True)
|
52
52
|
def get_single_paper_recommendations(
|
53
53
|
paper_id: str,
|
54
54
|
tool_call_id: Annotated[str, InjectedToolCallId],
|
55
|
-
limit: int =
|
55
|
+
limit: int = 5,
|
56
56
|
year: Optional[str] = None,
|
57
|
-
) ->
|
57
|
+
) -> Command[Any]:
|
58
58
|
"""
|
59
|
-
Get
|
59
|
+
Get recommendations for on a single paper using its Semantic Scholar ID.
|
60
|
+
No other ID types are supported.
|
60
61
|
|
61
62
|
Args:
|
62
63
|
paper_id (str): The Semantic Scholar Paper ID to get recommendations for.
|
@@ -68,7 +69,9 @@ def get_single_paper_recommendations(
|
|
68
69
|
Returns:
|
69
70
|
Dict[str, Any]: The recommendations and related information.
|
70
71
|
"""
|
71
|
-
logger.info(
|
72
|
+
logger.info(
|
73
|
+
"Starting single paper recommendations search with paper ID: %s", paper_id
|
74
|
+
)
|
72
75
|
|
73
76
|
endpoint = f"{cfg.api_endpoint}/{paper_id}"
|
74
77
|
params = {
|
@@ -90,32 +93,59 @@ def get_single_paper_recommendations(
|
|
90
93
|
paper_id,
|
91
94
|
response.status_code,
|
92
95
|
)
|
96
|
+
if response.status_code != 200:
|
97
|
+
raise ValueError("Invalid paper ID or API error.")
|
93
98
|
# print(f"Request params: {params}")
|
94
99
|
logging.info("Request params: %s", params)
|
95
100
|
|
96
101
|
data = response.json()
|
97
102
|
recommendations = data.get("recommendedPapers", [])
|
98
103
|
|
104
|
+
if not recommendations:
|
105
|
+
return Command(
|
106
|
+
update={
|
107
|
+
"papers": {},
|
108
|
+
"messages": [
|
109
|
+
ToolMessage(
|
110
|
+
content=f"No recommendations found for {paper_id}.",
|
111
|
+
tool_call_id=tool_call_id,
|
112
|
+
)
|
113
|
+
],
|
114
|
+
}
|
115
|
+
)
|
116
|
+
|
99
117
|
# Extract paper ID and title from recommendations
|
100
118
|
filtered_papers = {
|
101
119
|
paper["paperId"]: {
|
120
|
+
# "semantic_scholar_id": paper["paperId"], # Store Semantic Scholar ID
|
102
121
|
"Title": paper.get("title", "N/A"),
|
103
122
|
"Abstract": paper.get("abstract", "N/A"),
|
104
123
|
"Year": paper.get("year", "N/A"),
|
105
124
|
"Citation Count": paper.get("citationCount", "N/A"),
|
106
125
|
"URL": paper.get("url", "N/A"),
|
126
|
+
# "arXiv_ID": paper.get("externalIds", {}).get(
|
127
|
+
# "ArXiv", "N/A"
|
128
|
+
# ), # Extract arXiv ID
|
107
129
|
}
|
108
130
|
for paper in recommendations
|
109
131
|
if paper.get("title") and paper.get("authors")
|
110
132
|
}
|
111
133
|
|
134
|
+
content = "Recommendations based on a single paper were successful."
|
135
|
+
content += " Here is a summary of the recommendations:"
|
136
|
+
content += f"Number of papers found: {len(filtered_papers)}\n"
|
137
|
+
content += f"Query Paper ID: {paper_id}\n"
|
138
|
+
content += f"Year: {year}\n" if year else ""
|
139
|
+
|
112
140
|
return Command(
|
113
141
|
update={
|
114
142
|
"papers": filtered_papers, # Now sending the dictionary directly
|
143
|
+
"last_displayed_papers": "papers",
|
115
144
|
"messages": [
|
116
145
|
ToolMessage(
|
117
|
-
content=
|
118
|
-
tool_call_id=tool_call_id
|
146
|
+
content=content,
|
147
|
+
tool_call_id=tool_call_id,
|
148
|
+
artifact=filtered_papers,
|
119
149
|
)
|
120
150
|
],
|
121
151
|
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: aiagents4pharma
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.21.0
|
4
4
|
Summary: AI Agents for drug discovery, drug development, and other pharmaceutical R&D.
|
5
5
|
Classifier: Programming Language :: Python :: 3
|
6
6
|
Classifier: License :: OSI Approved :: MIT License
|
@@ -110,7 +110,7 @@ free credits [here](https://build.nvidia.com/explore/discover)._
|
|
110
110
|
```
|
111
111
|
2. **Install dependencies:**
|
112
112
|
```bash
|
113
|
-
pip install .
|
113
|
+
pip install -r requirements.txt
|
114
114
|
```
|
115
115
|
3. **Initialize OPENAI_API_KEY and NVIDIA_API_KEY**
|
116
116
|
```bash
|
@@ -7,6 +7,7 @@ aiagents4pharma/talk2biomodels/api/kegg.py,sha256=QzYDAfJ16E7tbHGxP8ZNWRizMkMRS_
|
|
7
7
|
aiagents4pharma/talk2biomodels/api/ols.py,sha256=qq0Qy-gJDxanQW-HfCChDsTQsY1M41ua8hMlTnfuzrA,2202
|
8
8
|
aiagents4pharma/talk2biomodels/api/uniprot.py,sha256=aPUAVBR7UYXDuuhDpKezAK2aTMzo-NxFYFq6C0W5u6U,1175
|
9
9
|
aiagents4pharma/talk2biomodels/configs/__init__.py,sha256=safyFKhkd5Wlirl9dMZIHWDLTpY2oLw9wjIM7ZtLIHk,88
|
10
|
+
aiagents4pharma/talk2biomodels/configs/config.yaml,sha256=X0CMsnx6hHNvV04wsENQSGXadx0aKIy6mziSopVUdZI,116
|
10
11
|
aiagents4pharma/talk2biomodels/configs/agents/__init__.py,sha256=_ZoG8snICK2bidWtc2KOGs738LWg9_r66V9mOMnEb-E,71
|
11
12
|
aiagents4pharma/talk2biomodels/configs/agents/t2b_agent/__init__.py,sha256=-fAORvyFmG2iSvFOFDixmt9OTQRR58y89uhhu2EgbA8,46
|
12
13
|
aiagents4pharma/talk2biomodels/configs/agents/t2b_agent/default.yaml,sha256=pSViMKwKyMQDm8LzbfIaGdxph73iHYaXMiv5YOuxM7k,536
|
@@ -114,42 +115,45 @@ aiagents4pharma/talk2knowledgegraphs/utils/extractions/__init__.py,sha256=7gwwtf
|
|
114
115
|
aiagents4pharma/talk2knowledgegraphs/utils/extractions/pcst.py,sha256=m5p0yoJb7I19ua5yeQfXPf7c4r6S1XPwttsrM7Qoy94,9336
|
115
116
|
aiagents4pharma/talk2scholars/__init__.py,sha256=gphERyVKZHvOnMQsml7TIHlaIshHJ75R1J3FKExkfuY,120
|
116
117
|
aiagents4pharma/talk2scholars/agents/__init__.py,sha256=ykszlVGxz3egLHZAttlNoTPxIrnQJZYva_ssR8fwIFk,117
|
117
|
-
aiagents4pharma/talk2scholars/agents/main_agent.py,sha256=
|
118
|
-
aiagents4pharma/talk2scholars/agents/s2_agent.py,sha256=
|
118
|
+
aiagents4pharma/talk2scholars/agents/main_agent.py,sha256=UiiqCMUko4t39uR4NtTvG3kRMf89x67dU_3NSAM4DWw,7603
|
119
|
+
aiagents4pharma/talk2scholars/agents/s2_agent.py,sha256=XilKQvlxEVNYK5cEc44x-62OZZ1qG77v1r0FkwLexcw,4581
|
119
120
|
aiagents4pharma/talk2scholars/configs/__init__.py,sha256=tf2gz8n7M4ko6xLdX_C925ELVIxoP6SgkPcbeh59ad4,151
|
120
|
-
aiagents4pharma/talk2scholars/configs/config.yaml,sha256=
|
121
|
+
aiagents4pharma/talk2scholars/configs/config.yaml,sha256=XaUi1aP0VGiZFeW_ZP68bVSiCJezied5yLzcx3Uljhc,308
|
121
122
|
aiagents4pharma/talk2scholars/configs/agents/__init__.py,sha256=yyh7PB2oY_JulnpSQCWS4wwCH_uzIdt47O2Ay48x_oU,75
|
122
123
|
aiagents4pharma/talk2scholars/configs/agents/talk2scholars/__init__.py,sha256=Tj4urOkjpu2cTlpJl0Fmr_18RZCR88vns-Gt-XquDzs,95
|
123
124
|
aiagents4pharma/talk2scholars/configs/agents/talk2scholars/main_agent/__init__.py,sha256=fqQQ-GlRcbzru2KmEk3oMma0R6_SzGM8dOXzYeU4oVA,46
|
124
|
-
aiagents4pharma/talk2scholars/configs/agents/talk2scholars/main_agent/default.yaml,sha256=
|
125
|
+
aiagents4pharma/talk2scholars/configs/agents/talk2scholars/main_agent/default.yaml,sha256=kizyUjDasjv3zt2xHcGMqTxnpR_FHAcOs1vgVaH7tsY,1882
|
125
126
|
aiagents4pharma/talk2scholars/configs/agents/talk2scholars/s2_agent/__init__.py,sha256=fqQQ-GlRcbzru2KmEk3oMma0R6_SzGM8dOXzYeU4oVA,46
|
126
|
-
aiagents4pharma/talk2scholars/configs/agents/talk2scholars/s2_agent/default.yaml,sha256=
|
127
|
+
aiagents4pharma/talk2scholars/configs/agents/talk2scholars/s2_agent/default.yaml,sha256=lQUvQDLqqPIxn4TkL58atG2dQFhysNuNyAbd6P8km3g,585
|
127
128
|
aiagents4pharma/talk2scholars/configs/app/__init__.py,sha256=JoSZV6N669kGMv5zLDszwf0ZjcRHx9TJfIqGhIIdPXE,70
|
128
129
|
aiagents4pharma/talk2scholars/configs/app/frontend/__init__.py,sha256=fqQQ-GlRcbzru2KmEk3oMma0R6_SzGM8dOXzYeU4oVA,46
|
129
|
-
aiagents4pharma/talk2scholars/configs/app/frontend/default.yaml,sha256=
|
130
|
+
aiagents4pharma/talk2scholars/configs/app/frontend/default.yaml,sha256=wsELBdRLv6UqZ9QZfwpS7K4xfMj5s-a99-aXqIs6WEI,868
|
130
131
|
aiagents4pharma/talk2scholars/configs/tools/__init__.py,sha256=w0BJK0MR6Et8Pw1htP8JV0Lr9F_N68CqvbpV14KBy_8,151
|
131
132
|
aiagents4pharma/talk2scholars/configs/tools/multi_paper_recommendation/__init__.py,sha256=fqQQ-GlRcbzru2KmEk3oMma0R6_SzGM8dOXzYeU4oVA,46
|
132
|
-
aiagents4pharma/talk2scholars/configs/tools/multi_paper_recommendation/default.yaml,sha256=
|
133
|
+
aiagents4pharma/talk2scholars/configs/tools/multi_paper_recommendation/default.yaml,sha256=iEsEW89MlQwKsAW4ZAxLt4pDBwA1qxImYQ2dfONIf6c,442
|
134
|
+
aiagents4pharma/talk2scholars/configs/tools/retrieve_semantic_scholar_paper_id/__init__.py,sha256=fqQQ-GlRcbzru2KmEk3oMma0R6_SzGM8dOXzYeU4oVA,46
|
133
135
|
aiagents4pharma/talk2scholars/configs/tools/search/__init__.py,sha256=fqQQ-GlRcbzru2KmEk3oMma0R6_SzGM8dOXzYeU4oVA,46
|
134
|
-
aiagents4pharma/talk2scholars/configs/tools/search/default.yaml,sha256=
|
136
|
+
aiagents4pharma/talk2scholars/configs/tools/search/default.yaml,sha256=tw8N1Mms0qHQbIY3KGDNK1NuT19dQGPiagxzWDdOAJk,504
|
135
137
|
aiagents4pharma/talk2scholars/configs/tools/single_paper_recommendation/__init__.py,sha256=fqQQ-GlRcbzru2KmEk3oMma0R6_SzGM8dOXzYeU4oVA,46
|
136
|
-
aiagents4pharma/talk2scholars/configs/tools/single_paper_recommendation/default.yaml,sha256=
|
138
|
+
aiagents4pharma/talk2scholars/configs/tools/single_paper_recommendation/default.yaml,sha256=TILecrowsu5VGdJPeac6fl5AXSf3piSHN0oKdjY2q1o,596
|
137
139
|
aiagents4pharma/talk2scholars/state/__init__.py,sha256=S6SxlszIMZSIMJehjevPF9sKyR-PAwWb5TEdo6xWXE8,103
|
138
|
-
aiagents4pharma/talk2scholars/state/state_talk2scholars.py,sha256=
|
140
|
+
aiagents4pharma/talk2scholars/state/state_talk2scholars.py,sha256=Jbwckhhpv03KFQYkYkuPsYz5OxT0Si-mra7qrynH5Jo,2246
|
139
141
|
aiagents4pharma/talk2scholars/tests/__init__.py,sha256=U3PsTiUZaUBD1IZanFGkDIOdFieDVJtGKQ5-woYUo8c,45
|
140
|
-
aiagents4pharma/talk2scholars/tests/
|
141
|
-
aiagents4pharma/talk2scholars/tests/test_main_agent.py,sha256=
|
142
|
-
aiagents4pharma/talk2scholars/tests/test_s2_agent.py,sha256
|
143
|
-
aiagents4pharma/talk2scholars/tests/test_s2_tools.py,sha256=
|
142
|
+
aiagents4pharma/talk2scholars/tests/test_llm_main_integration.py,sha256=SAMG-Kb2S9sei8Us5vUWCUJikTKXPZVKQ6aJJPEhJsc,1880
|
143
|
+
aiagents4pharma/talk2scholars/tests/test_main_agent.py,sha256=TTPfVGWWq6BXJVgfR958qttD6dGRnpJHZMqo86k4aMo,5562
|
144
|
+
aiagents4pharma/talk2scholars/tests/test_s2_agent.py,sha256=-yEoG2v5SMkCLCrSA2DFcNE-xMOSn97N4UTomzCeW40,7559
|
145
|
+
aiagents4pharma/talk2scholars/tests/test_s2_tools.py,sha256=QEwraJk9_Kp6ZSGYyYDXWH62wIjSwi1Pptwwbx1fuG0,13176
|
144
146
|
aiagents4pharma/talk2scholars/tests/test_state.py,sha256=_iHXvoZnU_eruf8l1sQKBSCIVnxNkH_9VzkVtZZA6bY,384
|
145
147
|
aiagents4pharma/talk2scholars/tools/__init__.py,sha256=YudBDRwaEzDnAcpxGZvEOfyh5-6xd51CTvTKTkywgXw,68
|
146
|
-
aiagents4pharma/talk2scholars/tools/s2/__init__.py,sha256=
|
147
|
-
aiagents4pharma/talk2scholars/tools/s2/display_results.py,sha256=
|
148
|
-
aiagents4pharma/talk2scholars/tools/s2/multi_paper_rec.py,sha256=
|
149
|
-
aiagents4pharma/talk2scholars/tools/s2/
|
150
|
-
aiagents4pharma/talk2scholars/tools/s2/
|
151
|
-
aiagents4pharma
|
152
|
-
aiagents4pharma
|
153
|
-
aiagents4pharma-1.
|
154
|
-
aiagents4pharma-1.
|
155
|
-
aiagents4pharma-1.
|
148
|
+
aiagents4pharma/talk2scholars/tools/s2/__init__.py,sha256=wytqCmGm8Fbl8y5qLdIkxhhG8VHLYMifCGjbH_LK2Fc,258
|
149
|
+
aiagents4pharma/talk2scholars/tools/s2/display_results.py,sha256=UR0PtEHGDpOhPH0Di5HT8-Fip2RkEMTJgzROsChb1gc,2959
|
150
|
+
aiagents4pharma/talk2scholars/tools/s2/multi_paper_rec.py,sha256=sYtoJWFmJuSTSHMrZmqiBfGS-mDKS1gAbKtNyjRnlwU,4979
|
151
|
+
aiagents4pharma/talk2scholars/tools/s2/query_results.py,sha256=EUfzRh5Qc_tMl5fDIFb9PIsQkkrU4Xb5MR0sud_X5-c,2017
|
152
|
+
aiagents4pharma/talk2scholars/tools/s2/retrieve_semantic_scholar_paper_id.py,sha256=Lg1L4HQCN2LaQEyWtLD73O67PMoXkPHi-Y8rCzHS0A4,2499
|
153
|
+
aiagents4pharma/talk2scholars/tools/s2/search.py,sha256=mnBQWDuQ50UVw6B-bRuL8Ek1av-pEtdgzVMxpEA2BpI,4296
|
154
|
+
aiagents4pharma/talk2scholars/tools/s2/single_paper_rec.py,sha256=xgnUj9W9JkeTvB2VJBJUAnia789GGNGqdqgJ_G16v2s,5120
|
155
|
+
aiagents4pharma-1.21.0.dist-info/LICENSE,sha256=IcIbyB1Hyk5ZDah03VNQvJkbNk2hkBCDqQ8qtnCvB4Q,1077
|
156
|
+
aiagents4pharma-1.21.0.dist-info/METADATA,sha256=YsjDHw3yfqfPClv0N3j35AObxHBhStDojFUUslyd_1Q,7757
|
157
|
+
aiagents4pharma-1.21.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
158
|
+
aiagents4pharma-1.21.0.dist-info/top_level.txt,sha256=-AH8rMmrSnJtq7HaAObS78UU-cTCwvX660dSxeM7a0A,16
|
159
|
+
aiagents4pharma-1.21.0.dist-info/RECORD,,
|
@@ -1,237 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Integration tests for talk2scholars system.
|
3
|
-
|
4
|
-
These tests ensure that:
|
5
|
-
1. The main agent and sub-agent work together.
|
6
|
-
2. The agents correctly interact with tools (search, recommendations).
|
7
|
-
3. The full pipeline processes queries and updates state correctly.
|
8
|
-
"""
|
9
|
-
|
10
|
-
# pylint: disable=redefined-outer-name
|
11
|
-
from unittest.mock import patch, Mock
|
12
|
-
import pytest
|
13
|
-
from langchain_core.messages import HumanMessage
|
14
|
-
from ..agents.main_agent import get_app as get_main_app
|
15
|
-
from ..agents.s2_agent import get_app as get_s2_app
|
16
|
-
from ..state.state_talk2scholars import Talk2Scholars
|
17
|
-
|
18
|
-
|
19
|
-
@pytest.fixture(autouse=True)
|
20
|
-
def mock_hydra():
|
21
|
-
"""Mock Hydra configuration to prevent external dependencies."""
|
22
|
-
with patch("hydra.initialize"), patch("hydra.compose") as mock_compose:
|
23
|
-
cfg_mock = Mock()
|
24
|
-
cfg_mock.agents.talk2scholars.main_agent.temperature = 0
|
25
|
-
cfg_mock.agents.talk2scholars.main_agent.main_agent = "Test main agent prompt"
|
26
|
-
cfg_mock.agents.talk2scholars.s2_agent.temperature = 0
|
27
|
-
cfg_mock.agents.talk2scholars.s2_agent.s2_agent = "Test s2 agent prompt"
|
28
|
-
mock_compose.return_value = cfg_mock
|
29
|
-
yield mock_compose
|
30
|
-
|
31
|
-
|
32
|
-
@pytest.fixture(autouse=True)
|
33
|
-
def mock_tools():
|
34
|
-
"""Mock tools to prevent execution of real API calls."""
|
35
|
-
with (
|
36
|
-
patch(
|
37
|
-
"aiagents4pharma.talk2scholars.tools.s2.search.search_tool"
|
38
|
-
) as mock_s2_search,
|
39
|
-
patch(
|
40
|
-
"aiagents4pharma.talk2scholars.tools.s2.display_results.display_results"
|
41
|
-
) as mock_s2_display,
|
42
|
-
patch(
|
43
|
-
"aiagents4pharma.talk2scholars.tools.s2.single_paper_rec."
|
44
|
-
"get_single_paper_recommendations"
|
45
|
-
) as mock_s2_single_rec,
|
46
|
-
patch(
|
47
|
-
"aiagents4pharma.talk2scholars.tools.s2.multi_paper_rec."
|
48
|
-
"get_multi_paper_recommendations"
|
49
|
-
) as mock_s2_multi_rec,
|
50
|
-
):
|
51
|
-
|
52
|
-
mock_s2_search.return_value = {"papers": {"id123": "Mock Paper"}}
|
53
|
-
mock_s2_display.return_value = "Displaying Mock Results"
|
54
|
-
mock_s2_single_rec.return_value = {"recommendations": ["Paper A", "Paper B"]}
|
55
|
-
mock_s2_multi_rec.return_value = {
|
56
|
-
"multi_recommendations": ["Paper X", "Paper Y"]
|
57
|
-
}
|
58
|
-
|
59
|
-
yield {
|
60
|
-
"search_tool": mock_s2_search,
|
61
|
-
"display_results": mock_s2_display,
|
62
|
-
"single_paper_rec": mock_s2_single_rec,
|
63
|
-
"multi_paper_rec": mock_s2_multi_rec,
|
64
|
-
}
|
65
|
-
|
66
|
-
|
67
|
-
def test_full_workflow():
|
68
|
-
"""Test the full workflow from main agent to S2 agent."""
|
69
|
-
thread_id = "test_thread"
|
70
|
-
main_app = get_main_app(thread_id)
|
71
|
-
|
72
|
-
# Define expected mock response with the actual structure
|
73
|
-
expected_paper = {
|
74
|
-
"530a059cb48477ad1e3d4f8f4b153274c8997332": {
|
75
|
-
"Title": "Explainable Artificial Intelligence",
|
76
|
-
"Abstract": None,
|
77
|
-
"Citation Count": 5544,
|
78
|
-
"Year": "2024",
|
79
|
-
"URL": "https://example.com/paper",
|
80
|
-
}
|
81
|
-
}
|
82
|
-
|
83
|
-
# Mock the search tool instead of the app
|
84
|
-
with patch(
|
85
|
-
"aiagents4pharma.talk2scholars.tools.s2.search.search_tool",
|
86
|
-
return_value={"papers": expected_paper},
|
87
|
-
):
|
88
|
-
state = Talk2Scholars(messages=[HumanMessage(content="Find AI papers")])
|
89
|
-
result = main_app.invoke(
|
90
|
-
state,
|
91
|
-
config={
|
92
|
-
"configurable": {
|
93
|
-
"thread_id": thread_id,
|
94
|
-
"checkpoint_ns": "test_ns",
|
95
|
-
"checkpoint_id": "test_checkpoint",
|
96
|
-
}
|
97
|
-
},
|
98
|
-
)
|
99
|
-
|
100
|
-
# Check values
|
101
|
-
assert "papers" in result
|
102
|
-
assert "messages" in result
|
103
|
-
assert len(result["papers"]) > 0
|
104
|
-
|
105
|
-
|
106
|
-
def test_s2_agent_execution():
|
107
|
-
"""Test if the S2 agent processes requests correctly and updates state."""
|
108
|
-
thread_id = "test_thread"
|
109
|
-
s2_app = get_s2_app(thread_id)
|
110
|
-
|
111
|
-
state = Talk2Scholars(messages=[HumanMessage(content="Get recommendations")])
|
112
|
-
|
113
|
-
result = s2_app.invoke(
|
114
|
-
state,
|
115
|
-
config={
|
116
|
-
"configurable": {
|
117
|
-
"thread_id": thread_id,
|
118
|
-
"checkpoint_ns": "test_ns",
|
119
|
-
"checkpoint_id": "test_checkpoint",
|
120
|
-
}
|
121
|
-
},
|
122
|
-
)
|
123
|
-
|
124
|
-
assert "messages" in result
|
125
|
-
assert "multi_papers" in result
|
126
|
-
assert result["multi_papers"] is not None
|
127
|
-
|
128
|
-
|
129
|
-
def test_tool_integration(mock_tools):
|
130
|
-
"""Test if the tools interact correctly with the workflow."""
|
131
|
-
thread_id = "test_thread"
|
132
|
-
s2_app = get_s2_app(thread_id)
|
133
|
-
|
134
|
-
state = Talk2Scholars(
|
135
|
-
messages=[HumanMessage(content="Search for AI ethics papers")]
|
136
|
-
)
|
137
|
-
|
138
|
-
mock_paper_id = "11159bdb213aaa243916f42f576396d483ba474b"
|
139
|
-
mock_response = {
|
140
|
-
"papers": {
|
141
|
-
mock_paper_id: {
|
142
|
-
"Title": "Mock AI Ethics Paper",
|
143
|
-
"Abstract": "A study on AI ethics",
|
144
|
-
"Citation Count": 100,
|
145
|
-
"URL": "https://example.com/mock-paper",
|
146
|
-
}
|
147
|
-
}
|
148
|
-
}
|
149
|
-
|
150
|
-
# Update both the fixture mock and patch the actual tool
|
151
|
-
mock_tools["search_tool"].return_value = {"papers": mock_response["papers"]}
|
152
|
-
|
153
|
-
with patch(
|
154
|
-
"aiagents4pharma.talk2scholars.tools.s2.search.search_tool",
|
155
|
-
return_value={"papers": mock_response["papers"]},
|
156
|
-
):
|
157
|
-
result = s2_app.invoke(
|
158
|
-
state,
|
159
|
-
config={
|
160
|
-
"configurable": {
|
161
|
-
"thread_id": thread_id,
|
162
|
-
"checkpoint_ns": "test_ns",
|
163
|
-
"checkpoint_id": "test_checkpoint",
|
164
|
-
}
|
165
|
-
},
|
166
|
-
)
|
167
|
-
|
168
|
-
assert "papers" in result
|
169
|
-
assert len(result["papers"]) > 0 # Verify we have papers
|
170
|
-
assert isinstance(result["papers"], dict) # Verify it's a dictionary
|
171
|
-
|
172
|
-
|
173
|
-
def test_empty_query():
|
174
|
-
"""Test how the system handles an empty query."""
|
175
|
-
thread_id = "test_thread"
|
176
|
-
main_app = get_main_app(thread_id)
|
177
|
-
|
178
|
-
state = Talk2Scholars(messages=[HumanMessage(content="")])
|
179
|
-
|
180
|
-
# Mock the s2_agent app
|
181
|
-
mock_s2_app = get_s2_app(thread_id)
|
182
|
-
|
183
|
-
with patch(
|
184
|
-
"aiagents4pharma.talk2scholars.agents.s2_agent.get_app",
|
185
|
-
return_value=mock_s2_app,
|
186
|
-
):
|
187
|
-
result = main_app.invoke(
|
188
|
-
state,
|
189
|
-
config={
|
190
|
-
"configurable": {
|
191
|
-
"thread_id": thread_id,
|
192
|
-
"checkpoint_ns": "test_ns",
|
193
|
-
"checkpoint_id": "test_checkpoint",
|
194
|
-
}
|
195
|
-
},
|
196
|
-
)
|
197
|
-
|
198
|
-
assert "messages" in result
|
199
|
-
last_message = result["messages"][-1].content.lower()
|
200
|
-
assert any(
|
201
|
-
phrase in last_message
|
202
|
-
for phrase in ["no valid input", "how can i assist", "please provide a query"]
|
203
|
-
)
|
204
|
-
|
205
|
-
|
206
|
-
def test_api_failure_handling():
|
207
|
-
"""Test if the system gracefully handles an API failure."""
|
208
|
-
thread_id = "test_thread"
|
209
|
-
s2_app = get_s2_app(thread_id)
|
210
|
-
|
211
|
-
expected_error = "API Timeout: Connection failed"
|
212
|
-
with patch("requests.get", side_effect=Exception(expected_error)):
|
213
|
-
state = Talk2Scholars(messages=[HumanMessage(content="Find latest NLP papers")])
|
214
|
-
|
215
|
-
result = s2_app.invoke(
|
216
|
-
state,
|
217
|
-
config={
|
218
|
-
"configurable": {
|
219
|
-
"thread_id": thread_id,
|
220
|
-
"checkpoint_ns": "test_ns",
|
221
|
-
"checkpoint_id": "test_checkpoint",
|
222
|
-
}
|
223
|
-
},
|
224
|
-
)
|
225
|
-
|
226
|
-
assert "messages" in result
|
227
|
-
last_message = result["messages"][-1].content.lower()
|
228
|
-
|
229
|
-
# Update assertions to match actual error message
|
230
|
-
assert any(
|
231
|
-
[
|
232
|
-
"unable to retrieve" in last_message,
|
233
|
-
"connection issue" in last_message,
|
234
|
-
"please try again later" in last_message,
|
235
|
-
]
|
236
|
-
)
|
237
|
-
assert "nlp papers" in last_message # Verify context is maintained
|
File without changes
|
File without changes
|
File without changes
|