aiagents4pharma 0.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.
Files changed (336) hide show
  1. aiagents4pharma/__init__.py +11 -0
  2. aiagents4pharma/talk2aiagents4pharma/.dockerignore +13 -0
  3. aiagents4pharma/talk2aiagents4pharma/Dockerfile +133 -0
  4. aiagents4pharma/talk2aiagents4pharma/README.md +1 -0
  5. aiagents4pharma/talk2aiagents4pharma/__init__.py +5 -0
  6. aiagents4pharma/talk2aiagents4pharma/agents/__init__.py +6 -0
  7. aiagents4pharma/talk2aiagents4pharma/agents/main_agent.py +70 -0
  8. aiagents4pharma/talk2aiagents4pharma/configs/__init__.py +5 -0
  9. aiagents4pharma/talk2aiagents4pharma/configs/agents/__init__.py +5 -0
  10. aiagents4pharma/talk2aiagents4pharma/configs/agents/main_agent/default.yaml +29 -0
  11. aiagents4pharma/talk2aiagents4pharma/configs/app/__init__.py +0 -0
  12. aiagents4pharma/talk2aiagents4pharma/configs/app/frontend/__init__.py +0 -0
  13. aiagents4pharma/talk2aiagents4pharma/configs/app/frontend/default.yaml +102 -0
  14. aiagents4pharma/talk2aiagents4pharma/configs/config.yaml +4 -0
  15. aiagents4pharma/talk2aiagents4pharma/docker-compose/cpu/.env.example +23 -0
  16. aiagents4pharma/talk2aiagents4pharma/docker-compose/cpu/docker-compose.yml +93 -0
  17. aiagents4pharma/talk2aiagents4pharma/docker-compose/gpu/.env.example +23 -0
  18. aiagents4pharma/talk2aiagents4pharma/docker-compose/gpu/docker-compose.yml +108 -0
  19. aiagents4pharma/talk2aiagents4pharma/install.md +154 -0
  20. aiagents4pharma/talk2aiagents4pharma/states/__init__.py +5 -0
  21. aiagents4pharma/talk2aiagents4pharma/states/state_talk2aiagents4pharma.py +18 -0
  22. aiagents4pharma/talk2aiagents4pharma/tests/__init__.py +3 -0
  23. aiagents4pharma/talk2aiagents4pharma/tests/test_main_agent.py +312 -0
  24. aiagents4pharma/talk2biomodels/.dockerignore +13 -0
  25. aiagents4pharma/talk2biomodels/Dockerfile +104 -0
  26. aiagents4pharma/talk2biomodels/README.md +1 -0
  27. aiagents4pharma/talk2biomodels/__init__.py +5 -0
  28. aiagents4pharma/talk2biomodels/agents/__init__.py +6 -0
  29. aiagents4pharma/talk2biomodels/agents/t2b_agent.py +104 -0
  30. aiagents4pharma/talk2biomodels/api/__init__.py +5 -0
  31. aiagents4pharma/talk2biomodels/api/ols.py +75 -0
  32. aiagents4pharma/talk2biomodels/api/uniprot.py +36 -0
  33. aiagents4pharma/talk2biomodels/configs/__init__.py +5 -0
  34. aiagents4pharma/talk2biomodels/configs/agents/__init__.py +5 -0
  35. aiagents4pharma/talk2biomodels/configs/agents/t2b_agent/__init__.py +3 -0
  36. aiagents4pharma/talk2biomodels/configs/agents/t2b_agent/default.yaml +14 -0
  37. aiagents4pharma/talk2biomodels/configs/app/__init__.py +0 -0
  38. aiagents4pharma/talk2biomodels/configs/app/frontend/__init__.py +0 -0
  39. aiagents4pharma/talk2biomodels/configs/app/frontend/default.yaml +72 -0
  40. aiagents4pharma/talk2biomodels/configs/config.yaml +7 -0
  41. aiagents4pharma/talk2biomodels/configs/tools/__init__.py +5 -0
  42. aiagents4pharma/talk2biomodels/configs/tools/ask_question/__init__.py +3 -0
  43. aiagents4pharma/talk2biomodels/configs/tools/ask_question/default.yaml +30 -0
  44. aiagents4pharma/talk2biomodels/configs/tools/custom_plotter/__init__.py +3 -0
  45. aiagents4pharma/talk2biomodels/configs/tools/custom_plotter/default.yaml +8 -0
  46. aiagents4pharma/talk2biomodels/configs/tools/get_annotation/__init__.py +3 -0
  47. aiagents4pharma/talk2biomodels/configs/tools/get_annotation/default.yaml +8 -0
  48. aiagents4pharma/talk2biomodels/install.md +63 -0
  49. aiagents4pharma/talk2biomodels/models/__init__.py +5 -0
  50. aiagents4pharma/talk2biomodels/models/basico_model.py +125 -0
  51. aiagents4pharma/talk2biomodels/models/sys_bio_model.py +60 -0
  52. aiagents4pharma/talk2biomodels/states/__init__.py +6 -0
  53. aiagents4pharma/talk2biomodels/states/state_talk2biomodels.py +49 -0
  54. aiagents4pharma/talk2biomodels/tests/BIOMD0000000449_url.xml +1585 -0
  55. aiagents4pharma/talk2biomodels/tests/__init__.py +3 -0
  56. aiagents4pharma/talk2biomodels/tests/article_on_model_537.pdf +0 -0
  57. aiagents4pharma/talk2biomodels/tests/test_api.py +31 -0
  58. aiagents4pharma/talk2biomodels/tests/test_ask_question.py +42 -0
  59. aiagents4pharma/talk2biomodels/tests/test_basico_model.py +67 -0
  60. aiagents4pharma/talk2biomodels/tests/test_get_annotation.py +190 -0
  61. aiagents4pharma/talk2biomodels/tests/test_getmodelinfo.py +92 -0
  62. aiagents4pharma/talk2biomodels/tests/test_integration.py +116 -0
  63. aiagents4pharma/talk2biomodels/tests/test_load_biomodel.py +35 -0
  64. aiagents4pharma/talk2biomodels/tests/test_param_scan.py +71 -0
  65. aiagents4pharma/talk2biomodels/tests/test_query_article.py +184 -0
  66. aiagents4pharma/talk2biomodels/tests/test_save_model.py +47 -0
  67. aiagents4pharma/talk2biomodels/tests/test_search_models.py +35 -0
  68. aiagents4pharma/talk2biomodels/tests/test_simulate_model.py +44 -0
  69. aiagents4pharma/talk2biomodels/tests/test_steady_state.py +86 -0
  70. aiagents4pharma/talk2biomodels/tests/test_sys_bio_model.py +67 -0
  71. aiagents4pharma/talk2biomodels/tools/__init__.py +17 -0
  72. aiagents4pharma/talk2biomodels/tools/ask_question.py +125 -0
  73. aiagents4pharma/talk2biomodels/tools/custom_plotter.py +165 -0
  74. aiagents4pharma/talk2biomodels/tools/get_annotation.py +342 -0
  75. aiagents4pharma/talk2biomodels/tools/get_modelinfo.py +159 -0
  76. aiagents4pharma/talk2biomodels/tools/load_arguments.py +134 -0
  77. aiagents4pharma/talk2biomodels/tools/load_biomodel.py +44 -0
  78. aiagents4pharma/talk2biomodels/tools/parameter_scan.py +310 -0
  79. aiagents4pharma/talk2biomodels/tools/query_article.py +64 -0
  80. aiagents4pharma/talk2biomodels/tools/save_model.py +98 -0
  81. aiagents4pharma/talk2biomodels/tools/search_models.py +96 -0
  82. aiagents4pharma/talk2biomodels/tools/simulate_model.py +137 -0
  83. aiagents4pharma/talk2biomodels/tools/steady_state.py +187 -0
  84. aiagents4pharma/talk2biomodels/tools/utils.py +23 -0
  85. aiagents4pharma/talk2cells/README.md +1 -0
  86. aiagents4pharma/talk2cells/__init__.py +5 -0
  87. aiagents4pharma/talk2cells/agents/__init__.py +6 -0
  88. aiagents4pharma/talk2cells/agents/scp_agent.py +87 -0
  89. aiagents4pharma/talk2cells/states/__init__.py +6 -0
  90. aiagents4pharma/talk2cells/states/state_talk2cells.py +15 -0
  91. aiagents4pharma/talk2cells/tests/scp_agent/test_scp_agent.py +22 -0
  92. aiagents4pharma/talk2cells/tools/__init__.py +6 -0
  93. aiagents4pharma/talk2cells/tools/scp_agent/__init__.py +6 -0
  94. aiagents4pharma/talk2cells/tools/scp_agent/display_studies.py +27 -0
  95. aiagents4pharma/talk2cells/tools/scp_agent/search_studies.py +78 -0
  96. aiagents4pharma/talk2knowledgegraphs/.dockerignore +13 -0
  97. aiagents4pharma/talk2knowledgegraphs/Dockerfile +131 -0
  98. aiagents4pharma/talk2knowledgegraphs/README.md +1 -0
  99. aiagents4pharma/talk2knowledgegraphs/__init__.py +5 -0
  100. aiagents4pharma/talk2knowledgegraphs/agents/__init__.py +5 -0
  101. aiagents4pharma/talk2knowledgegraphs/agents/t2kg_agent.py +99 -0
  102. aiagents4pharma/talk2knowledgegraphs/configs/__init__.py +5 -0
  103. aiagents4pharma/talk2knowledgegraphs/configs/agents/t2kg_agent/__init__.py +3 -0
  104. aiagents4pharma/talk2knowledgegraphs/configs/agents/t2kg_agent/default.yaml +62 -0
  105. aiagents4pharma/talk2knowledgegraphs/configs/app/__init__.py +5 -0
  106. aiagents4pharma/talk2knowledgegraphs/configs/app/frontend/__init__.py +3 -0
  107. aiagents4pharma/talk2knowledgegraphs/configs/app/frontend/default.yaml +79 -0
  108. aiagents4pharma/talk2knowledgegraphs/configs/config.yaml +13 -0
  109. aiagents4pharma/talk2knowledgegraphs/configs/tools/__init__.py +5 -0
  110. aiagents4pharma/talk2knowledgegraphs/configs/tools/graphrag_reasoning/__init__.py +3 -0
  111. aiagents4pharma/talk2knowledgegraphs/configs/tools/graphrag_reasoning/default.yaml +24 -0
  112. aiagents4pharma/talk2knowledgegraphs/configs/tools/multimodal_subgraph_extraction/__init__.py +0 -0
  113. aiagents4pharma/talk2knowledgegraphs/configs/tools/multimodal_subgraph_extraction/default.yaml +33 -0
  114. aiagents4pharma/talk2knowledgegraphs/configs/tools/subgraph_extraction/__init__.py +3 -0
  115. aiagents4pharma/talk2knowledgegraphs/configs/tools/subgraph_extraction/default.yaml +43 -0
  116. aiagents4pharma/talk2knowledgegraphs/configs/tools/subgraph_summarization/__init__.py +3 -0
  117. aiagents4pharma/talk2knowledgegraphs/configs/tools/subgraph_summarization/default.yaml +9 -0
  118. aiagents4pharma/talk2knowledgegraphs/configs/utils/database/milvus/__init__.py +3 -0
  119. aiagents4pharma/talk2knowledgegraphs/configs/utils/database/milvus/default.yaml +61 -0
  120. aiagents4pharma/talk2knowledgegraphs/configs/utils/enrichments/ols_terms/default.yaml +3 -0
  121. aiagents4pharma/talk2knowledgegraphs/configs/utils/enrichments/reactome_pathways/default.yaml +3 -0
  122. aiagents4pharma/talk2knowledgegraphs/configs/utils/enrichments/uniprot_proteins/default.yaml +6 -0
  123. aiagents4pharma/talk2knowledgegraphs/configs/utils/pubchem_utils/default.yaml +5 -0
  124. aiagents4pharma/talk2knowledgegraphs/datasets/__init__.py +5 -0
  125. aiagents4pharma/talk2knowledgegraphs/datasets/biobridge_primekg.py +607 -0
  126. aiagents4pharma/talk2knowledgegraphs/datasets/dataset.py +25 -0
  127. aiagents4pharma/talk2knowledgegraphs/datasets/primekg.py +212 -0
  128. aiagents4pharma/talk2knowledgegraphs/datasets/starkqa_primekg.py +210 -0
  129. aiagents4pharma/talk2knowledgegraphs/docker-compose/cpu/.env.example +23 -0
  130. aiagents4pharma/talk2knowledgegraphs/docker-compose/cpu/docker-compose.yml +93 -0
  131. aiagents4pharma/talk2knowledgegraphs/docker-compose/gpu/.env.example +23 -0
  132. aiagents4pharma/talk2knowledgegraphs/docker-compose/gpu/docker-compose.yml +108 -0
  133. aiagents4pharma/talk2knowledgegraphs/entrypoint.sh +180 -0
  134. aiagents4pharma/talk2knowledgegraphs/install.md +165 -0
  135. aiagents4pharma/talk2knowledgegraphs/milvus_data_dump.py +886 -0
  136. aiagents4pharma/talk2knowledgegraphs/states/__init__.py +5 -0
  137. aiagents4pharma/talk2knowledgegraphs/states/state_talk2knowledgegraphs.py +40 -0
  138. aiagents4pharma/talk2knowledgegraphs/tests/__init__.py +0 -0
  139. aiagents4pharma/talk2knowledgegraphs/tests/test_agents_t2kg_agent.py +318 -0
  140. aiagents4pharma/talk2knowledgegraphs/tests/test_datasets_biobridge_primekg.py +248 -0
  141. aiagents4pharma/talk2knowledgegraphs/tests/test_datasets_dataset.py +33 -0
  142. aiagents4pharma/talk2knowledgegraphs/tests/test_datasets_primekg.py +86 -0
  143. aiagents4pharma/talk2knowledgegraphs/tests/test_datasets_starkqa_primekg.py +125 -0
  144. aiagents4pharma/talk2knowledgegraphs/tests/test_tools_graphrag_reasoning.py +257 -0
  145. aiagents4pharma/talk2knowledgegraphs/tests/test_tools_milvus_multimodal_subgraph_extraction.py +1444 -0
  146. aiagents4pharma/talk2knowledgegraphs/tests/test_tools_multimodal_subgraph_extraction.py +159 -0
  147. aiagents4pharma/talk2knowledgegraphs/tests/test_tools_subgraph_extraction.py +152 -0
  148. aiagents4pharma/talk2knowledgegraphs/tests/test_tools_subgraph_summarization.py +201 -0
  149. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_database_milvus_connection_manager.py +812 -0
  150. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_embeddings_embeddings.py +51 -0
  151. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_embeddings_huggingface.py +49 -0
  152. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_embeddings_nim_molmim.py +59 -0
  153. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_embeddings_ollama.py +63 -0
  154. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_embeddings_sentencetransformer.py +47 -0
  155. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_enrichments_enrichments.py +40 -0
  156. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_enrichments_ollama.py +94 -0
  157. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_enrichments_ols.py +70 -0
  158. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_enrichments_pubchem.py +45 -0
  159. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_enrichments_reactome.py +44 -0
  160. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_enrichments_uniprot.py +48 -0
  161. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_extractions_milvus_multimodal_pcst.py +759 -0
  162. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_kg_utils.py +78 -0
  163. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_pubchem_utils.py +123 -0
  164. aiagents4pharma/talk2knowledgegraphs/tools/__init__.py +11 -0
  165. aiagents4pharma/talk2knowledgegraphs/tools/graphrag_reasoning.py +138 -0
  166. aiagents4pharma/talk2knowledgegraphs/tools/load_arguments.py +22 -0
  167. aiagents4pharma/talk2knowledgegraphs/tools/milvus_multimodal_subgraph_extraction.py +965 -0
  168. aiagents4pharma/talk2knowledgegraphs/tools/multimodal_subgraph_extraction.py +374 -0
  169. aiagents4pharma/talk2knowledgegraphs/tools/subgraph_extraction.py +291 -0
  170. aiagents4pharma/talk2knowledgegraphs/tools/subgraph_summarization.py +123 -0
  171. aiagents4pharma/talk2knowledgegraphs/utils/__init__.py +5 -0
  172. aiagents4pharma/talk2knowledgegraphs/utils/database/__init__.py +5 -0
  173. aiagents4pharma/talk2knowledgegraphs/utils/database/milvus_connection_manager.py +586 -0
  174. aiagents4pharma/talk2knowledgegraphs/utils/embeddings/__init__.py +5 -0
  175. aiagents4pharma/talk2knowledgegraphs/utils/embeddings/embeddings.py +81 -0
  176. aiagents4pharma/talk2knowledgegraphs/utils/embeddings/huggingface.py +111 -0
  177. aiagents4pharma/talk2knowledgegraphs/utils/embeddings/nim_molmim.py +54 -0
  178. aiagents4pharma/talk2knowledgegraphs/utils/embeddings/ollama.py +87 -0
  179. aiagents4pharma/talk2knowledgegraphs/utils/embeddings/sentence_transformer.py +73 -0
  180. aiagents4pharma/talk2knowledgegraphs/utils/enrichments/__init__.py +12 -0
  181. aiagents4pharma/talk2knowledgegraphs/utils/enrichments/enrichments.py +37 -0
  182. aiagents4pharma/talk2knowledgegraphs/utils/enrichments/ollama.py +129 -0
  183. aiagents4pharma/talk2knowledgegraphs/utils/enrichments/ols_terms.py +89 -0
  184. aiagents4pharma/talk2knowledgegraphs/utils/enrichments/pubchem_strings.py +78 -0
  185. aiagents4pharma/talk2knowledgegraphs/utils/enrichments/reactome_pathways.py +71 -0
  186. aiagents4pharma/talk2knowledgegraphs/utils/enrichments/uniprot_proteins.py +98 -0
  187. aiagents4pharma/talk2knowledgegraphs/utils/extractions/__init__.py +5 -0
  188. aiagents4pharma/talk2knowledgegraphs/utils/extractions/milvus_multimodal_pcst.py +762 -0
  189. aiagents4pharma/talk2knowledgegraphs/utils/extractions/multimodal_pcst.py +298 -0
  190. aiagents4pharma/talk2knowledgegraphs/utils/extractions/pcst.py +229 -0
  191. aiagents4pharma/talk2knowledgegraphs/utils/kg_utils.py +67 -0
  192. aiagents4pharma/talk2knowledgegraphs/utils/pubchem_utils.py +104 -0
  193. aiagents4pharma/talk2scholars/.dockerignore +13 -0
  194. aiagents4pharma/talk2scholars/Dockerfile +104 -0
  195. aiagents4pharma/talk2scholars/README.md +1 -0
  196. aiagents4pharma/talk2scholars/__init__.py +7 -0
  197. aiagents4pharma/talk2scholars/agents/__init__.py +13 -0
  198. aiagents4pharma/talk2scholars/agents/main_agent.py +89 -0
  199. aiagents4pharma/talk2scholars/agents/paper_download_agent.py +96 -0
  200. aiagents4pharma/talk2scholars/agents/pdf_agent.py +101 -0
  201. aiagents4pharma/talk2scholars/agents/s2_agent.py +135 -0
  202. aiagents4pharma/talk2scholars/agents/zotero_agent.py +127 -0
  203. aiagents4pharma/talk2scholars/configs/__init__.py +7 -0
  204. aiagents4pharma/talk2scholars/configs/agents/__init__.py +7 -0
  205. aiagents4pharma/talk2scholars/configs/agents/talk2scholars/__init__.py +7 -0
  206. aiagents4pharma/talk2scholars/configs/agents/talk2scholars/main_agent/__init__.py +3 -0
  207. aiagents4pharma/talk2scholars/configs/agents/talk2scholars/main_agent/default.yaml +52 -0
  208. aiagents4pharma/talk2scholars/configs/agents/talk2scholars/paper_download_agent/__init__.py +3 -0
  209. aiagents4pharma/talk2scholars/configs/agents/talk2scholars/paper_download_agent/default.yaml +19 -0
  210. aiagents4pharma/talk2scholars/configs/agents/talk2scholars/pdf_agent/__init__.py +3 -0
  211. aiagents4pharma/talk2scholars/configs/agents/talk2scholars/pdf_agent/default.yaml +19 -0
  212. aiagents4pharma/talk2scholars/configs/agents/talk2scholars/s2_agent/__init__.py +3 -0
  213. aiagents4pharma/talk2scholars/configs/agents/talk2scholars/s2_agent/default.yaml +44 -0
  214. aiagents4pharma/talk2scholars/configs/agents/talk2scholars/zotero_agent/__init__.py +3 -0
  215. aiagents4pharma/talk2scholars/configs/agents/talk2scholars/zotero_agent/default.yaml +19 -0
  216. aiagents4pharma/talk2scholars/configs/app/__init__.py +7 -0
  217. aiagents4pharma/talk2scholars/configs/app/frontend/__init__.py +3 -0
  218. aiagents4pharma/talk2scholars/configs/app/frontend/default.yaml +72 -0
  219. aiagents4pharma/talk2scholars/configs/config.yaml +16 -0
  220. aiagents4pharma/talk2scholars/configs/tools/__init__.py +21 -0
  221. aiagents4pharma/talk2scholars/configs/tools/multi_paper_recommendation/__init__.py +3 -0
  222. aiagents4pharma/talk2scholars/configs/tools/multi_paper_recommendation/default.yaml +26 -0
  223. aiagents4pharma/talk2scholars/configs/tools/paper_download/__init__.py +3 -0
  224. aiagents4pharma/talk2scholars/configs/tools/paper_download/default.yaml +124 -0
  225. aiagents4pharma/talk2scholars/configs/tools/question_and_answer/__init__.py +3 -0
  226. aiagents4pharma/talk2scholars/configs/tools/question_and_answer/default.yaml +62 -0
  227. aiagents4pharma/talk2scholars/configs/tools/retrieve_semantic_scholar_paper_id/__init__.py +3 -0
  228. aiagents4pharma/talk2scholars/configs/tools/retrieve_semantic_scholar_paper_id/default.yaml +12 -0
  229. aiagents4pharma/talk2scholars/configs/tools/search/__init__.py +3 -0
  230. aiagents4pharma/talk2scholars/configs/tools/search/default.yaml +26 -0
  231. aiagents4pharma/talk2scholars/configs/tools/single_paper_recommendation/__init__.py +3 -0
  232. aiagents4pharma/talk2scholars/configs/tools/single_paper_recommendation/default.yaml +26 -0
  233. aiagents4pharma/talk2scholars/configs/tools/zotero_read/__init__.py +3 -0
  234. aiagents4pharma/talk2scholars/configs/tools/zotero_read/default.yaml +57 -0
  235. aiagents4pharma/talk2scholars/configs/tools/zotero_write/__inti__.py +3 -0
  236. aiagents4pharma/talk2scholars/configs/tools/zotero_write/default.yaml +55 -0
  237. aiagents4pharma/talk2scholars/docker-compose/cpu/.env.example +21 -0
  238. aiagents4pharma/talk2scholars/docker-compose/cpu/docker-compose.yml +90 -0
  239. aiagents4pharma/talk2scholars/docker-compose/gpu/.env.example +21 -0
  240. aiagents4pharma/talk2scholars/docker-compose/gpu/docker-compose.yml +105 -0
  241. aiagents4pharma/talk2scholars/install.md +122 -0
  242. aiagents4pharma/talk2scholars/state/__init__.py +7 -0
  243. aiagents4pharma/talk2scholars/state/state_talk2scholars.py +98 -0
  244. aiagents4pharma/talk2scholars/tests/__init__.py +3 -0
  245. aiagents4pharma/talk2scholars/tests/test_agents_main_agent.py +256 -0
  246. aiagents4pharma/talk2scholars/tests/test_agents_paper_agents_download_agent.py +139 -0
  247. aiagents4pharma/talk2scholars/tests/test_agents_pdf_agent.py +114 -0
  248. aiagents4pharma/talk2scholars/tests/test_agents_s2_agent.py +198 -0
  249. aiagents4pharma/talk2scholars/tests/test_agents_zotero_agent.py +160 -0
  250. aiagents4pharma/talk2scholars/tests/test_s2_tools_display_dataframe.py +91 -0
  251. aiagents4pharma/talk2scholars/tests/test_s2_tools_query_dataframe.py +191 -0
  252. aiagents4pharma/talk2scholars/tests/test_states_state.py +38 -0
  253. aiagents4pharma/talk2scholars/tests/test_tools_paper_downloader.py +507 -0
  254. aiagents4pharma/talk2scholars/tests/test_tools_question_and_answer_tool.py +105 -0
  255. aiagents4pharma/talk2scholars/tests/test_tools_s2_multi.py +307 -0
  256. aiagents4pharma/talk2scholars/tests/test_tools_s2_retrieve.py +67 -0
  257. aiagents4pharma/talk2scholars/tests/test_tools_s2_search.py +286 -0
  258. aiagents4pharma/talk2scholars/tests/test_tools_s2_single.py +298 -0
  259. aiagents4pharma/talk2scholars/tests/test_utils_arxiv_downloader.py +469 -0
  260. aiagents4pharma/talk2scholars/tests/test_utils_base_paper_downloader.py +598 -0
  261. aiagents4pharma/talk2scholars/tests/test_utils_biorxiv_downloader.py +669 -0
  262. aiagents4pharma/talk2scholars/tests/test_utils_medrxiv_downloader.py +500 -0
  263. aiagents4pharma/talk2scholars/tests/test_utils_nvidia_nim_reranker.py +117 -0
  264. aiagents4pharma/talk2scholars/tests/test_utils_pdf_answer_formatter.py +67 -0
  265. aiagents4pharma/talk2scholars/tests/test_utils_pdf_batch_processor.py +92 -0
  266. aiagents4pharma/talk2scholars/tests/test_utils_pdf_collection_manager.py +173 -0
  267. aiagents4pharma/talk2scholars/tests/test_utils_pdf_document_processor.py +68 -0
  268. aiagents4pharma/talk2scholars/tests/test_utils_pdf_generate_answer.py +72 -0
  269. aiagents4pharma/talk2scholars/tests/test_utils_pdf_gpu_detection.py +129 -0
  270. aiagents4pharma/talk2scholars/tests/test_utils_pdf_paper_loader.py +116 -0
  271. aiagents4pharma/talk2scholars/tests/test_utils_pdf_rag_pipeline.py +88 -0
  272. aiagents4pharma/talk2scholars/tests/test_utils_pdf_retrieve_chunks.py +190 -0
  273. aiagents4pharma/talk2scholars/tests/test_utils_pdf_singleton_manager.py +159 -0
  274. aiagents4pharma/talk2scholars/tests/test_utils_pdf_vector_normalization.py +121 -0
  275. aiagents4pharma/talk2scholars/tests/test_utils_pdf_vector_store.py +406 -0
  276. aiagents4pharma/talk2scholars/tests/test_utils_pubmed_downloader.py +1007 -0
  277. aiagents4pharma/talk2scholars/tests/test_utils_read_helper_utils.py +106 -0
  278. aiagents4pharma/talk2scholars/tests/test_utils_s2_utils_ext_ids.py +403 -0
  279. aiagents4pharma/talk2scholars/tests/test_utils_tool_helper_utils.py +85 -0
  280. aiagents4pharma/talk2scholars/tests/test_utils_zotero_human_in_the_loop.py +266 -0
  281. aiagents4pharma/talk2scholars/tests/test_utils_zotero_path.py +496 -0
  282. aiagents4pharma/talk2scholars/tests/test_utils_zotero_pdf_downloader_utils.py +46 -0
  283. aiagents4pharma/talk2scholars/tests/test_utils_zotero_read.py +743 -0
  284. aiagents4pharma/talk2scholars/tests/test_utils_zotero_write.py +151 -0
  285. aiagents4pharma/talk2scholars/tools/__init__.py +9 -0
  286. aiagents4pharma/talk2scholars/tools/paper_download/__init__.py +12 -0
  287. aiagents4pharma/talk2scholars/tools/paper_download/paper_downloader.py +442 -0
  288. aiagents4pharma/talk2scholars/tools/paper_download/utils/__init__.py +22 -0
  289. aiagents4pharma/talk2scholars/tools/paper_download/utils/arxiv_downloader.py +207 -0
  290. aiagents4pharma/talk2scholars/tools/paper_download/utils/base_paper_downloader.py +336 -0
  291. aiagents4pharma/talk2scholars/tools/paper_download/utils/biorxiv_downloader.py +313 -0
  292. aiagents4pharma/talk2scholars/tools/paper_download/utils/medrxiv_downloader.py +196 -0
  293. aiagents4pharma/talk2scholars/tools/paper_download/utils/pubmed_downloader.py +323 -0
  294. aiagents4pharma/talk2scholars/tools/pdf/__init__.py +7 -0
  295. aiagents4pharma/talk2scholars/tools/pdf/question_and_answer.py +170 -0
  296. aiagents4pharma/talk2scholars/tools/pdf/utils/__init__.py +37 -0
  297. aiagents4pharma/talk2scholars/tools/pdf/utils/answer_formatter.py +62 -0
  298. aiagents4pharma/talk2scholars/tools/pdf/utils/batch_processor.py +198 -0
  299. aiagents4pharma/talk2scholars/tools/pdf/utils/collection_manager.py +172 -0
  300. aiagents4pharma/talk2scholars/tools/pdf/utils/document_processor.py +76 -0
  301. aiagents4pharma/talk2scholars/tools/pdf/utils/generate_answer.py +97 -0
  302. aiagents4pharma/talk2scholars/tools/pdf/utils/get_vectorstore.py +59 -0
  303. aiagents4pharma/talk2scholars/tools/pdf/utils/gpu_detection.py +150 -0
  304. aiagents4pharma/talk2scholars/tools/pdf/utils/nvidia_nim_reranker.py +97 -0
  305. aiagents4pharma/talk2scholars/tools/pdf/utils/paper_loader.py +123 -0
  306. aiagents4pharma/talk2scholars/tools/pdf/utils/rag_pipeline.py +113 -0
  307. aiagents4pharma/talk2scholars/tools/pdf/utils/retrieve_chunks.py +197 -0
  308. aiagents4pharma/talk2scholars/tools/pdf/utils/singleton_manager.py +140 -0
  309. aiagents4pharma/talk2scholars/tools/pdf/utils/tool_helper.py +86 -0
  310. aiagents4pharma/talk2scholars/tools/pdf/utils/vector_normalization.py +150 -0
  311. aiagents4pharma/talk2scholars/tools/pdf/utils/vector_store.py +327 -0
  312. aiagents4pharma/talk2scholars/tools/s2/__init__.py +21 -0
  313. aiagents4pharma/talk2scholars/tools/s2/display_dataframe.py +110 -0
  314. aiagents4pharma/talk2scholars/tools/s2/multi_paper_rec.py +111 -0
  315. aiagents4pharma/talk2scholars/tools/s2/query_dataframe.py +233 -0
  316. aiagents4pharma/talk2scholars/tools/s2/retrieve_semantic_scholar_paper_id.py +128 -0
  317. aiagents4pharma/talk2scholars/tools/s2/search.py +101 -0
  318. aiagents4pharma/talk2scholars/tools/s2/single_paper_rec.py +102 -0
  319. aiagents4pharma/talk2scholars/tools/s2/utils/__init__.py +5 -0
  320. aiagents4pharma/talk2scholars/tools/s2/utils/multi_helper.py +223 -0
  321. aiagents4pharma/talk2scholars/tools/s2/utils/search_helper.py +205 -0
  322. aiagents4pharma/talk2scholars/tools/s2/utils/single_helper.py +216 -0
  323. aiagents4pharma/talk2scholars/tools/zotero/__init__.py +7 -0
  324. aiagents4pharma/talk2scholars/tools/zotero/utils/__init__.py +7 -0
  325. aiagents4pharma/talk2scholars/tools/zotero/utils/read_helper.py +270 -0
  326. aiagents4pharma/talk2scholars/tools/zotero/utils/review_helper.py +74 -0
  327. aiagents4pharma/talk2scholars/tools/zotero/utils/write_helper.py +194 -0
  328. aiagents4pharma/talk2scholars/tools/zotero/utils/zotero_path.py +180 -0
  329. aiagents4pharma/talk2scholars/tools/zotero/utils/zotero_pdf_downloader.py +133 -0
  330. aiagents4pharma/talk2scholars/tools/zotero/zotero_read.py +105 -0
  331. aiagents4pharma/talk2scholars/tools/zotero/zotero_review.py +162 -0
  332. aiagents4pharma/talk2scholars/tools/zotero/zotero_write.py +91 -0
  333. aiagents4pharma-0.0.0.dist-info/METADATA +335 -0
  334. aiagents4pharma-0.0.0.dist-info/RECORD +336 -0
  335. aiagents4pharma-0.0.0.dist-info/WHEEL +4 -0
  336. aiagents4pharma-0.0.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,165 @@
