aiagents4pharma 1.14.1__py3-none-any.whl → 1.15.1__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/configs/talk2biomodels/agents/t2b_agent/default.yaml +7 -1
- aiagents4pharma/configs/talk2biomodels/tools/ask_question/default.yaml +39 -0
- aiagents4pharma/talk2biomodels/agents/t2b_agent.py +3 -1
- aiagents4pharma/talk2biomodels/states/state_talk2biomodels.py +1 -0
- aiagents4pharma/talk2biomodels/tests/test_query_article.py +76 -0
- aiagents4pharma/talk2biomodels/tools/__init__.py +1 -0
- aiagents4pharma/talk2biomodels/tools/query_article.py +59 -0
- {aiagents4pharma-1.14.1.dist-info → aiagents4pharma-1.15.1.dist-info}/METADATA +2 -1
- {aiagents4pharma-1.14.1.dist-info → aiagents4pharma-1.15.1.dist-info}/RECORD +12 -9
- {aiagents4pharma-1.14.1.dist-info → aiagents4pharma-1.15.1.dist-info}/LICENSE +0 -0
- {aiagents4pharma-1.14.1.dist-info → aiagents4pharma-1.15.1.dist-info}/WHEEL +0 -0
- {aiagents4pharma-1.14.1.dist-info → aiagents4pharma-1.15.1.dist-info}/top_level.txt +0 -0
@@ -5,4 +5,10 @@ state_modifier: >
|
|
5
5
|
then pass the use_uploaded_model argument
|
6
6
|
as True. If the user asks for simulation
|
7
7
|
or param_scan or steady state, suggest a
|
8
|
-
value for the `experiment_name` argument.
|
8
|
+
value for the `experiment_name` argument.
|
9
|
+
|
10
|
+
If the user asks question related to the
|
11
|
+
uploaded document/pdf/article/document,
|
12
|
+
use the tool `query_article` to answer the
|
13
|
+
question. Please note that the `experiment_name`
|
14
|
+
argument may be unrelated to the question asked.
|
@@ -0,0 +1,39 @@
|
|
1
|
+
_target_: talk2biomodels.tools.ask_question.AskQuestionTool
|
2
|
+
steady_state_prompt: >
|
3
|
+
Following are header columns of the data:
|
4
|
+
`species_name`: Name of the species,
|
5
|
+
`compartment`: Compartment of the species,
|
6
|
+
`initial_concentration`: Concentration of the species at the start of steady state,
|
7
|
+
`steady_state_concentration`: Concentration of the species at steady state,
|
8
|
+
`steady_state_transition_time`: Time taken to reach steady state,
|
9
|
+
`display_name`: An alias for the species name.
|
10
|
+
|
11
|
+
Here are some instructions to help you answer questions:
|
12
|
+
|
13
|
+
1. Before you answer any question, follow the plan and solve
|
14
|
+
technique. Start by understanding the question, then plan your
|
15
|
+
approach to solve the question, and finally solve the question
|
16
|
+
by following the plan. Always give a brief explanation of your
|
17
|
+
answer to the user.
|
18
|
+
|
19
|
+
2. If the user wants to know the time taken by the model to reach
|
20
|
+
steady state, you should look at the steady_state_transition_time
|
21
|
+
column of the data for the model species. The highest value in
|
22
|
+
this column is the time taken by the model to reach steady state.
|
23
|
+
|
24
|
+
3. To get accurate results, trim the data to the relevant columns
|
25
|
+
before performing any calculations. This will help you avoid
|
26
|
+
errors in your calculations, and ignore irrelevant data.
|
27
|
+
|
28
|
+
4. Please use the units provided below to answer the questions.
|
29
|
+
simulation_prompt: >
|
30
|
+
Following is the information about the data frame:
|
31
|
+
1. First column is the time column, and the rest of the columns
|
32
|
+
are the species names.
|
33
|
+
|
34
|
+
2. While the time column records the simulation time points, the
|
35
|
+
rest of the columns record the concentration of the species at
|
36
|
+
each time point.
|
37
|
+
|
38
|
+
3. Please use the units provided below to answer the questions.
|
39
|
+
|
@@ -19,6 +19,7 @@ from ..tools.get_annotation import GetAnnotationTool
|
|
19
19
|
from ..tools.ask_question import AskQuestionTool
|
20
20
|
from ..tools.parameter_scan import ParameterScanTool
|
21
21
|
from ..tools.steady_state import SteadyStateTool
|
22
|
+
from ..tools.query_article import QueryArticle
|
22
23
|
from ..states.state_talk2biomodels import Talk2Biomodels
|
23
24
|
|
24
25
|
# Initialize logger
|
@@ -46,7 +47,8 @@ def get_app(uniq_id, llm_model='gpt-4o-mini'):
|
|
46
47
|
GetModelInfoTool(),
|
47
48
|
SteadyStateTool(),
|
48
49
|
ParameterScanTool(),
|
49
|
-
GetAnnotationTool()
|
50
|
+
GetAnnotationTool(),
|
51
|
+
QueryArticle()
|
50
52
|
])
|
51
53
|
|
52
54
|
# Define the model
|
@@ -27,6 +27,7 @@ class Talk2Biomodels(AgentState):
|
|
27
27
|
The state for the Talk2BioModels agent.
|
28
28
|
"""
|
29
29
|
llm_model: str
|
30
|
+
pdf_file_name: str
|
30
31
|
# A StateGraph may receive a concurrent updates
|
31
32
|
# which is not supported by the StateGraph. Hence,
|
32
33
|
# we need to add a reducer function to handle the
|
@@ -0,0 +1,76 @@
|
|
1
|
+
'''
|
2
|
+
Test cases for Talk2Biomodels query_article tool.
|
3
|
+
'''
|
4
|
+
|
5
|
+
from pydantic import BaseModel, Field
|
6
|
+
from langchain_core.messages import HumanMessage, ToolMessage
|
7
|
+
from langchain_openai import ChatOpenAI
|
8
|
+
from ..agents.t2b_agent import get_app
|
9
|
+
|
10
|
+
class Article(BaseModel):
|
11
|
+
'''
|
12
|
+
Article schema.
|
13
|
+
'''
|
14
|
+
title: str = Field(description="Title of the article.")
|
15
|
+
|
16
|
+
def test_query_article_with_an_article():
|
17
|
+
'''
|
18
|
+
Test the query_article tool by providing an article.
|
19
|
+
'''
|
20
|
+
unique_id = 12345
|
21
|
+
app = get_app(unique_id)
|
22
|
+
config = {"configurable": {"thread_id": unique_id}}
|
23
|
+
# Update state by providing the pdf file name
|
24
|
+
app.update_state(config,
|
25
|
+
{"pdf_file_name": "aiagents4pharma/talk2biomodels/tests/article_on_model_537.pdf"})
|
26
|
+
prompt = "What is the title of the article?"
|
27
|
+
# Test the tool query_article
|
28
|
+
response = app.invoke(
|
29
|
+
{"messages": [HumanMessage(content=prompt)]},
|
30
|
+
config=config
|
31
|
+
)
|
32
|
+
# Get the response from the tool
|
33
|
+
assistant_msg = response["messages"][-1].content
|
34
|
+
# Prepare a LLM that can be used as a judge
|
35
|
+
llm = ChatOpenAI(model='gpt-4o-mini', temperature=0)
|
36
|
+
# Make it return a structured output
|
37
|
+
structured_llm = llm.with_structured_output(Article)
|
38
|
+
# Prepare a prompt for the judge
|
39
|
+
prompt = "Given the text below, what is the title of the article?"
|
40
|
+
prompt += f"\n\n{assistant_msg}"
|
41
|
+
# Get the structured output
|
42
|
+
article = structured_llm.invoke(prompt)
|
43
|
+
# Check if the article title is correct
|
44
|
+
expected_title = "A Multiscale Model of IL-6–Mediated "
|
45
|
+
expected_title += "Immune Regulation in Crohn’s Disease"
|
46
|
+
# Check if the article title is correct
|
47
|
+
assert article.title == expected_title
|
48
|
+
|
49
|
+
def test_query_article_without_an_article():
|
50
|
+
'''
|
51
|
+
Test the query_article tool without providing an article.
|
52
|
+
The status of the tool should be error.
|
53
|
+
'''
|
54
|
+
unique_id = 12345
|
55
|
+
app = get_app(unique_id)
|
56
|
+
config = {"configurable": {"thread_id": unique_id}}
|
57
|
+
prompt = "What is the title of the uploaded article?"
|
58
|
+
# Test the tool query_article
|
59
|
+
app.invoke(
|
60
|
+
{"messages": [HumanMessage(content=prompt)]},
|
61
|
+
config=config
|
62
|
+
)
|
63
|
+
current_state = app.get_state(config)
|
64
|
+
# Get the messages from the current state
|
65
|
+
# and reverse the order
|
66
|
+
reversed_messages = current_state.values["messages"][::-1]
|
67
|
+
# Loop through the reversed messages
|
68
|
+
# until a ToolMessage is found.
|
69
|
+
tool_status_is_error = False
|
70
|
+
for msg in reversed_messages:
|
71
|
+
if isinstance(msg, ToolMessage):
|
72
|
+
# Skip until it finds a ToolMessage
|
73
|
+
if msg.name == "query_article" and msg.status == "error":
|
74
|
+
tool_status_is_error = True
|
75
|
+
break
|
76
|
+
assert tool_status_is_error
|
@@ -0,0 +1,59 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
|
3
|
+
"""
|
4
|
+
Tool for asking questions to the article.
|
5
|
+
"""
|
6
|
+
|
7
|
+
import logging
|
8
|
+
from typing import Type, Annotated
|
9
|
+
from pydantic import BaseModel, Field
|
10
|
+
from langchain_core.tools import BaseTool
|
11
|
+
from langchain_core.vectorstores import InMemoryVectorStore
|
12
|
+
from langchain_openai.embeddings import OpenAIEmbeddings
|
13
|
+
from langchain_community.document_loaders import PyPDFLoader
|
14
|
+
from langgraph.prebuilt import InjectedState
|
15
|
+
|
16
|
+
# Initialize logger
|
17
|
+
logging.basicConfig(level=logging.INFO)
|
18
|
+
logger = logging.getLogger(__name__)
|
19
|
+
|
20
|
+
class QueryArticleInput(BaseModel):
|
21
|
+
"""
|
22
|
+
Input schema for the query_articles tool.
|
23
|
+
"""
|
24
|
+
question: Annotated[str, Field(description="User question to search articles.")]
|
25
|
+
state: Annotated[dict, InjectedState]
|
26
|
+
|
27
|
+
# Note: It's important that every field has type hints. BaseTool is a
|
28
|
+
# Pydantic class and not having type hints can lead to unexpected behavior.
|
29
|
+
class QueryArticle(BaseTool):
|
30
|
+
"""
|
31
|
+
Tool to ask questions to the article.
|
32
|
+
"""
|
33
|
+
name: str = "query_article"
|
34
|
+
description: str = "Ask questions to the article."
|
35
|
+
args_schema: Type[BaseModel] = QueryArticleInput
|
36
|
+
|
37
|
+
def _run(self,
|
38
|
+
question: str,
|
39
|
+
state: Annotated[dict, InjectedState]):
|
40
|
+
"""
|
41
|
+
Run the tool.
|
42
|
+
|
43
|
+
Args:
|
44
|
+
query (str): The search query.
|
45
|
+
"""
|
46
|
+
logger.log(logging.INFO, "loading the article from %s", state['pdf_file_name'])
|
47
|
+
logger.log(logging.INFO, "searching the article with the question: %s", question)
|
48
|
+
# Load the article
|
49
|
+
loader = PyPDFLoader(state['pdf_file_name'])
|
50
|
+
# Load the pages of the article
|
51
|
+
pages = []
|
52
|
+
for page in loader.lazy_load():
|
53
|
+
pages.append(page)
|
54
|
+
# Create a vector store from the pages
|
55
|
+
vector_store = InMemoryVectorStore.from_documents(pages, OpenAIEmbeddings())
|
56
|
+
# Search the article with the question
|
57
|
+
docs = vector_store.similarity_search(question)
|
58
|
+
# Return the content of the pages
|
59
|
+
return "\n".join([doc.page_content for doc in docs])
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: aiagents4pharma
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.15.1
|
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
|
@@ -29,6 +29,7 @@ Requires-Dist: pandas==2.2.3
|
|
29
29
|
Requires-Dist: plotly==5.24.1
|
30
30
|
Requires-Dist: pydantic==2.9.2
|
31
31
|
Requires-Dist: pylint==3.3.1
|
32
|
+
Requires-Dist: pypdf==5.2.0
|
32
33
|
Requires-Dist: pytest==8.3.3
|
33
34
|
Requires-Dist: pytest-asyncio==0.25.2
|
34
35
|
Requires-Dist: streamlit==1.39.0
|
@@ -4,12 +4,13 @@ aiagents4pharma/configs/config.yaml,sha256=4t7obD0gOSfqnDDZZBB53ZC7zsmk7QDcM7T_1
|
|
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
|
-
aiagents4pharma/configs/talk2biomodels/agents/t2b_agent/default.yaml,sha256=
|
7
|
+
aiagents4pharma/configs/talk2biomodels/agents/t2b_agent/default.yaml,sha256=eLrJIezoPJ6_DvrSYsi3eALl03o0hJhntej3ESoeKKg,551
|
8
8
|
aiagents4pharma/configs/talk2biomodels/tools/__init__.py,sha256=WxK7h5n39l-NSMvjLZyxDqzwWlVA6mQ69gzsbJ17vEk,72
|
9
9
|
aiagents4pharma/configs/talk2biomodels/tools/ask_question/__init__.py,sha256=-fAORvyFmG2iSvFOFDixmt9OTQRR58y89uhhu2EgbA8,46
|
10
|
+
aiagents4pharma/configs/talk2biomodels/tools/ask_question/default.yaml,sha256=yy-Sq1u4dBlTFi_UeoWYoHkWRDWueJWVNK_rcUCC5bw,1747
|
10
11
|
aiagents4pharma/talk2biomodels/__init__.py,sha256=2ICwVh1u07SZv31Jd2DKHobauOxWNWY29_Gqq3kOnNQ,159
|
11
12
|
aiagents4pharma/talk2biomodels/agents/__init__.py,sha256=sn5-fREjMdEvb-OUan3iOqrgYGjplNx3J8hYOaW0Po8,128
|
12
|
-
aiagents4pharma/talk2biomodels/agents/t2b_agent.py,sha256=
|
13
|
+
aiagents4pharma/talk2biomodels/agents/t2b_agent.py,sha256=5h4n7dF13KuT5f9vzfK7EQTu_b0a0hB7ScLFlTKaNko,3449
|
13
14
|
aiagents4pharma/talk2biomodels/api/__init__.py,sha256=_GmDQqDLYpsUPUeE1nBNlT5AI9oTXIcqgOfNfvmonqA,123
|
14
15
|
aiagents4pharma/talk2biomodels/api/kegg.py,sha256=QzYDAfJ16E7tbHGxP8ZNWRizMkMRS_HJuucueXEC1Gg,2943
|
15
16
|
aiagents4pharma/talk2biomodels/api/ols.py,sha256=qq0Qy-gJDxanQW-HfCChDsTQsY1M41ua8hMlTnfuzrA,2202
|
@@ -18,7 +19,7 @@ aiagents4pharma/talk2biomodels/models/__init__.py,sha256=5fTHHm3PVloYPNKXbgNlcPg
|
|
18
19
|
aiagents4pharma/talk2biomodels/models/basico_model.py,sha256=PH25FTOuUjsmw_UUxoRb-4kptOYpicEn4GqS0phS3nk,4807
|
19
20
|
aiagents4pharma/talk2biomodels/models/sys_bio_model.py,sha256=JeoiGQAvQABHnG0wKR2XBmmxqQdtgO6kxaLDUTUmr1s,2001
|
20
21
|
aiagents4pharma/talk2biomodels/states/__init__.py,sha256=YLg1-N0D9qyRRLRqwqfLCLAqZYDtMVZTfI8Y0b_4tbA,139
|
21
|
-
aiagents4pharma/talk2biomodels/states/state_talk2biomodels.py,sha256=
|
22
|
+
aiagents4pharma/talk2biomodels/states/state_talk2biomodels.py,sha256=d_tDh93ip36hlUpMh-KOkYfBZ2SQwZlaY8p-1ZWKPhY,1355
|
22
23
|
aiagents4pharma/talk2biomodels/tests/__init__.py,sha256=Jbw5tJxSrjGoaK5IX3pJWDCNzhrVQ10lkYq2oQ_KQD8,45
|
23
24
|
aiagents4pharma/talk2biomodels/tests/test_api.py,sha256=7Kz2r5F5tjmn3F0LoM33oP-21W633936YHiyf5toGg0,1716
|
24
25
|
aiagents4pharma/talk2biomodels/tests/test_ask_question.py,sha256=yRkKK9HLB1bGGWm_WwOckwaUmmRfRAD9z2NFFGLIGTY,1560
|
@@ -27,11 +28,12 @@ aiagents4pharma/talk2biomodels/tests/test_get_annotation.py,sha256=mKOacH28OB6xp
|
|
27
28
|
aiagents4pharma/talk2biomodels/tests/test_getmodelinfo.py,sha256=6kChSc_MCnzXlDao_R8pKdhIELlg3MZrUa7hg8piJ4E,883
|
28
29
|
aiagents4pharma/talk2biomodels/tests/test_integration.py,sha256=ZsBXWSFLIcdzrO8obLJx8Ib2f9AAW3BI7H9Eqjdc5to,5057
|
29
30
|
aiagents4pharma/talk2biomodels/tests/test_param_scan.py,sha256=vRbnn4uVWFbfZbU4gVCjHi5WDCUrErut8ElzAPE5y84,2648
|
31
|
+
aiagents4pharma/talk2biomodels/tests/test_query_article.py,sha256=HhFgU5HzCipecEYlfbpPxN-SCIPKep22gpXCutWXRb8,2820
|
30
32
|
aiagents4pharma/talk2biomodels/tests/test_search_models.py,sha256=8ODFubLxWYD3I3KQWuUnJ2GZRzMjFpXInFBLxKxG_ME,929
|
31
33
|
aiagents4pharma/talk2biomodels/tests/test_simulate_model.py,sha256=GjLE1DZpcKUAFSmoHD86vkfK0b5LJPM8a4WYyraazig,1487
|
32
34
|
aiagents4pharma/talk2biomodels/tests/test_steady_state.py,sha256=zt15KQoQku6jyzvpJXwINGTyhEnQl8wX81ueHlxnUCA,3467
|
33
35
|
aiagents4pharma/talk2biomodels/tests/test_sys_bio_model.py,sha256=HSmBBViMi0jYf4gWX21IbppAfDzG0nr_S3KtKS9fZVQ,2165
|
34
|
-
aiagents4pharma/talk2biomodels/tools/__init__.py,sha256=
|
36
|
+
aiagents4pharma/talk2biomodels/tools/__init__.py,sha256=6H2HWv5Q4NZYEmw-Ti5KZnJlEqhaC2HXSDZa6kiSl-U,350
|
35
37
|
aiagents4pharma/talk2biomodels/tools/ask_question.py,sha256=hWXg7o0sTMDWH1ZnxtashTALvXpvNoaomfcniEhw-Bw,4684
|
36
38
|
aiagents4pharma/talk2biomodels/tools/custom_plotter.py,sha256=HWwKTX3o4dk0GcRVTO2hPrFSu98mtJ4TKC_hbHXOe1c,4018
|
37
39
|
aiagents4pharma/talk2biomodels/tools/get_annotation.py,sha256=jCGkidvafuk1YzAH9GFwaVUF35maXTjg6XqBg_zLk44,12475
|
@@ -39,6 +41,7 @@ aiagents4pharma/talk2biomodels/tools/get_modelinfo.py,sha256=qA-4FOI-O728Nmn7s8J
|
|
39
41
|
aiagents4pharma/talk2biomodels/tools/load_arguments.py,sha256=bffNIlBDTCSFYiZprA73yi8Jbb8z3Oh2decVNh1UnZc,4162
|
40
42
|
aiagents4pharma/talk2biomodels/tools/load_biomodel.py,sha256=pyVzLQoMnuJYEwsjeOlqcUrbU1F1Z-pNlgkhFaoKpy0,689
|
41
43
|
aiagents4pharma/talk2biomodels/tools/parameter_scan.py,sha256=aNh94LgBgVXBIczuNkbSsOZ9j54YVEdZWmZbZr7Nk8k,12465
|
44
|
+
aiagents4pharma/talk2biomodels/tools/query_article.py,sha256=1tpYiE69MYcqiNcRaBgNiYzkkNmuTnlxLuBL_FnRuBU,2058
|
42
45
|
aiagents4pharma/talk2biomodels/tools/search_models.py,sha256=Iq2ddofOOfZYtAurCISq3bAq5rbwB3l_rL1lgEFyFCI,2653
|
43
46
|
aiagents4pharma/talk2biomodels/tools/simulate_model.py,sha256=qXs9lg9XgA7EaRiX3wBS8w_ug8tI-G3pzhcRg6dTRio,5060
|
44
47
|
aiagents4pharma/talk2biomodels/tools/steady_state.py,sha256=j3ckuNlUtv7lT922MbN0JhT9H0JpWAdx2mLPwao6uu8,7123
|
@@ -93,8 +96,8 @@ aiagents4pharma/talk2knowledgegraphs/utils/embeddings/sentence_transformer.py,sh
|
|
93
96
|
aiagents4pharma/talk2knowledgegraphs/utils/enrichments/__init__.py,sha256=tW426knki2DBIHcWyF_K04iMMdbpIn_e_TpPmTgz2dI,113
|
94
97
|
aiagents4pharma/talk2knowledgegraphs/utils/enrichments/enrichments.py,sha256=Bx8x6zzk5614ApWB90N_iv4_Y_Uq0-KwUeBwYSdQMU4,924
|
95
98
|
aiagents4pharma/talk2knowledgegraphs/utils/enrichments/ollama.py,sha256=8eoxR-VHo0G7ReQIwje7xEhE-SJlHdef7_wJRpnvFIc,4116
|
96
|
-
aiagents4pharma-1.
|
97
|
-
aiagents4pharma-1.
|
98
|
-
aiagents4pharma-1.
|
99
|
-
aiagents4pharma-1.
|
100
|
-
aiagents4pharma-1.
|
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,,
|
File without changes
|
File without changes
|
File without changes
|