aiagents4pharma 1.27.2__py3-none-any.whl → 1.29.0__py3-none-any.whl

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.
Files changed (53) hide show
  1. aiagents4pharma/talk2scholars/agents/__init__.py +1 -0
  2. aiagents4pharma/talk2scholars/agents/main_agent.py +35 -209
  3. aiagents4pharma/talk2scholars/agents/pdf_agent.py +106 -0
  4. aiagents4pharma/talk2scholars/agents/s2_agent.py +10 -6
  5. aiagents4pharma/talk2scholars/agents/zotero_agent.py +12 -6
  6. aiagents4pharma/talk2scholars/configs/agents/talk2scholars/__init__.py +1 -0
  7. aiagents4pharma/talk2scholars/configs/agents/talk2scholars/main_agent/default.yaml +2 -48
  8. aiagents4pharma/talk2scholars/configs/agents/talk2scholars/pdf_agent/__init__.py +3 -0
  9. aiagents4pharma/talk2scholars/configs/agents/talk2scholars/s2_agent/default.yaml +5 -28
  10. aiagents4pharma/talk2scholars/configs/agents/talk2scholars/zotero_agent/default.yaml +5 -21
  11. aiagents4pharma/talk2scholars/configs/config.yaml +3 -0
  12. aiagents4pharma/talk2scholars/configs/tools/__init__.py +2 -0
  13. aiagents4pharma/talk2scholars/configs/tools/multi_paper_recommendation/default.yaml +1 -1
  14. aiagents4pharma/talk2scholars/configs/tools/question_and_answer/__init__.py +3 -0
  15. aiagents4pharma/talk2scholars/configs/tools/search/default.yaml +1 -1
  16. aiagents4pharma/talk2scholars/configs/tools/single_paper_recommendation/default.yaml +1 -1
  17. aiagents4pharma/talk2scholars/configs/tools/zotero_read/default.yaml +42 -1
  18. aiagents4pharma/talk2scholars/configs/tools/zotero_write/__inti__.py +3 -0
  19. aiagents4pharma/talk2scholars/state/state_talk2scholars.py +1 -0
  20. aiagents4pharma/talk2scholars/tests/test_main_agent.py +186 -111
  21. aiagents4pharma/talk2scholars/tests/test_pdf_agent.py +126 -0
  22. aiagents4pharma/talk2scholars/tests/test_question_and_answer_tool.py +186 -0
  23. aiagents4pharma/talk2scholars/tests/test_s2_display.py +74 -0
  24. aiagents4pharma/talk2scholars/tests/test_s2_multi.py +282 -0
  25. aiagents4pharma/talk2scholars/tests/test_s2_query.py +78 -0
  26. aiagents4pharma/talk2scholars/tests/test_s2_retrieve.py +65 -0
  27. aiagents4pharma/talk2scholars/tests/test_s2_search.py +266 -0
  28. aiagents4pharma/talk2scholars/tests/test_s2_single.py +274 -0
  29. aiagents4pharma/talk2scholars/tests/test_zotero_path.py +57 -0
  30. aiagents4pharma/talk2scholars/tests/test_zotero_read.py +412 -0
  31. aiagents4pharma/talk2scholars/tests/test_zotero_write.py +626 -0
  32. aiagents4pharma/talk2scholars/tools/__init__.py +1 -0
  33. aiagents4pharma/talk2scholars/tools/pdf/__init__.py +5 -0
  34. aiagents4pharma/talk2scholars/tools/pdf/question_and_answer.py +170 -0
  35. aiagents4pharma/talk2scholars/tools/s2/multi_paper_rec.py +50 -34
  36. aiagents4pharma/talk2scholars/tools/s2/query_results.py +1 -1
  37. aiagents4pharma/talk2scholars/tools/s2/retrieve_semantic_scholar_paper_id.py +8 -8
  38. aiagents4pharma/talk2scholars/tools/s2/search.py +36 -23
  39. aiagents4pharma/talk2scholars/tools/s2/single_paper_rec.py +44 -38
  40. aiagents4pharma/talk2scholars/tools/zotero/__init__.py +2 -0
  41. aiagents4pharma/talk2scholars/tools/zotero/utils/__init__.py +5 -0
  42. aiagents4pharma/talk2scholars/tools/zotero/utils/zotero_path.py +63 -0
  43. aiagents4pharma/talk2scholars/tools/zotero/zotero_read.py +64 -19
  44. aiagents4pharma/talk2scholars/tools/zotero/zotero_write.py +247 -0
  45. {aiagents4pharma-1.27.2.dist-info → aiagents4pharma-1.29.0.dist-info}/METADATA +6 -5
  46. {aiagents4pharma-1.27.2.dist-info → aiagents4pharma-1.29.0.dist-info}/RECORD +49 -33
  47. aiagents4pharma/talk2scholars/tests/test_call_s2.py +0 -100
  48. aiagents4pharma/talk2scholars/tests/test_call_zotero.py +0 -94
  49. aiagents4pharma/talk2scholars/tests/test_s2_tools.py +0 -355
  50. aiagents4pharma/talk2scholars/tests/test_zotero_tool.py +0 -171
  51. {aiagents4pharma-1.27.2.dist-info → aiagents4pharma-1.29.0.dist-info}/LICENSE +0 -0
  52. {aiagents4pharma-1.27.2.dist-info → aiagents4pharma-1.29.0.dist-info}/WHEEL +0 -0
  53. {aiagents4pharma-1.27.2.dist-info → aiagents4pharma-1.29.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env python3
2
+
3
+ """
4
+ Utility functions for Zotero tools.
5
+ """
6
+
7
+ import logging
8
+
9
+ # Configure logging
10
+ logging.basicConfig(level=logging.INFO)
11
+ logger = logging.getLogger(__name__)
12
+
13
+
14
+ def get_item_collections(zot):
15
+ """
16
+ Fetch all Zotero collections and map item keys to their full collection paths.
17
+
18
+ Args:
19
+ zot (Zotero): An initialized Zotero client.
20
+
21
+ Returns:
22
+ dict: A dictionary mapping item keys to a list of full collection paths.
23
+ """
24
+ logger.info("Fetching Zotero collections...")
25
+
26
+ # Fetch all collections
27
+ collections = zot.collections()
28
+
29
+ # Create mappings: collection key → name and collection key → parent key
30
+ collection_map = {col["key"]: col["data"]["name"] for col in collections}
31
+ parent_map = {
32
+ col["key"]: col["data"].get("parentCollection") for col in collections
33
+ }
34
+
35
+ # Build full paths for collections
36
+ def build_collection_path(col_key):
37
+ path = []
38
+ while col_key:
39
+ path.insert(0, collection_map.get(col_key, "Unknown"))
40
+ col_key = parent_map.get(col_key)
41
+ return "/" + "/".join(path) # Convert to "/path/to/collection"
42
+
43
+ collection_paths = {key: build_collection_path(key) for key in collection_map}
44
+
45
+ # Manually create an item-to-collection mapping with full paths
46
+ item_to_collections = {}
47
+
48
+ for collection in collections:
49
+ collection_key = collection["key"]
50
+ collection_items = zot.collection_items(
51
+ collection_key
52
+ ) # Fetch items in the collection
53
+
54
+ for item in collection_items:
55
+ item_key = item["data"]["key"]
56
+ if item_key in item_to_collections:
57
+ item_to_collections[item_key].append(collection_paths[collection_key])
58
+ else:
59
+ item_to_collections[item_key] = [collection_paths[collection_key]]
60
+
61
+ logger.info("Successfully mapped items to collection paths.")
62
+
63
+ return item_to_collections
@@ -13,6 +13,11 @@ from langchain_core.tools import tool
13
13
  from langchain_core.tools.base import InjectedToolCallId
14
14
  from langgraph.types import Command
15
15
  from pydantic import BaseModel, Field
16
+ from aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path import (
17
+ get_item_collections,
18
+ )
19
+
20
+ # pylint: disable=R0914,R0912,R0915
16
21
 
17
22
  # Configure logging
18
23
  logging.basicConfig(level=logging.INFO)
@@ -27,7 +32,7 @@ class ZoteroSearchInput(BaseModel):
27
32
  )
