aiagents4pharma 1.15.1__py3-none-any.whl → 1.16.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 (31) hide show
  1. aiagents4pharma/__init__.py +1 -1
  2. aiagents4pharma/configs/config.yaml +2 -1
  3. aiagents4pharma/configs/talk2biomodels/tools/__init__.py +2 -1
  4. aiagents4pharma/configs/talk2biomodels/tools/get_annotation/__init__.py +3 -0
  5. aiagents4pharma/configs/talk2biomodels/tools/get_annotation/default.yaml +6 -0
  6. aiagents4pharma/talk2biomodels/tests/test_get_annotation.py +29 -14
  7. aiagents4pharma/talk2biomodels/tests/test_getmodelinfo.py +32 -1
  8. aiagents4pharma/talk2biomodels/tests/test_integration.py +3 -4
  9. aiagents4pharma/talk2biomodels/tools/get_annotation.py +59 -37
  10. aiagents4pharma/talk2biomodels/tools/get_modelinfo.py +23 -4
  11. aiagents4pharma/{talk2competitors → talk2scholars}/agents/main_agent.py +7 -7
  12. aiagents4pharma/{talk2competitors → talk2scholars}/agents/s2_agent.py +4 -4
  13. aiagents4pharma/{talk2competitors → talk2scholars}/state/__init__.py +1 -1
  14. aiagents4pharma/{talk2competitors/state/state_talk2competitors.py → talk2scholars/state/state_talk2scholars.py} +3 -3
  15. aiagents4pharma/{talk2competitors → talk2scholars}/tests/test_langgraph.py +2 -2
  16. {aiagents4pharma-1.15.1.dist-info → aiagents4pharma-1.16.0.dist-info}/METADATA +7 -6
  17. {aiagents4pharma-1.15.1.dist-info → aiagents4pharma-1.16.0.dist-info}/RECORD +31 -29
  18. /aiagents4pharma/{talk2competitors → talk2scholars}/__init__.py +0 -0
  19. /aiagents4pharma/{talk2competitors → talk2scholars}/agents/__init__.py +0 -0
  20. /aiagents4pharma/{talk2competitors → talk2scholars}/config/__init__.py +0 -0
  21. /aiagents4pharma/{talk2competitors → talk2scholars}/config/config.py +0 -0
  22. /aiagents4pharma/{talk2competitors → talk2scholars}/tests/__init__.py +0 -0
  23. /aiagents4pharma/{talk2competitors → talk2scholars}/tools/__init__.py +0 -0
  24. /aiagents4pharma/{talk2competitors → talk2scholars}/tools/s2/__init__.py +0 -0
  25. /aiagents4pharma/{talk2competitors → talk2scholars}/tools/s2/display_results.py +0 -0
  26. /aiagents4pharma/{talk2competitors → talk2scholars}/tools/s2/multi_paper_rec.py +0 -0
  27. /aiagents4pharma/{talk2competitors → talk2scholars}/tools/s2/search.py +0 -0
  28. /aiagents4pharma/{talk2competitors → talk2scholars}/tools/s2/single_paper_rec.py +0 -0
  29. {aiagents4pharma-1.15.1.dist-info → aiagents4pharma-1.16.0.dist-info}/LICENSE +0 -0
  30. {aiagents4pharma-1.15.1.dist-info → aiagents4pharma-1.16.0.dist-info}/WHEEL +0 -0
  31. {aiagents4pharma-1.15.1.dist-info → aiagents4pharma-1.16.0.dist-info}/top_level.txt +0 -0
@@ -6,6 +6,6 @@ from . import (
6
6
  configs,
7
7
  talk2biomodels,
8
8
  talk2cells,
9
- talk2competitors,
9
+ talk2scholars,
10
10
  talk2knowledgegraphs,
11
11
  )
@@ -1,4 +1,5 @@
1
1
  defaults:
2
2
  - _self_
3
3
  - talk2biomodels/agents/t2b_agent: default
4
- - talk2biomodels/tools/ask_question: default
4
+ - talk2biomodels/tools/ask_question: default
5
+ - talk2biomodels/tools/get_annotation: default
@@ -1,4 +1,5 @@
1
1
  '''
2
2
  Import all the modules in the package
3
3
  '''
4
- from . import ask_question
4
+ from . import ask_question
5
+ from . import get_annotation
@@ -0,0 +1,3 @@
1
+ '''
2
+ Import all the modules in the package
3
+ '''
@@ -0,0 +1,6 @@
1
+ _target_: talk2biomodels.tools.get_annotation.GetAnnotationTool
2
+ prompt: >
3
+ Given the user question, extract the relevant species names.
4
+ If the user aks for a specific species, extract that species.
5
+ If none of the species match the user question, return None.
6
+ If the user asks for all species, return all species.
@@ -16,6 +16,7 @@ def make_graph_fixture():
16
16
  unique_id = random.randint(1000, 9999)
17
17
  graph = get_app(unique_id)
18
18
  config = {"configurable": {"thread_id": unique_id}}
19
+ graph.update_state(config, {"llm_model": "gpt-4o-mini"})
19
20
  return graph, config
20
21
 
21
22
  def test_no_model_provided(make_graph):
@@ -34,7 +35,7 @@ def test_no_model_provided(make_graph):
34
35
  # Assert that the state key model_id is empty.
35
36
  assert current_state.values["model_id"] == []
36
37
 
