aiagents4pharma 1.28.0__py3-none-any.whl → 1.30.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.
- aiagents4pharma/talk2scholars/agents/__init__.py +1 -0
- aiagents4pharma/talk2scholars/agents/main_agent.py +35 -209
- aiagents4pharma/talk2scholars/agents/paper_download_agent.py +86 -0
- aiagents4pharma/talk2scholars/agents/s2_agent.py +10 -6
- aiagents4pharma/talk2scholars/agents/zotero_agent.py +12 -6
- aiagents4pharma/talk2scholars/configs/agents/talk2scholars/main_agent/default.yaml +2 -48
- aiagents4pharma/talk2scholars/configs/agents/talk2scholars/paper_download_agent/__init__.py +3 -0
- aiagents4pharma/talk2scholars/configs/agents/talk2scholars/s2_agent/default.yaml +5 -28
- aiagents4pharma/talk2scholars/configs/agents/talk2scholars/zotero_agent/default.yaml +5 -21
- aiagents4pharma/talk2scholars/configs/config.yaml +3 -0
- aiagents4pharma/talk2scholars/configs/tools/__init__.py +1 -0
- aiagents4pharma/talk2scholars/configs/tools/download_arxiv_paper/__init__.py +3 -0
- aiagents4pharma/talk2scholars/configs/tools/multi_paper_recommendation/default.yaml +1 -1
- aiagents4pharma/talk2scholars/configs/tools/search/default.yaml +1 -1
- aiagents4pharma/talk2scholars/configs/tools/single_paper_recommendation/default.yaml +1 -1
- aiagents4pharma/talk2scholars/configs/tools/zotero_read/default.yaml +42 -1
- aiagents4pharma/talk2scholars/configs/tools/zotero_write/__inti__.py +3 -0
- aiagents4pharma/talk2scholars/state/state_talk2scholars.py +1 -0
- aiagents4pharma/talk2scholars/tests/test_main_agent.py +186 -111
- aiagents4pharma/talk2scholars/tests/test_paper_download_agent.py +142 -0
- aiagents4pharma/talk2scholars/tests/test_paper_download_tools.py +154 -0
- aiagents4pharma/talk2scholars/tests/test_s2_display.py +74 -0
- aiagents4pharma/talk2scholars/tests/test_s2_multi.py +282 -0
- aiagents4pharma/talk2scholars/tests/test_s2_query.py +78 -0
- aiagents4pharma/talk2scholars/tests/test_s2_retrieve.py +65 -0
- aiagents4pharma/talk2scholars/tests/test_s2_search.py +266 -0
- aiagents4pharma/talk2scholars/tests/test_s2_single.py +274 -0
- aiagents4pharma/talk2scholars/tests/test_zotero_path.py +57 -0
- aiagents4pharma/talk2scholars/tests/test_zotero_read.py +412 -0
- aiagents4pharma/talk2scholars/tests/test_zotero_write.py +626 -0
- aiagents4pharma/talk2scholars/tools/paper_download/__init__.py +17 -0
- aiagents4pharma/talk2scholars/tools/paper_download/abstract_downloader.py +43 -0
- aiagents4pharma/talk2scholars/tools/paper_download/arxiv_downloader.py +108 -0
- aiagents4pharma/talk2scholars/tools/paper_download/download_arxiv_input.py +60 -0
- aiagents4pharma/talk2scholars/tools/s2/multi_paper_rec.py +50 -34
- aiagents4pharma/talk2scholars/tools/s2/retrieve_semantic_scholar_paper_id.py +8 -8
- aiagents4pharma/talk2scholars/tools/s2/search.py +36 -23
- aiagents4pharma/talk2scholars/tools/s2/single_paper_rec.py +44 -38
- aiagents4pharma/talk2scholars/tools/zotero/__init__.py +2 -0
- aiagents4pharma/talk2scholars/tools/zotero/utils/__init__.py +5 -0
- aiagents4pharma/talk2scholars/tools/zotero/utils/zotero_path.py +63 -0
- aiagents4pharma/talk2scholars/tools/zotero/zotero_read.py +64 -19
- aiagents4pharma/talk2scholars/tools/zotero/zotero_write.py +247 -0
- {aiagents4pharma-1.28.0.dist-info → aiagents4pharma-1.30.0.dist-info}/METADATA +6 -5
- {aiagents4pharma-1.28.0.dist-info → aiagents4pharma-1.30.0.dist-info}/RECORD +48 -30
- aiagents4pharma/talk2scholars/tests/test_call_s2.py +0 -100
- aiagents4pharma/talk2scholars/tests/test_call_zotero.py +0 -94
- aiagents4pharma/talk2scholars/tests/test_s2_tools.py +0 -355
- aiagents4pharma/talk2scholars/tests/test_zotero_tool.py +0 -171
- {aiagents4pharma-1.28.0.dist-info → aiagents4pharma-1.30.0.dist-info}/LICENSE +0 -0
- {aiagents4pharma-1.28.0.dist-info → aiagents4pharma-1.30.0.dist-info}/WHEEL +0 -0
- {aiagents4pharma-1.28.0.dist-info → aiagents4pharma-1.30.0.dist-info}/top_level.txt +0 -0
@@ -9,117 +9,21 @@ for multi-agent systems and implements proper state management.
|
|
9
9
|
"""
|
10
10
|
|
11
11
|
import logging
|
12
|
-
from typing import Literal, Callable
|
13
|
-
from pydantic import BaseModel
|
14
12
|
import hydra
|
13
|
+
from langgraph_supervisor import create_supervisor
|
14
|
+
from langchain_openai import ChatOpenAI
|
15
15
|
from langchain_core.language_models.chat_models import BaseChatModel
|
16
|
-
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage
|
17
16
|
from langgraph.checkpoint.memory import MemorySaver
|
18
|
-
from
|
19
|
-
from
|
20
|
-
from ..agents import s2_agent
|
21
|
-
from ..agents import zotero_agent
|
17
|
+
from ..agents.s2_agent import get_app as get_app_s2
|
18
|
+
from ..agents.zotero_agent import get_app as get_app_zotero
|
22
19
|
from ..state.state_talk2scholars import Talk2Scholars
|
23
20
|
|
24
|
-
#
|
21
|
+
# Initialize logger
|
25
22
|
logging.basicConfig(level=logging.INFO)
|
26
23
|
logger = logging.getLogger(__name__)
|
27
24
|
|
28
25
|
|
29
|
-
def
|
30
|
-
"""
|
31
|
-
Loads the Hydra configuration for the main agent.
|
32
|
-
|
33
|
-
This function initializes the Hydra configuration system and retrieves the settings
|
34
|
-
for the `Talk2Scholars` agent, ensuring that all required parameters are loaded.
|
35
|
-
|
36
|
-
Returns:
|
37
|
-
DictConfig: The configuration object containing parameters for the main agent.
|
38
|
-
"""
|
39
|
-
with hydra.initialize(version_base=None, config_path="../configs"):
|
40
|
-
cfg = hydra.compose(
|
41
|
-
config_name="config", overrides=["agents/talk2scholars/main_agent=default"]
|
42
|
-
)
|
43
|
-
return cfg.agents.talk2scholars.main_agent
|
44
|
-
|
45
|
-
|
46
|
-
def make_supervisor_node(llm_model: BaseChatModel, thread_id: str) -> Callable:
|
47
|
-
"""
|
48
|
-
Creates the supervisor node responsible for routing user queries to the appropriate sub-agents.
|
49
|
-
|
50
|
-
This function initializes the routing logic by leveraging the system and router prompts defined
|
51
|
-
in the Hydra configuration. The supervisor determines whether to
|
52
|
-
call a sub-agent (like `s2_agent`, `zotero_agent`)
|
53
|
-
or directly generate a response using the language model.
|
54
|
-
|
55
|
-
Args:
|
56
|
-
llm_model (BaseChatModel): The language model used for decision-making.
|
57
|
-
thread_id (str): Unique identifier for the current conversation session.
|
58
|
-
|
59
|
-
Returns:
|
60
|
-
Callable: The supervisor node function that processes user queries and
|
61
|
-
decides the next step.
|
62
|
-
"""
|
63
|
-
cfg = get_hydra_config()
|
64
|
-
logger.info("Hydra configuration for Talk2Scholars main agent loaded: %s", cfg)
|
65
|
-
members = ["s2_agent", "zotero_agent"]
|
66
|
-
options = ["FINISH"] + members
|
67
|
-
# Define system prompt for general interactions
|
68
|
-
system_prompt = cfg.system_prompt
|
69
|
-
# Define router prompt for routing to sub-agents
|
70
|
-
router_prompt = cfg.router_prompt + " " + " ".join(members)
|
71
|
-
|
72
|
-
class Router(BaseModel):
|
73
|
-
"""Worker to route to next. If no workers needed, route to FINISH."""
|
74
|
-
|
75
|
-
next: Literal[*options]
|
76
|
-
|
77
|
-
def supervisor_node(
|
78
|
-
state: Talk2Scholars,
|
79
|
-
) -> Command:
|
80
|
-
"""
|
81
|
-
Handles the routing logic for the supervisor agent.
|
82
|
-
|
83
|
-
This function determines the next agent to invoke based on the router prompt response.
|
84
|
-
If no further processing is required, it generates an AI response using the system prompt.
|
85
|
-
|
86
|
-
Args:
|
87
|
-
state (Talk2Scholars): The current conversation state, including messages
|
88
|
-
exchanged so far.
|
89
|
-
|
90
|
-
Returns:
|
91
|
-
Command: A command dictating whether to invoke a sub-agent or generate a final response.
|
92
|
-
"""
|
93
|
-
messages = [SystemMessage(content=router_prompt)] + list(state["messages"])
|
94
|
-
structured_llm = llm_model.with_structured_output(Router)
|
95
|
-
response = structured_llm.invoke(messages)
|
96
|
-
goto = response.next
|
97
|
-
logger.info("Routing to: %s, Thread ID: %s", goto, thread_id)
|
98
|
-
if goto == "FINISH":
|
99
|
-
goto = END # Using END from langgraph.graph
|
100
|
-
# If no agents were called, and the last message was
|
101
|
-
# from the user, call the LLM to respond to the user
|
102
|
-
# with a slightly different system prompt.
|
103
|
-
if isinstance(messages[-1], HumanMessage):
|
104
|
-
response = llm_model.invoke(
|
105
|
-
[
|
106
|
-
SystemMessage(content=system_prompt),
|
107
|
-
]
|
108
|
-
+ messages[1:]
|
109
|
-
)
|
110
|
-
return Command(
|
111
|
-
goto=goto, update={"messages": AIMessage(content=response.content)}
|
112
|
-
)
|
113
|
-
# Go to the requested agent
|
114
|
-
return Command(goto=goto)
|
115
|
-
|
116
|
-
return supervisor_node
|
117
|
-
|
118
|
-
|
119
|
-
def get_app(
|
120
|
-
thread_id: str,
|
121
|
-
llm_model: BaseChatModel
|
122
|
-
):
|
26
|
+
def get_app(uniq_id, llm_model: BaseChatModel):
|
123
27
|
"""
|
124
28
|
Initializes and returns the LangGraph-based hierarchical agent system.
|
125
29
|
|
@@ -139,114 +43,36 @@ def get_app(
|
|
139
43
|
>>> app = get_app("thread_123")
|
140
44
|
>>> result = app.invoke(initial_state)
|
141
45
|
"""
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
"""
|
148
|
-
Invokes the Semantic Scholar (S2) agent to retrieve relevant research papers.
|
149
|
-
|
150
|
-
This function calls the `s2_agent` and updates the conversation state with retrieved
|
151
|
-
academic papers. The agent uses Semantic Scholar's API to find papers based on
|
152
|
-
user queries.
|
153
|
-
|
154
|
-
Args:
|
155
|
-
state (Talk2Scholars): The current state of the conversation, containing messages
|
156
|
-
and any previous search results.
|
157
|
-
|
158
|
-
Returns:
|
159
|
-
Command: A command to update the conversation state with the retrieved papers
|
160
|
-
and return control to the supervisor node.
|
161
|
-
|
162
|
-
Example:
|
163
|
-
>>> result = call_s2_agent(current_state)
|
164
|
-
>>> next_step = result.goto
|
165
|
-
"""
|
166
|
-
logger.info("Calling S2 agent")
|
167
|
-
app = s2_agent.get_app(thread_id, llm_model)
|
168
|
-
|
169
|
-
# Invoke the S2 agent, passing state,
|
170
|
-
# Pass both config_id and thread_id
|
171
|
-
response = app.invoke(
|
172
|
-
state,
|
173
|
-
{
|
174
|
-
"configurable": {
|
175
|
-
"config_id": thread_id,
|
176
|
-
"thread_id": thread_id,
|
177
|
-
}
|
178
|
-
},
|
46
|
+
if llm_model.model_name == "gpt-4o-mini":
|
47
|
+
llm_model = ChatOpenAI(
|
48
|
+
model="gpt-4o-mini",
|
49
|
+
temperature=0,
|
50
|
+
model_kwargs={"parallel_tool_calls": False},
|
179
51
|
)
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
"multi_papers": response.get("multi_papers", {}),
|
186
|
-
"last_displayed_papers": response.get("last_displayed_papers", {}),
|
187
|
-
},
|
188
|
-
# Always return to supervisor
|
189
|
-
goto="supervisor",
|
190
|
-
)
|
191
|
-
|
192
|
-
def call_zotero_agent(
|
193
|
-
state: Talk2Scholars,
|
194
|
-
) -> Command[Literal["supervisor"]]:
|
195
|
-
"""
|
196
|
-
Invokes the Zotero agent to retrieve and process papers from the user's Zotero library.
|
197
|
-
|
198
|
-
This function calls the Zotero agent, which interacts with the user's Zotero database
|
199
|
-
to retrieve relevant papers based on the conversation context. It updates the
|
200
|
-
conversation state with the retrieved papers and relevant metadata.
|
201
|
-
|
202
|
-
Args:
|
203
|
-
state (Talk2Scholars): The current conversation state, containing user messages
|
204
|
-
and any previously retrieved Zotero data.
|
205
|
-
|
206
|
-
Returns:
|
207
|
-
Command: A command that updates the conversation state with retrieved Zotero
|
208
|
-
papers and metadata before returning control to the supervisor node.
|
209
|
-
|
210
|
-
Example:
|
211
|
-
>>> result = call_zotero_agent(current_state)
|
212
|
-
>>> next_step = result.goto
|
213
|
-
"""
|
214
|
-
logger.info("Calling Zotero agent")
|
215
|
-
app = zotero_agent.get_app(thread_id, llm_model)
|
216
|
-
# Invoke the Zotero agent, passing state
|
217
|
-
response = app.invoke(
|
218
|
-
state,
|
219
|
-
{
|
220
|
-
"configurable": {
|
221
|
-
"config_id": thread_id,
|
222
|
-
"thread_id": thread_id,
|
223
|
-
}
|
224
|
-
},
|
225
|
-
)
|
226
|
-
logger.info("Zotero agent completed with response")
|
227
|
-
return Command(
|
228
|
-
update={
|
229
|
-
"messages": response["messages"],
|
230
|
-
"zotero_read": response.get("zotero_read", {}),
|
231
|
-
"last_displayed_papers": response.get("last_displayed_papers", {}),
|
232
|
-
},
|
233
|
-
# Always return to supervisor
|
234
|
-
goto="supervisor",
|
52
|
+
# Load hydra configuration
|
53
|
+
logger.log(logging.INFO, "Launching Talk2Scholars with thread_id %s", uniq_id)
|
54
|
+
with hydra.initialize(version_base=None, config_path="../configs/"):
|
55
|
+
cfg = hydra.compose(
|
56
|
+
config_name="config", overrides=["agents/talk2scholars/main_agent=default"]
|
235
57
|
)
|
58
|
+
cfg = cfg.agents.talk2scholars.main_agent
|
59
|
+
logger.log(logging.INFO, "System_prompt of Talk2Scholars: %s", cfg.system_prompt)
|
60
|
+
# Create supervisor workflow
|
61
|
+
workflow = create_supervisor(
|
62
|
+
[
|
63
|
+
get_app_s2(uniq_id, llm_model), # semantic scholar
|
64
|
+
get_app_zotero(uniq_id, llm_model), # zotero
|
65
|
+
],
|
66
|
+
model=llm_model,
|
67
|
+
state_schema=Talk2Scholars,
|
68
|
+
# Full history is needed to extract
|
69
|
+
# the tool artifacts
|
70
|
+
output_mode="full_history",
|
71
|
+
add_handoff_back_messages=False,
|
72
|
+
prompt=cfg.system_prompt,
|
73
|
+
)
|
74
|
+
|
75
|
+
# Compile and run
|
76
|
+
app = workflow.compile(checkpointer=MemorySaver(), name="Talk2Scholars_MainAgent")
|
236
77
|
|
237
|
-
# Initialize LLM
|
238
|
-
logger.info("Using model %s with temperature %s", llm_model, cfg.temperature)
|
239
|
-
|
240
|
-
# Build the graph
|
241
|
-
workflow = StateGraph(Talk2Scholars)
|
242
|
-
supervisor = make_supervisor_node(llm_model, thread_id)
|
243
|
-
# Add nodes
|
244
|
-
workflow.add_node("supervisor", supervisor)
|
245
|
-
workflow.add_node("s2_agent", call_s2_agent)
|
246
|
-
workflow.add_node("zotero_agent", call_zotero_agent)
|
247
|
-
# Add edges
|
248
|
-
workflow.add_edge(START, "supervisor")
|
249
|
-
# Compile the workflow
|
250
|
-
app = workflow.compile(checkpointer=MemorySaver())
|
251
|
-
logger.info("Main agent workflow compiled")
|
252
78
|
return app
|
@@ -0,0 +1,86 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
"""
|
3
|
+
This module defines the paper download agent that connects to the arXiv API to fetch
|
4
|
+
paper details and PDFs. It is part of the Talk2Scholars project.
|
5
|
+
"""
|
6
|
+
|
7
|
+
import logging
|
8
|
+
from typing import Any, Dict
|
9
|
+
import hydra
|
10
|
+
from langchain_core.language_models.chat_models import BaseChatModel
|
11
|
+
from langgraph.graph import START, StateGraph
|
12
|
+
from langgraph.prebuilt.chat_agent_executor import create_react_agent
|
13
|
+
from langgraph.prebuilt.tool_node import ToolNode
|
14
|
+
from langgraph.checkpoint.memory import MemorySaver
|
15
|
+
from ..state.state_talk2scholars import Talk2Scholars
|
16
|
+
from ..tools.paper_download import download_arxiv_paper
|
17
|
+
from ..tools.s2.query_results import query_results
|
18
|
+
|
19
|
+
# Initialize logger
|
20
|
+
logging.basicConfig(level=logging.INFO)
|
21
|
+
logger = logging.getLogger(__name__)
|
22
|
+
|
23
|
+
def get_app(uniq_id, llm_model: BaseChatModel):
|
24
|
+
"""
|
25
|
+
Initializes and returns the LangGraph application for the Talk2Scholars paper download agent.
|
26
|
+
|
27
|
+
Args:
|
28
|
+
uniq_id (str): A unique identifier for tracking the current session.
|
29
|
+
llm_model (BaseChatModel, optional): The language model to be used by the agent.
|
30
|
+
Defaults to ChatOpenAI(model="gpt-4o-mini", temperature=0.5).
|
31
|
+
|
32
|
+
Returns:
|
33
|
+
StateGraph: A compiled LangGraph application that enables the paper download agent to
|
34
|
+
process user queries and retrieve arXiv papers.
|
35
|
+
"""
|
36
|
+
|
37
|
+
# Load Hydra configuration
|
38
|
+
logger.info("Loading Hydra configuration for Talk2Scholars paper download agent")
|
39
|
+
with hydra.initialize(version_base=None, config_path="../configs"):
|
40
|
+
cfg = hydra.compose(
|
41
|
+
config_name="config",
|
42
|
+
overrides=["agents/talk2scholars/paper_download_agent=default"]
|
43
|
+
)
|
44
|
+
cfg = cfg.agents.talk2scholars.paper_download_agent
|
45
|
+
|
46
|
+
# Define tools properly
|
47
|
+
tools = ToolNode(
|
48
|
+
[download_arxiv_paper, query_results]
|
49
|
+
)
|
50
|
+
|
51
|
+
# Define the model
|
52
|
+
logger.info("Using OpenAI model %s", llm_model)
|
53
|
+
model = create_react_agent(
|
54
|
+
llm_model,
|
55
|
+
tools=tools,
|
56
|
+
state_schema=Talk2Scholars,
|
57
|
+
prompt=cfg.prompt,
|
58
|
+
checkpointer=MemorySaver(),
|
59
|
+
)
|
60
|
+
|
61
|
+
def paper_download_agent_node(state: Talk2Scholars) -> Dict[str, Any]:
|
62
|
+
"""
|
63
|
+
Processes the current state to fetch the arXiv paper.
|
64
|
+
"""
|
65
|
+
logger.info("Creating paper download agent node with thread_id: %s", uniq_id)
|
66
|
+
result = model.invoke(state, {"configurable": {"thread_id": uniq_id}})
|
67
|
+
return result
|
68
|
+
|
69
|
+
# Define new graph
|
70
|
+
workflow = StateGraph(Talk2Scholars)
|
71
|
+
|
72
|
+
# Adding node for paper download agent
|
73
|
+
workflow.add_node("paper_download_agent", paper_download_agent_node)
|
74
|
+
|
75
|
+
# Entering into the agent
|
76
|
+
workflow.add_edge(START, "paper_download_agent")
|
77
|
+
|
78
|
+
# Memory management for states between graph runs
|
79
|
+
checkpointer = MemorySaver()
|
80
|
+
|
81
|
+
# Compile the graph
|
82
|
+
app = workflow.compile(checkpointer=checkpointer)
|
83
|
+
|
84
|
+
# Logging the information and returning the app
|
85
|
+
logger.info("Compiled the graph")
|
86
|
+
return app
|
@@ -28,9 +28,7 @@ logging.basicConfig(level=logging.INFO)
|
|
28
28
|
logger = logging.getLogger(__name__)
|
29
29
|
|
30
30
|
|
31
|
-
def get_app(
|
32
|
-
uniq_id, llm_model: BaseChatModel
|
33
|
-
):
|
31
|
+
def get_app(uniq_id, llm_model: BaseChatModel):
|
34
32
|
"""
|
35
33
|
Initializes and returns the LangGraph application for the Semantic Scholar (S2) agent.
|
36
34
|
|
@@ -86,6 +84,7 @@ def get_app(
|
|
86
84
|
config_name="config", overrides=["agents/talk2scholars/s2_agent=default"]
|
87
85
|
)
|
88
86
|
cfg = cfg.agents.talk2scholars.s2_agent
|
87
|
+
logger.log(logging.INFO, "Loaded configuration for S2 agent")
|
89
88
|
|
90
89
|
# Define the tools
|
91
90
|
tools = ToolNode(
|
@@ -107,7 +106,7 @@ def get_app(
|
|
107
106
|
llm_model,
|
108
107
|
tools=tools,
|
109
108
|
state_schema=Talk2Scholars,
|
110
|
-
|
109
|
+
prompt=cfg.s2_agent,
|
111
110
|
checkpointer=MemorySaver(),
|
112
111
|
)
|
113
112
|
|
@@ -122,7 +121,12 @@ def get_app(
|
|
122
121
|
# This compiles it into a LangChain Runnable,
|
123
122
|
# meaning you can use it as you would any other runnable.
|
124
123
|
# Note that we're (optionally) passing the memory when compiling the graph
|
125
|
-
app = workflow.compile(checkpointer=checkpointer)
|
126
|
-
logger.log(
|
124
|
+
app = workflow.compile(checkpointer=checkpointer, name="agent_s2")
|
125
|
+
logger.log(
|
126
|
+
logging.INFO,
|
127
|
+
"Compiled the graph with thread_id %s and llm_model %s",
|
128
|
+
uniq_id,
|
129
|
+
llm_model,
|
130
|
+
)
|
127
131
|
|
128
132
|
return app
|
@@ -14,6 +14,7 @@ from langgraph.prebuilt import create_react_agent, ToolNode
|
|
14
14
|
from langgraph.checkpoint.memory import MemorySaver
|
15
15
|
from ..state.state_talk2scholars import Talk2Scholars
|
16
16
|
from ..tools.zotero.zotero_read import zotero_search_tool
|
17
|
+
from ..tools.zotero.zotero_write import zotero_save_tool
|
17
18
|
from ..tools.s2.display_results import display_results as s2_display
|
18
19
|
from ..tools.s2.query_results import query_results as s2_query_results
|
19
20
|
from ..tools.s2.retrieve_semantic_scholar_paper_id import (
|
@@ -25,9 +26,7 @@ logging.basicConfig(level=logging.INFO)
|
|
25
26
|
logger = logging.getLogger(__name__)
|
26
27
|
|
27
28
|
|
28
|
-
def get_app(
|
29
|
-
uniq_id, llm_model: BaseChatModel
|
30
|
-
):
|
29
|
+
def get_app(uniq_id, llm_model: BaseChatModel):
|
31
30
|
"""
|
32
31
|
Initializes and returns the LangGraph application for the Zotero agent.
|
33
32
|
|
@@ -83,6 +82,7 @@ def get_app(
|
|
83
82
|
overrides=["agents/talk2scholars/zotero_agent=default"],
|
84
83
|
)
|
85
84
|
cfg = cfg.agents.talk2scholars.zotero_agent
|
85
|
+
logger.log(logging.INFO, "Loaded configuration for Zotero agent")
|
86
86
|
|
87
87
|
# Define the tools
|
88
88
|
tools = ToolNode(
|
@@ -91,6 +91,7 @@ def get_app(
|
|
91
91
|
s2_display,
|
92
92
|
s2_query_results,
|
93
93
|
retrieve_semantic_scholar_paper_id,
|
94
|
+
zotero_save_tool,
|
94
95
|
]
|
95
96
|
)
|
96
97
|
|
@@ -102,7 +103,7 @@ def get_app(
|
|
102
103
|
llm_model,
|
103
104
|
tools=tools,
|
104
105
|
state_schema=Talk2Scholars,
|
105
|
-
|
106
|
+
prompt=cfg.zotero_agent,
|
106
107
|
checkpointer=MemorySaver(),
|
107
108
|
)
|
108
109
|
|
@@ -114,7 +115,12 @@ def get_app(
|
|
114
115
|
checkpointer = MemorySaver()
|
115
116
|
|
116
117
|
# Compile the graph
|
117
|
-
app = workflow.compile(checkpointer=checkpointer)
|
118
|
-
logger.log(
|
118
|
+
app = workflow.compile(checkpointer=checkpointer, name="agent_zotero")
|
119
|
+
logger.log(
|
120
|
+
logging.INFO,
|
121
|
+
"Compiled the graph with thread_id %s and llm_model %s",
|
122
|
+
uniq_id,
|
123
|
+
llm_model,
|
124
|
+
)
|
119
125
|
|
120
126
|
return app
|
@@ -1,9 +1,4 @@
|
|
1
1
|
_target_: agents.main_agent.get_app
|
2
|
-
openai_api_key: ${oc.env:OPENAI_API_KEY}
|
3
|
-
openai_llms:
|
4
|
-
- "gpt-4o-mini"
|
5
|
-
- "gpt-4-turbo"
|
6
|
-
- "gpt-3.5-turbo"
|
7
2
|
temperature: 0
|
8
3
|
system_prompt: >
|
9
4
|
You are the Talk2Scholars agent coordinating academic paper discovery and analysis.
|
@@ -14,46 +9,5 @@ system_prompt: >
|
|
14
9
|
general paper searches and recommendations.
|
15
10
|
2. Zotero_agent: This agent can be used to retrieve, display, and query
|
16
11
|
papers from the Zotero library. Use this agent only when the user
|
17
|
-
explicitly asks for papers from Zotero.
|
18
|
-
|
19
|
-
router_prompt: >
|
20
|
-
You are a supervisor tasked with managing a conversation between the
|
21
|
-
following workers/members: ["s2_agent", "zotero_agent"] Given the user request, respond with the
|
22
|
-
worker to act next. Each worker will perform a task and respond with
|
23
|
-
their results and status. When finished, respond with FINISH.
|
24
|
-
|
25
|
-
Here is a description of the workers:
|
26
|
-
1. S2_agent: This agent can be used to search and recommend papers
|
27
|
-
from Semantic Scholar. Use this agent when the user asks for
|
28
|
-
general paper searches and recommendations. This agent can also
|
29
|
-
retrieve the Semantic Scholar ID of a paper. It can also be used to
|
30
|
-
provide more information about a paper.
|
31
|
-
2. Zotero_agent: This agent can be used to retrieve, display, and query
|
32
|
-
papers from the Zotero library. Use this agent only when the user
|
33
|
-
explicitly asks for papers from Zotero. This agent can also
|
34
|
-
retrieve the Semantic Scholar ID of a paper.
|
35
|
-
|
36
|
-
CRITICAL RULES:
|
37
|
-
1. Do not generate any content or modify worker outputs
|
38
|
-
2. Route to FINISH ONLY when a worker has COMPLETELY finished their task
|
39
|
-
3. For the S2_agent and zotero_agent, ensure it has both SEARCHED and DISPLAYED results before FINISH
|
40
|
-
|
41
|
-
Available workers: members
|
42
|
-
|
43
|
-
Worker descriptions:
|
44
|
-
1. S2_agent: Routes to this agent ONLY for:
|
45
|
-
- Initial paper searches
|
46
|
-
- Getting paper recommendations
|
47
|
-
- Retrieving paper IDs based on the title of a paper
|
48
|
-
- Displaying search/recommendation results
|
49
|
-
- Query over papers
|
50
|
-
2. Zotero_agent: Routes to this agent ONLY for:
|
51
|
-
- Paper/journals searches from Zotero library
|
52
|
-
- Displaying search results
|
53
|
-
- Retrieving paper IDs based on the title of a paper
|
54
|
-
- Query over papers
|
55
|
-
|
56
|
-
Respond with FINISH when and ONLY when:
|
57
|
-
1. A worker has COMPLETELY finished their task (including display)
|
58
|
-
2. The results have been displayed to the user using display_results
|
59
|
-
3. No further action is needed
|
12
|
+
explicitly asks for papers from Zotero. This tool can also be used to
|
13
|
+
save papers in under collections in the zotero library
|
@@ -1,42 +1,19 @@
|
|
1
1
|
_target_: agents.s2_agent.get_app
|
2
|
-
openai_api_key: ${oc.env:OPENAI_API_KEY}
|
3
|
-
openai_llms:
|
4
|
-
- "gpt-4o-mini"
|
5
|
-
- "gpt-4-turbo"
|
6
|
-
- "gpt-3.5-turbo"
|
7
|
-
temperature: 0
|
8
2
|
s2_agent: >
|
9
3
|
You are an academic research assistant with access to the
|
10
4
|
Semantic Scholar API for paper discovery and analysis.
|
11
5
|
|
12
6
|
AVAILABLE TOOLS:
|
13
|
-
1.
|
7
|
+
1. search - Search for academic papers by query string
|
14
8
|
2. display_results - Display the papers retrieved by other tools
|
15
9
|
3. single_paper_rec - Get recommendations based on a SINGLE paper
|
16
10
|
4. multi_paper_rec - Get recommendations based on MULTIPLE papers
|
17
11
|
5. query_results - Ask questions about the current set of papers
|
18
12
|
6. retrieve_semantic_scholar_paper_id - Get Semantic Scholar ID for a paper title
|
19
13
|
|
20
|
-
|
21
|
-
display them.
|
22
|
-
You must strictly rely on retrieved information and avoid
|
23
|
-
generating unsupported content. Do not generate hallucinations
|
24
|
-
or fabricate details of any article. Stay focused on accurate,
|
25
|
-
sourced academic insights.
|
26
|
-
|
27
|
-
CRITICAL INSTRUCTIONS:
|
28
|
-
1. You must ONLY use information retrieved directly from the API
|
29
|
-
2. NEVER generate or fabricate paper details
|
30
|
-
3. NEVER modify or enhance the API responses
|
31
|
-
4. If information is missing from the API response, state that it's not available
|
32
|
-
5. ALWAYS CALL THE DISPLAY_RESULTS TOOL after completing a search
|
33
|
-
|
34
|
-
WORKFLOW STEPS (ALWAYS FOLLOW THIS EXACT SEQUENCE):
|
14
|
+
WORKFLOW STEPS:
|
35
15
|
1. When user requests papers, use search/recommendation tools to find papers
|
36
|
-
2.
|
16
|
+
2. Use `display_results` tool to display the response from the search/recommendation tools
|
37
17
|
3. Use `query_results` tool to query over the selected paper only when the user asks to
|
38
|
-
4.
|
39
|
-
|
40
|
-
|
41
|
-
Remember: The display_results tool is MANDATORY after every search -
|
42
|
-
without it, users cannot see the search results.
|
18
|
+
4. When the user wants recommendations, you can get the "paper_id" using `query_results` tool in the "last_displayed_results" key, then
|
19
|
+
pass the "paper_id" to `search`, `single_paper_rec` or `multi_paper_rec` tools depending on the user's query. Do not use "arxiv_id"
|
@@ -1,10 +1,4 @@
|
|
1
1
|
target: agents.zotero_agent.get_app
|
2
|
-
openai_api_key: ${oc.env:OPENAI_API_KEY}
|
3
|
-
openai_llms:
|
4
|
-
- "gpt-4o-mini"
|
5
|
-
- "gpt-4-turbo"
|
6
|
-
- "gpt-3.5-turbo"
|
7
|
-
temperature: 0
|
8
2
|
zotero_agent: >
|
9
3
|
You are a specialized Zotero library agent with access to tools for paper retrieval and management.
|
10
4
|
|
@@ -13,23 +7,13 @@ zotero_agent: >
|
|
13
7
|
2. display_results - Display the papers retrieved by other tools
|
14
8
|
3. query_results - Ask questions about the current set of papers
|
15
9
|
4. retrieve_semantic_scholar_paper_id - Get Semantic Scholar ID for a paper title for the papers from zotero library
|
10
|
+
5. zotero_write - Save paper to users zotero library under specfied collections
|
16
11
|
|
17
|
-
You also have tools to gain more insights on the papers and display them.
|
18
|
-
You must strictly rely on retrieved information and avoid generating unsupported content. Do not generate hallucinations or fabricate details of any article. Stay focused on accurate, sourced academic insights.
|
19
12
|
|
20
|
-
|
21
|
-
1. You must ONLY use information retrieved directly from the Zotero Library
|
22
|
-
2. NEVER generate or fabricate paper details
|
23
|
-
3. NEVER modify or enhance the responses
|
24
|
-
4. If information is missing from the response, state that it's not available
|
25
|
-
5. ALWAYS CALL THE DISPLAY_RESULTS TOOL after completing a search
|
26
|
-
|
27
|
-
WORKFLOW STEPS (ALWAYS FOLLOW THIS EXACT SEQUENCE):
|
13
|
+
WORKFLOW STEPS
|
28
14
|
1. When user requests papers, use `zotero_search_tool` to find papers
|
29
|
-
2.
|
15
|
+
2. Use `display_results` tool to display the response
|
30
16
|
3. Use `query_results` tool to query over the selected paper only when the user asks to
|
31
17
|
4. Use `retrieve_semantic_scholar_paper_id` to get the semantic scholar id of a paper title for the papers from zotero library
|
32
|
-
5.
|
33
|
-
|
34
|
-
|
35
|
-
Remember: The display_results tool is MANDATORY after every search - without it, users cannot see the search results.
|
18
|
+
5. Use `zotero_write` to save the papers to users zotero library under collections and call `display_results` only after you recive
|
19
|
+
the save was successfull
|
@@ -2,12 +2,15 @@ defaults:
|
|
2
2
|
- _self_
|
3
3
|
- agents/talk2scholars/main_agent: default
|
4
4
|
- agents/talk2scholars/s2_agent: default
|
5
|
+
- agents/talk2scholars/paper_download_agent: default
|
5
6
|
- agents/talk2scholars/zotero_agent: default
|
6
7
|
- app/frontend: default
|
7
8
|
- agents/talk2scholars/pdf_agent: default
|
8
9
|
- tools/search: default
|
10
|
+
- tools/download_arxiv_paper: default
|
9
11
|
- tools/single_paper_recommendation: default
|
10
12
|
- tools/multi_paper_recommendation: default
|
11
13
|
- tools/retrieve_semantic_scholar_paper_id: default
|
12
14
|
- tools/question_and_answer: default
|
13
15
|
- tools/zotero_read: default
|
16
|
+
- tools/zotero_write: default
|