28
33
  only_articles: bool = Field(
29
34
  default=True,
30
- description="Whether to only search for journal articles/" "conference papers.",
35
+ description="Whether to only search for journal articles/conference papers.",
31
36
  )
32
37
  limit: int = Field(
33
38
  default=2, description="Maximum number of results to return", ge=1, le=100
@@ -35,12 +40,6 @@ class ZoteroSearchInput(BaseModel):
35
40
  tool_call_id: Annotated[str, InjectedToolCallId]
36
41
 
37
42
 
38
- # Load hydra configuration
39
- with hydra.initialize(version_base=None, config_path="../../configs"):
40
- cfg = hydra.compose(config_name="config", overrides=["tools/zotero_read=default"])
41
- cfg = cfg.tools.zotero_read
42
-
43
-
44
43
  @tool(args_schema=ZoteroSearchInput, parse_docstring=True)
45
44
  def zotero_search_tool(
46
45
  query: str,
@@ -59,22 +58,55 @@ def zotero_search_tool(
59
58
  Returns:
60
59
  Dict[str, Any]: The search results and related information.
61
60
  """
62
- logger.info(
63
- "Searching Zotero for query: '%s' (only_articles: %s, limit: %d)",
64
- query,
65
- only_articles,
66
- limit,
67
- )
61
+ # Load hydra configuration
62
+ with hydra.initialize(version_base=None, config_path="../../configs"):
63
+ cfg = hydra.compose(
64
+ config_name="config", overrides=["tools/zotero_read=default"]
65
+ )
66
+ logger.info("Loaded configuration for Zotero search tool")
67
+ cfg = cfg.tools.zotero_read
68
+ logger.info(
69
+ "Searching Zotero for query: '%s' (only_articles: %s, limit: %d)",
70
+ query,
71
+ only_articles,
72
+ limit,
73
+ )
68
74
 
69
75
  # Initialize Zotero client
70
76
  zot = zotero.Zotero(cfg.user_id, cfg.library_type, cfg.api_key)
71
77
 
72
- # Get items matching the query
73
- items = zot.items(q=query, limit=min(limit, cfg.zotero.max_limit))
78
+ # Fetch collection mapping once
79
+ item_to_collections = get_item_collections(zot)
80
+
81
+ # If the query is empty, fetch all items (up to max_limit), otherwise use the query
82
+ try:
83
+ if query.strip() == "":
84
+ logger.info(
85
+ "Empty query provided, fetching all items up to max_limit: %d",
86
+ cfg.zotero.max_limit,
87
+ )
88
+ items = zot.items(limit=cfg.zotero.max_limit)
89
+ else:
90
+ items = zot.items(q=query, limit=min(limit, cfg.zotero.max_limit))
91
+ except Exception as e:
92
+ logger.error("Failed to fetch items from Zotero: %s", e)
93
+ raise RuntimeError(
94
+ "Failed to fetch items from Zotero. Please retry the same query."
95
+ ) from e
96
+
74
97
  logger.info("Received %d items from Zotero", len(items))
75
98
 
99
+ if not items:
100
+ logger.error("No items returned from Zotero for query: '%s'", query)
101
+ raise RuntimeError(
102
+ "No items returned from Zotero. Please retry the same query."
103
+ )
104
+
76
105
  # Define filter criteria
77
106
  filter_item_types = cfg.zotero.filter_item_types if only_articles else []
107
+ filter_excluded_types = (
108
+ cfg.zotero.filter_excluded_types
109
+ ) # Exclude non-research items
78
110
 
79
111
  # Filter and format papers
80
112
  filtered_papers = {}
@@ -88,10 +120,16 @@ def zotero_search_tool(
88
120
  continue
89
121
 
90
122
  item_type = data.get("itemType")
91
- if only_articles and (
123
+ logger.debug("Item type: %s", item_type)
124
+
125
+ # Exclude attachments, notes, and other unwanted types
126
+ if (
92
127
  not item_type
93
128
  or not isinstance(item_type, str)
94
- or item_type not in filter_item_types
129
+ or item_type in filter_excluded_types # Skip attachments & notes
130
+ or (
131
+ only_articles and item_type not in filter_item_types
132
+ ) # Skip non-research types
95
133
  ):
96
134
  continue
97
135
 
@@ -99,20 +137,27 @@ def zotero_search_tool(
99
137
  if not key:
100
138
  continue
101
139
 
140
+ # Use the imported utility function's mapping to get collection paths
141
+ collection_paths = item_to_collections.get(key, ["/Unknown"])
142
+
102
143
  filtered_papers[key] = {
103
144
  "Title": data.get("title", "N/A"),
104
145
  "Abstract": data.get("abstractNote", "N/A"),
105
146
  "Date": data.get("date", "N/A"),
106
147
  "URL": data.get("url", "N/A"),
107
148
  "Type": item_type if isinstance(item_type, str) else "N/A",
149
+ "Collections": collection_paths, # Now displays full paths
108
150
  }
109
151
 
110
152
  if not filtered_papers:
111
- logger.warning("No matching papers found for query: '%s'", query)
153
+ logger.error("No matching papers returned from Zotero for query: '%s'", query)
154
+ raise RuntimeError(
155
+ "No matching papers returned from Zotero. Please retry the same query."
156
+ )
112
157
 
113
158
  logger.info("Filtered %d items", len(filtered_papers))
114
159
 
115
- # Prepare content with top 3 paper titles and types
160
+ # Prepare content with top 2 paper titles and types
116
161
  top_papers = list(filtered_papers.values())[:2]
117
162
  top_papers_info = "\n".join(
118
163
  [
@@ -0,0 +1,247 @@
1
+ #!/usr/bin/env python3
2
+
3
+ """
4
+ This tool is used to save fetched papers to Zotero library.
5
+ """
6
+
7
+ import logging
8
+ from typing import Annotated, Any
9
+ import hydra
10
+ from pyzotero import zotero
11
+ from langchain_core.messages import ToolMessage
12
+ from langchain_core.tools import tool
13
+ from langchain_core.tools.base import InjectedToolCallId
14
+ from langgraph.types import Command
15
+ from langgraph.prebuilt import InjectedState
16
+ from pydantic import BaseModel, Field
17
+ from aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path import (
18
+ get_item_collections,
19
+ )
20
+
21
+ # pylint: disable=R0914,R0912,R0915
22
+
23
+ # Configure logging
24
+ logging.basicConfig(level=logging.INFO)
25
+ logger = logging.getLogger(__name__)
26
+
27
+
28
+ class ZoteroSaveInput(BaseModel):
29
+ """Input schema for the Zotero save tool."""
30
+
31
+ tool_call_id: Annotated[str, InjectedToolCallId]
32
+ collection_path: str = Field(
33
+ default=None,
34
+ description=(
35
+ "The path where the paper should be saved in the Zotero library."
36
+ "Example: '/machine/cern/mobile'"
37
+ ),
38
+ )
39
+ state: Annotated[dict, InjectedState]
40
+
41
+
42
+ @tool(args_schema=ZoteroSaveInput, parse_docstring=True)
43
+ def zotero_save_tool(
44
+ tool_call_id: Annotated[str, InjectedToolCallId],
45
+ collection_path: str,
46
+ state: Annotated[dict, InjectedState],
47
+ ) -> Command[Any]:
48
+ """
49
+ Use this tool to save previously fetched papers from Semantic Scholar
50
+ to a specified Zotero collection.
51
+
52
+ Args:
53
+ tool_call_id (Annotated[str, InjectedToolCallId]): The tool call ID.
54
+ collection_path (str): The Zotero collection path where papers should be saved.
55
+ state (Annotated[dict, InjectedState]): The state containing previously fetched papers.
56
+
57
+ Returns:
58
+ Command[Any]: The save results and related information.
59
+ """
60
+ # Load hydra configuration
61
+ with hydra.initialize(version_base=None, config_path="../../configs"):
62
+ cfg = hydra.compose(
63
+ config_name="config", overrides=["tools/zotero_write=default"]
64
+ )
65
+ cfg = cfg.tools.zotero_write
66
+ logger.info("Loaded configuration for Zotero write tool")
67
+ logger.info(
68
+ "Saving fetched papers to Zotero under collection path: %s", collection_path
69
+ )
70
+
71
+ # Initialize Zotero client
72
+ zot = zotero.Zotero(cfg.user_id, cfg.library_type, cfg.api_key)
73
+
74
+ # Retrieve last displayed papers from the agent state
75
+ last_displayed_key = state.get("last_displayed_papers", {})
76
+ if isinstance(last_displayed_key, str):
77
+ # If it's a string (key to another state object), get that object
78
+ fetched_papers = state.get(last_displayed_key, {})
79
+ logger.info("Using papers from '%s' state key", last_displayed_key)
80
+ else:
81
+ # If it's already the papers object
82
+ fetched_papers = last_displayed_key
83
+ logger.info("Using papers directly from last_displayed_papers")
84
+
85
+ if not fetched_papers:
86
+ logger.warning("No fetched papers found to save.")
87
+ raise RuntimeError(
88
+ "No fetched papers were found to save. Please retry the same query."
89
+ )
90
+
91
+ # First, check if zotero_read exists in state and has collection data
92
+ zotero_read_data = state.get("zotero_read", {})
93
+ logger.info("Retrieved zotero_read from state: %d items", len(zotero_read_data))
94
+
95
+ # If zotero_read is empty, use get_item_collections as fallback
96
+ if not zotero_read_data:
97
+ logger.info(
98
+ "zotero_read is empty, fetching paths dynamically using get_item_collections"
99
+ )
100
+ try:
101
+ zotero_read_data = get_item_collections(zot)
102
+ logger.info(
103
+ "Successfully generated %d path mappings", len(zotero_read_data)
104
+ )
105
+ except Exception as e:
106
+ logger.error("Error generating path mappings: %s", str(e))
107
+ raise RuntimeError(
108
+ "Failed to generate collection path mappings. Please retry the same query."
109
+ ) from e
110
+
111
+ # Get all collections to find the correct one
112
+ collections = zot.collections()
113
+ logger.info("Found %d collections", len(collections))
114
+
115
+ # Normalize the requested collection path (remove trailing slash, lowercase for comparison)
116
+ normalized_path = collection_path.rstrip("/").lower()
117
+
118
+ # Find matching collection
119
+ matched_collection_key = None
120
+
121
+ # First, try to directly find the collection key in zotero_read data
122
+ for key, paths in zotero_read_data.items():
123
+ if isinstance(paths, list):
124
+ for path in paths:
125
+ if path.lower() == normalized_path:
126
+ matched_collection_key = key
127
+ logger.info(
128
+ "Found direct match in zotero_read: %s -> %s", path, key
129
+ )
130
+ break
131
+ elif isinstance(paths, str) and paths.lower() == normalized_path:
132
+ matched_collection_key = key
133
+ logger.info("Found direct match in zotero_read: %s -> %s", paths, key)
134
+ break
135
+
136
+ # If not found in zotero_read, try matching by collection name
137
+ if not matched_collection_key:
138
+ for col in collections:
139
+ col_name = col["data"]["name"]
140
+ if f"/{col_name}".lower() == normalized_path:
141
+ matched_collection_key = col["key"]
142
+ logger.info(
143
+ "Found direct match by collection name: %s (key: %s)",
144
+ col_name,
145
+ col["key"],
146
+ )
147
+ break
148
+
149
+ # If still not found, try part-matching
150
+ if not matched_collection_key:
151
+ name_to_key = {col["data"]["name"].lower(): col["key"] for col in collections}
152
+ collection_name = normalized_path.lstrip("/")
153
+ if collection_name in name_to_key:
154
+ matched_collection_key = name_to_key[collection_name]
155
+ logger.info(
156
+ "Found match by collection name: %s -> %s",
157
+ collection_name,
158
+ matched_collection_key,
159
+ )
160
+ else:
161
+ path_parts = normalized_path.strip("/").split("/")
162
+ for part in path_parts:
163
+ if part in name_to_key:
164
+ matched_collection_key = name_to_key[part]
165
+ logger.info(
166
+ "Found match by path component: %s -> %s",
167
+ part,
168
+ matched_collection_key,
169
+ )
170
+ break
171
+
172
+ # Do not fall back to a default collection: raise error if no match found
173
+ if not matched_collection_key:
174
+ logger.error(
175
+ "Invalid collection path: %s. No matching collection found in Zotero.",
176
+ collection_path,
177
+ )
178
+
179
+ available_paths = ", ".join(["/" + col["data"]["name"] for col in collections])
180
+ raise RuntimeError(
181
+ f"Error: The collection path '{collection_path}' does not exist in Zotero. "
182
+ f"Available collections are: {available_paths}"
183
+ )
184
+
185
+ # Format papers for Zotero and assign to the specified collection
186
+ zotero_items = []
187
+ for paper_id, paper in fetched_papers.items():
188
+ title = paper.get("Title", paper.get("title", "N/A"))
189
+ abstract = paper.get("Abstract", paper.get("abstractNote", "N/A"))
190
+ date = paper.get("Date", paper.get("date", "N/A"))
191
+ url = paper.get("URL", paper.get("url", paper.get("URL", "N/A")))
192
+ citations = paper.get("Citations", "N/A")
193
+
194
+ zotero_items.append(
195
+ {
196
+ "itemType": "journalArticle",
197
+ "title": title,
198
+ "abstractNote": abstract,
199
+ "date": date,
200
+ "url": url,
201
+ "extra": f"Paper ID: {paper_id}\nCitations: {citations}",
202
+ "collections": [matched_collection_key],
203
+ }
204
+ )
205
+
206
+ # Save items to Zotero
207
+ try:
208
+ response = zot.create_items(zotero_items)
209
+ logger.info("Papers successfully saved to Zotero: %s", response)
210
+ except Exception as e:
211
+ logger.error("Error saving to Zotero: %s", str(e))
212
+ raise RuntimeError(f"Error saving papers to Zotero: {str(e)}") from e
213
+
214
+ # Get the collection name for better feedback
215
+ collection_name = ""
216
+ for col in collections:
217
+ if col["key"] == matched_collection_key:
218
+ collection_name = col["data"]["name"]
219
+ break
220
+
221
+ content = (
222
+ f"Save was successful. Papers have been saved to Zotero collection '{collection_name}' "
223
+ f"with the requested path '{collection_path}'.\n"
224
+ )
225
+ content += "Summary of saved papers:\n"
226
+ content += f"Number of articles saved: {len(fetched_papers)}\n"
227
+ content += f"Query: {state.get('query', 'N/A')}\n"
228
+ top_papers = list(fetched_papers.values())[:2]
229
+ top_papers_info = "\n".join(
230
+ [
231
+ f"{i+1}. {paper.get('Title', 'N/A')} ({paper.get('URL', 'N/A')})"
232
+ for i, paper in enumerate(top_papers)
233
+ ]
234
+ )
235
+ content += "Here are the top articles:\n" + top_papers_info
236
+
237
+ return Command(
238
+ update={
239
+ "messages": [
240
+ ToolMessage(
241
+ content=content,
242
+ tool_call_id=tool_call_id,
243
+ artifact=fetched_papers,
244
+ )
245
+ ],
246
+ }
247
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: aiagents4pharma
3
- Version: 1.27.2
3
+ Version: 1.29.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
@@ -91,6 +91,7 @@ Our toolkit currently consists of the following agents:
91
91
  ![Python Version from PEP 621 TOML](https://img.shields.io/python/required-version-toml?tomlFilePath=https%3A%2F%2Fraw.githubusercontent.com%2FVirtualPatientEngine%2FAIAgents4Pharma%2Frefs%2Fheads%2Fmain%2Fpyproject.toml)
92
92
 
93
93
  ### Installation
94
+
94
95
  _Please use version 1.26.2 or later for better support with NVIDIA NIM models._
95
96
 
96
97
  #### Option 1: PyPI
@@ -135,10 +136,10 @@ cd AIAgents4Pharma/aiagents4pharma/talk2knowledgegraphs
135
136
  LANGCHAIN_TRACING_V2=true
136
137
  LANGCHAIN_API_KEY=your_langchain_api_key_here
137
138
  # Notes:
138
- # - The API endpoint for Ollama is already set in env.example.
139
- # - Both API keys (OPENAI_API_KEY and NVIDIA_API_KEY) are required for Talk2AIAgents4Pharma.
140
- # - If using Talk2KnowledgeGraphs separately, only the OPENAI_API_KEY is needed.
141
- # - Langsmith API for tracing is optional for both, set it in env.example if required.
139
+ # The API endpoint for Ollama is already set in env.example.
140
+ # Both API keys (OPENAI_API_KEY and NVIDIA_API_KEY) are required for Talk2AIAgents4Pharma.
141
+ # If using Talk2KnowledgeGraphs separately, only the OPENAI_API_KEY is needed.
142
+ # Langsmith API for tracing is optional for both, set it in env.example if required.
142
143
  ```
143
144
 
144
145
  4. Save the file.
@@ -135,59 +135,75 @@ aiagents4pharma/talk2knowledgegraphs/utils/enrichments/pubchem_strings.py,sha256
135
135
  aiagents4pharma/talk2knowledgegraphs/utils/extractions/__init__.py,sha256=7gwwtfzKhB8GuOBD47XRi0NprwEXkOzwNl5eeu-hDTI,86
136
136
  aiagents4pharma/talk2knowledgegraphs/utils/extractions/pcst.py,sha256=m5p0yoJb7I19ua5yeQfXPf7c4r6S1XPwttsrM7Qoy94,9336
137
137
  aiagents4pharma/talk2scholars/__init__.py,sha256=gphERyVKZHvOnMQsml7TIHlaIshHJ75R1J3FKExkfuY,120
138
- aiagents4pharma/talk2scholars/agents/__init__.py,sha256=WxEauzCzLEGyhdIRkxSBpNW5c_Uzf7iJUdM57IQkXH8,144
139
- aiagents4pharma/talk2scholars/agents/main_agent.py,sha256=nZIhOyEUSHECM4-wEHbDrfHRLkqoxW0H4fy6-MpA6N8,9397
140
- aiagents4pharma/talk2scholars/agents/s2_agent.py,sha256=ZiXtQVX2UbIyMOSXajuloWepEm7DKs6ZpPS0HgHzw0g,4492
141
- aiagents4pharma/talk2scholars/agents/zotero_agent.py,sha256=flIvg1ORaMiQpGEbsRM4zJHRNXi6UUv7emHDjH5HVY4,3961
138
+ aiagents4pharma/talk2scholars/agents/__init__.py,sha256=ZwFiHOlDGJk1601J5xEZDy0btPzqiOk2UCocKxohde8,168
139
+ aiagents4pharma/talk2scholars/agents/main_agent.py,sha256=TABzGSOg7I0_fJ0qybBVqZDdrU8YCjyG_m-kasO4WgE,2854
140
+ aiagents4pharma/talk2scholars/agents/pdf_agent.py,sha256=c9-_z5qp5Zkgh6piEIlgI4uo4OMXD3janZNmfYwnFCg,3729
141
+ aiagents4pharma/talk2scholars/agents/s2_agent.py,sha256=ua1bjKE2HBKZuLnDn8me5fuV1lSvdZbwAlo3Yp27TT4,4659
142
+ aiagents4pharma/talk2scholars/agents/zotero_agent.py,sha256=5jfIJiLsRdlCJjkF7BQMkP5PsEY_Gr7SfztWKozbUGo,4223
142
143
  aiagents4pharma/talk2scholars/configs/__init__.py,sha256=tf2gz8n7M4ko6xLdX_C925ELVIxoP6SgkPcbeh59ad4,151
143
- aiagents4pharma/talk2scholars/configs/config.yaml,sha256=IBrHX_mACNb7R4rrI_zbWgscAMUdIAkOg9LDgLN1o28,386
144
+ aiagents4pharma/talk2scholars/configs/config.yaml,sha256=dQIMg3jLGYAudkc1Zz85qqvFf-HdVXPfewUfAfPNNzU,501
144
145
  aiagents4pharma/talk2scholars/configs/agents/__init__.py,sha256=yyh7PB2oY_JulnpSQCWS4wwCH_uzIdt47O2Ay48x_oU,75
145
- aiagents4pharma/talk2scholars/configs/agents/talk2scholars/__init__.py,sha256=MI4RmoQQ2P-JQgCJ8XEucqF6g2VlNNi37yxcsXFj9Oo,122
146
+ aiagents4pharma/talk2scholars/configs/agents/talk2scholars/__init__.py,sha256=64GEWAoKOd_YHLi27eSOcOC5eSLK0IG_FNra3ZBt02Y,146
146
147
  aiagents4pharma/talk2scholars/configs/agents/talk2scholars/main_agent/__init__.py,sha256=fqQQ-GlRcbzru2KmEk3oMma0R6_SzGM8dOXzYeU4oVA,46
147
- aiagents4pharma/talk2scholars/configs/agents/talk2scholars/main_agent/default.yaml,sha256=wHbFTQSfdRc0JO2lbzXXHliFNz40Oza-mGmVphNOoPw,2615
148
+ aiagents4pharma/talk2scholars/configs/agents/talk2scholars/main_agent/default.yaml,sha256=rZfZ_dJArjlznHzusjxCnOjhptLTyejFiB0euV5R13c,662
149
+ aiagents4pharma/talk2scholars/configs/agents/talk2scholars/pdf_agent/__init__.py,sha256=fqQQ-GlRcbzru2KmEk3oMma0R6_SzGM8dOXzYeU4oVA,46
148
150
  aiagents4pharma/talk2scholars/configs/agents/talk2scholars/s2_agent/__init__.py,sha256=fqQQ-GlRcbzru2KmEk3oMma0R6_SzGM8dOXzYeU4oVA,46
149
- aiagents4pharma/talk2scholars/configs/agents/talk2scholars/s2_agent/default.yaml,sha256=WQOHG1WwnoQSUyIRfEEK6LLGwmWy2gaZNXpb12WsgNk,1975
151
+ aiagents4pharma/talk2scholars/configs/agents/talk2scholars/s2_agent/default.yaml,sha256=sn6vX6r-P0CR7UWS63ZqCmMKKn4As8pZoITRWx8sdoo,1151
150
152
  aiagents4pharma/talk2scholars/configs/agents/talk2scholars/zotero_agent/__init__.py,sha256=fqQQ-GlRcbzru2KmEk3oMma0R6_SzGM8dOXzYeU4oVA,46
151
- aiagents4pharma/talk2scholars/configs/agents/talk2scholars/zotero_agent/default.yaml,sha256=ZYmGnZnr_Q2q3UpkJDvmezADdJxspUGgngyZiMKJFq8,1958
153
+ aiagents4pharma/talk2scholars/configs/agents/talk2scholars/zotero_agent/default.yaml,sha256=lWBreotqsu1jlHi1uZ9vY60zi-MiiG2VuHxo5IoAvkE,1112
152
154
  aiagents4pharma/talk2scholars/configs/app/__init__.py,sha256=JoSZV6N669kGMv5zLDszwf0ZjcRHx9TJfIqGhIIdPXE,70
153
155
  aiagents4pharma/talk2scholars/configs/app/frontend/__init__.py,sha256=fqQQ-GlRcbzru2KmEk3oMma0R6_SzGM8dOXzYeU4oVA,46
154
156
  aiagents4pharma/talk2scholars/configs/app/frontend/default.yaml,sha256=wsELBdRLv6UqZ9QZfwpS7K4xfMj5s-a99-aXqIs6WEI,868
155
- aiagents4pharma/talk2scholars/configs/tools/__init__.py,sha256=z5PzYS1WyoC4PiWVIIOGICldps2yMh2E_2HFZA9ltpQ,177
157
+ aiagents4pharma/talk2scholars/configs/tools/__init__.py,sha256=GwpgnRrfjyZDVsangewSVTG3H3GBYM6s_YaQd9-zI10,238
156
158
  aiagents4pharma/talk2scholars/configs/tools/multi_paper_recommendation/__init__.py,sha256=fqQQ-GlRcbzru2KmEk3oMma0R6_SzGM8dOXzYeU4oVA,46
157
- aiagents4pharma/talk2scholars/configs/tools/multi_paper_recommendation/default.yaml,sha256=iEsEW89MlQwKsAW4ZAxLt4pDBwA1qxImYQ2dfONIf6c,442
159
+ aiagents4pharma/talk2scholars/configs/tools/multi_paper_recommendation/default.yaml,sha256=QV7HrG7NdjBEjTMszh27MbGBYMbf_78V3sCGftdTtvo,442
160
+ aiagents4pharma/talk2scholars/configs/tools/question_and_answer/__init__.py,sha256=fqQQ-GlRcbzru2KmEk3oMma0R6_SzGM8dOXzYeU4oVA,46
158
161
  aiagents4pharma/talk2scholars/configs/tools/retrieve_semantic_scholar_paper_id/__init__.py,sha256=fqQQ-GlRcbzru2KmEk3oMma0R6_SzGM8dOXzYeU4oVA,46
159
162
  aiagents4pharma/talk2scholars/configs/tools/retrieve_semantic_scholar_paper_id/default.yaml,sha256=HG-N8yRjlX9zFwbIBvaDI9ndKjfL-gqPTCCPMLgdUpw,271
160
163
  aiagents4pharma/talk2scholars/configs/tools/search/__init__.py,sha256=fqQQ-GlRcbzru2KmEk3oMma0R6_SzGM8dOXzYeU4oVA,46
161
- aiagents4pharma/talk2scholars/configs/tools/search/default.yaml,sha256=tw8N1Mms0qHQbIY3KGDNK1NuT19dQGPiagxzWDdOAJk,504
164
+ aiagents4pharma/talk2scholars/configs/tools/search/default.yaml,sha256=153R4NmtG2bGKpxwo73tR15IetGKdrD4QgZRlz8zS18,504
162
165
  aiagents4pharma/talk2scholars/configs/tools/single_paper_recommendation/__init__.py,sha256=fqQQ-GlRcbzru2KmEk3oMma0R6_SzGM8dOXzYeU4oVA,46
163
- aiagents4pharma/talk2scholars/configs/tools/single_paper_recommendation/default.yaml,sha256=TILecrowsu5VGdJPeac6fl5AXSf3piSHN0oKdjY2q1o,596
166
+ aiagents4pharma/talk2scholars/configs/tools/single_paper_recommendation/default.yaml,sha256=1QtFWqnGftIipftlALnG_IdCAOwzJTyOpUSUfWqQ7cA,596
164
167
  aiagents4pharma/talk2scholars/configs/tools/zotero_read/__init__.py,sha256=fqQQ-GlRcbzru2KmEk3oMma0R6_SzGM8dOXzYeU4oVA,46
165
- aiagents4pharma/talk2scholars/configs/tools/zotero_read/default.yaml,sha256=iILspz9EvN8jpVHzMsW3L9BDEST5eqOUO7TnhxwXBrI,468
168
+ aiagents4pharma/talk2scholars/configs/tools/zotero_read/default.yaml,sha256=6ZvZdCsnudPeVjnatv78Z0QfMwsHZuliE2RCIRCW05Y,1221
169
+ aiagents4pharma/talk2scholars/configs/tools/zotero_write/__inti__.py,sha256=fqQQ-GlRcbzru2KmEk3oMma0R6_SzGM8dOXzYeU4oVA,46
166
170
  aiagents4pharma/talk2scholars/state/__init__.py,sha256=S6SxlszIMZSIMJehjevPF9sKyR-PAwWb5TEdo6xWXE8,103
167
- aiagents4pharma/talk2scholars/state/state_talk2scholars.py,sha256=DoCtKP2qd69mXPwfOb-aYw9Hq2fYmx6b76S-HlsVSNo,2382
171
+ aiagents4pharma/talk2scholars/state/state_talk2scholars.py,sha256=E0epqlBurzNcMzN4WV6nh--YkVAesbxQTuBBlJhESVA,2436
168
172
  aiagents4pharma/talk2scholars/tests/__init__.py,sha256=U3PsTiUZaUBD1IZanFGkDIOdFieDVJtGKQ5-woYUo8c,45
169
- aiagents4pharma/talk2scholars/tests/test_call_s2.py,sha256=ZL5HmnYNVyaBJgPGQi9JnbD1d1rtWnWusVxVRVW3aHc,3375
170
- aiagents4pharma/talk2scholars/tests/test_call_zotero.py,sha256=N4g6Pt2vuaxIhHQbIqlMaDUF4O7vIvRqa7pPIkpL8FI,3314
171
173
  aiagents4pharma/talk2scholars/tests/test_llm_main_integration.py,sha256=SAMG-Kb2S9sei8Us5vUWCUJikTKXPZVKQ6aJJPEhJsc,1880
172
- aiagents4pharma/talk2scholars/tests/test_main_agent.py,sha256=8FKujCVhkurCe5IE6OGPTmz1p4eH1CDi467vM6VtM5A,4318
174
+ aiagents4pharma/talk2scholars/tests/test_main_agent.py,sha256=5QnOPKNrQCd5GdYU-vVF3bUrmitOsUcazZA7BsXeomo,5947
175
+ aiagents4pharma/talk2scholars/tests/test_pdf_agent.py,sha256=TN4Sq5-SCxv-9VfFyq7sOlBlxbekmnWuB7-qh4MrhkA,4656
176
+ aiagents4pharma/talk2scholars/tests/test_question_and_answer_tool.py,sha256=TpCDiGfsC2y6bOkm0ZTXjT1Vp8D-Po25wiEH5aDT_DA,6491
173
177
  aiagents4pharma/talk2scholars/tests/test_routing_logic.py,sha256=AZrvaEBDk51KL6edrZY3GpQ_N6VbrlADqXFeg_jxDoQ,2284
174
178
  aiagents4pharma/talk2scholars/tests/test_s2_agent.py,sha256=BhW1wGc-wUPS4fwNBQRtBXJaJ_i7L6t_G9Bq57fK7rI,7784
175
- aiagents4pharma/talk2scholars/tests/test_s2_tools.py,sha256=QEwraJk9_Kp6ZSGYyYDXWH62wIjSwi1Pptwwbx1fuG0,13176
179
+ aiagents4pharma/talk2scholars/tests/test_s2_display.py,sha256=w1TqgEdl9WpW_A2Ud1slfI5fkRFkKtKadAlkEfSLOZk,2247
180
+ aiagents4pharma/talk2scholars/tests/test_s2_multi.py,sha256=fkTQ268WqOYvJEtTteVJ7eav3QuMAahhYR6LOnx1Huk,10161
181
+ aiagents4pharma/talk2scholars/tests/test_s2_query.py,sha256=hEcBt142nn_bKV9lor__Yk4LusgE1tN5dA-qpT606Bc,2443
182
+ aiagents4pharma/talk2scholars/tests/test_s2_retrieve.py,sha256=YtA2nbPRtoSR7mPqEjqLF5ERGVzTfeULztsNoCI48X8,2003
183
+ aiagents4pharma/talk2scholars/tests/test_s2_search.py,sha256=ZnfBO0b9xMwMvT1oaw1yIFxLToSej1_KSyEzHr6HbOQ,9068
184
+ aiagents4pharma/talk2scholars/tests/test_s2_single.py,sha256=J4r_J4gPeIIWAIUlahClINnCu7bEiW5AcphRNChv2Eo,9317
176
185
  aiagents4pharma/talk2scholars/tests/test_state.py,sha256=_iHXvoZnU_eruf8l1sQKBSCIVnxNkH_9VzkVtZZA6bY,384
177
186
  aiagents4pharma/talk2scholars/tests/test_zotero_agent.py,sha256=3TKz6yjNfYulaQv-MBv1zXCmR9xh9g3ju4Ge5HDdt1o,6136
178
- aiagents4pharma/talk2scholars/tests/test_zotero_tool.py,sha256=LI7KBTxPga7E-841pugjpNqtWgoIz0mDIJEZzdIL9eI,5759
179
- aiagents4pharma/talk2scholars/tools/__init__.py,sha256=-9iXVIGzFLak6a14Ib8yDg1bfiHgJz2nAhwWEk1jhOk,89
187
+ aiagents4pharma/talk2scholars/tests/test_zotero_path.py,sha256=XeXYqTlSkJgZ02tCz84VNDHGYnmrxrGFLxlLq_Bargs,2356
188
+ aiagents4pharma/talk2scholars/tests/test_zotero_read.py,sha256=vLAPAFeL8MjDju_HlsLnio-9HxzN1RqOApr9jyemYBk,14951
189
+ aiagents4pharma/talk2scholars/tests/test_zotero_write.py,sha256=76V7ezb6Xw-BEEwdJQvJs78JPGRYpAsijHIi3bTGsW8,23206
190
+ aiagents4pharma/talk2scholars/tools/__init__.py,sha256=UtGutYNNaRcr2nOmT_XqbTiaJpgVYKo3KVGVPFVrX2Y,107
191
+ aiagents4pharma/talk2scholars/tools/pdf/__init__.py,sha256=WOm-o-fFzyjFZBaHg658Gjzdiu1Kt-h9xvzvw0hR7aE,103
192
+ aiagents4pharma/talk2scholars/tools/pdf/question_and_answer.py,sha256=22JvT7F0rY11TF40pBfe9Cn2Y-6Tx73NfWDt4NJv700,6639
180
193
  aiagents4pharma/talk2scholars/tools/s2/__init__.py,sha256=wytqCmGm8Fbl8y5qLdIkxhhG8VHLYMifCGjbH_LK2Fc,258
181
194
  aiagents4pharma/talk2scholars/tools/s2/display_results.py,sha256=UR0PtEHGDpOhPH0Di5HT8-Fip2RkEMTJgzROsChb1gc,2959
182
- aiagents4pharma/talk2scholars/tools/s2/multi_paper_rec.py,sha256=QM30Oq3518cuEWwpfA5R7NzNmNklYUkt9Y1D5jdjmG4,5430
183
- aiagents4pharma/talk2scholars/tools/s2/query_results.py,sha256=EUfzRh5Qc_tMl5fDIFb9PIsQkkrU4Xb5MR0sud_X5-c,2017
184
- aiagents4pharma/talk2scholars/tools/s2/retrieve_semantic_scholar_paper_id.py,sha256=Lg1L4HQCN2LaQEyWtLD73O67PMoXkPHi-Y8rCzHS0A4,2499
185
- aiagents4pharma/talk2scholars/tools/s2/search.py,sha256=i5KMFJWK31CjYtVT1McJpLzgcwvyTHZe2aHZlscfK3Q,4667
186
- aiagents4pharma/talk2scholars/tools/s2/single_paper_rec.py,sha256=7PoZfcstxDThWX6NYOgxN_9M_nwgMPAALch8OmjraVY,5568
187
- aiagents4pharma/talk2scholars/tools/zotero/__init__.py,sha256=1UW4r5ECvAwYpo1Fjf7lQPO--M8I85baYCHocFOAq4M,53
188
- aiagents4pharma/talk2scholars/tools/zotero/zotero_read.py,sha256=NJ65fAJ4u2Zq15uvEajVOhI4QnNvyqA6FHPaEDqvMw0,4321
189
- aiagents4pharma-1.27.2.dist-info/LICENSE,sha256=IcIbyB1Hyk5ZDah03VNQvJkbNk2hkBCDqQ8qtnCvB4Q,1077
190
- aiagents4pharma-1.27.2.dist-info/METADATA,sha256=Awt5OTnDlzVBDMXh0VTkcr95PcyrMQ8aNusmrhOOaZU,13252
191
- aiagents4pharma-1.27.2.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
192
- aiagents4pharma-1.27.2.dist-info/top_level.txt,sha256=-AH8rMmrSnJtq7HaAObS78UU-cTCwvX660dSxeM7a0A,16
193
- aiagents4pharma-1.27.2.dist-info/RECORD,,
195
+ aiagents4pharma/talk2scholars/tools/s2/multi_paper_rec.py,sha256=Y-nIjtPSYvL7kLaN9_cueQM-VZF1SPZZ1_FB8KhS0XY,6352
196
+ aiagents4pharma/talk2scholars/tools/s2/query_results.py,sha256=S4yBNtg1loDu4ckLPrW4H8GAswriPaRU4U08cOuw2HE,2028
197
+ aiagents4pharma/talk2scholars/tools/s2/retrieve_semantic_scholar_paper_id.py,sha256=llzMMnEQKeYVamJbF4_DTMx-BgVe79vwDcUIFGLrmUY,2615
198
+ aiagents4pharma/talk2scholars/tools/s2/search.py,sha256=496sv4aAfqB65zgjNxU2AGnhclcRRNF0VuG4fguN3gw,5319
199
+ aiagents4pharma/talk2scholars/tools/s2/single_paper_rec.py,sha256=YJ1P-BAn5d2vGKIg3OTsYH1g8as5LeqaRuraL0buqJo,6095
200
+ aiagents4pharma/talk2scholars/tools/zotero/__init__.py,sha256=HF47ta_r94Y4gP3fK3WG_ix8kg1zUQw8yWjLJksnTfc,100
201
+ aiagents4pharma/talk2scholars/tools/zotero/zotero_read.py,sha256=eRqdQCyWws8q6iC_w4OIBR6w9Ha5x5UT5S8jifNxcqw,6142
202
+ aiagents4pharma/talk2scholars/tools/zotero/zotero_write.py,sha256=dqYc5HWMK3vz77psHYUosMLE63NYg9Nk6xbWy8TOrU4,9246
203
+ aiagents4pharma/talk2scholars/tools/zotero/utils/__init__.py,sha256=Ll8YQZj9sYJpXmoGxj_0ZcuEHDj06_CUqdDlTlevGL4,53
204
+ aiagents4pharma/talk2scholars/tools/zotero/utils/zotero_path.py,sha256=nHmYe3kcrygNOslHki4YeMztfnmRDPul4gZvXl_XsV0,1954
205
+ aiagents4pharma-1.29.0.dist-info/LICENSE,sha256=IcIbyB1Hyk5ZDah03VNQvJkbNk2hkBCDqQ8qtnCvB4Q,1077
206
+ aiagents4pharma-1.29.0.dist-info/METADATA,sha256=qYpzGvw6Raduy-RwlrnMNTElHqb4HP9n3LslreZaNl0,13245
207
+ aiagents4pharma-1.29.0.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
208
+ aiagents4pharma-1.29.0.dist-info/top_level.txt,sha256=-AH8rMmrSnJtq7HaAObS78UU-cTCwvX660dSxeM7a0A,16
209
+ aiagents4pharma-1.29.0.dist-info/RECORD,,