37
- def test_specific_species_provided(make_graph):
38
+ def test_valid_species_provided(make_graph):
38
39
  '''
39
40
  Test the tool by providing a specific species name.
40
41
  We are testing a condition where the user asks for annotations
@@ -54,9 +55,15 @@ def test_specific_species_provided(make_graph):
54
55
  # The assert statement checks if IL6 is present in the returned annotations.
55
56
  assert dic_annotations_data[0]['data']["Species Name"][0] == "IL6"
56
57
 
58
+ def test_invalid_species_provided(make_graph):
59
+ '''
60
+ Test the tool by providing an invalid species name.
61
+ We are testing a condition where the user asks for annotations
62
+ of an invalid species in a specific model.
63
+ '''
57
64
  # Test with an invalid species name
58
65
  app, config = make_graph
59
- prompt = "Extract annotations of species NADH in model 537."
66
+ prompt = "Extract annotations of only species NADH in model 537."
60
67
  app.invoke(
61
68
  {"messages": [HumanMessage(content=prompt)]},
62
69
  config=config
@@ -73,15 +80,20 @@ def test_specific_species_provided(make_graph):
73
80
  if isinstance(msg, ToolMessage) and msg.name == "get_annotation":
74
81
  #If a ToolMessage exists and artifact is None (meaning no valid annotation was found)
75
82
  #and the rejected species (NADH) is mentioned, the test passes.
76
- if msg.artifact is None and 'NADH' in msg.content:
83
+ if msg.artifact is None and msg.status == "error":
77
84
  #If artifact is None, it means no annotation was found
78
85
  # (likely due to an invalid species).
79
- #If artifact contains data, the tool successfully retrieved annotations.
80
86
  test_condition = True
81
87
  break
82
88
  # assert test_condition
83
- assert test_condition, "Expected rejection message for NADH but did not find it."
89
+ assert test_condition
84
90
 
91
+ def test_invalid_and_valid_species_provided(make_graph):
92
+ '''
93
+ Test the tool by providing an invalid species name and a valid species name.
94
+ We are testing a condition where the user asks for annotations
95
+ of an invalid species and a valid species in a specific model.
96
+ '''
85
97
  # Test with an invalid species name and a valid species name
86
98
  app, config = make_graph
87
99
  prompt = "Extract annotations of species NADH, NAD, and IL7 in model 64."
@@ -90,21 +102,24 @@ def test_specific_species_provided(make_graph):
90
102
  config=config
91
103
  )
92
104
  current_state = app.get_state(config)
93
- # dic_annotations_data = current_state.values["dic_annotations_data"]
105
+ dic_annotations_data = current_state.values["dic_annotations_data"]
106
+ # List of species that are expected to be found in the annotations
107
+ extracted_species = []
108
+ for idx in dic_annotations_data[0]['data']["Species Name"]:
109
+ extracted_species.append(dic_annotations_data[0]['data']["Species Name"][idx])
94
110
  reversed_messages = current_state.values["messages"][::-1]
95
111
  # Loop through the reversed messages until a
96
112
  # ToolMessage is found.
97
- artifact_was_none = False
113
+ tool_status_success = False
98
114
  for msg in reversed_messages:
99
115
  # Assert that the one of the messages is a ToolMessage
100
116
  # and its artifact is None.
101
117
  if isinstance(msg, ToolMessage) and msg.name == "get_annotation":
102
- # print (msg.artifact, msg.content)
103
-
104
- if msg.artifact is True and 'IL7' in msg.content:
105
- artifact_was_none = True
118
+ if msg.artifact is True and msg.status == "success":
119
+ tool_status_success = True
106
120
  break
107
- assert artifact_was_none
121
+ assert tool_status_success
122
+ assert set(extracted_species) == set(["NADH", "NAD"])
108
123
 
109
124
  def test_all_species_annotations(make_graph):
110
125
  '''
@@ -146,7 +161,7 @@ def test_all_species_annotations(make_graph):
146
161
  # Expect a successful extraction (artifact is True) and that the content
147
162
  # matches what is returned by prepare_content_msg for species.
148
163
  # And that the first or second description of the LacI protein is missing.