1
+ #!/usr/bin/env python3
2
+
3
+ """
4
+ Tool for plotting a custom y-axis of a simulation plot.
5
+ """
6
+
7
+ import logging
8
+ from typing import Annotated, Literal
9
+
10
+ import hydra
11
+ import pandas as pd
12
+ from langchain_core.prompts import ChatPromptTemplate
13
+ from langchain_core.tools import BaseTool
14
+ from langgraph.prebuilt import InjectedState
15
+ from pydantic import BaseModel, Field
16
+
17
+ from .load_biomodel import ModelData, load_biomodel
18
+ from .utils import get_model_units
19
+
20
+ # Initialize logger
21
+ logging.basicConfig(level=logging.INFO)
22
+ logger = logging.getLogger(__name__)
23
+
24
+
25
+ def extract_relevant_species(question, species_names, state):
26
+ """
27
+ Extract the relevant species from the user question.
28
+
29
+ Args:
30
+ question (str): The user question.
31
+ species_names (list): The species names available in the simulation results.
32
+ state (dict): The state of the graph.
33
+
34
+ Returns:
35
+ CustomHeader: The relevant species
36
+ """
37
+
38
+ # In the following code, we extract the species
39
+ # from the user question. We use Literal to restrict
40
+ # the species names to the ones available in the
41
+ # simulation results.
42
+ class CustomHeader(BaseModel):
43
+ """
44
+ A list of species based on user question.
45
+
46
+ This is a Pydantic model that restricts the species
47
+ names to the ones available in the simulation results.
48
+
49
+ If no species is relevant, set the attribute
50
+ `relevant_species` to None.
51
+ """
52
+
53
+ relevant_species: None | list[Literal[*species_names,]] = Field(
54
+ description="This is a list of species based on the user question."
55
+ "It is restricted to the species available in the simulation results."
56
+ "If no species is relevant, set this attribute to None."
57
+ "If the user asks for very specific species (for example, using the"
58
+ "keyword `only` in the question), set this attribute to correspond "
59
+ "to the species available in the simulation results, otherwise set it to None."
60
+ )
61
+
62
+ # Load hydra configuration
63
+ with hydra.initialize(version_base=None, config_path="../configs"):
64
+ cfg = hydra.compose(config_name="config", overrides=["tools/custom_plotter=default"])
65
+ cfg = cfg.tools.custom_plotter
66
+ # Get the system prompt
67
+ system_prompt = cfg.system_prompt_custom_header
68
+ # Create an instance of the LLM model
69
+ logging.log(logging.INFO, "LLM model: %s", state["llm_model"])
70
+ llm = state["llm_model"]
71
+ llm_with_structured_output = llm.with_structured_output(CustomHeader)
72
+ prompt = ChatPromptTemplate.from_messages([("system", system_prompt), ("human", "{input}")])
73
+ few_shot_structured_llm = prompt | llm_with_structured_output
74
+ return few_shot_structured_llm.invoke(question)
75
+
76
+
77
+ class CustomPlotterInput(BaseModel):
78
+ """
79
+ Input schema for the custom plotter tool.
80
+ """
81
+
82
+ question: str = Field(description="Description of the plot")
83
+ sys_bio_model: ModelData = Field(description="model data", default=None)
84
+ simulation_name: str = Field(description="Name assigned to the simulation")
85
+ state: Annotated[dict, InjectedState]
86
+
87
+
88
+ # Note: It's important that every field has type hints.
89
+ # BaseTool is a Pydantic class and not having type hints
90
+ # can lead to unexpected behavior.
91
+ # Note: It's important that every field has type hints.
92
+ # BaseTool is a Pydantic class and not having type hints
93
+ # can lead to unexpected behavior.
94
+ class CustomPlotterTool(BaseTool):
95
+ """
96
+ Tool for custom plotting the y-axis of a plot.
97
+ """
98
+
99
+ name: str = "custom_plotter"
100
+ description: str = """A visualization tool designed to extract and display a subset
101
+ of the larger simulation plot generated by the simulate_model tool.
102
+ It allows users to specify particular species for the y-axis,
103
+ providing a more targeted view of key species without the clutter
104
+ of the full plot."""
105
+ args_schema: type[BaseModel] = CustomPlotterInput
106
+ response_format: str = "content_and_artifact"
107
+
108
+ def _run(
109
+ self,
110
+ question: str,
111
+ sys_bio_model: ModelData,
112
+ simulation_name: str,
113
+ state: Annotated[dict, InjectedState],
114
+ ) -> tuple[str, None | list[str]]:
115
+ """
116
+ Run the tool.
117
+
118
+ Args:
119
+ question (str): The question about the custom plot.
120
+ sys_bio_model (ModelData): The model data.
121
+ simulation_name (str): The name assigned to the simulation.
122
+ state (dict): The state of the graph.
123
+
124
+ Returns:
125
+ str: The answer to the question
126
+ """
127
+ logger.log(logging.INFO, "Calling custom_plotter tool %s, %s", question, sys_bio_model)
128
+ # Load the model
129
+ sbml_file_path = state["sbml_file_path"][-1] if len(state["sbml_file_path"]) > 0 else None
130
+ model_object = load_biomodel(sys_bio_model, sbml_file_path=sbml_file_path)
131
+ dic_simulated_data = {}
132
+ for data in state["dic_simulated_data"]:
133
+ for key in data:
134
+ if key not in dic_simulated_data:
135
+ dic_simulated_data[key] = []
136
+ dic_simulated_data[key] += [data[key]]
137
+ # Create a pandas dataframe from the dictionary
138
+ df = pd.DataFrame.from_dict(dic_simulated_data)
139
+ # Get the simulated data for the current tool call
140
+ df = pd.DataFrame(df[df["name"] == simulation_name]["data"].iloc[0])
141
+ # df = pd.DataFrame.from_dict(state['dic_simulated_data'])
142
+ species_names = df.columns.tolist()
143
+ # Exclude the time column
144
+ species_names.remove("Time")
145
+ logging.log(logging.INFO, "Species names: %s", species_names)
146
+ # Extract the relevant species from the user question
147
+ results = extract_relevant_species(question, species_names, state)
148
+ print(results)
149
+ if results.relevant_species is None:
150
+ raise ValueError(
151
+ "No species found in the simulation results \
152
+ that matches the user prompt."
153
+ )
154
+ extracted_species = []
155
+ # Extract the species from the results
156
+ # that are available in the simulation results
157
+ for species in results.relevant_species:
158
+ if species in species_names:
159
+ extracted_species.append(species)
160
+ logging.info("Extracted species: %s", extracted_species)
161
+ # Include the time column
162
+ extracted_species.insert(0, "Time")
163
+ return f"Custom plot {simulation_name}", {
164
+ "dic_data": df[extracted_species].to_dict(orient="records")
165
+ } | get_model_units(model_object)
@@ -0,0 +1,342 @@
1
+ #!/usr/bin/env python3
2
+
3
+ """
4
+ This module contains the `GetAnnotationTool` for fetching species annotations
5
+ based on the provided model and species names.
6
+ """
7
+
8
+ import logging
9
+ import math
10
+ from dataclasses import dataclass
11
+ from typing import Annotated, Literal
12
+
13
+ import basico
14
+ import hydra
15
+ import pandas as pd
16
+ from langchain_core.messages import ToolMessage
17
+ from langchain_core.tools.base import BaseTool, InjectedToolCallId
18
+ from langgraph.prebuilt import InjectedState
19
+ from langgraph.types import Command
20
+ from pydantic import BaseModel, Field
21
+
22
+ from ..api.ols import search_ols_labels
23
+ from ..api.uniprot import search_uniprot_labels
24
+
25
+ # from langchain_openai import ChatOpenAI
26
+ from .load_biomodel import ModelData, load_biomodel
27
+
28
+ # Initialize logger
29
+ logging.basicConfig(level=logging.INFO)
30
+ logger = logging.getLogger(__name__)
31
+
32
+ ols_ontology_abbreviations = {"pato", "chebi", "sbo", "fma", "pr", "go"}
33
+
34
+
35
+ def extract_relevant_species_names(model_object, arg_data, state):
36
+ """
37
+ Extract relevant species names based on the user question.
38
+ """
39
+ # Load hydra configuration
40
+ with hydra.initialize(version_base=None, config_path="../configs"):
41
+ cfg = hydra.compose(config_name="config", overrides=["tools/get_annotation=default"])
42
+ cfg = cfg.tools.get_annotation
43
+ logger.info(
44
+ "Loaded the following system prompt for the LLM to get a structured output: %s",
45
+ cfg.prompt,
46
+ )
47
+
48
+ # Extract all the species names from the model
49
+ df_species = basico.model_info.get_species(model=model_object.copasi_model)
50
+ if df_species is None:
51
+ raise ValueError("Unable to extract species from the model.")
52
+ # Get all the species names
53
+ all_species_names = df_species.index.tolist()
54
+
55
+ # Define a structured output for the LLM model
56
+ class CustomHeader(BaseModel):
57
+ """
58
+ A list of species based on user question.
59
+ """
60
+
61
+ relevant_species: None | list[Literal[*all_species_names,]] = Field(
62
+ description="""List of species based on user question.
63
+ If no relevant species are found, it must be None."""
64
+ )
65
+
66
+ # Create an instance of the LLM model
67
+ llm = state["llm_model"]
68
+ # Get the structured output from the LLM model
69
+ llm_with_structured_output = llm.with_structured_output(CustomHeader)
70
+ # Define the question for the LLM model using the prompt
71
+ question = cfg.prompt
72
+ question += f"Here is the user question: {arg_data.user_question}"
73
+ # Invoke the LLM model with the user question
74
+ results = llm_with_structured_output.invoke(question)
75
+ logging.info("Results from the LLM model: %s", results)
76
+ # Check if the returned species names are empty
77
+ if not results.relevant_species:
78
+ raise ValueError("Model does not contain the requested species.")
79
+ extracted_species = []
80
+ # Extract all the species names from the model
81
+ for species in results.relevant_species:
82
+ if species in all_species_names:
83
+ extracted_species.append(species)
84
+ logger.info("Extracted species: %s", extracted_species)
85
+ return extracted_species
86
+
87
+
88
+ def prepare_content_msg(species_without_description: list[str]):
89
+ """
90
+ Prepare the content message.
91
+ """
92
+ content = "Successfully extracted annotations for the species."
93
+ if species_without_description:
94
+ content += f"""The descriptions for the following species
95
+ were not found:
96
+ {", ".join(species_without_description)}."""
97
+ return content
98
+
99
+
100
+ @dataclass
101
+ class ArgumentData:
102
+ """
103
+ Dataclass for storing the argument data.
104
+ """
105
+
106
+ experiment_name: Annotated[
107
+ str,
108
+ "An AI assigned _ separated name of"
109
+ " the experiment based on human query"
110
+ " and the context of the experiment."
111
+ " This must be set before the experiment is run.",
112
+ ]
113
+ user_question: Annotated[str, "Description of the user question"]
114
+
115
+
116
+ class GetAnnotationInput(BaseModel):
117
+ """
118
+ Input schema for annotation tool.
119
+ """
120
+
121
+ arg_data: ArgumentData = Field(description="argument data")
122
+ sys_bio_model: ModelData = Field(description="model data")
123
+ tool_call_id: Annotated[str, InjectedToolCallId]
124
+ state: Annotated[dict, InjectedState]
125
+
126
+
127
+ class GetAnnotationTool(BaseTool):
128
+ """
129
+ Tool for fetching species annotations based on the provided model and species names.
130
+ """
131
+
132
+ name: str = "get_annotation"
133
+ description: str = """A tool to extract annotations for a list of species names
134
+ based on the provided model. Annotations include
135
+ the species name, description, database, ID, link,
136
+ and qualifier. The tool can handle multiple species
137
+ in a single invoke."""
138
+ args_schema: type[BaseModel] = GetAnnotationInput
139
+ return_direct: bool = False
140
+
141
+ def _run(
142
+ self,
143
+ arg_data: ArgumentData,
144
+ tool_call_id: Annotated[str, InjectedToolCallId],
145
+ state: Annotated[dict, InjectedState],
146
+ sys_bio_model: ModelData = None,
147
+ ) -> str:
148
+ """
149
+ Run the tool.
150
+ """
151
+ logger.info(
152
+ "Running the GetAnnotationTool tool for species %s, %s",
153
+ arg_data.user_question,
154
+ arg_data.experiment_name,
155
+ )
156
+
157
+ # Prepare the model object
158
+ sbml_file_path = state["sbml_file_path"][-1] if state["sbml_file_path"] else None
159
+ model_object = load_biomodel(sys_bio_model, sbml_file_path=sbml_file_path)
160
+
161
+ # Extract relevant species names based on the user question
162
+ list_species_names = extract_relevant_species_names(model_object, arg_data, state)
163
+ print(list_species_names)
164
+
165
+ (annotations_df, species_without_description) = self._fetch_annotations(list_species_names)
166
+
167
+ # Process annotations
168
+ annotations_df = self._process_annotations(annotations_df)
169
+
170
+ # Prepare the simulated data
171
+ dic_annotations_data = {
172
+ "name": arg_data.experiment_name,
173
+ "source": (sys_bio_model.biomodel_id if sys_bio_model.biomodel_id else "upload"),
174
+ "tool_call_id": tool_call_id,
175
+ "data": annotations_df.to_dict(),
176
+ }
177
+
178
+ # Update the state with the annotations data
179
+ dic_updated_state_for_model = {}
180
+ for key, value in {
181
+ "model_id": [sys_bio_model.biomodel_id],
182
+ "sbml_file_path": [sbml_file_path],
183
+ "dic_annotations_data": [dic_annotations_data],
184
+ }.items():
185
+ if value:
186
+ dic_updated_state_for_model[key] = value
187
+
188
+ return Command(
189
+ update=dic_updated_state_for_model
190
+ | {
191
+ "messages": [
192
+ ToolMessage(
193
+ content=prepare_content_msg(species_without_description),
194
+ artifact=True,
195
+ tool_call_id=tool_call_id,
196
+ )
197
+ ]
198
+ }
199
+ )
200
+
201
+ def _fetch_annotations(self, list_species_names: list[str]) -> tuple:
202
+ """
203
+ Fetch annotations for the given species names from the model.
204
+ In this method, we fetch the MIRIAM annotations for the species names.
205
+ If the annotation is not found, we add the species to the list of
206
+ species not found. If the annotation is found, we extract the descriptions
207
+ from the annotation and add them to the data list.
208
+
209
+ Args:
210
+ list_species_names (List[str]): List of species names to fetch annotations for.
211
+
212
+ Returns:
213
+ tuple: A tuple containing the annotations dataframe, species not found list,
214
+ and description not found list.
215
+ """
216
+ description_not_found = []
217
+ data = []
218
+
219
+ # Loop through the species names
220
+ for species in list_species_names:
221
+ # Get the MIRIAM annotation for the species
222
+ annotation = basico.get_miriam_annotation(name=species)
223
+
224
+ # Extract the descriptions from the annotation
225
+ descriptions = annotation.get("descriptions", [])
226
+
227
+ if descriptions == []:
228
+ description_not_found.append(species)
229
+ continue
230
+
231
+ # Loop through the descriptions and add them to the data list
232
+ for desc in descriptions:
233
+ data.append(
234
+ {
235
+ "Species Name": species,
236
+ "Link": desc["id"],
237
+ "Qualifier": desc["qualifier"],
238
+ }
239
+ )
240
+
241
+ # Create a dataframe from the data list
242
+ annotations_df = pd.DataFrame(data)
243
+
244
+ # Return the annotations dataframe and the species not found list
245
+ return annotations_df, description_not_found
246
+
247
+ def _process_annotations(self, annotations_df: pd.DataFrame) -> pd.DataFrame:
248
+ """
249
+ Process annotations dataframe to add additional information.
250
+ In this method, we add a new column for the ID, a new column for the database,
251
+ and a new column for the description. We then reorder the columns and process
252
+ the link to format it correctly.
253
+
254
+ Args:
255
+ annotations_df (pd.DataFrame): Annotations dataframe to process.
256
+
257
+ Returns:
258
+ pd.DataFrame: Processed annotations dataframe
259
+ """
260
+ logger.info("Processing annotations.")
261
+ # Add a new column for the ID
262
+ # Get the ID from the link key
263
+ annotations_df["Id"] = annotations_df["Link"].str.split("/").str[-1]
264
+
265
+ # Add a new column for the database
266
+ # Get the database from the link key
267
+ annotations_df["Database"] = annotations_df["Link"].str.split("/").str[-2]
268
+
269
+ # Fetch descriptions for the IDs based on the database type
270
+ # by qyerying the respective APIs
271
+ identifiers = annotations_df[["Id", "Database"]].to_dict(orient="records")
272
+ descriptions = self._fetch_descriptions(identifiers)
273
+
274
+ # Add a new column for the description
275
+ # Get the description from the descriptions dictionary
276
+ # based on the ID. If the description is not found, use '-'
277
+ annotations_df["Description"] = annotations_df["Id"].apply(
278
+ lambda x: descriptions.get(x, "-")
279
+ )
280
+ # annotations_df.index = annotations_df.index + 1
281
+
282
+ # Reorder the columns
283
+ annotations_df = annotations_df[
284
+ ["Species Name", "Description", "Database", "Id", "Link", "Qualifier"]
285
+ ]
286
+
287
+ # Process the link to format it correctly
288
+ annotations_df["Link"] = annotations_df["Link"].apply(self._process_link)
289
+
290
+ # Return the processed annotations dataframe
291
+ return annotations_df
292
+
293
+ def _process_link(self, link: str) -> str:
294
+ """
295
+ Process link to format it correctly.
296
+ """
297
+ for ols_ontology_abbreviation in ols_ontology_abbreviations:
298
+ if ols_ontology_abbreviation + "/" in link:
299
+ link = link.replace(f"{ols_ontology_abbreviation}/", "")
300
+ return link
301
+
302
+ def _fetch_descriptions(self, data: list[dict[str, str]]) -> dict[str, str]:
303
+ """
304
+ Fetch protein names or labels based on the database type.
305
+ """
306
+ logger.info("Fetching descriptions for the IDs.")
307
+ results = {}
308
+ grouped_data = {}
309
+
310
+ # In the following loop, we create a dictionary with database as the key
311
+ # and a list of identifiers as the value. If either the database or the
312
+ # identifier is NaN, we set it to None.
313
+ for entry in data:
314
+ identifier = entry.get("Id")
315
+ database = entry.get("Database")
316
+ # Check if database is NaN
317
+ if isinstance(database, float):
318
+ if math.isnan(database):
319
+ database = None
320
+ results[identifier or "unknown"] = "-"
321
+ else:
322
+ database = database.lower()
323
+ grouped_data.setdefault(database, []).append(identifier)
324
+
325
+ # In the following loop, we fetch the descriptions for the identifiers
326
+ # based on the database type.
327
+ # Constants
328
+
329
+ for database, identifiers in grouped_data.items():
330
+ if database == "uniprot":
331
+ results.update(search_uniprot_labels(identifiers))
332
+ elif database in ols_ontology_abbreviations:
333
+ annotations = search_ols_labels(
334
+ [{"Id": id_, "Database": database} for id_ in identifiers]
335
+ )
336
+ for identifier in identifiers:
337
+ results[identifier] = annotations.get(database, {}).get(identifier, "-")
338
+ else:
339
+ # For any other database types, do not fetch; mark as unknown
340
+ for identifier in identifiers:
341
+ results[identifier] = "-"
342
+ return results
@@ -0,0 +1,159 @@
1
+ #!/usr/bin/env python3
2
+
3
+ """
4
+ Tool for get model information.
5
+ """
6
+
7
+ import logging
8
+ from dataclasses import dataclass
9
+ from typing import Annotated
10
+
11
+ import basico
12
+ from langchain_core.messages import ToolMessage
13
+ from langchain_core.tools import BaseTool
14
+ from langchain_core.tools.base import InjectedToolCallId
15
+ from langgraph.prebuilt import InjectedState
16
+ from langgraph.types import Command
17
+ from pydantic import BaseModel, Field
18
+
19
+ from .load_biomodel import ModelData, load_biomodel
20
+
21
+ # Initialize logger
22
+ logging.basicConfig(level=logging.INFO)
23
+ logger = logging.getLogger(__name__)
24
+
25
+
26
+ @dataclass
27
+ class RequestedModelInfo:
28
+ """
29
+ Dataclass for storing the requested model information.
30
+ """
31
+
32
+ species: bool = Field(description="Get species from the model.", default=False)
33
+ parameters: bool = Field(description="Get parameters from the model.", default=False)
34
+ compartments: bool = Field(description="Get compartments from the model.", default=False)
35
+ units: bool = Field(description="Get units from the model.", default=False)
36
+ description: bool = Field(description="Get description from the model.", default=False)
37
+ name: bool = Field(description="Get name from the model.", default=False)
38
+
39
+
40
+ class GetModelInfoInput(BaseModel):
41
+ """
42
+ Input schema for the GetModelInfo tool.
43
+ """
44
+
45
+ requested_model_info: RequestedModelInfo = Field(description="requested model information")
46
+ sys_bio_model: ModelData = Field(description="model data")
47
+ tool_call_id: Annotated[str, InjectedToolCallId]
48
+ state: Annotated[dict, InjectedState]
49
+
50
+
51
+ # Note: It's important that every field has type hints. BaseTool is a
52
+ # Pydantic class and not having type hints can lead to unexpected behavior.
53
+ class GetModelInfoTool(BaseTool):
54
+ """
55
+ This tool ise used extract model information.
56
+ """
57
+
58
+ name: str = "get_modelinfo"
59
+ description: str = """A tool for extracting name,
60
+ description, species, parameters,
61
+ compartments, and units from a model."""
62
+ args_schema: type[BaseModel] = GetModelInfoInput
63
+
64
+ def _run(
65
+ self,
66
+ requested_model_info: RequestedModelInfo,
67
+ tool_call_id: Annotated[str, InjectedToolCallId],
68
+ state: Annotated[dict, InjectedState],
69
+ sys_bio_model: ModelData | None = None,
70
+ ) -> Command:
71
+ """
72
+ Run the tool.
73
+
74
+ Args:
75
+ requested_model_info (RequestedModelInfo): The requested model information.
76
+ tool_call_id (str): The tool call ID. This is injected by the system.
77
+ state (dict): The state of the tool.
78
+ sys_bio_model (ModelData): The model data.
79
+
80
+ Returns:
81
+ Command: The updated state of the tool.
82
+ """
83
+ logger.log(
84
+ logging.INFO,
85
+ "Calling get_modelinfo tool %s, %s",
86
+ sys_bio_model,
87
+ requested_model_info,
88
+ )
89
+ # print (state, 'state')
90
+ sbml_file_path = state["sbml_file_path"][-1] if len(state["sbml_file_path"]) > 0 else None
91
+ model_obj = load_biomodel(sys_bio_model, sbml_file_path=sbml_file_path)
92
+ dic_results = {}
93
+ # Extract species from the model
94
+ if requested_model_info.species:
95
+ df_species = basico.model_info.get_species(model=model_obj.copasi_model)
96
+ if df_species is None:
97
+ raise ValueError("Unable to extract species from the model.")
98
+ # Convert index into a column
99
+ df_species.reset_index(inplace=True)
100
+ dic_results["Species"] = df_species[
101
+ [
102
+ "name",
103
+ "compartment",
104
+ "type",
105
+ "unit",
106
+ "initial_concentration",
107
+ "display_name",
108
+ ]
109
+ ]
110
+ # Convert this into a dictionary
111
+ dic_results["Species"] = dic_results["Species"].to_dict(orient="records")
112
+
113
+ # Extract parameters from the model
114
+ if requested_model_info.parameters:
115
+ df_parameters = basico.model_info.get_parameters(model=model_obj.copasi_model)
116
+ if df_parameters is None:
117
+ raise ValueError("Unable to extract parameters from the model.")
118
+ # Convert index into a column
119
+ df_parameters.reset_index(inplace=True)
120
+ dic_results["Parameters"] = df_parameters[
121
+ ["name", "type", "unit", "initial_value", "display_name"]
122
+ ]
123
+ # Convert this into a dictionary
124
+ dic_results["Parameters"] = dic_results["Parameters"].to_dict(orient="records")
125
+
126
+ # Extract compartments from the model
127
+ if requested_model_info.compartments:
128
+ df_compartments = basico.model_info.get_compartments(model=model_obj.copasi_model)
129
+ dic_results["Compartments"] = df_compartments.index.tolist()
130
+ dic_results["Compartments"] = ",".join(dic_results["Compartments"])
131
+
132
+ # Extract description from the model
133
+ if requested_model_info.description:
134
+ dic_results["Description"] = model_obj.description
135
+
136
+ # Extract description from the model
137
+ if requested_model_info.name:
138
+ dic_results["Name"] = model_obj.name
139
+
140
+ # Extract time unit from the model
141
+ if requested_model_info.units:
142
+ dic_results["Units"] = basico.model_info.get_model_units(model=model_obj.copasi_model)
143
+
144
+ # Prepare the dictionary of updated state for the model
145
+ dic_updated_state_for_model = {}
146
+ for key, value in {
147
+ "model_id": [sys_bio_model.biomodel_id],
148
+ "sbml_file_path": [sbml_file_path],
149
+ }.items():
150
+ if value:
151
+ dic_updated_state_for_model[key] = value
152
+
153
+ return Command(
154
+ update=dic_updated_state_for_model
155
+ | {
156
+ # update the message history
157
+ "messages": [ToolMessage(content=dic_results, tool_call_id=tool_call_id)],
158
+ }
159
+ )