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
@@ -6,28 +6,17 @@ Main agent for the talk2scholars app using ReAct pattern.
|
|
6
6
|
This module implements a hierarchical agent system where a supervisor agent
|
7
7
|
routes queries to specialized sub-agents. It follows the LangGraph patterns
|
8
8
|
for multi-agent systems and implements proper state management.
|
9
|
-
|
10
|
-
The main components are:
|
11
|
-
1. Supervisor node with ReAct pattern for intelligent routing.
|
12
|
-
2. S2 agent node for handling academic paper queries.
|
13
|
-
3. Shared state management via Talk2Scholars.
|
14
|
-
4. Hydra-based configuration system.
|
15
|
-
|
16
|
-
Example:
|
17
|
-
app = get_app("thread_123", "gpt-4o-mini")
|
18
|
-
result = app.invoke({
|
19
|
-
"messages": [("human", "Find papers about AI agents")]
|
20
|
-
})
|
21
9
|
"""
|
22
10
|
|
23
11
|
import logging
|
24
12
|
from typing import Literal, Callable
|
13
|
+
from pydantic import BaseModel
|
25
14
|
import hydra
|
26
15
|
from langchain_core.language_models.chat_models import BaseChatModel
|
16
|
+
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage
|
27
17
|
from langchain_openai import ChatOpenAI
|
28
18
|
from langgraph.checkpoint.memory import MemorySaver
|
29
19
|
from langgraph.graph import END, START, StateGraph
|
30
|
-
from langgraph.prebuilt import create_react_agent
|
31
20
|
from langgraph.types import Command
|
32
21
|
from ..agents import s2_agent
|
33
22
|
from ..state.state_talk2scholars import Talk2Scholars
|
@@ -39,13 +28,13 @@ logger = logging.getLogger(__name__)
|
|
39
28
|
|
40
29
|
def get_hydra_config():
|
41
30
|
"""
|
42
|
-
Loads
|
31
|
+
Loads the Hydra configuration for the main agent.
|
43
32
|
|
44
|
-
This function
|
45
|
-
agent, ensuring that all required parameters are
|
33
|
+
This function initializes the Hydra configuration system and retrieves the settings
|
34
|
+
for the `Talk2Scholars` agent, ensuring that all required parameters are loaded.
|
46
35
|
|
47
36
|
Returns:
|
48
|
-
|
37
|
+
DictConfig: The configuration object containing parameters for the main agent.
|
49
38
|
"""
|
50
39
|
with hydra.initialize(version_base=None, config_path="../configs"):
|
51
40
|
cfg = hydra.compose(
|
@@ -54,116 +43,127 @@ def get_hydra_config():
|
|
54
43
|
return cfg.agents.talk2scholars.main_agent
|
55
44
|
|
56
45
|
|
57
|
-
def make_supervisor_node(
|
46
|
+
def make_supervisor_node(llm_model: BaseChatModel, thread_id: str) -> Callable:
|
58
47
|
"""
|
59
|
-
Creates
|
48
|
+
Creates the supervisor node responsible for routing user queries to the appropriate sub-agents.
|
60
49
|
|
61
|
-
This function initializes
|
62
|
-
|
63
|
-
|
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`)
|
53
|
+
or directly generate a response using the language model.
|
64
54
|
|
65
55
|
Args:
|
66
|
-
|
67
|
-
thread_id (str): Unique identifier for the conversation session.
|
56
|
+
llm_model (BaseChatModel): The language model used for decision-making.
|
57
|
+
thread_id (str): Unique identifier for the current conversation session.
|
68
58
|
|
69
59
|
Returns:
|
70
|
-
Callable:
|
71
|
-
|
72
|
-
Example:
|
73
|
-
supervisor = make_supervisor_node(llm, "thread_123")
|
74
|
-
workflow.add_node("supervisor", supervisor)
|
60
|
+
Callable: The supervisor node function that processes user queries and
|
61
|
+
decides the next step.
|
75
62
|
"""
|
76
|
-
logger.info("Loading Hydra configuration for Talk2Scholars main agent.")
|
77
63
|
cfg = get_hydra_config()
|
78
|
-
logger.info("Hydra configuration
|
64
|
+
logger.info("Hydra configuration for Talk2Scholars main agent loaded: %s", cfg)
|
65
|
+
members = ["s2_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
|
71
|
+
|
72
|
+
class Router(BaseModel):
|
73
|
+
"""Worker to route to next. If no workers needed, route to FINISH."""
|
79
74
|
|
80
|
-
|
81
|
-
supervisor_agent = create_react_agent(
|
82
|
-
llm,
|
83
|
-
tools=[], # Will add sub-agents later
|
84
|
-
state_modifier=cfg.main_agent,
|
85
|
-
state_schema=Talk2Scholars,
|
86
|
-
checkpointer=MemorySaver(),
|
87
|
-
)
|
75
|
+
next: Literal[*options]
|
88
76
|
|
89
77
|
def supervisor_node(
|
90
78
|
state: Talk2Scholars,
|
91
|
-
) -> Command
|
79
|
+
) -> Command:
|
92
80
|
"""
|
93
|
-
|
81
|
+
Handles the routing logic for the supervisor agent.
|
94
82
|
|
95
|
-
This function
|
96
|
-
|
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.
|
97
85
|
|
98
86
|
Args:
|
99
|
-
state (Talk2Scholars): The current state
|
100
|
-
|
87
|
+
state (Talk2Scholars): The current conversation state, including messages
|
88
|
+
exchanged so far.
|
101
89
|
|
102
90
|
Returns:
|
103
|
-
Command:
|
104
|
-
|
105
|
-
Example:
|
106
|
-
result = supervisor_node(current_state)
|
107
|
-
next_step = result.goto
|
91
|
+
Command: A command dictating whether to invoke a sub-agent or generate a final response.
|
108
92
|
"""
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
93
|
+
messages = [SystemMessage(content=router_prompt)] + 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
|
121
114
|
return Command(goto=goto)
|
122
115
|
|
123
116
|
return supervisor_node
|
124
117
|
|
125
118
|
|
126
|
-
def get_app(
|
119
|
+
def get_app(
|
120
|
+
thread_id: str,
|
121
|
+
llm_model: BaseChatModel = ChatOpenAI(model="gpt-4o-mini", temperature=0),
|
122
|
+
):
|
127
123
|
"""
|
128
|
-
Initializes and returns the LangGraph
|
124
|
+
Initializes and returns the LangGraph-based hierarchical agent system.
|
129
125
|
|
130
|
-
This function
|
131
|
-
and sub-agents
|
126
|
+
This function constructs the agent workflow by defining nodes for the supervisor
|
127
|
+
and sub-agents. It compiles the graph using `StateGraph` to enable structured
|
128
|
+
conversational workflows.
|
132
129
|
|
133
130
|
Args:
|
134
|
-
thread_id (str):
|
135
|
-
llm_model (
|
131
|
+
thread_id (str): A unique session identifier for tracking conversation state.
|
132
|
+
llm_model (BaseChatModel, optional): The language model used for query processing.
|
133
|
+
Defaults to `ChatOpenAI(model="gpt-4o-mini", temperature=0)`.
|
136
134
|
|
137
135
|
Returns:
|
138
|
-
StateGraph: A compiled LangGraph application
|
136
|
+
StateGraph: A compiled LangGraph application that can process user queries.
|
139
137
|
|
140
138
|
Example:
|
141
|
-
app = get_app("thread_123")
|
142
|
-
result = app.invoke(initial_state)
|
139
|
+
>>> app = get_app("thread_123")
|
140
|
+
>>> result = app.invoke(initial_state)
|
143
141
|
"""
|
144
142
|
cfg = get_hydra_config()
|
145
143
|
|
146
144
|
def call_s2_agent(
|
147
145
|
state: Talk2Scholars,
|
148
|
-
) -> Command[Literal["supervisor"
|
146
|
+
) -> Command[Literal["supervisor"]]:
|
149
147
|
"""
|
150
|
-
|
148
|
+
Invokes the Semantic Scholar (S2) agent to retrieve relevant research papers.
|
151
149
|
|
152
|
-
This function
|
153
|
-
|
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.
|
154
153
|
|
155
154
|
Args:
|
156
|
-
state (Talk2Scholars): The current conversation
|
157
|
-
and any
|
155
|
+
state (Talk2Scholars): The current state of the conversation, containing messages
|
156
|
+
and any previous search results.
|
158
157
|
|
159
158
|
Returns:
|
160
|
-
Command:
|
159
|
+
Command: A command to update the conversation state with the retrieved papers
|
160
|
+
and return control to the supervisor node.
|
161
161
|
|
162
162
|
Example:
|
163
|
-
result = call_s2_agent(current_state)
|
164
|
-
next_step = result.goto
|
163
|
+
>>> result = call_s2_agent(current_state)
|
164
|
+
>>> next_step = result.goto
|
165
165
|
"""
|
166
|
-
logger.info("Calling S2 agent
|
166
|
+
logger.info("Calling S2 agent")
|
167
167
|
app = s2_agent.get_app(thread_id, llm_model)
|
168
168
|
|
169
169
|
# Invoke the S2 agent, passing state,
|
@@ -177,31 +177,30 @@ def get_app(thread_id: str, llm_model: str = "gpt-4o-mini") -> StateGraph:
|
|
177
177
|
}
|
178
178
|
},
|
179
179
|
)
|
180
|
-
logger.info("S2 agent completed with response
|
181
|
-
|
180
|
+
logger.info("S2 agent completed with response")
|
182
181
|
return Command(
|
183
|
-
goto=END,
|
184
182
|
update={
|
185
183
|
"messages": response["messages"],
|
186
184
|
"papers": response.get("papers", {}),
|
187
185
|
"multi_papers": response.get("multi_papers", {}),
|
186
|
+
"last_displayed_papers": response.get("last_displayed_papers", {}),
|
188
187
|
},
|
188
|
+
# Always return to supervisor
|
189
|
+
goto="supervisor",
|
189
190
|
)
|
190
191
|
|
191
192
|
# Initialize LLM
|
192
|
-
logger.info("Using
|
193
|
-
llm = ChatOpenAI(model=llm_model, temperature=cfg.temperature)
|
193
|
+
logger.info("Using model %s with temperature %s", llm_model, cfg.temperature)
|
194
194
|
|
195
195
|
# Build the graph
|
196
196
|
workflow = StateGraph(Talk2Scholars)
|
197
|
-
supervisor = make_supervisor_node(
|
198
|
-
|
197
|
+
supervisor = make_supervisor_node(llm_model, thread_id)
|
198
|
+
# Add nodes
|
199
199
|
workflow.add_node("supervisor", supervisor)
|
200
200
|
workflow.add_node("s2_agent", call_s2_agent)
|
201
|
+
# Add edges
|
201
202
|
workflow.add_edge(START, "supervisor")
|
202
|
-
workflow
|
203
|
-
|
204
|
-
# Compile the graph without initial state
|
203
|
+
# Compile the workflow
|
205
204
|
app = workflow.compile(checkpointer=MemorySaver())
|
206
205
|
logger.info("Main agent workflow compiled")
|
207
206
|
return app
|
@@ -5,37 +5,80 @@ Agent for interacting with Semantic Scholar
|
|
5
5
|
"""
|
6
6
|
|
7
7
|
import logging
|
8
|
+
from typing import Any, Dict
|
8
9
|
import hydra
|
9
10
|
from langchain_openai import ChatOpenAI
|
11
|
+
from langchain_core.language_models.chat_models import BaseChatModel
|
10
12
|
from langgraph.graph import START, StateGraph
|
11
13
|
from langgraph.prebuilt import create_react_agent, ToolNode
|
12
14
|
from langgraph.checkpoint.memory import MemorySaver
|
13
15
|
from ..state.state_talk2scholars import Talk2Scholars
|
14
16
|
from ..tools.s2.search import search_tool as s2_search
|
15
17
|
from ..tools.s2.display_results import display_results as s2_display
|
18
|
+
from ..tools.s2.query_results import query_results as s2_query_results
|
19
|
+
from ..tools.s2.retrieve_semantic_scholar_paper_id import (
|
20
|
+
retrieve_semantic_scholar_paper_id as s2_retrieve_id,
|
21
|
+
)
|
16
22
|
from ..tools.s2.single_paper_rec import (
|
17
23
|
get_single_paper_recommendations as s2_single_rec,
|
18
24
|
)
|
19
25
|
from ..tools.s2.multi_paper_rec import get_multi_paper_recommendations as s2_multi_rec
|
20
26
|
|
21
|
-
|
22
27
|
# Initialize logger
|
23
28
|
logging.basicConfig(level=logging.INFO)
|
24
29
|
logger = logging.getLogger(__name__)
|
25
30
|
|
26
31
|
|
27
|
-
def get_app(
|
32
|
+
def get_app(
|
33
|
+
uniq_id, llm_model: BaseChatModel = ChatOpenAI(model="gpt-4o-mini", temperature=0)
|
34
|
+
):
|
28
35
|
"""
|
29
|
-
|
36
|
+
Initializes and returns the LangGraph application for the Semantic Scholar (S2) agent.
|
37
|
+
|
38
|
+
This function sets up the S2 agent, which integrates various tools to search, retrieve,
|
39
|
+
and display research papers from Semantic Scholar. The agent follows the ReAct pattern
|
40
|
+
for structured interaction.
|
41
|
+
|
42
|
+
Args:
|
43
|
+
uniq_id (str): Unique identifier for the current conversation session.
|
44
|
+
llm_model (BaseChatModel, optional): The language model to be used by the agent.
|
45
|
+
Defaults to `ChatOpenAI(model="gpt-4o-mini", temperature=0)`.
|
46
|
+
|
47
|
+
Returns:
|
48
|
+
StateGraph: A compiled LangGraph application that enables the S2 agent to process
|
49
|
+
user queries and retrieve research papers.
|
50
|
+
|
51
|
+
Example:
|
52
|
+
>>> app = get_app("thread_123")
|
53
|
+
>>> result = app.invoke(initial_state)
|
30
54
|
"""
|
31
55
|
|
32
|
-
def agent_s2_node(state: Talk2Scholars):
|
56
|
+
# def agent_s2_node(state: Talk2Scholars) -> Command[Literal["supervisor"]]:
|
57
|
+
def agent_s2_node(state: Talk2Scholars) -> Dict[str, Any]:
|
33
58
|
"""
|
34
|
-
|
59
|
+
Processes the user query and retrieves relevant research papers.
|
60
|
+
|
61
|
+
This function calls the language model using the configured `ReAct` agent to analyze
|
62
|
+
the state and generate an appropriate response. The function then returns control
|
63
|
+
to the main supervisor.
|
64
|
+
|
65
|
+
Args:
|
66
|
+
state (Talk2Scholars): The current conversation state, including messages exchanged
|
67
|
+
and any previously retrieved research papers.
|
68
|
+
|
69
|
+
Returns:
|
70
|
+
Dict[str, Any]: A dictionary containing the updated conversation state.
|
71
|
+
|
72
|
+
Example:
|
73
|
+
>>> result = agent_s2_node(current_state)
|
74
|
+
>>> papers = result.get("papers", [])
|
35
75
|
"""
|
36
76
|
logger.log(logging.INFO, "Creating Agent_S2 node with thread_id %s", uniq_id)
|
37
|
-
|
38
|
-
|
77
|
+
result = model.invoke(state, {"configurable": {"thread_id": uniq_id}})
|
78
|
+
|
79
|
+
return result
|
80
|
+
|
81
|
+
logger.log(logging.INFO, "thread_id, llm_model: %s, %s", uniq_id, llm_model)
|
39
82
|
|
40
83
|
# Load hydra configuration
|
41
84
|
logger.log(logging.INFO, "Load Hydra configuration for Talk2Scholars S2 agent.")
|
@@ -46,30 +89,31 @@ def get_app(uniq_id, llm_model="gpt-4o-mini"):
|
|
46
89
|
cfg = cfg.agents.talk2scholars.s2_agent
|
47
90
|
|
48
91
|
# Define the tools
|
49
|
-
tools = ToolNode(
|
92
|
+
tools = ToolNode(
|
93
|
+
[
|
94
|
+
s2_search,
|
95
|
+
s2_display,
|
96
|
+
s2_query_results,
|
97
|
+
s2_retrieve_id,
|
98
|
+
s2_single_rec,
|
99
|
+
s2_multi_rec,
|
100
|
+
]
|
101
|
+
)
|
50
102
|
|
51
103
|
# Define the model
|
52
104
|
logger.log(logging.INFO, "Using OpenAI model %s", llm_model)
|
53
|
-
llm = ChatOpenAI(model=llm_model, temperature=cfg.temperature)
|
54
105
|
|
55
106
|
# Create the agent
|
56
107
|
model = create_react_agent(
|
57
|
-
|
108
|
+
llm_model,
|
58
109
|
tools=tools,
|
59
110
|
state_schema=Talk2Scholars,
|
60
|
-
# prompt=cfg.s2_agent,
|
61
111
|
state_modifier=cfg.s2_agent,
|
62
112
|
checkpointer=MemorySaver(),
|
63
113
|
)
|
64
114
|
|
65
|
-
# Define a new graph
|
66
115
|
workflow = StateGraph(Talk2Scholars)
|
67
|
-
|
68
|
-
# Define the two nodes we will cycle between
|
69
116
|
workflow.add_node("agent_s2", agent_s2_node)
|
70
|
-
|
71
|
-
# Set the entrypoint as `agent`
|
72
|
-
# This means that this node is the first one called
|
73
117
|
workflow.add_edge(START, "agent_s2")
|
74
118
|
|
75
119
|
# Initialize memory to persist state between graph runs
|
@@ -5,14 +5,35 @@ openai_llms:
|
|
5
5
|
- "gpt-4-turbo"
|
6
6
|
- "gpt-3.5-turbo"
|
7
7
|
temperature: 0
|
8
|
-
|
9
|
-
You are
|
8
|
+
system_prompt: >
|
9
|
+
You are the Talk2Scholars agent coordinating academic paper discovery and analysis.
|
10
10
|
|
11
|
-
|
12
|
-
1.
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
11
|
+
You have access to the following agents:
|
12
|
+
1. S2_agent: This agent can be used to search and recommend papers
|
13
|
+
from Semantic Scholar. Use this agent when the user asks for
|
14
|
+
general paper searches and recommendations. This agent can also
|
15
|
+
retrieve the Semantic Scholar ID of a paper.
|
16
|
+
router_prompt: >
|
17
|
+
You are a supervisor tasked with managing a conversation between the
|
18
|
+
following workers: {members}. Given the user request, respond with the
|
19
|
+
worker to act next. Each worker will perform a task and respond with
|
20
|
+
their results and status. When finished, respond with FINISH.
|
21
|
+
|
22
|
+
Here is a description of the workers:
|
23
|
+
1. S2_agent: This agent can be used to search and recommend papers
|
24
|
+
from Semantic Scholar. Use this agent when the user asks for
|
25
|
+
general paper searches and recommendations. This agent can also
|
26
|
+
retrieve the Semantic Scholar ID of a paper. It can also be used to
|
27
|
+
provide more information about a paper.
|
28
|
+
|
29
|
+
Here are some instructions for the workers:
|
30
|
+
1. Call the S2 agent for general paper searches and recommendations.
|
31
|
+
2. The S2 agent has access to tools for querying and displaying papers.
|
32
|
+
3. If the user wants suggestions for papers and you don’t have
|
33
|
+
a Semantic Scholar ID for it but do have the title from
|
34
|
+
the last displayed results, use the S2 agent to retrieve the
|
35
|
+
Semantic Scholar ID of the paper. Then, use the S2 agent again to display
|
36
|
+
recommendations for the paper.
|
37
|
+
4. You can call the S2 agent to get more information about a paper based
|
38
|
+
on the context of the conversation.
|
39
|
+
5. Respond with FINISH when all tasks are completed.
|
@@ -6,19 +6,11 @@ openai_llms:
|
|
6
6
|
- "gpt-3.5-turbo"
|
7
7
|
temperature: 0
|
8
8
|
s2_agent: >
|
9
|
-
You are
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
- Shows the current research papers.
|
18
|
-
- If no papers are found, it will instruct you to perform a search.
|
19
|
-
|
20
|
-
3. get_single_paper_recommendations:
|
21
|
-
- Provides recommendations based on a single selected paper.
|
22
|
-
|
23
|
-
4. get_multi_paper_recommendations:
|
24
|
-
- Provides recommendations based on multiple selected papers.
|
9
|
+
You are an academic research assistant with access to the
|
10
|
+
Semantic Scholar API for paper discovery and analysis.
|
11
|
+
You also have tools to gain more insights on the papers and
|
12
|
+
display them.
|
13
|
+
You must strictly rely on retrieved information and avoid
|
14
|
+
generating unsupported content. Do not generate hallucinations
|
15
|
+
or fabricate details of any article. Stay focused on accurate,
|
16
|
+
sourced academic insights.
|
@@ -1,14 +1,13 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
# Page configuration
|
2
|
+
page:
|
3
|
+
title: "Talk2Scholars"
|
4
|
+
icon: "🤖"
|
5
|
+
layout: "wide"
|
6
6
|
|
7
7
|
# Available LLM models
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
- "gpt-3.5-turbo"
|
8
|
+
llms:
|
9
|
+
available_models:
|
10
|
+
- "OpenAI/gpt-4o-mini"
|
12
11
|
# # Chat UI configuration
|
13
12
|
# chat:
|
14
13
|
# assistant_avatar: "🤖"
|
@@ -16,6 +15,9 @@ llm_models:
|
|
16
15
|
# input_placeholder: "Say something ..."
|
17
16
|
# spinner_text: "Fetching response ..."
|
18
17
|
|
18
|
+
api_keys:
|
19
|
+
openai_key: "OPENAI_API_KEY"
|
20
|
+
nvidia_key: "NVIDIA_API_KEY"
|
19
21
|
# # Feedback configuration
|
20
22
|
# feedback:
|
21
23
|
# type: "thumbs"
|
@@ -1,9 +1,14 @@
|
|
1
1
|
"""
|
2
|
-
|
2
|
+
State management for the Talk2Scholars agent.
|
3
|
+
|
4
|
+
This module defines the state class `Talk2Scholars`, which maintains the conversation
|
5
|
+
context, retrieved papers, and other relevant metadata. The state ensures consistency
|
6
|
+
across agent interactions.
|
3
7
|
"""
|
4
8
|
|
5
9
|
import logging
|
6
10
|
from typing import Annotated, Any, Dict
|
11
|
+
from langchain_core.language_models import BaseChatModel
|
7
12
|
from langgraph.prebuilt.chat_agent_executor import AgentState
|
8
13
|
|
9
14
|
# Configure logging
|
@@ -12,22 +17,46 @@ logger = logging.getLogger(__name__)
|
|
12
17
|
|
13
18
|
|
14
19
|
def replace_dict(existing: Dict[str, Any], new: Dict[str, Any]) -> Dict[str, Any]:
|
15
|
-
"""
|
20
|
+
"""
|
21
|
+
Replaces the existing dictionary with a new dictionary.
|
22
|
+
|
23
|
+
This function logs the state update and ensures that the old state is replaced
|
24
|
+
with the new one.
|
25
|
+
|
26
|
+
Args:
|
27
|
+
existing (Dict[str, Any]): The current dictionary state.
|
28
|
+
new (Dict[str, Any]): The new dictionary state to replace the existing one.
|
29
|
+
|
30
|
+
Returns:
|
31
|
+
Dict[str, Any]: The updated dictionary state.
|
32
|
+
|
33
|
+
Example:
|
34
|
+
>>> old_state = {"papers": {"id1": "Paper 1"}}
|
35
|
+
>>> new_state = {"papers": {"id2": "Paper 2"}}
|
36
|
+
>>> updated_state = replace_dict(old_state, new_state)
|
37
|
+
>>> print(updated_state)
|
38
|
+
{"papers": {"id2": "Paper 2"}}
|
39
|
+
"""
|
16
40
|
logger.info("Updating existing state %s with the state dict: %s", existing, new)
|
17
41
|
return new
|
18
42
|
|
19
43
|
|
20
44
|
class Talk2Scholars(AgentState):
|
21
45
|
"""
|
22
|
-
|
46
|
+
Represents the state of the Talk2Scholars agent.
|
47
|
+
|
48
|
+
This class extends `AgentState` to maintain conversation history, retrieved papers,
|
49
|
+
and interactions with the language model.
|
23
50
|
|
24
51
|
Attributes:
|
25
|
-
|
26
|
-
|
27
|
-
|
52
|
+
last_displayed_papers (Dict[str, Any]): Stores the most recently displayed papers.
|
53
|
+
papers (Dict[str, Any]): Stores the research papers retrieved from the agent's queries.
|
54
|
+
multi_papers (Dict[str, Any]): Stores multiple recommended papers from various sources.
|
55
|
+
llm_model (BaseChatModel): The language model instance used for generating responses.
|
28
56
|
"""
|
29
57
|
|
30
58
|
# Agent state fields
|
59
|
+
last_displayed_papers: Annotated[Dict[str, Any], replace_dict]
|
31
60
|
papers: Annotated[Dict[str, Any], replace_dict]
|
32
61
|
multi_papers: Annotated[Dict[str, Any], replace_dict]
|
33
|
-
llm_model:
|
62
|
+
llm_model: BaseChatModel
|