149
- if (msg.artifact is True and msg.content == prepare_content_msg([],[])
164
+ if (msg.artifact is True and msg.content == prepare_content_msg([])
150
165
  and msg.status=="success" and (first_descp_laci_protein == '-' or
151
166
  second_descp_laci_protein == '-')):
152
167
  test_condition = True
@@ -164,7 +179,7 @@ def test_all_species_annotations(make_graph):
164
179
  # Expect a successful extraction (artifact is True) and that the content
165
180
  # matches for for missing description ['ORI'].
166
181
  if (msg.artifact is True and
167
- msg.content == prepare_content_msg([],['ORI'])
182
+ msg.content == prepare_content_msg(['ORI'])
168
183
  and msg.status == "success"):
169
184
  test_condition = True
170
185
  break
@@ -2,7 +2,7 @@
2
2
  Test cases for Talk2Biomodels get_modelinfo tool.
3
3
  '''
4
4
 
5
- from langchain_core.messages import HumanMessage
5
+ from langchain_core.messages import HumanMessage, ToolMessage
6
6
  from ..agents.t2b_agent import get_app
7
7
 
8
8
  def test_get_modelinfo_tool():
@@ -24,3 +24,34 @@ def test_get_modelinfo_tool():
24
24
  assistant_msg = response["messages"][-1].content
25
25
  # Check if the assistant message is a string
26
26
  assert isinstance(assistant_msg, str)
27
+
28
+ def test_model_with_no_species():
29
+ '''
30
+ Test the get_modelinfo tool with a model that does not
31
+ return any species.
32
+
33
+ This should raise a tool error.
34
+ '''
35
+ unique_id = 12345
36
+ app = get_app(unique_id)
37
+ config = {"configurable": {"thread_id": unique_id}}
38
+ prompt = "Extract all species from model 20"
39
+ # Test the tool get_modelinfo
40
+ app.invoke(
41
+ {"messages": [HumanMessage(content=prompt)]},
42
+ config=config
43
+ )
44
+ current_state = app.get_state(config)
45
+ reversed_messages = current_state.values["messages"][::-1]
46
+ # Loop through the reversed messages until a
47
+ # ToolMessage is found.
48
+ test_condition = False
49
+ for msg in reversed_messages:
50
+ # Check if the message is a ToolMessage from the get_modelinfo tool
51
+ if isinstance(msg, ToolMessage) and msg.name == "get_modelinfo":
52
+ # Check if the message is an error message
53
+ if (msg.status == "error" and
54
+ "ValueError('Unable to extract species from the model.')" in msg.content):
55
+ test_condition = True
56
+ break
57
+ assert test_condition
@@ -17,10 +17,9 @@ def test_integration():
17
17
  # ##########################################
18
18
  # ## Test simulate_model tool
19
19
  # ##########################################
20
- prompt = '''Simulate the model 537 for 100 hours and intervals
21
- 100 with an initial concentration of `DoseQ2W`
22
- set to 300 and `Dose` set to 0. Reset the concentration
23
- of `Ab{serum}` to 100 every 25 hours.'''
20
+ prompt = '''Simulate the model 537 for 100 hours and time intervals
21
+ 100 with an initial concentration of `DoseQ2W` set to 300 and `Dose`
22
+ set to 0. Reset the concentration of `Ab{serum}` to 100 every 25 hours.'''
24
23
  # Test the tool get_modelinfo
25
24
  response = app.invoke(
26
25
  {"messages": [HumanMessage(content=prompt)]},
@@ -5,9 +5,10 @@ This module contains the `GetAnnotationTool` for fetching species annotations
5
5
  based on the provided model and species names.
6
6
  """
7
7
  import math
8
- from typing import List, Annotated, Type
8
+ from typing import List, Annotated, Type, TypedDict, Union, Literal
9
9
  import logging
10
10
  from dataclasses import dataclass
11
+ import hydra
11
12
  from pydantic import BaseModel, Field
12
13
  import basico
13
14
  import pandas as pd
@@ -16,6 +17,7 @@ from langgraph.prebuilt import InjectedState
16
17
  from langchain_core.tools.base import BaseTool
17
18
  from langchain_core.tools.base import InjectedToolCallId
18
19
  from langchain_core.messages import ToolMessage
20
+ from langchain_openai import ChatOpenAI
19
21
  from .load_biomodel import ModelData, load_biomodel
20
22
  from ..api.uniprot import search_uniprot_labels
21
23
  from ..api.ols import search_ols_labels
@@ -27,16 +29,56 @@ logger = logging.getLogger(__name__)
27
29
 
28
30
  ols_ontology_abbreviations = {'pato', 'chebi', 'sbo', 'fma', 'pr','go'}
29
31
 
30
- def prepare_content_msg(species_not_found: List[str],
31
- species_without_description: List[str]):
32
+ def extract_relevant_species_names(model_object, arg_data, state):
33
+ """
34
+ Extract relevant species names based on the user question.
35
+ """
36
+ # Load hydra configuration
37
+ with hydra.initialize(version_base=None, config_path="../../configs"):
38
+ cfg = hydra.compose(config_name='config',
39
+ overrides=['talk2biomodels/tools/get_annotation=default'])
40
+ cfg = cfg.talk2biomodels.tools.get_annotation
41
+ logger.info("Loaded the following system prompt for the LLM"
42
+ " to get a structured output: %s", cfg.prompt)
43
+
44
+ # Extract all the species names from the model
45
+ df_species = basico.model_info.get_species(model=model_object.copasi_model)
46
+ if df_species is None:
47
+ raise ValueError("Unable to extract species from the model.")
48
+ # Get all the species names
49
+ all_species_names = df_species.index.tolist()
50
+
51
+ # Define a structured output for the LLM model
52
+ class CustomHeader(TypedDict):
53
+ """
54
+ A list of species based on user question.
55
+ """
56
+ relevant_species: Union[None, List[Literal[*all_species_names]]] = Field(
57
+ description="""List of species based on user question.
58
+ If no relevant species are found, it must be None.""")
59
+
60
+ # Create an instance of the LLM model
61
+ llm = ChatOpenAI(model=state['llm_model'], temperature=0)
62
+ # Get the structured output from the LLM model
63
+ llm_with_structured_output = llm.with_structured_output(CustomHeader)
64
+ # Define the question for the LLM model using the prompt
65
+ question = cfg.prompt
66
+ question += f'Here is the user question: {arg_data.user_question}'
67
+ # Invoke the LLM model with the user question
68
+ dic = llm_with_structured_output.invoke(question)
69
+ extracted_species = []
70
+ # Extract all the species names from the model
71
+ for species in dic['relevant_species']:
72
+ if species in all_species_names:
73
+ extracted_species.append(species)
74
+ logger.info("Extracted species: %s", extracted_species)
75
+ return extracted_species
76
+
77
+ def prepare_content_msg(species_without_description: List[str]):
32
78
  """
33
79
  Prepare the content message.
34
80
  """
35
81
  content = 'Successfully extracted annotations for the species.'
36
- if species_not_found:
37
- content += f'''The following species do not exist, and
38
- hence their annotations were not extracted:
39
- {', '.join(species_not_found)}.'''
40
82
  if species_without_description:
41
83
  content += f'''The descriptions for the following species
42
84
  were not found:
@@ -52,12 +94,7 @@ class ArgumentData:
52
94
  " the experiment based on human query"
53
95
  " and the context of the experiment."
54
96
  " This must be set before the experiment is run."]
55
- list_species_names: List[str] = Field(
56
- default=None,
57
- description='''List of species names to fetch annotations for.
58
- If not provided, annotations for all
59
- species in the model will be fetched.'''
60
- )
97
+ user_question: Annotated[str, "Description of the user question"]
61
98
 
62
99
  class GetAnnotationInput(BaseModel):
63
100
  """
@@ -90,31 +127,22 @@ class GetAnnotationTool(BaseTool):
90
127
  Run the tool.
91
128
  """
92
129
  logger.info("Running the GetAnnotationTool tool for species %s, %s",
93
- arg_data.list_species_names,
130
+ arg_data.user_question,
94
131
  arg_data.experiment_name)
95
132
 
96
133
  # Prepare the model object
97
134
  sbml_file_path = state['sbml_file_path'][-1] if state['sbml_file_path'] else None
98
135
  model_object = load_biomodel(sys_bio_model, sbml_file_path=sbml_file_path)
99
136
 
100
- # Extract all the species names from the model
101
- df_species = basico.model_info.get_species(model=model_object.copasi_model)
137
+ # Extract relevant species names based on the user question
138
+ list_species_names = extract_relevant_species_names(model_object, arg_data, state)
102
139
 
103
- if df_species is None:
104
- # for example this may happen with model 20
105
- raise ValueError("Unable to extract species from the model.")
106
- # Fetch annotations for the species names
107
- arg_data.list_species_names = arg_data.list_species_names or df_species.index.tolist()
140
+ # Check if the returned species names are empty
141
+ if not list_species_names:
142
+ raise ValueError("Model does not contain the requested species.")
108
143
 
109
144
  (annotations_df,
110
- species_not_found,
111
- species_without_description) = self._fetch_annotations(arg_data.list_species_names)
112
-
113
- # Check if annotations are empty
114
- # If empty, return a message
115
- if annotations_df.empty:
116
- logger.warning("The annotations dataframe is empty.")
117
- return prepare_content_msg(species_not_found, species_without_description)
145
+ species_without_description) = self._fetch_annotations(list_species_names)
118
146
 
119
147
  # Process annotations
120
148
  annotations_df = self._process_annotations(annotations_df)
