aiagents4pharma 1.0.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/__init__.py +5 -0
- aiagents4pharma/talk2biomodels/__init__.py +5 -0
- aiagents4pharma/talk2biomodels/models/__init__.py +5 -0
- aiagents4pharma/talk2biomodels/models/basico_model.py +90 -0
- aiagents4pharma/talk2biomodels/models/sys_bio_model.py +54 -0
- aiagents4pharma/talk2biomodels/tools/__init__.py +7 -0
- aiagents4pharma/talk2biomodels/tools/ask_question.py +136 -0
- aiagents4pharma/talk2biomodels/tools/model_description.py +161 -0
- aiagents4pharma/talk2biomodels/tools/plot_figure.py +135 -0
- aiagents4pharma/talk2biomodels/tools/simulate_model.py +179 -0
- aiagents4pharma-1.0.0.dist-info/LICENSE +21 -0
- aiagents4pharma-1.0.0.dist-info/METADATA +135 -0
- aiagents4pharma-1.0.0.dist-info/RECORD +15 -0
- aiagents4pharma-1.0.0.dist-info/WHEEL +5 -0
- aiagents4pharma-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,90 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
|
3
|
+
"""
|
4
|
+
BasicoModel class for loading and simulating SBML models
|
5
|
+
using the basico package.
|
6
|
+
"""
|
7
|
+
|
8
|
+
from typing import Optional, Dict, Union
|
9
|
+
from pydantic import Field, model_validator
|
10
|
+
import pandas as pd
|
11
|
+
import basico
|
12
|
+
from .sys_bio_model import SysBioModel
|
13
|
+
|
14
|
+
class BasicoModel(SysBioModel):
|
15
|
+
"""
|
16
|
+
Model that loads and simulates SBML models using the basico package.
|
17
|
+
Can load models from an SBML file or download them using a BioModels model_id.
|
18
|
+
"""
|
19
|
+
model_id: Optional[int] = Field(None, description="BioModels model ID to download and load")
|
20
|
+
sbml_file_path: Optional[str] = Field(None, description="Path to an SBML file to load")
|
21
|
+
simulation_results: Optional[str] = None
|
22
|
+
name: Optional[str] = Field("", description="Name of the model")
|
23
|
+
description: Optional[str] = Field("", description="Description of the model")
|
24
|
+
|
25
|
+
# Additional attribute not included in the schema
|
26
|
+
copasi_model: Optional[object] = None # Holds the loaded Copasi model
|
27
|
+
|
28
|
+
@model_validator(mode="after")
|
29
|
+
def check_model_id_or_sbml_file_path(self):
|
30
|
+
"""
|
31
|
+
Validate that either model_id or sbml_file_path is provided.
|
32
|
+
"""
|
33
|
+
if not self.model_id and not self.sbml_file_path:
|
34
|
+
raise ValueError("Either model_id or sbml_file_path must be provided.")
|
35
|
+
if self.model_id:
|
36
|
+
self.copasi_model = basico.load_biomodel(self.model_id)
|
37
|
+
self.description = basico.biomodels.get_model_info(self.model_id)["description"]
|
38
|
+
elif self.sbml_file_path:
|
39
|
+
self.copasi_model = basico.load_model(self.sbml_file_path)
|
40
|
+
return self
|
41
|
+
|
42
|
+
def simulate(self,
|
43
|
+
parameters: Optional[Dict[str, Union[float, int]]] = None,
|
44
|
+
duration: Union[int, float] = 10,
|
45
|
+
interval: int = 10
|
46
|
+
) -> pd.DataFrame:
|
47
|
+
"""
|
48
|
+
Simulate the COPASI model over a specified range of time points.
|
49
|
+
|
50
|
+
Args:
|
51
|
+
parameters: Dictionary of model parameters to update before simulation.
|
52
|
+
duration: Duration of the simulation in time units.
|
53
|
+
interval: Interval between time points in the simulation.
|
54
|
+
|
55
|
+
Returns:
|
56
|
+
Pandas DataFrame with time-course simulation results.
|
57
|
+
"""
|
58
|
+
|
59
|
+
# Update parameters in the model
|
60
|
+
if parameters:
|
61
|
+
for param_name, param_value in parameters.items():
|
62
|
+
# check if the param_name is not None
|
63
|
+
if param_name is None:
|
64
|
+
continue
|
65
|
+
basico.model_info.set_species(name=param_name,
|
66
|
+
exact=True,
|
67
|
+
initial_concentration=param_value,
|
68
|
+
model=self.copasi_model)
|
69
|
+
|
70
|
+
# Run the simulation and return results
|
71
|
+
df_result = basico.run_time_course(model=self.copasi_model,
|
72
|
+
intervals=interval,
|
73
|
+
duration=duration)
|
74
|
+
df_result.columns = df_result.columns.str.replace('{', '[', regex=False).\
|
75
|
+
str.replace('}', ']', regex=False)
|
76
|
+
df_result.reset_index(inplace=True)
|
77
|
+
self.simulation_results = df_result
|
78
|
+
return df_result.copy()
|
79
|
+
|
80
|
+
def get_model_metadata(self) -> Dict[str, Union[str, int]]:
|
81
|
+
"""
|
82
|
+
Retrieve metadata specific to the COPASI model.
|
83
|
+
|
84
|
+
Returns:
|
85
|
+
Dictionary of model metadata.
|
86
|
+
"""
|
87
|
+
return {
|
88
|
+
"Model Type": "SBML Model (COPASI)",
|
89
|
+
"Parameter Count": len(basico.get_parameters())
|
90
|
+
}
|
@@ -0,0 +1,54 @@
|
|
1
|
+
'''
|
2
|
+
An abstract base class for BioModels in the BioModels repository.
|
3
|
+
'''
|
4
|
+
|
5
|
+
from abc import ABC, abstractmethod
|
6
|
+
from typing import List, Dict, Union, Optional
|
7
|
+
from pydantic import BaseModel, Field, model_validator
|
8
|
+
|
9
|
+
class SysBioModel(ABC, BaseModel):
|
10
|
+
"""
|
11
|
+
Abstract base class for BioModels in the BioModels repository.
|
12
|
+
This class serves as a general structure for models, allowing
|
13
|
+
different mathematical approaches to be implemented in subclasses.
|
14
|
+
"""
|
15
|
+
model_id: Optional[int] = Field(None, description="BioModel ID of the model")
|
16
|
+
sbml_file_path: Optional[str] = Field(None, description="Path to an SBML file")
|
17
|
+
name: Optional[str] = Field(..., description="Name of the model")
|
18
|
+
description: Optional[str] = Field("", description="Description of the model")
|
19
|
+
|
20
|
+
@model_validator(mode="after")
|
21
|
+
def check_model_id_or_sbml_file_path(self):
|
22
|
+
"""
|
23
|
+
Validate that either model_id or sbml_file_path is provided.
|
24
|
+
"""
|
25
|
+
if not self.model_id and not self.sbml_file_path:
|
26
|
+
raise ValueError("Either model_id or sbml_file_path must be provided.")
|
27
|
+
return self
|
28
|
+
|
29
|
+
@abstractmethod
|
30
|
+
def get_model_metadata(self) -> Dict[str, Union[str, int]]:
|
31
|
+
"""
|
32
|
+
Abstract method to retrieve metadata of the model.
|
33
|
+
This method should return a dictionary containing model metadata.
|
34
|
+
|
35
|
+
Returns:
|
36
|
+
dict: Dictionary with model metadata
|
37
|
+
"""
|
38
|
+
|
39
|
+
@abstractmethod
|
40
|
+
def simulate(self,
|
41
|
+
parameters: Dict[str, Union[float, int]],
|
42
|
+
duration: Union[int, float]) -> List[float]:
|
43
|
+
"""
|
44
|
+
Abstract method to run a simulation of the model.
|
45
|
+
This method should be implemented to simulate model
|
46
|
+
behavior based on the provided parameters.
|
47
|
+
|
48
|
+
Args:
|
49
|
+
parameters: Dictionary of parameter values.
|
50
|
+
duration: Duration of the simulation.
|
51
|
+
|
52
|
+
Returns:
|
53
|
+
list: List of simulation results.
|
54
|
+
"""
|
@@ -0,0 +1,136 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
|
3
|
+
"""
|
4
|
+
Tool for asking a question about the simulation results.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from typing import Type, Optional
|
8
|
+
from dataclasses import dataclass
|
9
|
+
import streamlit as st
|
10
|
+
from pydantic import BaseModel, Field
|
11
|
+
from langchain_core.tools.base import BaseTool
|
12
|
+
from langchain_core.callbacks import CallbackManagerForToolRun
|
13
|
+
from langchain.agents.agent_types import AgentType
|
14
|
+
from langchain_experimental.agents import create_pandas_dataframe_agent
|
15
|
+
from langchain_openai import ChatOpenAI
|
16
|
+
from ..models.basico_model import BasicoModel
|
17
|
+
|
18
|
+
@dataclass
|
19
|
+
class ModelData:
|
20
|
+
"""
|
21
|
+
Dataclass for storing the model data.
|
22
|
+
"""
|
23
|
+
modelid: Optional[int] = None
|
24
|
+
sbml_file_path: Optional[str] = None
|
25
|
+
model_object: Optional[BasicoModel] = None
|
26
|
+
|
27
|
+
class AskQuestionInput(BaseModel):
|
28
|
+
"""
|
29
|
+
Input schema for the AskQuestion tool.
|
30
|
+
"""
|
31
|
+
question: str = Field(description="question about the simulation results")
|
32
|
+
sys_bio_model: ModelData = Field(description="model data", default=None)
|
33
|
+
st_session_key: str = Field(description="Streamlit session key", default=None)
|
34
|
+
|
35
|
+
# Note: It's important that every field has type hints. BaseTool is a
|
36
|
+
# Pydantic class and not having type hints can lead to unexpected behavior.
|
37
|
+
class AskQuestionTool(BaseTool):
|
38
|
+
"""
|
39
|
+
Tool for calculating the product of two numbers.
|
40
|
+
"""
|
41
|
+
name: str = "ask_question"
|
42
|
+
description: str = "A tool to ask question about the simulation results."
|
43
|
+
args_schema: Type[BaseModel] = AskQuestionInput
|
44
|
+
return_direct: bool = True
|
45
|
+
|
46
|
+
def _run(self,
|
47
|
+
question: str,
|
48
|
+
sys_bio_model: ModelData = ModelData(),
|
49
|
+
st_session_key: str = None,
|
50
|
+
run_manager: Optional[CallbackManagerForToolRun] = None) -> str:
|
51
|
+
"""
|
52
|
+
Run the tool.
|
53
|
+
|
54
|
+
Args:
|
55
|
+
question (str): The question to ask about the simulation results.
|
56
|
+
st_session_key (str): The Streamlit session key.
|
57
|
+
run_manager (Optional[CallbackManagerForToolRun]): The CallbackManagerForToolRun object.
|
58
|
+
|
59
|
+
Returns:
|
60
|
+
str: The answer to the question.
|
61
|
+
"""
|
62
|
+
# Check if sys_bio_model is provided in the input
|
63
|
+
if sys_bio_model.modelid or sys_bio_model.sbml_file_path or sys_bio_model.model_object:
|
64
|
+
if sys_bio_model.modelid is not None:
|
65
|
+
model_object = BasicoModel(model_id=sys_bio_model.modelid)
|
66
|
+
elif sys_bio_model.sbml_file_path is not None:
|
67
|
+
model_object = BasicoModel(sbml_file_path=sys_bio_model.sbml_file_path)
|
68
|
+
else:
|
69
|
+
model_object = sys_bio_model.model_object
|
70
|
+
else:
|
71
|
+
# If the sys_bio_model is not provided in the input,
|
72
|
+
# get it from the Streamlit session state
|
73
|
+
if st_session_key:
|
74
|
+
if st_session_key not in st.session_state:
|
75
|
+
return f"Session key {st_session_key} not found in Streamlit session state."
|
76
|
+
model_object = st.session_state[st_session_key]
|
77
|
+
else:
|
78
|
+
return "Please provide a valid model object or \
|
79
|
+
Streamlit session key that contains the model object."
|
80
|
+
# Update the object in the streamlit session state
|
81
|
+
if st_session_key:
|
82
|
+
st.session_state[st_session_key] = model_object
|
83
|
+
if model_object.simulation_results is None:
|
84
|
+
model_object.simulate()
|
85
|
+
df = model_object.simulation_results
|
86
|
+
# If there is a Streamlit session key,
|
87
|
+
# display the simulation results
|
88
|
+
if st_session_key:
|
89
|
+
st.text(f"Simulation Results of the model {model_object.model_id}")
|
90
|
+
st.dataframe(df, use_container_width = False, width = 650)
|
91
|
+
# Check if run_manager's metadata has the key 'prompt_content'
|
92
|
+
prompt_content = None
|
93
|
+
if run_manager and 'prompt' in run_manager.metadata:
|
94
|
+
prompt_content = run_manager.metadata['prompt']
|
95
|
+
# Create a pandas dataframe agent with OpenAI
|
96
|
+
df_agent = create_pandas_dataframe_agent(ChatOpenAI(model="gpt-3.5-turbo"),
|
97
|
+
allow_dangerous_code=True,
|
98
|
+
agent_type=AgentType.OPENAI_FUNCTIONS,
|
99
|
+
df=df,
|
100
|
+
prefix=prompt_content)
|
101
|
+
llm_result = df_agent.invoke(question)
|
102
|
+
return llm_result["output"]
|
103
|
+
|
104
|
+
def call_run(self,
|
105
|
+
question: str,
|
106
|
+
sys_bio_model: ModelData = ModelData(),
|
107
|
+
st_session_key: str = None,
|
108
|
+
run_manager: Optional[CallbackManagerForToolRun] = None) -> str:
|
109
|
+
"""
|
110
|
+
Run the tool.
|
111
|
+
|
112
|
+
Args:
|
113
|
+
question (str): The question to ask about the simulation results.
|
114
|
+
sys_bio_model (ModelData): The model data.
|
115
|
+
st_session_key (str): The Streamlit session key.
|
116
|
+
run_manager (Optional[CallbackManagerForToolRun]): The CallbackManagerForToolRun object.
|
117
|
+
|
118
|
+
Returns:
|
119
|
+
str: The answer to the question.
|
120
|
+
"""
|
121
|
+
return self._run(question=question,
|
122
|
+
sys_bio_model=sys_bio_model,
|
123
|
+
st_session_key=st_session_key,
|
124
|
+
run_manager=run_manager)
|
125
|
+
|
126
|
+
def get_metadata(self):
|
127
|
+
"""
|
128
|
+
Get metadata for the tool.
|
129
|
+
|
130
|
+
Returns:
|
131
|
+
dict: The metadata for the tool.
|
132
|
+
"""
|
133
|
+
return {
|
134
|
+
"name": self.name,
|
135
|
+
"description": self.description
|
136
|
+
}
|
@@ -0,0 +1,161 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
|
3
|
+
"""
|
4
|
+
Tool for asking a question about the model description.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from typing import Type, Optional
|
8
|
+
from dataclasses import dataclass
|
9
|
+
from pydantic import BaseModel, Field, model_validator
|
10
|
+
import streamlit as st
|
11
|
+
from langchain_core.tools import BaseTool
|
12
|
+
from langchain_core.output_parsers import StrOutputParser
|
13
|
+
from langchain_core.callbacks import CallbackManagerForToolRun
|
14
|
+
from langchain_core.prompts import ChatPromptTemplate
|
15
|
+
from langchain_openai import ChatOpenAI
|
16
|
+
from ..models.basico_model import BasicoModel
|
17
|
+
|
18
|
+
@dataclass
|
19
|
+
class ModelData:
|
20
|
+
"""
|
21
|
+
Dataclass for storing the model data.
|
22
|
+
"""
|
23
|
+
modelid: Optional[int] = None
|
24
|
+
sbml_file_path: Optional[str] = None
|
25
|
+
model_object: Optional[BasicoModel] = None
|
26
|
+
|
27
|
+
# Check if model_object is an instance of BasicoModel
|
28
|
+
# otherwise make it None. This is important because
|
29
|
+
# sometimes the LLM may invoke the tool with an
|
30
|
+
# inappropriate model_object.
|
31
|
+
@model_validator(mode="before")
|
32
|
+
@classmethod
|
33
|
+
def check_model_object(cls, data):
|
34
|
+
"""
|
35
|
+
Check if model_object is an instance of BasicoModel.
|
36
|
+
"""
|
37
|
+
if 'model_object' in data:
|
38
|
+
if not isinstance(data['model_object'], BasicoModel):
|
39
|
+
data['model_object'] = None
|
40
|
+
return data
|
41
|
+
|
42
|
+
|
43
|
+
class ModelDescriptionInput(BaseModel):
|
44
|
+
"""
|
45
|
+
Input schema for the ModelDescription tool.
|
46
|
+
"""
|
47
|
+
question: str = Field(description="question about the model description")
|
48
|
+
sys_bio_model: ModelData = Field(description="model data", default=None)
|
49
|
+
st_session_key: str = Field(description="Streamlit session key", default=None)
|
50
|
+
|
51
|
+
|
52
|
+
# Note: It's important that every field has type hints. BaseTool is a
|
53
|
+
# Pydantic class and not having type hints can lead to unexpected behavior.
|
54
|
+
class ModelDescriptionTool(BaseTool):
|
55
|
+
"""
|
56
|
+
Tool for returning the description of the specified BioModel.
|
57
|
+
"""
|
58
|
+
name: str = "model_description"
|
59
|
+
description: str = '''A tool to ask about the description of the model.'''
|
60
|
+
|
61
|
+
args_schema: Type[BaseModel] = ModelDescriptionInput
|
62
|
+
return_direct: bool = True
|
63
|
+
|
64
|
+
def _run(self,
|
65
|
+
question: str,
|
66
|
+
sys_bio_model: ModelData = ModelData(),
|
67
|
+
st_session_key: str = None,
|
68
|
+
run_manager: Optional[CallbackManagerForToolRun] = None) -> str:
|
69
|
+
"""
|
70
|
+
Run the tool.
|
71
|
+
|
72
|
+
Args:
|
73
|
+
question (str): The question to ask about the model description.
|
74
|
+
st_session_key (str): The Streamlit session key.
|
75
|
+
run_manager (Optional[CallbackManagerForToolRun]): The CallbackManagerForToolRun object.
|
76
|
+
|
77
|
+
Returns:
|
78
|
+
str: The answer to the question.
|
79
|
+
"""
|
80
|
+
# Check if sys_bio_model is provided in the input schema
|
81
|
+
if sys_bio_model.modelid or sys_bio_model.sbml_file_path \
|
82
|
+
or sys_bio_model.model_object not in [None, "", {}]:
|
83
|
+
if sys_bio_model.modelid:
|
84
|
+
model_object = BasicoModel(model_id=sys_bio_model.modelid)
|
85
|
+
elif sys_bio_model.sbml_file_path:
|
86
|
+
model_object = BasicoModel(sbml_file_path=sys_bio_model.sbml_file_path)
|
87
|
+
else:
|
88
|
+
print (sys_bio_model.model_object, 'model_object')
|
89
|
+
model_object = sys_bio_model.model_object
|
90
|
+
if st_session_key:
|
91
|
+
st.session_state[st_session_key] = model_object
|
92
|
+
# Check if sys_bio_model is provided in the Streamlit session state
|
93
|
+
elif st_session_key:
|
94
|
+
if st_session_key not in st.session_state:
|
95
|
+
return f"Session key {st_session_key} " \
|
96
|
+
"not found in Streamlit session state."
|
97
|
+
model_object = st.session_state[st_session_key]
|
98
|
+
else:
|
99
|
+
return "Please provide a valid model object or Streamlit "\
|
100
|
+
"session key that contains the model object."
|
101
|
+
# check if model_object is None
|
102
|
+
if model_object is None:
|
103
|
+
return "Please provide a BioModels ID or an SBML file path for the model."
|
104
|
+
description = model_object.description
|
105
|
+
if description in [None, ""]:
|
106
|
+
return "No description found for the model."
|
107
|
+
# Append the BioModel ID of the model to the description
|
108
|
+
description = f"{description} (BioModel ID: {model_object.model_id})"
|
109
|
+
llm = ChatOpenAI(model="gpt-3.5-turbo")
|
110
|
+
# Check if run_manager's metadata has the key 'prompt_content'
|
111
|
+
if run_manager and 'prompt' in run_manager.metadata:
|
112
|
+
prompt_content = run_manager.metadata['prompt']
|
113
|
+
else:
|
114
|
+
prompt_content = '''
|
115
|
+
Given the description of a System biology model:
|
116
|
+
{description},
|
117
|
+
answer the user question:
|
118
|
+
{question}.
|
119
|
+
'''
|
120
|
+
prompt_template = ChatPromptTemplate.from_messages(
|
121
|
+
[("system", prompt_content),
|
122
|
+
("user", "{description} {question}")]
|
123
|
+
)
|
124
|
+
parser = StrOutputParser()
|
125
|
+
chain = prompt_template | llm | parser
|
126
|
+
return chain.invoke({"description": description,
|
127
|
+
"question": question})
|
128
|
+
|
129
|
+
def call_run(self,
|
130
|
+
question: str,
|
131
|
+
sys_bio_model: ModelData = ModelData(),
|
132
|
+
st_session_key: str = None,
|
133
|
+
run_manager: Optional[CallbackManagerForToolRun] = None) -> str:
|
134
|
+
"""
|
135
|
+
Run the tool.
|
136
|
+
|
137
|
+
Args:
|
138
|
+
question (str): The question to ask about the model description.
|
139
|
+
sys_bio_model (ModelData): The model data.
|
140
|
+
st_session_key (str): The Streamlit session key.
|
141
|
+
run_manager (Optional[CallbackManagerForToolRun]): The CallbackManagerForToolRun object.
|
142
|
+
|
143
|
+
Returns:
|
144
|
+
str: The answer to the question
|
145
|
+
"""
|
146
|
+
return self._run(question=question,
|
147
|
+
sys_bio_model=sys_bio_model,
|
148
|
+
st_session_key=st_session_key,
|
149
|
+
run_manager=run_manager)
|
150
|
+
|
151
|
+
def get_metadata(self):
|
152
|
+
"""
|
153
|
+
Get metadata for the tool.
|
154
|
+
|
155
|
+
Returns:
|
156
|
+
dict: The metadata for the tool.
|
157
|
+
"""
|
158
|
+
return {
|
159
|
+
"name": self.name,
|
160
|
+
"description": self.description
|
161
|
+
}
|
@@ -0,0 +1,135 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
|
3
|
+
"""
|
4
|
+
Tool for plotting a figure.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from typing import Type, Optional
|
8
|
+
from dataclasses import dataclass
|
9
|
+
import matplotlib.pyplot as plt
|
10
|
+
from pydantic import BaseModel, Field
|
11
|
+
import streamlit as st
|
12
|
+
from langchain_openai import ChatOpenAI
|
13
|
+
from langchain_core.tools import BaseTool
|
14
|
+
from langchain_core.prompts import ChatPromptTemplate
|
15
|
+
from langchain_core.output_parsers.openai_tools import JsonOutputKeyToolsParser
|
16
|
+
from langchain_experimental.tools import PythonAstREPLTool
|
17
|
+
from ..models.basico_model import BasicoModel
|
18
|
+
|
19
|
+
@dataclass
|
20
|
+
class ModelData:
|
21
|
+
"""
|
22
|
+
Dataclass for storing the model data.
|
23
|
+
"""
|
24
|
+
modelid: Optional[int] = None
|
25
|
+
sbml_file_path: Optional[str] = None
|
26
|
+
model_object: Optional[BasicoModel] = None
|
27
|
+
|
28
|
+
class PlotImageInput(BaseModel):
|
29
|
+
"""
|
30
|
+
Input schema for the PlotImage tool.
|
31
|
+
"""
|
32
|
+
question: str = Field(description="Description of the plot")
|
33
|
+
sys_bio_model: ModelData = Field(description="model data", default=None)
|
34
|
+
st_session_key: str = Field(description="Streamlit session key", default=None)
|
35
|
+
|
36
|
+
# Note: It's important that every field has type hints. BaseTool is a
|
37
|
+
# Pydantic class and not having type hints can lead to unexpected behavior.
|
38
|
+
class PlotImageTool(BaseTool):
|
39
|
+
"""
|
40
|
+
Tool for plotting a figure.
|
41
|
+
"""
|
42
|
+
name: str = "plot_figure"
|
43
|
+
description: str = "A tool to plot or visualize the simulation results."
|
44
|
+
args_schema: Type[BaseModel] = PlotImageInput
|
45
|
+
|
46
|
+
def _run(self,
|
47
|
+
question: str,
|
48
|
+
sys_bio_model: ModelData = ModelData(),
|
49
|
+
st_session_key: str = None) -> str:
|
50
|
+
"""
|
51
|
+
Run the tool.
|
52
|
+
|
53
|
+
Args:
|
54
|
+
question (str): The question to ask about the model description.
|
55
|
+
st_session_key (str): The Streamlit session key.
|
56
|
+
|
57
|
+
Returns:
|
58
|
+
str: The answer to the question
|
59
|
+
"""
|
60
|
+
# Check if sys_bio_model is provided
|
61
|
+
if sys_bio_model.modelid or sys_bio_model.sbml_file_path or sys_bio_model.model_object:
|
62
|
+
if sys_bio_model.modelid:
|
63
|
+
model_object = BasicoModel(model_id=sys_bio_model.modelid)
|
64
|
+
elif sys_bio_model.sbml_file_path:
|
65
|
+
model_object = BasicoModel(sbml_file_path=sys_bio_model.sbml_file_path)
|
66
|
+
else:
|
67
|
+
model_object = sys_bio_model.model_object
|
68
|
+
if st_session_key:
|
69
|
+
st.session_state[st_session_key] = model_object
|
70
|
+
else:
|
71
|
+
# If the model_object is not provided,
|
72
|
+
# get it from the Streamlit session state
|
73
|
+
if st_session_key:
|
74
|
+
if st_session_key not in st.session_state:
|
75
|
+
return f"Session key {st_session_key} not found in Streamlit session state."
|
76
|
+
model_object = st.session_state[st_session_key]
|
77
|
+
else:
|
78
|
+
return "Please provide a valid model object or \
|
79
|
+
Streamlit session key that contains the model object."
|
80
|
+
if model_object is None:
|
81
|
+
return "Please run the simulation first before plotting the figure."
|
82
|
+
if model_object.simulation_results is None:
|
83
|
+
model_object.simulate()
|
84
|
+
df = model_object.simulation_results
|
85
|
+
tool = PythonAstREPLTool(locals={"df": df})
|
86
|
+
llm = ChatOpenAI(model="gpt-3.5-turbo")
|
87
|
+
llm_with_tools = llm.bind_tools([tool], tool_choice=tool.name)
|
88
|
+
system = f"""
|
89
|
+
You have access to a pandas dataframe `df`.
|
90
|
+
Here is the output of `df.head().to_markdown()`:
|
91
|
+
{df.head().to_markdown()}
|
92
|
+
Given a user question, write the Python code to
|
93
|
+
plot a figure of the answer using matplolib.
|
94
|
+
Return ONLY the valid Python code and nothing else.
|
95
|
+
The firgure size should be equal or smaller than (2, 2).
|
96
|
+
Show the grid and legend. The font size of the legend should be 6.
|
97
|
+
Also write a suitable title for the figure. The font size of the title should be 8.
|
98
|
+
The font size of the x-axis and y-axis labels should be 8.
|
99
|
+
The font size of the x-axis and y-axis ticks should be 6.
|
100
|
+
Make sure that the x-axis has at least 10 tick marks.
|
101
|
+
Use color-blind friendly colors. The figure must be of high quality.
|
102
|
+
Don't assume you have access to any libraries other
|
103
|
+
than built-in Python ones, pandas, streamlit and matplotlib.
|
104
|
+
"""
|
105
|
+
prompt = ChatPromptTemplate.from_messages([("system", system), ("human", "{question}")])
|
106
|
+
parser = JsonOutputKeyToolsParser(key_name=tool.name, first_tool_only=True)
|
107
|
+
code_chain = prompt | llm_with_tools | parser
|
108
|
+
response = code_chain.invoke({"question": question})
|
109
|
+
exec(response['query'], globals(), {"df": df, "plt": plt})
|
110
|
+
# load for plotly
|
111
|
+
fig = plt.gcf()
|
112
|
+
if st_session_key:
|
113
|
+
st.pyplot(fig, use_container_width=False)
|
114
|
+
st.dataframe(df)
|
115
|
+
return "Figure plotted successfully"
|
116
|
+
|
117
|
+
def call_run(self,
|
118
|
+
question: str,
|
119
|
+
sys_bio_model: ModelData = ModelData(),
|
120
|
+
st_session_key: str = None) -> str:
|
121
|
+
"""
|
122
|
+
Run the tool.
|
123
|
+
"""
|
124
|
+
return self._run(question=question,
|
125
|
+
sys_bio_model=sys_bio_model,
|
126
|
+
st_session_key=st_session_key)
|
127
|
+
|
128
|
+
def get_metadata(self):
|
129
|
+
"""
|
130
|
+
Get metadata for the tool.
|
131
|
+
"""
|
132
|
+
return {
|
133
|
+
"name": self.name,
|
134
|
+
"description": self.description
|
135
|
+
}
|
@@ -0,0 +1,179 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
|
3
|
+
"""
|
4
|
+
Tool for simulating a model.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from typing import Type, Union, List, Optional
|
8
|
+
from dataclasses import dataclass
|
9
|
+
from pydantic import BaseModel, Field
|
10
|
+
from langchain_core.tools import BaseTool
|
11
|
+
import streamlit as st
|
12
|
+
import plotly.express as px
|
13
|
+
from ..models.basico_model import BasicoModel
|
14
|
+
|
15
|
+
@dataclass
|
16
|
+
class ModelData:
|
17
|
+
"""
|
18
|
+
Dataclass for storing the model data.
|
19
|
+
"""
|
20
|
+
modelid: Optional[int] = None
|
21
|
+
sbml_file_path: Optional[str] = None
|
22
|
+
|
23
|
+
@dataclass
|
24
|
+
class TimeData:
|
25
|
+
"""
|
26
|
+
Dataclass for storing the time data.
|
27
|
+
"""
|
28
|
+
duration: Union[int, float] = 100
|
29
|
+
interval: Union[int, float] = 10
|
30
|
+
|
31
|
+
@dataclass
|
32
|
+
class SpeciesData:
|
33
|
+
"""
|
34
|
+
Dataclass for storing the species data.
|
35
|
+
"""
|
36
|
+
species_name: List[str] = None
|
37
|
+
species_concentration: List[Union[int, float]] = None
|
38
|
+
|
39
|
+
class SimulateModelInput(BaseModel):
|
40
|
+
"""
|
41
|
+
Input schema for the SimulateModel tool.
|
42
|
+
"""
|
43
|
+
st_session_key: str = Field(description="Streamlit session key", default=None)
|
44
|
+
model_data: ModelData = Field(description="model data", default=None)
|
45
|
+
time_data: TimeData = Field(description="time data", default=None)
|
46
|
+
species_data: SpeciesData = Field(description="species data", default=None)
|
47
|
+
|
48
|
+
# Note: It's important that every field has type hints. BaseTool is a
|
49
|
+
# Pydantic class and not having type hints can lead to unexpected behavior.
|
50
|
+
class SimulateModelTool(BaseTool):
|
51
|
+
"""
|
52
|
+
Tool for simulating a model.
|
53
|
+
"""
|
54
|
+
name: str = "simulate_model"
|
55
|
+
description: str = "A tool for simulating a model."
|
56
|
+
args_schema: Type[BaseModel] = SimulateModelInput
|
57
|
+
|
58
|
+
def _run(self,
|
59
|
+
model_data: ModelData = None,
|
60
|
+
time_data: TimeData = None,
|
61
|
+
species_data: SpeciesData = None,
|
62
|
+
st_session_key: str = None):
|
63
|
+
"""
|
64
|
+
Run the tool.
|
65
|
+
|
66
|
+
Args:
|
67
|
+
model_data (Optional[ModelData]): The model data.
|
68
|
+
time_data (Optional[TimeData]): The time data.
|
69
|
+
species_data (Optional[SpeciesData]): The species data.
|
70
|
+
st_session_key (str): The Streamlit session key
|
71
|
+
|
72
|
+
Returns:
|
73
|
+
str: The result of the simulation.
|
74
|
+
"""
|
75
|
+
# Retrieve the model ID, duration, and interval
|
76
|
+
modelid = model_data.modelid if model_data is not None else None
|
77
|
+
duration = time_data.duration if time_data is not None else 100.0
|
78
|
+
interval = time_data.interval if time_data is not None else 10
|
79
|
+
# Prepare the dictionary of species data
|
80
|
+
# that will be passed to the simulate method
|
81
|
+
# of the BasicoModel class
|
82
|
+
dic_species_data = None
|
83
|
+
if species_data is not None:
|
84
|
+
dic_species_data = dict(zip(species_data.species_name,
|
85
|
+
species_data.species_concentration))
|
86
|
+
# Retrieve the SBML file path from the Streamlit session state
|
87
|
+
# otherwise retrieve it from the model_data object if the user
|
88
|
+
# has provided it.
|
89
|
+
sbml_file_path = model_data.sbml_file_path if model_data is not None else None
|
90
|
+
if st_session_key:
|
91
|
+
if st_session_key not in st.session_state:
|
92
|
+
return f"Session key {st_session_key} not found in Streamlit session state."
|
93
|
+
if 'sbml_file_path' in st.session_state:
|
94
|
+
sbml_file_path = st.session_state.sbml_file_path
|
95
|
+
# Check if both modelid and sbml_file_path are None
|
96
|
+
if modelid is None and sbml_file_path is None:
|
97
|
+
# Then load the model from the Streamlit session state
|
98
|
+
# if the streamlit session exists
|
99
|
+
if st_session_key:
|
100
|
+
model_object = st.session_state[st_session_key]
|
101
|
+
# If this model object is None, then return an error message
|
102
|
+
if model_object is None:
|
103
|
+
return "Please provide a BioModels ID or an SBML file path for simulation."
|
104
|
+
# Retrieve the model ID from the model object
|
105
|
+
modelid = model_object.model_id
|
106
|
+
else:
|
107
|
+
# Otherwise return an error message
|
108
|
+
return "Please provide a BioModels ID or an SBML file path for simulation."
|
109
|
+
elif modelid:
|
110
|
+
# Create a BasicoModel object with the model ID
|
111
|
+
# model_object = BasicoModel(model_id=modelid)
|
112
|
+
model_object = BasicoModel(model_id=modelid)
|
113
|
+
# Save the model object in the Streamlit session state
|
114
|
+
st.session_state[st_session_key] = model_object
|
115
|
+
elif sbml_file_path:
|
116
|
+
# Create a BasicoModel object with the SBML file path
|
117
|
+
model_object = BasicoModel(sbml_file_path=sbml_file_path)
|
118
|
+
modelid = model_object.model_id
|
119
|
+
# Save the model object in the Streamlit session state
|
120
|
+
st.session_state[st_session_key] = model_object
|
121
|
+
# Simulate the model
|
122
|
+
df = model_object.simulate(parameters=dic_species_data,
|
123
|
+
duration=duration,
|
124
|
+
interval=interval)
|
125
|
+
# Convert the DataFrame to long format for plotting
|
126
|
+
# and ignore the index column
|
127
|
+
df = df.melt(id_vars='Time',
|
128
|
+
var_name='Species',
|
129
|
+
value_name='Concentration')
|
130
|
+
# Plot the simulation results using Plotly
|
131
|
+
fig = px.line(df,
|
132
|
+
x='Time',
|
133
|
+
y='Concentration',
|
134
|
+
color='Species',
|
135
|
+
title=f"Concentration of Species over Time in the model {modelid}",
|
136
|
+
height=600,
|
137
|
+
width=800
|
138
|
+
)
|
139
|
+
# Display the plot in Streamlit
|
140
|
+
st.plotly_chart(fig, use_container_width = False)
|
141
|
+
if modelid is None:
|
142
|
+
modelid = "internal"
|
143
|
+
content = f"Simulation results for the model {modelid}."
|
144
|
+
return content
|
145
|
+
|
146
|
+
def call_run(self,
|
147
|
+
model_data: ModelData = None,
|
148
|
+
time_data: TimeData = None,
|
149
|
+
species_data: SpeciesData = None,
|
150
|
+
st_session_key: str = None) -> str:
|
151
|
+
"""
|
152
|
+
Run the tool.
|
153
|
+
|
154
|
+
Args:
|
155
|
+
model_data (Optional[ModelData]): The model data.
|
156
|
+
time_data (Optional[TimeData]): The time data.
|
157
|
+
species_data (Optional[SpeciesData]): The species data.
|
158
|
+
st_session_key (str): The Streamlit session key
|
159
|
+
|
160
|
+
Returns:
|
161
|
+
str: The result of the simulation.
|
162
|
+
"""
|
163
|
+
return self._run(model_data=model_data,
|
164
|
+
time_data=time_data,
|
165
|
+
species_data=species_data,
|
166
|
+
st_session_key=st_session_key)
|
167
|
+
|
168
|
+
def get_metadata(self):
|
169
|
+
"""
|
170
|
+
Get metadata for the tool.
|
171
|
+
|
172
|
+
Returns:
|
173
|
+
dict: The metadata for the tool.
|
174
|
+
"""
|
175
|
+
return {
|
176
|
+
"name": self.name,
|
177
|
+
"description": self.description,
|
178
|
+
"return_direct": self.return_direct,
|
179
|
+
}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2024 VirtualPatientEngine
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
@@ -0,0 +1,135 @@
|
|
1
|
+
Metadata-Version: 2.1
|
2
|
+
Name: aiagents4pharma
|
3
|
+
Version: 1.0.0
|
4
|
+
Summary: AI Agents for drug discovery, drug development, and other pharmaceutical R&D
|
5
|
+
Classifier: Programming Language :: Python :: 3
|
6
|
+
Classifier: License :: OSI Approved :: MIT License
|
7
|
+
Classifier: Operating System :: OS Independent
|
8
|
+
Requires-Python: >=3.10
|
9
|
+
Description-Content-Type: text/markdown
|
10
|
+
License-File: LICENSE
|
11
|
+
Requires-Dist: copasi-basico==0.78
|
12
|
+
Requires-Dist: coverage==7.6.4
|
13
|
+
Requires-Dist: langchain==0.3.7
|
14
|
+
Requires-Dist: langchain-community==0.3.5
|
15
|
+
Requires-Dist: langchain-core==0.3.15
|
16
|
+
Requires-Dist: langchain-experimental==0.3.3
|
17
|
+
Requires-Dist: langchain-openai==0.2.5
|
18
|
+
Requires-Dist: matplotlib==3.9.2
|
19
|
+
Requires-Dist: openai==1.53.0
|
20
|
+
Requires-Dist: pandas==2.2.3
|
21
|
+
Requires-Dist: plotly==5.24.1
|
22
|
+
Requires-Dist: pydantic==2.9.2
|
23
|
+
Requires-Dist: pylint==3.3.1
|
24
|
+
Requires-Dist: pytest==8.3.3
|
25
|
+
Requires-Dist: streamlit==1.39.0
|
26
|
+
Requires-Dist: tabulate==0.9.0
|
27
|
+
Requires-Dist: tqdm==4.66.6
|
28
|
+
|
29
|
+
[](https://github.com/VirtualPatientEngine/AIAgents4Pharma/actions/workflows/tests.yml)
|
30
|
+
|
31
|
+
<h1 align="center" style="border-bottom: none;">🤖 AIAgents4Pharma</h1>
|
32
|
+
|
33
|
+
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.
|
34
|
+
|
35
|
+
Our toolkit currently consists of three intelligent agents, each designed to simplify and enhance access to specialized data in biology:
|
36
|
+
|
37
|
+
- **Talk2BioModels**: Engage directly with mathematical models in systems biology.
|
38
|
+
- **Talk2Cells** *(Coming soon)*: Query and analyze sequencing data with ease.
|
39
|
+
- **Talk2KnowledgeGraphs** *(Coming soon)*: Access and explore complex biological knowledge graphs for insightful data connections.
|
40
|
+
|
41
|
+
---
|
42
|
+
|
43
|
+
## Overview of Agents
|
44
|
+
|
45
|
+
### 1. Talk2BioModels
|
46
|
+
|
47
|
+
**Talk2BioModels** is an AI agent designed to facilitate interaction with mathematical models in systems biology. Systems biology models are critical in understanding complex biological mechanisms, but they’re often inaccessible to those without coding or mathematical expertise. Talk2BioModels simplifies this, enabling researchers to focus on analysis and interpretation rather than on programming. With Talk2BioModels, users can interact directly with these models through natural language. By simply asking questions or making requests, users can:
|
48
|
+
|
49
|
+
- Forward simulation of both internal and open-source models (BioModels).
|
50
|
+
- Adjust parameters within the model to simulate different conditions.
|
51
|
+
- Query simulation results.
|
52
|
+
|
53
|
+
### 2. Talk2Cells *(Coming soon)*
|
54
|
+
|
55
|
+
**Talk2Cells** is being developed to provide direct access to and analysis of sequencing data, such as RNA-Seq or DNA-Seq, using natural language.
|
56
|
+
|
57
|
+
### 3. Talk2KnowledgeGraphs *(Work in Progress)*
|
58
|
+
|
59
|
+
**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.
|
60
|
+
|
61
|
+
## Getting Started
|
62
|
+
|
63
|
+
### Prerequisites
|
64
|
+
|
65
|
+
- **Python 3.10+**
|
66
|
+
- **Git**
|
67
|
+
- Required libraries specified in `requirements.txt`
|
68
|
+
|
69
|
+
### Installation
|
70
|
+
|
71
|
+
1. **Clone the repository:**
|
72
|
+
```bash
|
73
|
+
git clone https://github.com/VirtualPatientEngine/AIAgents4Pharma
|
74
|
+
cd AIAgents4Pharma
|
75
|
+
```
|
76
|
+
|
77
|
+
2. **Install dependencies:**
|
78
|
+
```bash
|
79
|
+
pip install -r requirements.txt
|
80
|
+
```
|
81
|
+
|
82
|
+
3. **Initialize OPENAI_API_KEY**
|
83
|
+
```bash
|
84
|
+
export OPENAI_API_KEY = ....
|
85
|
+
```
|
86
|
+
|
87
|
+
4. **Launch the agent:**
|
88
|
+
To launch the Talk2BioModels agent, run:
|
89
|
+
```bash
|
90
|
+
streamlit run app/frontend/streamlit_app.py
|
91
|
+
```
|
92
|
+
|
93
|
+
For detailed instructions on each agent, please refer to their respective folders.
|
94
|
+
|
95
|
+
---
|
96
|
+
|
97
|
+
## Usage
|
98
|
+
|
99
|
+
**Talk2BioModels** currently provides an interactive console where you can enter natural language queries to simulate models, adjust parameters, and query the simulated results.
|
100
|
+
|
101
|
+
More detailed usage examples, including sample data for Talk2Cells and Talk2KnowledgeGraphs, will be provided as development progresses.
|
102
|
+
|
103
|
+
---
|
104
|
+
|
105
|
+
## Contributing
|
106
|
+
|
107
|
+
We welcome contributions to AIAgents4Pharma! Here’s how you can help:
|
108
|
+
|
109
|
+
1. **Fork the repository**
|
110
|
+
2. **Create a new branch** for your feature (`git checkout -b feat/feature-name`)
|
111
|
+
3. **Commit your changes** (`git commit -m 'feat: Add new feature'`)
|
112
|
+
4. **Push to the branch** (`git push origin feat/feature-name`)
|
113
|
+
5. **Open a pull request**
|
114
|
+
|
115
|
+
### Current Needs
|
116
|
+
- **Beta testers** for Talk2BioModels.
|
117
|
+
- **Developers** with experience in natural language processing, bioinformatics, or knowledge graphs for contributions to AIAgents4Pharma.
|
118
|
+
|
119
|
+
Check out our [CONTRIBUTING.md](CONTRIBUTING.md) for more information.
|
120
|
+
|
121
|
+
---
|
122
|
+
|
123
|
+
## Roadmap
|
124
|
+
|
125
|
+
### Completed
|
126
|
+
- **Talk2BioModels**: Initial release with core capabilities for interacting with systems biology models.
|
127
|
+
|
128
|
+
### Planned
|
129
|
+
- **User Interface**: Interactive web UI for all agents.
|
130
|
+
- **Talk2Cells**: Integration of sequencing data analysis tools.
|
131
|
+
- **Talk2KnowledgeGraphs**: Interface for biological knowledge graph interaction.
|
132
|
+
|
133
|
+
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.
|
134
|
+
|
135
|
+
**Get Started** with AIAgents4Pharma today and transform the way you interact with biological data.
|
@@ -0,0 +1,15 @@
|
|
1
|
+
aiagents4pharma/__init__.py,sha256=OF-rmtiLauF4NIlzEvMrWhNiX-mo5NJ4vrUtQbcLwts,93
|
2
|
+
aiagents4pharma/talk2biomodels/__init__.py,sha256=MueXwbnuiQyiju7mW6NepFUiZJdodMzmUK3TkQT7iPk,99
|
3
|
+
aiagents4pharma/talk2biomodels/models/__init__.py,sha256=5fTHHm3PVloYPNKXbgNlcPgv3-u28ZquxGydFYDfhJA,122
|
4
|
+
aiagents4pharma/talk2biomodels/models/basico_model.py,sha256=zJeLfqGJnQp9baJUsovgQV_WFsVTP2TVZmOG60GyeP8,3639
|
5
|
+
aiagents4pharma/talk2biomodels/models/sys_bio_model.py,sha256=xN-ZXCpIxNkEXuDIvi_AW6LpCyPqXReGyhLPyJIXNqs,1980
|
6
|
+
aiagents4pharma/talk2biomodels/tools/__init__.py,sha256=AM03pbYT3nOzI5jf_CJmSDaDwrI-IZ0Zq9hLA2tOXpw,182
|
7
|
+
aiagents4pharma/talk2biomodels/tools/ask_question.py,sha256=WYEtNuy-wAuwMbP9W9l0qmcHmIuW1ZFMX7SvoYgkv0A,5530
|
8
|
+
aiagents4pharma/talk2biomodels/tools/model_description.py,sha256=NawUK549IqlC36dUmJjIBI1QGeLpNV-JlBt7AiV2BDs,6295
|
9
|
+
aiagents4pharma/talk2biomodels/tools/plot_figure.py,sha256=8QHH6gA7vI85e8RsWJSX8ZAH_WsuIBGLpYqyr4CllVQ,5648
|
10
|
+
aiagents4pharma/talk2biomodels/tools/simulate_model.py,sha256=phUtNScCZQ281MvcU0N2NMkg4Lb8NmfXiMAVt3ON_UQ,6959
|
11
|
+
aiagents4pharma-1.0.0.dist-info/LICENSE,sha256=IcIbyB1Hyk5ZDah03VNQvJkbNk2hkBCDqQ8qtnCvB4Q,1077
|
12
|
+
aiagents4pharma-1.0.0.dist-info/METADATA,sha256=h0lOu1rCm0LNRLdvyFa7NG1OVz6ORrL1wWx8fA73kvA,5460
|
13
|
+
aiagents4pharma-1.0.0.dist-info/WHEEL,sha256=a7TGlA-5DaHMRrarXjVbQagU3Man_dCnGIWMJr5kRWo,91
|
14
|
+
aiagents4pharma-1.0.0.dist-info/top_level.txt,sha256=-AH8rMmrSnJtq7HaAObS78UU-cTCwvX660dSxeM7a0A,16
|
15
|
+
aiagents4pharma-1.0.0.dist-info/RECORD,,
|
@@ -0,0 +1 @@
|
|
1
|
+
aiagents4pharma
|