@@ -141,8 +169,7 @@ class GetAnnotationTool(BaseTool):
141
169
  update=dic_updated_state_for_model | {
142
170
  "messages": [
143
171
  ToolMessage(
144
- content=prepare_content_msg(species_not_found,
145
- species_without_description),
172
+ content=prepare_content_msg(species_without_description),
146
173
  artifact=True,
147
174
  tool_call_id=tool_call_id
148
175
  )
@@ -165,7 +192,6 @@ class GetAnnotationTool(BaseTool):
165
192
  tuple: A tuple containing the annotations dataframe, species not found list,
166
193
  and description not found list.
167
194
  """
168
- species_not_found = []
169
195
  description_not_found = []
170
196
  data = []
171
197
 
@@ -173,10 +199,6 @@ class GetAnnotationTool(BaseTool):
173
199
  for species in list_species_names:
174
200
  # Get the MIRIAM annotation for the species
175
201
  annotation = basico.get_miriam_annotation(name=species)
176
- # If the annotation is not found, add the species to the list
177
- if annotation is None:
178
- species_not_found.append(species)
179
- continue
180
202
 
181
203
  # Extract the descriptions from the annotation
182
204
  descriptions = annotation.get("descriptions", [])
@@ -197,7 +219,7 @@ class GetAnnotationTool(BaseTool):
197
219
  annotations_df = pd.DataFrame(data)
198
220
 
199
221
  # Return the annotations dataframe and the species not found list
200
- return annotations_df, species_not_found, description_not_found
222
+ return annotations_df, description_not_found
201
223
 
202
224
  def _process_annotations(self, annotations_df: pd.DataFrame) -> pd.DataFrame:
203
225
  """
@@ -83,14 +83,33 @@ class GetModelInfoTool(BaseTool):
83
83
  # Extract species from the model
84
84
  if requested_model_info.species:
85
85
  df_species = basico.model_info.get_species(model=model_obj.copasi_model)
86
- dic_results['Species'] = df_species['display_name'].tolist()
87
- dic_results['Species'] = ','.join(dic_results['Species'])
86
+ if df_species is None:
87
+ raise ValueError("Unable to extract species from the model.")
88
+ # Convert index into a column
89
+ df_species.reset_index(inplace=True)
90
+ dic_results['Species'] = df_species[
91
+ ['name',
92
+ 'compartment',
93
+ 'type',
94
+ 'unit',
95
+ 'initial_concentration',
96
+ 'display_name']]
97
+ # Convert this into a dictionary
98
+ dic_results['Species'] = dic_results['Species'].to_dict(orient='records')
88
99
 
89
100
  # Extract parameters from the model
90
101
  if requested_model_info.parameters:
91
102
  df_parameters = basico.model_info.get_parameters(model=model_obj.copasi_model)
92
- dic_results['Parameters'] = df_parameters.index.tolist()
93
- dic_results['Parameters'] = ','.join(dic_results['Parameters'])
103
+ # Convert index into a column
104
+ df_parameters.reset_index(inplace=True)
105
+ dic_results['Parameters'] = df_parameters[
106
+ ['name',
107
+ 'type',
108
+ 'unit',
109
+ 'initial_value',
110
+ 'display_name']]
111
+ # Convert this into a dictionary
112
+ dic_results['Parameters'] = dic_results['Parameters'].to_dict(orient='records')
94
113
 
95
114
  # Extract compartments from the model
96
115
  if requested_model_info.compartments:
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env python3
2
2
 
3
3
  """
4
- Main agent for the talk2competitors app.
4
+ Main agent for the talk2scholars app.
5
5
  """
6
6
 
7
7
  import logging
@@ -15,7 +15,7 @@ from langgraph.graph import END, START, StateGraph
15
15
  from langgraph.types import Command
16
16
  from ..agents import s2_agent
17
17
  from ..config.config import config
18
- from ..state.state_talk2competitors import Talk2Competitors
18
+ from ..state.state_talk2scholars import Talk2Scholars
19
19
 
20
20
  logging.basicConfig(level=logging.INFO)
21
21
  logger = logging.getLogger(__name__)
@@ -34,12 +34,12 @@ def make_supervisor_node(llm: BaseChatModel) -> str:
34
34
  """
35
35
  # options = ["FINISH", "s2_agent"]
36
36
 
37
- def supervisor_node(state: Talk2Competitors) -> Command[Literal["s2_agent", "__end__"]]:
37
+ def supervisor_node(state: Talk2Scholars) -> Command[Literal["s2_agent", "__end__"]]:
38
38
  """
39
39
  Supervisor node that routes to appropriate sub-agents.
40
40
 
41
41
  Args:
42
- state (Talk2Competitors): The current state of the conversation.
42
+ state (Talk2Scholars): The current state of the conversation.
43
43
 
44
44
  Returns:
45
45
  Command[Literal["s2_agent", "__end__"]]: The command to execute next.
@@ -91,12 +91,12 @@ def get_app(thread_id: str, llm_model ='gpt-4o-mini') -> StateGraph:
91
91
  Returns:
92
92
  The compiled langraph app.
93
93
  """
94
- def call_s2_agent(state: Talk2Competitors) -> Command[Literal["__end__"]]:
94
+ def call_s2_agent(state: Talk2Scholars) -> Command[Literal["__end__"]]:
95
95
  """
96
96
  Node for calling the S2 agent.
97
97
 
98
98
  Args:
99
- state (Talk2Competitors): The current state of the conversation.
99
+ state (Talk2Scholars): The current state of the conversation.
100
100
 
101
101
  Returns:
102
102
  Command[Literal["__end__"]]: The command to execute next.
@@ -115,7 +115,7 @@ def get_app(thread_id: str, llm_model ='gpt-4o-mini') -> StateGraph:
115
115
  },
116
116
  )
117
117
  llm = ChatOpenAI(model=llm_model, temperature=0)
118
- workflow = StateGraph(Talk2Competitors)
118
+ workflow = StateGraph(Talk2Scholars)
119
119
 
120
120
  supervisor = make_supervisor_node(llm)
121
121
  workflow.add_node("supervisor", supervisor)
@@ -11,7 +11,7 @@ from langgraph.graph import START, StateGraph
11
11
  from langgraph.prebuilt import create_react_agent
12
12
  from langgraph.checkpoint.memory import MemorySaver
13
13
  from ..config.config import config
14
- from ..state.state_talk2competitors import Talk2Competitors
14
+ from ..state.state_talk2scholars import Talk2Scholars
15
15
  # from ..tools.s2 import s2_tools
16
16
  from ..tools.s2.search import search_tool
17
17
  from ..tools.s2.display_results import display_results
@@ -28,7 +28,7 @@ def get_app(uniq_id, llm_model='gpt-4o-mini'):
28
28
  '''
29
29
  This function returns the langraph app.
30
30
  '''
31
- def agent_s2_node(state: Talk2Competitors):
31
+ def agent_s2_node(state: Talk2Scholars):
32
32
  '''
33
33
  This function calls the model.
34
34
  '''
@@ -47,13 +47,13 @@ def get_app(uniq_id, llm_model='gpt-4o-mini'):
47
47
  model = create_react_agent(
48
48
  llm,
49
49
  tools=tools,
50
- state_schema=Talk2Competitors,
50
+ state_schema=Talk2Scholars,
51
51
  state_modifier=config.S2_AGENT_PROMPT,
52
52
  checkpointer=MemorySaver()
53
53
  )
54
54
 
55
55
  # Define a new graph
56
- workflow = StateGraph(Talk2Competitors)
56
+ workflow = StateGraph(Talk2Scholars)
57
57
 
58
58
  # Define the two nodes we will cycle between
59
59
  workflow.add_node("agent_s2", agent_s2_node)
@@ -2,4 +2,4 @@
2
2
  This file is used to import all the modules in the package.
3
3
  '''
4
4
 
5
- from . import state_talk2competitors
5
+ from . import state_talk2scholars
@@ -1,5 +1,5 @@
1
1
  """
2
- This is the state file for the talk2comp agent.
2
+ This is the state file for the talk2scholars agent.
3
3
  """
4
4
 
5
5
  import logging
@@ -19,9 +19,9 @@ def replace_dict(existing: Dict[str, Any], new: Dict[str, Any]) -> Dict[str, Any
19
19
  return new
20
20
 
21
21
 
22
- class Talk2Competitors(AgentState):
22
+ class Talk2Scholars(AgentState):
23
23
  """
24
- The state for the talk2comp agent, inheriting from AgentState.
24
+ The state for the talk2scholars agent, inheriting from AgentState.
25
25
  """
26
26
 
27
27
  papers: Annotated[Dict[str, Any], replace_dict] # Changed from List to Dict
@@ -1,5 +1,5 @@
1
1
  """
2
- Unit and integration tests for Talk2Competitors system.
2
+ Unit and integration tests for Talk2Scholars system.
3
3
  Each test focuses on a single, specific functionality.
4
4
  Tests are deterministic and independent of each other.
5
5
  """
@@ -10,7 +10,7 @@ import pytest
10
10
  from langchain_core.messages import AIMessage, HumanMessage
11
11
 
12
12
  from ..agents.main_agent import get_app, make_supervisor_node
13
- from ..state.state_talk2competitors import replace_dict
13
+ from ..state.state_talk2scholars import replace_dict
14
14
  from ..tools.s2.display_results import display_results
15
15
  from ..tools.s2.multi_paper_rec import get_multi_paper_recommendations
16
16
  from ..tools.s2.search import search_tool
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: aiagents4pharma
3
- Version: 1.15.1
3
+ Version: 1.16.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
@@ -50,11 +50,10 @@ Requires-Dist: streamlit-feedback
50
50
  [![Talk2BioModels](https://github.com/VirtualPatientEngine/AIAgents4Pharma/actions/workflows/tests_talk2biomodels.yml/badge.svg)](https://github.com/VirtualPatientEngine/AIAgents4Pharma/actions/workflows/tests_talk2biomodels.yml)
51
51
  [![Talk2Cells](https://github.com/VirtualPatientEngine/AIAgents4Pharma/actions/workflows/tests_talk2cells.yml/badge.svg)](https://github.com/VirtualPatientEngine/AIAgents4Pharma/actions/workflows/tests_talk2cells.yml)
52
52
  [![Talk2KnowledgeGraphs](https://github.com/VirtualPatientEngine/AIAgents4Pharma/actions/workflows/tests_talk2knowledgegraphs.yml/badge.svg)](https://github.com/VirtualPatientEngine/AIAgents4Pharma/actions/workflows/tests_talk2knowledgegraphs.yml)
53
- [![Talk2Competitors](https://github.com/VirtualPatientEngine/AIAgents4Pharma/actions/workflows/tests_talk2competitors.yml/badge.svg)](https://github.com/VirtualPatientEngine/AIAgents4Pharma/actions/workflows/tests_talk2competitors.yml)
53
+ [![Talk2Scholars](https://github.com/VirtualPatientEngine/AIAgents4Pharma/actions/workflows/tests_talk2scholars.yml/badge.svg)](https://github.com/VirtualPatientEngine/AIAgents4Pharma/actions/workflows/tests_talk2scholars.yml)
54
54
  ![GitHub Release](https://img.shields.io/github/v/release/VirtualPatientEngine/AIAgents4Pharma)
55
55
  ![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)
56
56
 
57
-
58
57
  <h1 align="center" style="border-bottom: none;">🤖 AIAgents4Pharma</h1>
59
58
 
60
59
  Welcome to **AIAgents4Pharma** – an open-source project by [Team VPE](https://github.com/VirtualPatientEngine) that brings together AI-driven tools to help researchers and pharma interact seamlessly with complex biological data.
@@ -64,7 +63,7 @@ Our toolkit currently consists of three intelligent agents, each designed to sim
64
63
  - **Talk2BioModels**: Engage directly with mathematical models in systems biology.
65
64
  - **Talk2Cells** _(Work in progress)_: Query and analyze sequencing data with ease.
66
65
  - **Talk2KnowledgeGraphs** _(Work in progress)_: Access and explore complex biological knowledge graphs for insightful data connections.
67
- - **Talk2Competitors** _(Coming soon)_: Get recommendations for articles related to your choice. Download, query, and write/retrieve them to your reference manager (currently supporting Zotero).
66
+ - **Talk2Scholars** _(Coming soon)_: Get recommendations for articles related to your choice. Download, query, and write/retrieve them to your reference manager (currently supporting Zotero).
68
67
 
69
68
  ---
70
69
 
@@ -87,7 +86,9 @@ Our toolkit currently consists of three intelligent agents, each designed to sim
87
86
 
88
87
  **Talk2KnowledgeGraphs** is an agent designed to enable interaction with biological knowledge graphs (KGs). KGs integrate vast amounts of structured biological data into a format that highlights relationships between entities, such as proteins, genes, and diseases.
89
88
 
90
- ### 4. Talk2Competitors _(Coming soon)_
89
+ ### 4. Talk2Scholars _(Work in Progress)_
90
+
91
+ Talk2Scholars is an AI-powered hierarchical agent system designed to revolutionize academic paper search and analysis. Through intelligent conversation, users can discover, analyze, and receive recommendations for academic papers using state-of-the-art natural language processing.
91
92
 
92
93
  ## Getting Started
93
94
 
@@ -198,7 +199,7 @@ Check out our [CONTRIBUTING.md](CONTRIBUTING.md) for more information.
198
199
  - **User Interface**: Interactive web UI for all agents.
199
200
  - **Talk2Cells**: Integration of sequencing data analysis tools.
200
201
  - **Talk2KnowledgeGraphs**: Interface for biological knowledge graph interaction.
201
- - **Talk2Competitors**: Interface for exploring articles
202
+ - **Talk2Scholars**: Interface for exploring articles
202
203
 
203
204
  We’re excited to bring AIAgents4Pharma to the bioinformatics and pharmaceutical research community. Together, let’s make data-driven biological research more accessible and insightful.
204
205
 
@@ -1,13 +1,15 @@
1
- aiagents4pharma/__init__.py,sha256=5muWWIg89VHPybfxonO_5xOMJPasKNsGdQRhozDaEmk,177
1
+ aiagents4pharma/__init__.py,sha256=nFCe1As_SuRkmhcdZVsU0aYjYccHxk1DbduLpy8XulY,174
2
2
  aiagents4pharma/configs/__init__.py,sha256=hNkSrXw1Ix1HhkGn_aaidr2coBYySfM0Hm_pMeRcX7k,76
3
- aiagents4pharma/configs/config.yaml,sha256=4t7obD0gOSfqnDDZZBB53ZC7zsmk7QDcM7T_1Hf1wIQ,112
3
+ aiagents4pharma/configs/config.yaml,sha256=e0w2GOBVWcoPDtX-z4S6yKbv2rja5PfGRBhmTPVIXNU,161
4
4
  aiagents4pharma/configs/talk2biomodels/__init__.py,sha256=safyFKhkd5Wlirl9dMZIHWDLTpY2oLw9wjIM7ZtLIHk,88
5
5
  aiagents4pharma/configs/talk2biomodels/agents/__init__.py,sha256=_ZoG8snICK2bidWtc2KOGs738LWg9_r66V9mOMnEb-E,71
6
6
  aiagents4pharma/configs/talk2biomodels/agents/t2b_agent/__init__.py,sha256=-fAORvyFmG2iSvFOFDixmt9OTQRR58y89uhhu2EgbA8,46
7
7
  aiagents4pharma/configs/talk2biomodels/agents/t2b_agent/default.yaml,sha256=eLrJIezoPJ6_DvrSYsi3eALl03o0hJhntej3ESoeKKg,551
8
- aiagents4pharma/configs/talk2biomodels/tools/__init__.py,sha256=WxK7h5n39l-NSMvjLZyxDqzwWlVA6mQ69gzsbJ17vEk,72
8
+ aiagents4pharma/configs/talk2biomodels/tools/__init__.py,sha256=B08KWjj7bpizuTETGnnngrEVK4nzdWGREdoCCSw1Sm4,102
9
9
  aiagents4pharma/configs/talk2biomodels/tools/ask_question/__init__.py,sha256=-fAORvyFmG2iSvFOFDixmt9OTQRR58y89uhhu2EgbA8,46
10
10
  aiagents4pharma/configs/talk2biomodels/tools/ask_question/default.yaml,sha256=yy-Sq1u4dBlTFi_UeoWYoHkWRDWueJWVNK_rcUCC5bw,1747
11
+ aiagents4pharma/configs/talk2biomodels/tools/get_annotation/__init__.py,sha256=-fAORvyFmG2iSvFOFDixmt9OTQRR58y89uhhu2EgbA8,46
12
+ aiagents4pharma/configs/talk2biomodels/tools/get_annotation/default.yaml,sha256=8vUlzU5Y3BPggId5bVMo9B23VG4mp2ziTglb4LmLCsc,319
11
13
  aiagents4pharma/talk2biomodels/__init__.py,sha256=2ICwVh1u07SZv31Jd2DKHobauOxWNWY29_Gqq3kOnNQ,159
12
14
  aiagents4pharma/talk2biomodels/agents/__init__.py,sha256=sn5-fREjMdEvb-OUan3iOqrgYGjplNx3J8hYOaW0Po8,128
13
15
  aiagents4pharma/talk2biomodels/agents/t2b_agent.py,sha256=5h4n7dF13KuT5f9vzfK7EQTu_b0a0hB7ScLFlTKaNko,3449
@@ -24,9 +26,9 @@ aiagents4pharma/talk2biomodels/tests/__init__.py,sha256=Jbw5tJxSrjGoaK5IX3pJWDCN
24
26
  aiagents4pharma/talk2biomodels/tests/test_api.py,sha256=7Kz2r5F5tjmn3F0LoM33oP-21W633936YHiyf5toGg0,1716
25
27
  aiagents4pharma/talk2biomodels/tests/test_ask_question.py,sha256=yRkKK9HLB1bGGWm_WwOckwaUmmRfRAD9z2NFFGLIGTY,1560
26
28
  aiagents4pharma/talk2biomodels/tests/test_basico_model.py,sha256=y82fpTJMPHwtXxlle1cGQ_2Bewwpxi0aJSVrVAYLhN0,2060
27
- aiagents4pharma/talk2biomodels/tests/test_get_annotation.py,sha256=mKOacH28OB6xpFPygAlhBUQS93gnI5j-jAfSGu6uQMI,7465
28
- aiagents4pharma/talk2biomodels/tests/test_getmodelinfo.py,sha256=6kChSc_MCnzXlDao_R8pKdhIELlg3MZrUa7hg8piJ4E,883
29
- aiagents4pharma/talk2biomodels/tests/test_integration.py,sha256=ZsBXWSFLIcdzrO8obLJx8Ib2f9AAW3BI7H9Eqjdc5to,5057
29
+ aiagents4pharma/talk2biomodels/tests/test_get_annotation.py,sha256=GqS3kCxxTTMTJFjTnJhilrxT6jbNb7Yi0fbaKkadU4E,8159
30
+ aiagents4pharma/talk2biomodels/tests/test_getmodelinfo.py,sha256=Y1sFhoMF4mbvlag7D-dEvv6ytjmAqzMLPvSvaVEI_Qk,2045
31
+ aiagents4pharma/talk2biomodels/tests/test_integration.py,sha256=QHGOKrKyd0kBGy1tOMmkNSqN2Jc2oIXoUrAMpv-elBc,5058
30
32
  aiagents4pharma/talk2biomodels/tests/test_param_scan.py,sha256=vRbnn4uVWFbfZbU4gVCjHi5WDCUrErut8ElzAPE5y84,2648
31
33
  aiagents4pharma/talk2biomodels/tests/test_query_article.py,sha256=HhFgU5HzCipecEYlfbpPxN-SCIPKep22gpXCutWXRb8,2820
32
34
  aiagents4pharma/talk2biomodels/tests/test_search_models.py,sha256=8ODFubLxWYD3I3KQWuUnJ2GZRzMjFpXInFBLxKxG_ME,929
@@ -36,8 +38,8 @@ aiagents4pharma/talk2biomodels/tests/test_sys_bio_model.py,sha256=HSmBBViMi0jYf4
36
38
  aiagents4pharma/talk2biomodels/tools/__init__.py,sha256=6H2HWv5Q4NZYEmw-Ti5KZnJlEqhaC2HXSDZa6kiSl-U,350
37
39
  aiagents4pharma/talk2biomodels/tools/ask_question.py,sha256=hWXg7o0sTMDWH1ZnxtashTALvXpvNoaomfcniEhw-Bw,4684
38
40
  aiagents4pharma/talk2biomodels/tools/custom_plotter.py,sha256=HWwKTX3o4dk0GcRVTO2hPrFSu98mtJ4TKC_hbHXOe1c,4018
39
- aiagents4pharma/talk2biomodels/tools/get_annotation.py,sha256=jCGkidvafuk1YzAH9GFwaVUF35maXTjg6XqBg_zLk44,12475
40
- aiagents4pharma/talk2biomodels/tools/get_modelinfo.py,sha256=qA-4FOI-O728Nmn7s8JJ8HKwxvA9MZbst7NkPKTAMV4,5391
41
+ aiagents4pharma/talk2biomodels/tools/get_annotation.py,sha256=l6gN_Urf-EJ5a_ZobIBeJB68BvLznsPUZR5sV04XR70,13420
42
+ aiagents4pharma/talk2biomodels/tools/get_modelinfo.py,sha256=57dkXrBeRpyiaW3dYkoWIfr6zSsFHcWRhvUVNyLcvUs,6363
41
43
  aiagents4pharma/talk2biomodels/tools/load_arguments.py,sha256=bffNIlBDTCSFYiZprA73yi8Jbb8z3Oh2decVNh1UnZc,4162
42
44
  aiagents4pharma/talk2biomodels/tools/load_biomodel.py,sha256=pyVzLQoMnuJYEwsjeOlqcUrbU1F1Z-pNlgkhFaoKpy0,689
43
45
  aiagents4pharma/talk2biomodels/tools/parameter_scan.py,sha256=aNh94LgBgVXBIczuNkbSsOZ9j54YVEdZWmZbZr7Nk8k,12465
@@ -55,22 +57,6 @@ aiagents4pharma/talk2cells/tools/__init__.py,sha256=38nK2a_lEFRjO3qD6Fo9a3983ZCY
55
57
  aiagents4pharma/talk2cells/tools/scp_agent/__init__.py,sha256=s7g0lyH1lMD9pcWHLPtwRJRvzmTh2II7DrxyLulpjmQ,163
56
58
  aiagents4pharma/talk2cells/tools/scp_agent/display_studies.py,sha256=6q59gh_NQaiOU2rn55A3sIIFKlXi4SK3iKgySvUDrtQ,600
57
59
  aiagents4pharma/talk2cells/tools/scp_agent/search_studies.py,sha256=MLe-twtFnOu-P8P9diYq7jvHBHbWFRRCZLcfpUzqPMg,2806
58
- aiagents4pharma/talk2competitors/__init__.py,sha256=haaikzND3c0Euqq86ndA4fl9q42aOop5rYG_8Zh1D-o,119
59
- aiagents4pharma/talk2competitors/agents/__init__.py,sha256=ykszlVGxz3egLHZAttlNoTPxIrnQJZYva_ssR8fwIFk,117
60
- aiagents4pharma/talk2competitors/agents/main_agent.py,sha256=UoHCpZd-HoeG0B6_gAF1cEP2OqMvrTuGe7MZDwL_u1U,3878
61
- aiagents4pharma/talk2competitors/agents/s2_agent.py,sha256=eTrhc4ZPvWOUWMHNYxK0WltsZedZUnAWNu-TeUa-ruk,2501
62
- aiagents4pharma/talk2competitors/config/__init__.py,sha256=HyM6paOpKZ5_tZnyVheSAFmxjT6Mb3PxvWKfP0rz-dE,113
63
- aiagents4pharma/talk2competitors/config/config.py,sha256=jd4ltMBJyTztm9wT7j3ujOyYxL2SXRgxQJ4OZUBmCG4,5387
64
- aiagents4pharma/talk2competitors/state/__init__.py,sha256=DzFjV3hZNes_pL4bDW2_8RsyK9BJcj6ejfBzU0KWn1k,106
65
- aiagents4pharma/talk2competitors/state/state_talk2competitors.py,sha256=GUl1ZfM77XsjIEu-3xy4dtvaiMTA1pXf6i1ozVcX5Gg,993
66
- aiagents4pharma/talk2competitors/tests/__init__.py,sha256=U3PsTiUZaUBD1IZanFGkDIOdFieDVJtGKQ5-woYUo8c,45
67
- aiagents4pharma/talk2competitors/tests/test_langgraph.py,sha256=sEROK1aU3wFqJhZohONVI6Pr7t1d3PSqs-4erVIyiJw,9283
68
- aiagents4pharma/talk2competitors/tools/__init__.py,sha256=YudBDRwaEzDnAcpxGZvEOfyh5-6xd51CTvTKTkywgXw,68
69
- aiagents4pharma/talk2competitors/tools/s2/__init__.py,sha256=9RQH3efTj6qkXk0ICKSc7Mzpkitt4gRGsQ1pGPrrREU,181
70
- aiagents4pharma/talk2competitors/tools/s2/display_results.py,sha256=B8JJGohi1Eyx8C3MhO_SiyQP3R6hPyUKJOAzcHmq3FU,584
71
- aiagents4pharma/talk2competitors/tools/s2/multi_paper_rec.py,sha256=FYLt47DAk6WOKfEk1Gj9zVvJGNyxA283PCp8IKW9U5M,4262
72
- aiagents4pharma/talk2competitors/tools/s2/search.py,sha256=pppjrQv5-8ep4fnqgTSBNgnbSnQsVIcNrRrH0p2TP1o,4025
73
- aiagents4pharma/talk2competitors/tools/s2/single_paper_rec.py,sha256=dAfUQxI7T5eu0eDxK8VAl7-JH0Wnw24CVkOQqwj-hXc,4810
74
60
  aiagents4pharma/talk2knowledgegraphs/__init__.py,sha256=4smVQoSMM6rflVnNkABqlDAAlSn4bYsq7rMVWjRGvis,103
75
61
  aiagents4pharma/talk2knowledgegraphs/datasets/__init__.py,sha256=L3gPuHskSegmtXskVrLIYr7FXe_ibKgJ2GGr1_Wok6k,173
76
62
  aiagents4pharma/talk2knowledgegraphs/datasets/biobridge_primekg.py,sha256=QlzDXmXREoa9MA6-GwzqRjdzndQeGBAF11Td6NFk_9Y,23426
@@ -96,8 +82,24 @@ aiagents4pharma/talk2knowledgegraphs/utils/embeddings/sentence_transformer.py,sh
96
82
  aiagents4pharma/talk2knowledgegraphs/utils/enrichments/__init__.py,sha256=tW426knki2DBIHcWyF_K04iMMdbpIn_e_TpPmTgz2dI,113
97
83
  aiagents4pharma/talk2knowledgegraphs/utils/enrichments/enrichments.py,sha256=Bx8x6zzk5614ApWB90N_iv4_Y_Uq0-KwUeBwYSdQMU4,924
98
84
  aiagents4pharma/talk2knowledgegraphs/utils/enrichments/ollama.py,sha256=8eoxR-VHo0G7ReQIwje7xEhE-SJlHdef7_wJRpnvFIc,4116
99
- aiagents4pharma-1.15.1.dist-info/LICENSE,sha256=IcIbyB1Hyk5ZDah03VNQvJkbNk2hkBCDqQ8qtnCvB4Q,1077
100
- aiagents4pharma-1.15.1.dist-info/METADATA,sha256=J1AkLBxq9Pb1bo2tfkr8isyCozXB1aUi79jOlx6KDp8,8637
101
- aiagents4pharma-1.15.1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
102
- aiagents4pharma-1.15.1.dist-info/top_level.txt,sha256=-AH8rMmrSnJtq7HaAObS78UU-cTCwvX660dSxeM7a0A,16
103
- aiagents4pharma-1.15.1.dist-info/RECORD,,
85
+ aiagents4pharma/talk2scholars/__init__.py,sha256=haaikzND3c0Euqq86ndA4fl9q42aOop5rYG_8Zh1D-o,119
86
+ aiagents4pharma/talk2scholars/agents/__init__.py,sha256=ykszlVGxz3egLHZAttlNoTPxIrnQJZYva_ssR8fwIFk,117
87
+ aiagents4pharma/talk2scholars/agents/main_agent.py,sha256=HN3MkfHSDDlfzCKP79yAkpf3uyz3ZOCDGNRQ4gRL5RI,3854
88
+ aiagents4pharma/talk2scholars/agents/s2_agent.py,sha256=HI037q-bq-bGf5DqtraSCWO493fAzUZ81lOEOCbMAaM,2486
89
+ aiagents4pharma/talk2scholars/config/__init__.py,sha256=HyM6paOpKZ5_tZnyVheSAFmxjT6Mb3PxvWKfP0rz-dE,113
90
+ aiagents4pharma/talk2scholars/config/config.py,sha256=jd4ltMBJyTztm9wT7j3ujOyYxL2SXRgxQJ4OZUBmCG4,5387
91
+ aiagents4pharma/talk2scholars/state/__init__.py,sha256=S6SxlszIMZSIMJehjevPF9sKyR-PAwWb5TEdo6xWXE8,103
92
+ aiagents4pharma/talk2scholars/state/state_talk2scholars.py,sha256=nwNRKdhoTXAtBGMMp6coMyUCaQVOnoGNqyjpKKw_FVM,998
93
+ aiagents4pharma/talk2scholars/tests/__init__.py,sha256=U3PsTiUZaUBD1IZanFGkDIOdFieDVJtGKQ5-woYUo8c,45
94
+ aiagents4pharma/talk2scholars/tests/test_langgraph.py,sha256=HcnahbazwaLaZg71OyCho2FLZ0ePedmv3XGvARFNe0g,9277
95
+ aiagents4pharma/talk2scholars/tools/__init__.py,sha256=YudBDRwaEzDnAcpxGZvEOfyh5-6xd51CTvTKTkywgXw,68
96
+ aiagents4pharma/talk2scholars/tools/s2/__init__.py,sha256=9RQH3efTj6qkXk0ICKSc7Mzpkitt4gRGsQ1pGPrrREU,181
97
+ aiagents4pharma/talk2scholars/tools/s2/display_results.py,sha256=B8JJGohi1Eyx8C3MhO_SiyQP3R6hPyUKJOAzcHmq3FU,584
98
+ aiagents4pharma/talk2scholars/tools/s2/multi_paper_rec.py,sha256=FYLt47DAk6WOKfEk1Gj9zVvJGNyxA283PCp8IKW9U5M,4262
99
+ aiagents4pharma/talk2scholars/tools/s2/search.py,sha256=pppjrQv5-8ep4fnqgTSBNgnbSnQsVIcNrRrH0p2TP1o,4025
100
+ aiagents4pharma/talk2scholars/tools/s2/single_paper_rec.py,sha256=dAfUQxI7T5eu0eDxK8VAl7-JH0Wnw24CVkOQqwj-hXc,4810
101
+ aiagents4pharma-1.16.0.dist-info/LICENSE,sha256=IcIbyB1Hyk5ZDah03VNQvJkbNk2hkBCDqQ8qtnCvB4Q,1077
102
+ aiagents4pharma-1.16.0.dist-info/METADATA,sha256=XH5jLQYNhAKOc4ixt5KovsExcjX14eEBrzTp40YluKY,8906
103
+ aiagents4pharma-1.16.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
104
+ aiagents4pharma-1.16.0.dist-info/top_level.txt,sha256=-AH8rMmrSnJtq7HaAObS78UU-cTCwvX660dSxeM7a0A,16
105
+ aiagents4pharma-1.16.0.dist-info/RECORD,,