aiagents4pharma 1.44.0__py3-none-any.whl → 1.45.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.
Files changed (289) hide show
  1. aiagents4pharma/__init__.py +2 -2
  2. aiagents4pharma/talk2aiagents4pharma/.dockerignore +13 -0
  3. aiagents4pharma/talk2aiagents4pharma/Dockerfile +105 -0
  4. aiagents4pharma/talk2aiagents4pharma/README.md +1 -0
  5. aiagents4pharma/talk2aiagents4pharma/__init__.py +4 -5
  6. aiagents4pharma/talk2aiagents4pharma/agents/__init__.py +3 -2
  7. aiagents4pharma/talk2aiagents4pharma/agents/main_agent.py +24 -23
  8. aiagents4pharma/talk2aiagents4pharma/configs/__init__.py +2 -2
  9. aiagents4pharma/talk2aiagents4pharma/configs/agents/__init__.py +2 -2
  10. aiagents4pharma/talk2aiagents4pharma/configs/agents/main_agent/default.yaml +2 -2
  11. aiagents4pharma/talk2aiagents4pharma/configs/config.yaml +1 -1
  12. aiagents4pharma/talk2aiagents4pharma/docker-compose/cpu/.env.example +23 -0
  13. aiagents4pharma/talk2aiagents4pharma/docker-compose/cpu/docker-compose.yml +93 -0
  14. aiagents4pharma/talk2aiagents4pharma/docker-compose/gpu/.env.example +23 -0
  15. aiagents4pharma/talk2aiagents4pharma/docker-compose/gpu/docker-compose.yml +108 -0
  16. aiagents4pharma/talk2aiagents4pharma/install.md +127 -0
  17. aiagents4pharma/talk2aiagents4pharma/states/__init__.py +3 -2
  18. aiagents4pharma/talk2aiagents4pharma/states/state_talk2aiagents4pharma.py +5 -3
  19. aiagents4pharma/talk2aiagents4pharma/tests/__init__.py +2 -2
  20. aiagents4pharma/talk2aiagents4pharma/tests/test_main_agent.py +72 -50
  21. aiagents4pharma/talk2biomodels/.dockerignore +13 -0
  22. aiagents4pharma/talk2biomodels/Dockerfile +104 -0
  23. aiagents4pharma/talk2biomodels/README.md +1 -0
  24. aiagents4pharma/talk2biomodels/__init__.py +4 -8
  25. aiagents4pharma/talk2biomodels/agents/__init__.py +3 -2
  26. aiagents4pharma/talk2biomodels/agents/t2b_agent.py +47 -42
  27. aiagents4pharma/talk2biomodels/api/__init__.py +4 -5
  28. aiagents4pharma/talk2biomodels/api/kegg.py +14 -10
  29. aiagents4pharma/talk2biomodels/api/ols.py +13 -10
  30. aiagents4pharma/talk2biomodels/api/uniprot.py +7 -6
  31. aiagents4pharma/talk2biomodels/configs/__init__.py +3 -4
  32. aiagents4pharma/talk2biomodels/configs/agents/__init__.py +2 -2
  33. aiagents4pharma/talk2biomodels/configs/agents/t2b_agent/__init__.py +2 -2
  34. aiagents4pharma/talk2biomodels/configs/agents/t2b_agent/default.yaml +1 -1
  35. aiagents4pharma/talk2biomodels/configs/config.yaml +1 -1
  36. aiagents4pharma/talk2biomodels/configs/tools/__init__.py +4 -5
  37. aiagents4pharma/talk2biomodels/configs/tools/ask_question/__init__.py +2 -2
  38. aiagents4pharma/talk2biomodels/configs/tools/ask_question/default.yaml +1 -2
  39. aiagents4pharma/talk2biomodels/configs/tools/custom_plotter/__init__.py +2 -2
  40. aiagents4pharma/talk2biomodels/configs/tools/custom_plotter/default.yaml +1 -1
  41. aiagents4pharma/talk2biomodels/configs/tools/get_annotation/__init__.py +2 -2
  42. aiagents4pharma/talk2biomodels/configs/tools/get_annotation/default.yaml +1 -1
  43. aiagents4pharma/talk2biomodels/install.md +63 -0
  44. aiagents4pharma/talk2biomodels/models/__init__.py +4 -4
  45. aiagents4pharma/talk2biomodels/models/basico_model.py +36 -28
  46. aiagents4pharma/talk2biomodels/models/sys_bio_model.py +13 -10
  47. aiagents4pharma/talk2biomodels/states/__init__.py +3 -2
  48. aiagents4pharma/talk2biomodels/states/state_talk2biomodels.py +12 -8
  49. aiagents4pharma/talk2biomodels/tests/BIOMD0000000449_url.xml +1585 -0
  50. aiagents4pharma/talk2biomodels/tests/__init__.py +2 -2
  51. aiagents4pharma/talk2biomodels/tests/article_on_model_537.pdf +0 -0
  52. aiagents4pharma/talk2biomodels/tests/test_api.py +18 -14
  53. aiagents4pharma/talk2biomodels/tests/test_ask_question.py +8 -9
  54. aiagents4pharma/talk2biomodels/tests/test_basico_model.py +15 -9
  55. aiagents4pharma/talk2biomodels/tests/test_get_annotation.py +54 -55
  56. aiagents4pharma/talk2biomodels/tests/test_getmodelinfo.py +28 -27
  57. aiagents4pharma/talk2biomodels/tests/test_integration.py +21 -33
  58. aiagents4pharma/talk2biomodels/tests/test_load_biomodel.py +14 -11
  59. aiagents4pharma/talk2biomodels/tests/test_param_scan.py +21 -20
  60. aiagents4pharma/talk2biomodels/tests/test_query_article.py +129 -29
  61. aiagents4pharma/talk2biomodels/tests/test_search_models.py +9 -13
  62. aiagents4pharma/talk2biomodels/tests/test_simulate_model.py +16 -15
  63. aiagents4pharma/talk2biomodels/tests/test_steady_state.py +12 -22
  64. aiagents4pharma/talk2biomodels/tests/test_sys_bio_model.py +33 -29
  65. aiagents4pharma/talk2biomodels/tools/__init__.py +15 -12
  66. aiagents4pharma/talk2biomodels/tools/ask_question.py +42 -32
  67. aiagents4pharma/talk2biomodels/tools/custom_plotter.py +51 -43
  68. aiagents4pharma/talk2biomodels/tools/get_annotation.py +99 -75
  69. aiagents4pharma/talk2biomodels/tools/get_modelinfo.py +57 -51
  70. aiagents4pharma/talk2biomodels/tools/load_arguments.py +52 -32
  71. aiagents4pharma/talk2biomodels/tools/load_biomodel.py +8 -2
  72. aiagents4pharma/talk2biomodels/tools/parameter_scan.py +107 -90
  73. aiagents4pharma/talk2biomodels/tools/query_article.py +14 -13
  74. aiagents4pharma/talk2biomodels/tools/search_models.py +37 -26
  75. aiagents4pharma/talk2biomodels/tools/simulate_model.py +47 -37
  76. aiagents4pharma/talk2biomodels/tools/steady_state.py +76 -58
  77. aiagents4pharma/talk2biomodels/tools/utils.py +4 -3
  78. aiagents4pharma/talk2cells/README.md +1 -0
  79. aiagents4pharma/talk2cells/__init__.py +4 -5
  80. aiagents4pharma/talk2cells/agents/__init__.py +3 -2
  81. aiagents4pharma/talk2cells/agents/scp_agent.py +21 -19
  82. aiagents4pharma/talk2cells/states/__init__.py +3 -2
  83. aiagents4pharma/talk2cells/states/state_talk2cells.py +4 -2
  84. aiagents4pharma/talk2cells/tests/scp_agent/test_scp_agent.py +8 -9
  85. aiagents4pharma/talk2cells/tools/__init__.py +3 -2
  86. aiagents4pharma/talk2cells/tools/scp_agent/__init__.py +4 -4
  87. aiagents4pharma/talk2cells/tools/scp_agent/display_studies.py +5 -3
  88. aiagents4pharma/talk2cells/tools/scp_agent/search_studies.py +21 -22
  89. aiagents4pharma/talk2knowledgegraphs/.dockerignore +13 -0
  90. aiagents4pharma/talk2knowledgegraphs/Dockerfile +103 -0
  91. aiagents4pharma/talk2knowledgegraphs/README.md +1 -0
  92. aiagents4pharma/talk2knowledgegraphs/__init__.py +4 -7
  93. aiagents4pharma/talk2knowledgegraphs/agents/__init__.py +3 -2
  94. aiagents4pharma/talk2knowledgegraphs/agents/t2kg_agent.py +40 -30
  95. aiagents4pharma/talk2knowledgegraphs/configs/__init__.py +3 -6
  96. aiagents4pharma/talk2knowledgegraphs/configs/agents/t2kg_agent/__init__.py +2 -2
  97. aiagents4pharma/talk2knowledgegraphs/configs/agents/t2kg_agent/default.yaml +8 -8
  98. aiagents4pharma/talk2knowledgegraphs/configs/app/__init__.py +3 -2
  99. aiagents4pharma/talk2knowledgegraphs/configs/app/frontend/__init__.py +2 -2
  100. aiagents4pharma/talk2knowledgegraphs/configs/app/frontend/default.yaml +1 -1
  101. aiagents4pharma/talk2knowledgegraphs/configs/config.yaml +1 -1
  102. aiagents4pharma/talk2knowledgegraphs/configs/tools/__init__.py +4 -5
  103. aiagents4pharma/talk2knowledgegraphs/configs/tools/graphrag_reasoning/__init__.py +2 -2
  104. aiagents4pharma/talk2knowledgegraphs/configs/tools/graphrag_reasoning/default.yaml +1 -1
  105. aiagents4pharma/talk2knowledgegraphs/configs/tools/subgraph_extraction/__init__.py +2 -2
  106. aiagents4pharma/talk2knowledgegraphs/configs/tools/subgraph_extraction/default.yaml +1 -1
  107. aiagents4pharma/talk2knowledgegraphs/configs/tools/subgraph_summarization/__init__.py +2 -2
  108. aiagents4pharma/talk2knowledgegraphs/configs/tools/subgraph_summarization/default.yaml +1 -1
  109. aiagents4pharma/talk2knowledgegraphs/configs/utils/enrichments/ols_terms/default.yaml +1 -1
  110. aiagents4pharma/talk2knowledgegraphs/configs/utils/enrichments/reactome_pathways/default.yaml +1 -1
  111. aiagents4pharma/talk2knowledgegraphs/configs/utils/enrichments/uniprot_proteins/default.yaml +1 -1
  112. aiagents4pharma/talk2knowledgegraphs/configs/utils/pubchem_utils/default.yaml +1 -1
  113. aiagents4pharma/talk2knowledgegraphs/datasets/__init__.py +4 -6
  114. aiagents4pharma/talk2knowledgegraphs/datasets/biobridge_primekg.py +115 -67
  115. aiagents4pharma/talk2knowledgegraphs/datasets/dataset.py +2 -0
  116. aiagents4pharma/talk2knowledgegraphs/datasets/primekg.py +35 -24
  117. aiagents4pharma/talk2knowledgegraphs/datasets/starkqa_primekg.py +29 -21
  118. aiagents4pharma/talk2knowledgegraphs/docker-compose/cpu/.env.example +23 -0
  119. aiagents4pharma/talk2knowledgegraphs/docker-compose/cpu/docker-compose.yml +93 -0
  120. aiagents4pharma/talk2knowledgegraphs/docker-compose/gpu/.env.example +23 -0
  121. aiagents4pharma/talk2knowledgegraphs/docker-compose/gpu/docker-compose.yml +108 -0
  122. aiagents4pharma/talk2knowledgegraphs/entrypoint.sh +190 -0
  123. aiagents4pharma/talk2knowledgegraphs/install.md +140 -0
  124. aiagents4pharma/talk2knowledgegraphs/milvus_data_dump.py +31 -65
  125. aiagents4pharma/talk2knowledgegraphs/states/__init__.py +3 -2
  126. aiagents4pharma/talk2knowledgegraphs/states/state_talk2knowledgegraphs.py +1 -0
  127. aiagents4pharma/talk2knowledgegraphs/tests/test_agents_t2kg_agent.py +65 -40
  128. aiagents4pharma/talk2knowledgegraphs/tests/test_datasets_biobridge_primekg.py +54 -48
  129. aiagents4pharma/talk2knowledgegraphs/tests/test_datasets_dataset.py +4 -0
  130. aiagents4pharma/talk2knowledgegraphs/tests/test_datasets_primekg.py +17 -4
  131. aiagents4pharma/talk2knowledgegraphs/tests/test_datasets_starkqa_primekg.py +33 -24
  132. aiagents4pharma/talk2knowledgegraphs/tests/test_tools_graphrag_reasoning.py +116 -69
  133. aiagents4pharma/talk2knowledgegraphs/tests/test_tools_milvus_multimodal_subgraph_extraction.py +334 -216
  134. aiagents4pharma/talk2knowledgegraphs/tests/test_tools_multimodal_subgraph_extraction.py +22 -15
  135. aiagents4pharma/talk2knowledgegraphs/tests/test_tools_subgraph_extraction.py +19 -12
  136. aiagents4pharma/talk2knowledgegraphs/tests/test_tools_subgraph_summarization.py +95 -48
  137. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_embeddings_embeddings.py +4 -0
  138. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_embeddings_huggingface.py +5 -0
  139. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_embeddings_nim_molmim.py +13 -18
  140. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_embeddings_ollama.py +10 -3
  141. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_enrichments_enrichments.py +4 -3
  142. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_enrichments_ollama.py +3 -2
  143. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_enrichments_ols.py +1 -0
  144. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_enrichments_pubchem.py +9 -4
  145. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_enrichments_reactome.py +6 -6
  146. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_enrichments_uniprot.py +4 -0
  147. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_extractions_milvus_multimodal_pcst.py +160 -97
  148. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_kg_utils.py +3 -4
  149. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_pubchem_utils.py +87 -13
  150. aiagents4pharma/talk2knowledgegraphs/tools/__init__.py +10 -7
  151. aiagents4pharma/talk2knowledgegraphs/tools/graphrag_reasoning.py +15 -20
  152. aiagents4pharma/talk2knowledgegraphs/tools/milvus_multimodal_subgraph_extraction.py +145 -142
  153. aiagents4pharma/talk2knowledgegraphs/tools/multimodal_subgraph_extraction.py +92 -90
  154. aiagents4pharma/talk2knowledgegraphs/tools/subgraph_extraction.py +25 -37
  155. aiagents4pharma/talk2knowledgegraphs/tools/subgraph_summarization.py +10 -13
  156. aiagents4pharma/talk2knowledgegraphs/utils/__init__.py +4 -7
  157. aiagents4pharma/talk2knowledgegraphs/utils/embeddings/__init__.py +4 -7
  158. aiagents4pharma/talk2knowledgegraphs/utils/embeddings/embeddings.py +4 -0
  159. aiagents4pharma/talk2knowledgegraphs/utils/embeddings/huggingface.py +11 -14
  160. aiagents4pharma/talk2knowledgegraphs/utils/embeddings/nim_molmim.py +7 -7
  161. aiagents4pharma/talk2knowledgegraphs/utils/embeddings/ollama.py +12 -6
  162. aiagents4pharma/talk2knowledgegraphs/utils/embeddings/sentence_transformer.py +8 -6
  163. aiagents4pharma/talk2knowledgegraphs/utils/enrichments/__init__.py +9 -6
  164. aiagents4pharma/talk2knowledgegraphs/utils/enrichments/enrichments.py +1 -0
  165. aiagents4pharma/talk2knowledgegraphs/utils/enrichments/ollama.py +15 -9
  166. aiagents4pharma/talk2knowledgegraphs/utils/enrichments/ols_terms.py +23 -20
  167. aiagents4pharma/talk2knowledgegraphs/utils/enrichments/pubchem_strings.py +12 -10
  168. aiagents4pharma/talk2knowledgegraphs/utils/enrichments/reactome_pathways.py +16 -10
  169. aiagents4pharma/talk2knowledgegraphs/utils/enrichments/uniprot_proteins.py +26 -18
  170. aiagents4pharma/talk2knowledgegraphs/utils/extractions/__init__.py +4 -5
  171. aiagents4pharma/talk2knowledgegraphs/utils/extractions/milvus_multimodal_pcst.py +14 -34
  172. aiagents4pharma/talk2knowledgegraphs/utils/extractions/multimodal_pcst.py +53 -47
  173. aiagents4pharma/talk2knowledgegraphs/utils/extractions/pcst.py +18 -14
  174. aiagents4pharma/talk2knowledgegraphs/utils/kg_utils.py +22 -23
  175. aiagents4pharma/talk2knowledgegraphs/utils/pubchem_utils.py +11 -10
  176. aiagents4pharma/talk2scholars/.dockerignore +13 -0
  177. aiagents4pharma/talk2scholars/Dockerfile +104 -0
  178. aiagents4pharma/talk2scholars/README.md +1 -0
  179. aiagents4pharma/talk2scholars/agents/__init__.py +1 -5
  180. aiagents4pharma/talk2scholars/agents/main_agent.py +6 -4
  181. aiagents4pharma/talk2scholars/agents/paper_download_agent.py +5 -4
  182. aiagents4pharma/talk2scholars/agents/pdf_agent.py +4 -2
  183. aiagents4pharma/talk2scholars/agents/s2_agent.py +2 -2
  184. aiagents4pharma/talk2scholars/agents/zotero_agent.py +10 -11
  185. aiagents4pharma/talk2scholars/configs/__init__.py +1 -3
  186. aiagents4pharma/talk2scholars/configs/agents/talk2scholars/__init__.py +1 -4
  187. aiagents4pharma/talk2scholars/configs/agents/talk2scholars/main_agent/default.yaml +1 -1
  188. aiagents4pharma/talk2scholars/configs/agents/talk2scholars/pdf_agent/default.yaml +1 -1
  189. aiagents4pharma/talk2scholars/configs/agents/talk2scholars/s2_agent/default.yaml +8 -8
  190. aiagents4pharma/talk2scholars/configs/agents/talk2scholars/zotero_agent/default.yaml +7 -7
  191. aiagents4pharma/talk2scholars/configs/tools/__init__.py +8 -6
  192. aiagents4pharma/talk2scholars/docker-compose/cpu/.env.example +21 -0
  193. aiagents4pharma/talk2scholars/docker-compose/cpu/docker-compose.yml +90 -0
  194. aiagents4pharma/talk2scholars/docker-compose/gpu/.env.example +21 -0
  195. aiagents4pharma/talk2scholars/docker-compose/gpu/docker-compose.yml +105 -0
  196. aiagents4pharma/talk2scholars/install.md +122 -0
  197. aiagents4pharma/talk2scholars/state/state_talk2scholars.py +8 -8
  198. aiagents4pharma/talk2scholars/tests/{test_main_agent.py → test_agents_main_agent.py} +41 -23
  199. aiagents4pharma/talk2scholars/tests/{test_paper_download_agent.py → test_agents_paper_agents_download_agent.py} +10 -16
  200. aiagents4pharma/talk2scholars/tests/{test_pdf_agent.py → test_agents_pdf_agent.py} +6 -10
  201. aiagents4pharma/talk2scholars/tests/{test_s2_agent.py → test_agents_s2_agent.py} +8 -16
  202. aiagents4pharma/talk2scholars/tests/{test_zotero_agent.py → test_agents_zotero_agent.py} +5 -7
  203. aiagents4pharma/talk2scholars/tests/{test_s2_display_dataframe.py → test_s2_tools_display_dataframe.py} +6 -7
  204. aiagents4pharma/talk2scholars/tests/{test_s2_query_dataframe.py → test_s2_tools_query_dataframe.py} +5 -15
  205. aiagents4pharma/talk2scholars/tests/{test_paper_downloader.py → test_tools_paper_downloader.py} +25 -63
  206. aiagents4pharma/talk2scholars/tests/{test_question_and_answer_tool.py → test_tools_question_and_answer_tool.py} +2 -6
  207. aiagents4pharma/talk2scholars/tests/{test_s2_multi.py → test_tools_s2_multi.py} +5 -5
  208. aiagents4pharma/talk2scholars/tests/{test_s2_retrieve.py → test_tools_s2_retrieve.py} +2 -1
  209. aiagents4pharma/talk2scholars/tests/{test_s2_search.py → test_tools_s2_search.py} +5 -5
  210. aiagents4pharma/talk2scholars/tests/{test_s2_single.py → test_tools_s2_single.py} +5 -5
  211. aiagents4pharma/talk2scholars/tests/{test_arxiv_downloader.py → test_utils_arxiv_downloader.py} +16 -25
  212. aiagents4pharma/talk2scholars/tests/{test_base_paper_downloader.py → test_utils_base_paper_downloader.py} +25 -47
  213. aiagents4pharma/talk2scholars/tests/{test_biorxiv_downloader.py → test_utils_biorxiv_downloader.py} +14 -42
  214. aiagents4pharma/talk2scholars/tests/{test_medrxiv_downloader.py → test_utils_medrxiv_downloader.py} +15 -49
  215. aiagents4pharma/talk2scholars/tests/{test_nvidia_nim_reranker.py → test_utils_nvidia_nim_reranker.py} +6 -16
  216. aiagents4pharma/talk2scholars/tests/{test_pdf_answer_formatter.py → test_utils_pdf_answer_formatter.py} +1 -0
  217. aiagents4pharma/talk2scholars/tests/{test_pdf_batch_processor.py → test_utils_pdf_batch_processor.py} +6 -15
  218. aiagents4pharma/talk2scholars/tests/{test_pdf_collection_manager.py → test_utils_pdf_collection_manager.py} +34 -11
  219. aiagents4pharma/talk2scholars/tests/{test_pdf_document_processor.py → test_utils_pdf_document_processor.py} +2 -3
  220. aiagents4pharma/talk2scholars/tests/{test_pdf_generate_answer.py → test_utils_pdf_generate_answer.py} +3 -6
  221. aiagents4pharma/talk2scholars/tests/{test_pdf_gpu_detection.py → test_utils_pdf_gpu_detection.py} +5 -16
  222. aiagents4pharma/talk2scholars/tests/{test_pdf_rag_pipeline.py → test_utils_pdf_rag_pipeline.py} +7 -17
  223. aiagents4pharma/talk2scholars/tests/{test_pdf_retrieve_chunks.py → test_utils_pdf_retrieve_chunks.py} +4 -11
  224. aiagents4pharma/talk2scholars/tests/{test_pdf_singleton_manager.py → test_utils_pdf_singleton_manager.py} +26 -23
  225. aiagents4pharma/talk2scholars/tests/{test_pdf_vector_normalization.py → test_utils_pdf_vector_normalization.py} +1 -1
  226. aiagents4pharma/talk2scholars/tests/{test_pdf_vector_store.py → test_utils_pdf_vector_store.py} +27 -55
  227. aiagents4pharma/talk2scholars/tests/{test_pubmed_downloader.py → test_utils_pubmed_downloader.py} +31 -91
  228. aiagents4pharma/talk2scholars/tests/{test_read_helper_utils.py → test_utils_read_helper_utils.py} +2 -6
  229. aiagents4pharma/talk2scholars/tests/{test_s2_utils_ext_ids.py → test_utils_s2_utils_ext_ids.py} +5 -15
  230. aiagents4pharma/talk2scholars/tests/{test_zotero_human_in_the_loop.py → test_utils_zotero_human_in_the_loop.py} +6 -13
  231. aiagents4pharma/talk2scholars/tests/{test_zotero_path.py → test_utils_zotero_path.py} +53 -45
  232. aiagents4pharma/talk2scholars/tests/{test_zotero_read.py → test_utils_zotero_read.py} +30 -91
  233. aiagents4pharma/talk2scholars/tests/{test_zotero_write.py → test_utils_zotero_write.py} +6 -16
  234. aiagents4pharma/talk2scholars/tools/__init__.py +1 -4
  235. aiagents4pharma/talk2scholars/tools/paper_download/paper_downloader.py +20 -35
  236. aiagents4pharma/talk2scholars/tools/paper_download/utils/__init__.py +7 -5
  237. aiagents4pharma/talk2scholars/tools/paper_download/utils/arxiv_downloader.py +9 -11
  238. aiagents4pharma/talk2scholars/tools/paper_download/utils/base_paper_downloader.py +14 -21
  239. aiagents4pharma/talk2scholars/tools/paper_download/utils/biorxiv_downloader.py +14 -22
  240. aiagents4pharma/talk2scholars/tools/paper_download/utils/medrxiv_downloader.py +11 -13
  241. aiagents4pharma/talk2scholars/tools/paper_download/utils/pubmed_downloader.py +14 -28
  242. aiagents4pharma/talk2scholars/tools/pdf/question_and_answer.py +4 -8
  243. aiagents4pharma/talk2scholars/tools/pdf/utils/__init__.py +16 -14
  244. aiagents4pharma/talk2scholars/tools/pdf/utils/answer_formatter.py +4 -4
  245. aiagents4pharma/talk2scholars/tools/pdf/utils/batch_processor.py +15 -17
  246. aiagents4pharma/talk2scholars/tools/pdf/utils/collection_manager.py +2 -2
  247. aiagents4pharma/talk2scholars/tools/pdf/utils/document_processor.py +5 -5
  248. aiagents4pharma/talk2scholars/tools/pdf/utils/generate_answer.py +4 -4
  249. aiagents4pharma/talk2scholars/tools/pdf/utils/get_vectorstore.py +2 -6
  250. aiagents4pharma/talk2scholars/tools/pdf/utils/gpu_detection.py +5 -9
  251. aiagents4pharma/talk2scholars/tools/pdf/utils/nvidia_nim_reranker.py +4 -4
  252. aiagents4pharma/talk2scholars/tools/pdf/utils/paper_loader.py +2 -2
  253. aiagents4pharma/talk2scholars/tools/pdf/utils/rag_pipeline.py +6 -15
  254. aiagents4pharma/talk2scholars/tools/pdf/utils/retrieve_chunks.py +7 -15
  255. aiagents4pharma/talk2scholars/tools/pdf/utils/singleton_manager.py +2 -2
  256. aiagents4pharma/talk2scholars/tools/pdf/utils/tool_helper.py +3 -4
  257. aiagents4pharma/talk2scholars/tools/pdf/utils/vector_normalization.py +8 -17
  258. aiagents4pharma/talk2scholars/tools/pdf/utils/vector_store.py +17 -33
  259. aiagents4pharma/talk2scholars/tools/s2/__init__.py +8 -6
  260. aiagents4pharma/talk2scholars/tools/s2/display_dataframe.py +3 -7
  261. aiagents4pharma/talk2scholars/tools/s2/multi_paper_rec.py +7 -6
  262. aiagents4pharma/talk2scholars/tools/s2/query_dataframe.py +5 -12
  263. aiagents4pharma/talk2scholars/tools/s2/retrieve_semantic_scholar_paper_id.py +2 -4
  264. aiagents4pharma/talk2scholars/tools/s2/search.py +6 -6
  265. aiagents4pharma/talk2scholars/tools/s2/single_paper_rec.py +5 -3
  266. aiagents4pharma/talk2scholars/tools/s2/utils/__init__.py +1 -3
  267. aiagents4pharma/talk2scholars/tools/s2/utils/multi_helper.py +12 -18
  268. aiagents4pharma/talk2scholars/tools/s2/utils/search_helper.py +11 -18
  269. aiagents4pharma/talk2scholars/tools/s2/utils/single_helper.py +11 -16
  270. aiagents4pharma/talk2scholars/tools/zotero/__init__.py +1 -4
  271. aiagents4pharma/talk2scholars/tools/zotero/utils/__init__.py +1 -4
  272. aiagents4pharma/talk2scholars/tools/zotero/utils/read_helper.py +21 -39
  273. aiagents4pharma/talk2scholars/tools/zotero/utils/review_helper.py +2 -6
  274. aiagents4pharma/talk2scholars/tools/zotero/utils/write_helper.py +8 -11
  275. aiagents4pharma/talk2scholars/tools/zotero/utils/zotero_path.py +4 -12
  276. aiagents4pharma/talk2scholars/tools/zotero/utils/zotero_pdf_downloader.py +13 -27
  277. aiagents4pharma/talk2scholars/tools/zotero/zotero_read.py +4 -7
  278. aiagents4pharma/talk2scholars/tools/zotero/zotero_review.py +8 -10
  279. aiagents4pharma/talk2scholars/tools/zotero/zotero_write.py +3 -2
  280. {aiagents4pharma-1.44.0.dist-info → aiagents4pharma-1.45.1.dist-info}/METADATA +115 -51
  281. aiagents4pharma-1.45.1.dist-info/RECORD +324 -0
  282. {aiagents4pharma-1.44.0.dist-info → aiagents4pharma-1.45.1.dist-info}/WHEEL +1 -2
  283. aiagents4pharma-1.44.0.dist-info/RECORD +0 -293
  284. aiagents4pharma-1.44.0.dist-info/top_level.txt +0 -1
  285. /aiagents4pharma/talk2scholars/tests/{test_state.py → test_states_state.py} +0 -0
  286. /aiagents4pharma/talk2scholars/tests/{test_pdf_paper_loader.py → test_utils_pdf_paper_loader.py} +0 -0
  287. /aiagents4pharma/talk2scholars/tests/{test_tool_helper_utils.py → test_utils_tool_helper_utils.py} +0 -0
  288. /aiagents4pharma/talk2scholars/tests/{test_zotero_pdf_downloader_utils.py → test_utils_zotero_pdf_downloader_utils.py} +0 -0
  289. {aiagents4pharma-1.44.0.dist-info → aiagents4pharma-1.45.1.dist-info}/licenses/LICENSE +0 -0
@@ -4,15 +4,19 @@ Test cases for tools/milvus_multimodal_subgraph_extraction.py
4
4
 
5
5
  import importlib
6
6
  import unittest
7
- from unittest.mock import patch, MagicMock
7
+ from unittest.mock import MagicMock, patch
8
+
8
9
  import numpy as np
9
10
  import pandas as pd
11
+
10
12
  from ..tools.milvus_multimodal_subgraph_extraction import MultimodalSubgraphExtractionTool
11
13
 
14
+
12
15
  class TestMultimodalSubgraphExtractionTool(unittest.TestCase):
13
16
  """
14
17
  Test cases for MultimodalSubgraphExtractionTool (Milvus)
15
18
  """
19
+
16
20
  def setUp(self):
17
21
  self.tool = MultimodalSubgraphExtractionTool()
18
22
  self.state = {
@@ -37,15 +41,16 @@ class TestMultimodalSubgraphExtractionTool(unittest.TestCase):
37
41
  self.cfg.search_metric_type = "L2"
38
42
  self.cfg.node_colors_dict = {"gene/protein": "red"}
39
43
 
40
- @patch("aiagents4pharma.talk2knowledgegraphs.tools."
41
- "milvus_multimodal_subgraph_extraction.Collection")
42
- @patch("aiagents4pharma.talk2knowledgegraphs.tools."
43
- "milvus_multimodal_subgraph_extraction.MultimodalPCSTPruning")
44
+ @patch(
45
+ "aiagents4pharma.talk2knowledgegraphs.tools."
46
+ "milvus_multimodal_subgraph_extraction.Collection"
47
+ )
48
+ @patch(
49
+ "aiagents4pharma.talk2knowledgegraphs.tools."
50
+ "milvus_multimodal_subgraph_extraction.MultimodalPCSTPruning"
51
+ )
44
52
  @patch("pymilvus.connections")
45
- def test_extract_multimodal_subgraph_wo_doc(self,
46
- mock_connections,
47
- mock_pcst,
48
- mock_collection):
53
+ def test_extract_multimodal_subgraph_wo_doc(self, mock_connections, mock_pcst, mock_collection):
49
54
  """
50
55
  Test the multimodal subgraph extraction tool for only text as modality.
51
56
  """
@@ -63,36 +68,42 @@ class TestMultimodalSubgraphExtractionTool(unittest.TestCase):
63
68
  colls["nodes"] = MagicMock()
64
69
  colls["nodes"] = MagicMock()
65
70
  colls["nodes"].query.return_value = [
66
- {"node_index": 0,
67
- "node_id": "id1",
68
- "node_name": "JAK1",
69
- "node_type": "gene/protein",
70
- "feat": "featA",
71
- "feat_emb": [0.1, 0.2, 0.3],
72
- "desc": "descA",
73
- "desc_emb": [0.1, 0.2, 0.3]},
74
- {"node_index": 1,
75
- "node_id": "id2",
76
- "node_name": "JAK2",
77
- "node_type": "gene/protein",
78
- "feat": "featB",
79
- "feat_emb": [0.4, 0.5, 0.6],
80
- "desc": "descB",
81
- "desc_emb": [0.4, 0.5, 0.6]}
71
+ {
72
+ "node_index": 0,
73
+ "node_id": "id1",
74
+ "node_name": "JAK1",
75
+ "node_type": "gene/protein",
76
+ "feat": "featA",
77
+ "feat_emb": [0.1, 0.2, 0.3],
78
+ "desc": "descA",
79
+ "desc_emb": [0.1, 0.2, 0.3],
80
+ },
81
+ {
82
+ "node_index": 1,
83
+ "node_id": "id2",
84
+ "node_name": "JAK2",
85
+ "node_type": "gene/protein",
86
+ "feat": "featB",
87
+ "feat_emb": [0.4, 0.5, 0.6],
88
+ "desc": "descB",
89
+ "desc_emb": [0.4, 0.5, 0.6],
90
+ },
82
91
  ]
83
92
  colls["nodes"].load.return_value = None
84
93
 
85
94
  colls["edges"] = MagicMock()
86
95
  colls["edges"].query.return_value = [
87
- {"triplet_index": 0,
88
- "head_id": "id1",
89
- "head_index": 0,
90
- "tail_id": "id2",
91
- "tail_index": 1,
92
- "edge_type": "gene/protein,ppi,gene/protein",
93
- "display_relation": "ppi",
94
- "feat": "featC",
95
- "feat_emb": [0.7, 0.8, 0.9]}
96
+ {
97
+ "triplet_index": 0,
98
+ "head_id": "id1",
99
+ "head_index": 0,
100
+ "tail_id": "id2",
101
+ "tail_index": 1,
102
+ "edge_type": "gene/protein,ppi,gene/protein",
103
+ "display_relation": "ppi",
104
+ "feat": "featC",
105
+ "feat_emb": [0.7, 0.8, 0.9],
106
+ }
96
107
  ]
97
108
  colls["edges"].load.return_value = None
98
109
 
@@ -105,30 +116,39 @@ class TestMultimodalSubgraphExtractionTool(unittest.TestCase):
105
116
  if "edges" in name:
106
117
  return colls["edges"]
107
118
  return None
119
+
108
120
  mock_collection.side_effect = collection_side_effect
109
121
 
110
122
  # Mock MultimodalPCSTPruning
111
123
  mock_pcst_instance = MagicMock()
112
124
  mock_pcst_instance.extract_subgraph.return_value = {
113
125
  "nodes": pd.Series([1, 2]),
114
- "edges": pd.Series([0])
126
+ "edges": pd.Series([0]),
115
127
  }
116
128
  mock_pcst.return_value = mock_pcst_instance
117
129
 
118
130
  # Patch hydra.compose to return config objects
119
- with patch("aiagents4pharma.talk2knowledgegraphs.tools."
120
- "milvus_multimodal_subgraph_extraction.hydra.initialize"), \
121
- patch("aiagents4pharma.talk2knowledgegraphs.tools."
122
- "milvus_multimodal_subgraph_extraction.hydra.compose") as mock_compose:
131
+ with (
132
+ patch(
133
+ "aiagents4pharma.talk2knowledgegraphs.tools."
134
+ "milvus_multimodal_subgraph_extraction.hydra.initialize"
135
+ ),
136
+ patch(
137
+ "aiagents4pharma.talk2knowledgegraphs.tools."
138
+ "milvus_multimodal_subgraph_extraction.hydra.compose"
139
+ ) as mock_compose,
140
+ ):
123
141
  mock_compose.return_value = MagicMock()
124
142
  mock_compose.return_value.app.frontend = self.cfg_db
125
143
  mock_compose.return_value.tools.multimodal_subgraph_extraction = self.cfg
126
144
 
127
145
  response = self.tool.invoke(
128
- input={"prompt": self.prompt,
129
- "tool_call_id": "subgraph_extraction_tool",
130
- "state": self.state,
131
- "arg_data": self.arg_data}
146
+ input={
147
+ "prompt": self.prompt,
148
+ "tool_call_id": "subgraph_extraction_tool",
149
+ "state": self.state,
150
+ "arg_data": self.arg_data,
151
+ }
132
152
  )
133
153
 
134
154
  # Check tool message
@@ -146,36 +166,47 @@ class TestMultimodalSubgraphExtractionTool(unittest.TestCase):
146
166
  self.assertGreater(len(dic_extracted_graph["graph_dict"]["edges"]), 0)
147
167
  self.assertIsInstance(dic_extracted_graph["graph_text"], str)
148
168
  # Check if the nodes are in the graph_text
149
- self.assertTrue(all(
150
- n[0] in dic_extracted_graph["graph_text"].replace('"', '')
151
- for subgraph_nodes in dic_extracted_graph["graph_dict"]["nodes"]
152
- for n in subgraph_nodes
153
- ))
169
+ self.assertTrue(
170
+ all(
171
+ n[0] in dic_extracted_graph["graph_text"].replace('"', "")
172
+ for subgraph_nodes in dic_extracted_graph["graph_dict"]["nodes"]
173
+ for n in subgraph_nodes
174
+ )
175
+ )
154
176
  # Check if the edges are in the graph_text
155
- self.assertTrue(all(
156
- ",".join([str(e[0])] + str(e[2]['label'][0]).split(",") + [str(e[1])])
157
- in dic_extracted_graph["graph_text"].replace('"', '').\
158
- replace("[", "").replace("]", "").replace("'", "")
159
- for subgraph_edges in dic_extracted_graph["graph_dict"]["edges"]
160
- for e in subgraph_edges
161
- ))
177
+ self.assertTrue(
178
+ all(
179
+ ",".join([str(e[0])] + str(e[2]["label"][0]).split(",") + [str(e[1])])
180
+ in dic_extracted_graph["graph_text"]
181
+ .replace('"', "")
182
+ .replace("[", "")
183
+ .replace("]", "")
184
+ .replace("'", "")
185
+ for subgraph_edges in dic_extracted_graph["graph_dict"]["edges"]
186
+ for e in subgraph_edges
187
+ )
188
+ )
162
189
 
163
190
  # Another test for unknown collection
164
191
  result = collection_side_effect("unknown")
165
192
  self.assertIsNone(result)
166
193
 
167
- @patch("aiagents4pharma.talk2knowledgegraphs.tools."
168
- "milvus_multimodal_subgraph_extraction.Collection")
169
- @patch("aiagents4pharma.talk2knowledgegraphs.tools."
170
- "milvus_multimodal_subgraph_extraction.pd.read_excel")
171
- @patch("aiagents4pharma.talk2knowledgegraphs.tools."
172
- "milvus_multimodal_subgraph_extraction.MultimodalPCSTPruning")
194
+ @patch(
195
+ "aiagents4pharma.talk2knowledgegraphs.tools."
196
+ "milvus_multimodal_subgraph_extraction.Collection"
197
+ )
198
+ @patch(
199
+ "aiagents4pharma.talk2knowledgegraphs.tools."
200
+ "milvus_multimodal_subgraph_extraction.pd.read_excel"
201
+ )
202
+ @patch(
203
+ "aiagents4pharma.talk2knowledgegraphs.tools."
204
+ "milvus_multimodal_subgraph_extraction.MultimodalPCSTPruning"
205
+ )
173
206
  @patch("pymilvus.connections")
174
- def test_extract_multimodal_subgraph_w_doc(self,
175
- mock_connections,
176
- mock_pcst,
177
- mock_read_excel,
178
- mock_collection):
207
+ def test_extract_multimodal_subgraph_w_doc(
208
+ self, mock_connections, mock_pcst, mock_read_excel, mock_collection
209
+ ):
179
210
  """
180
211
  Test the multimodal subgraph extraction tool for text as modality, plus genes.
181
212
  """
@@ -183,17 +214,12 @@ class TestMultimodalSubgraphExtractionTool(unittest.TestCase):
183
214
  mock_connections.has_connection.return_value = True
184
215
 
185
216
  # With uploaded_files (with doc)
186
- self.state["uploaded_files"] = [
187
- {"file_type": "multimodal", "file_path": "dummy.xlsx"}
188
- ]
217
+ self.state["uploaded_files"] = [{"file_type": "multimodal", "file_path": "dummy.xlsx"}]
189
218
  self.state["embedding_model"].embed_query.return_value = [0.1, 0.2, 0.3]
190
219
  self.state["selections"] = {"gene/protein": ["JAK1", "JAK2"]}
191
220
 
192
221
  # Mock pd.read_excel to return a dict of DataFrames
193
- df = pd.DataFrame({
194
- "name": ["JAK1", "JAK2"],
195
- "node_type": ["gene/protein", "gene/protein"]
196
- })
222
+ df = pd.DataFrame({"name": ["JAK1", "JAK2"], "node_type": ["gene/protein", "gene/protein"]})
197
223
  mock_read_excel.return_value = {"gene/protein": df}
198
224
 
199
225
  # Mock Collection for nodes and edges
@@ -201,36 +227,42 @@ class TestMultimodalSubgraphExtractionTool(unittest.TestCase):
201
227
  colls["nodes"] = MagicMock()
202
228
  colls["nodes"] = MagicMock()
203
229
  colls["nodes"].query.return_value = [
204
- {"node_index": 0,
205
- "node_id": "id1",
206
- "node_name": "JAK1",
207
- "node_type": "gene/protein",
208
- "feat": "featA",
209
- "feat_emb": [0.1, 0.2, 0.3],
210
- "desc": "descA",
211
- "desc_emb": [0.1, 0.2, 0.3]},
212
- {"node_index": 1,
213
- "node_id": "id2",
214
- "node_name": "JAK2",
215
- "node_type": "gene/protein",
216
- "feat": "featB",
217
- "feat_emb": [0.4, 0.5, 0.6],
218
- "desc": "descB",
219
- "desc_emb": [0.4, 0.5, 0.6]}
230
+ {
231
+ "node_index": 0,
232
+ "node_id": "id1",
233
+ "node_name": "JAK1",
234
+ "node_type": "gene/protein",
235
+ "feat": "featA",
236
+ "feat_emb": [0.1, 0.2, 0.3],
237
+ "desc": "descA",
238
+ "desc_emb": [0.1, 0.2, 0.3],
239
+ },
240
+ {
241
+ "node_index": 1,
242
+ "node_id": "id2",
243
+ "node_name": "JAK2",
244
+ "node_type": "gene/protein",
245
+ "feat": "featB",
246
+ "feat_emb": [0.4, 0.5, 0.6],
247
+ "desc": "descB",
248
+ "desc_emb": [0.4, 0.5, 0.6],
249
+ },
220
250
  ]
221
251
  colls["nodes"].load.return_value = None
222
252
 
223
253
  colls["edges"] = MagicMock()
224
254
  colls["edges"].query.return_value = [
225
- {"triplet_index": 0,
226
- "head_id": "id1",
227
- "head_index": 0,
228
- "tail_id": "id2",
229
- "tail_index": 1,
230
- "edge_type": "gene/protein,ppi,gene/protein",
231
- "display_relation": "ppi",
232
- "feat": "featC",
233
- "feat_emb": [0.7, 0.8, 0.9]}
255
+ {
256
+ "triplet_index": 0,
257
+ "head_id": "id1",
258
+ "head_index": 0,
259
+ "tail_id": "id2",
260
+ "tail_index": 1,
261
+ "edge_type": "gene/protein,ppi,gene/protein",
262
+ "display_relation": "ppi",
263
+ "feat": "featC",
264
+ "feat_emb": [0.7, 0.8, 0.9],
265
+ }
234
266
  ]
235
267
  colls["edges"].load.return_value = None
236
268
 
@@ -243,30 +275,39 @@ class TestMultimodalSubgraphExtractionTool(unittest.TestCase):
243
275
  if "edges" in name:
244
276
  return colls["edges"]
245
277
  return None
278
+
246
279
  mock_collection.side_effect = collection_side_effect
247
280
 
248
281
  # Mock MultimodalPCSTPruning
249
282
  mock_pcst_instance = MagicMock()
250
283
  mock_pcst_instance.extract_subgraph.return_value = {
251
284
  "nodes": pd.Series([1, 2]),
252
- "edges": pd.Series([0])
285
+ "edges": pd.Series([0]),
253
286
  }
254
287
  mock_pcst.return_value = mock_pcst_instance
255
288
 
256
289
  # Patch hydra.compose to return config objects
257
- with patch("aiagents4pharma.talk2knowledgegraphs.tools."
258
- "milvus_multimodal_subgraph_extraction.hydra.initialize"), \
259
- patch("aiagents4pharma.talk2knowledgegraphs.tools."
260
- "milvus_multimodal_subgraph_extraction.hydra.compose") as mock_compose:
290
+ with (
291
+ patch(
292
+ "aiagents4pharma.talk2knowledgegraphs.tools."
293
+ "milvus_multimodal_subgraph_extraction.hydra.initialize"
294
+ ),
295
+ patch(
296
+ "aiagents4pharma.talk2knowledgegraphs.tools."
297
+ "milvus_multimodal_subgraph_extraction.hydra.compose"
298
+ ) as mock_compose,
299
+ ):
261
300
  mock_compose.return_value = MagicMock()
262
301
  mock_compose.return_value.app.frontend = self.cfg_db
263
302
  mock_compose.return_value.tools.multimodal_subgraph_extraction = self.cfg
264
303
 
265
304
  response = self.tool.invoke(
266
- input={"prompt": self.prompt,
267
- "tool_call_id": "subgraph_extraction_tool",
268
- "state": self.state,
269
- "arg_data": self.arg_data}
305
+ input={
306
+ "prompt": self.prompt,
307
+ "tool_call_id": "subgraph_extraction_tool",
308
+ "state": self.state,
309
+ "arg_data": self.arg_data,
310
+ }
270
311
  )
271
312
 
272
313
  # Check tool message
@@ -284,19 +325,26 @@ class TestMultimodalSubgraphExtractionTool(unittest.TestCase):
284
325
  self.assertGreater(len(dic_extracted_graph["graph_dict"]["edges"]), 0)
285
326
  self.assertIsInstance(dic_extracted_graph["graph_text"], str)
286
327
  # Check if the nodes are in the graph_text
287
- self.assertTrue(all(
288
- n[0] in dic_extracted_graph["graph_text"].replace('"', '')
289
- for subgraph_nodes in dic_extracted_graph["graph_dict"]["nodes"]
290
- for n in subgraph_nodes
291
- ))
328
+ self.assertTrue(
329
+ all(
330
+ n[0] in dic_extracted_graph["graph_text"].replace('"', "")
331
+ for subgraph_nodes in dic_extracted_graph["graph_dict"]["nodes"]
332
+ for n in subgraph_nodes
333
+ )
334
+ )
292
335
  # Check if the edges are in the graph_text
293
- self.assertTrue(all(
294
- ",".join([str(e[0])] + str(e[2]['label'][0]).split(",") + [str(e[1])])
295
- in dic_extracted_graph["graph_text"].replace('"', '').\
296
- replace("[", "").replace("]", "").replace("'", "")
297
- for subgraph_edges in dic_extracted_graph["graph_dict"]["edges"]
298
- for e in subgraph_edges
299
- ))
336
+ self.assertTrue(
337
+ all(
338
+ ",".join([str(e[0])] + str(e[2]["label"][0]).split(",") + [str(e[1])])
339
+ in dic_extracted_graph["graph_text"]
340
+ .replace('"', "")
341
+ .replace("[", "")
342
+ .replace("]", "")
343
+ .replace("'", "")
344
+ for subgraph_edges in dic_extracted_graph["graph_dict"]["edges"]
345
+ for e in subgraph_edges
346
+ )
347
+ )
300
348
 
301
349
  # Another test for unknown collection
302
350
  result = collection_side_effect("unknown")
@@ -307,84 +355,100 @@ class TestMultimodalSubgraphExtractionTool(unittest.TestCase):
307
355
  Test the multimodal subgraph extraction tool for only text as modality,
308
356
  simulating GPU (cudf/cupy) environment.
309
357
  """
310
- module_name = "aiagents4pharma.talk2knowledgegraphs.tools."+\
311
- "milvus_multimodal_subgraph_extraction"
358
+ module_name = (
359
+ "aiagents4pharma.talk2knowledgegraphs.tools." + "milvus_multimodal_subgraph_extraction"
360
+ )
312
361
  with patch.dict("sys.modules", {"cupy": np, "cudf": pd}):
313
362
  mod = importlib.reload(importlib.import_module(module_name))
314
363
  # Patch Collection and MultimodalPCSTPruning after reload
315
- with patch(f"{module_name}.Collection") as mock_collection, \
316
- patch(f"{module_name}.MultimodalPCSTPruning") as mock_pcst, \
317
- patch("pymilvus.connections") as mock_connections:
364
+ with (
365
+ patch(f"{module_name}.Collection") as mock_collection,
366
+ patch(f"{module_name}.MultimodalPCSTPruning") as mock_pcst,
367
+ patch("pymilvus.connections") as mock_connections,
368
+ ):
318
369
  # Setup mocks as in the original test
319
370
  mock_connections.has_connection.return_value = True
320
371
  colls = {}
321
372
  colls["nodes"] = MagicMock()
322
373
  colls["nodes"].query.return_value = [
323
- {"node_index": 0,
324
- "node_id": "id1",
325
- "node_name": "JAK1",
326
- "node_type": "gene/protein",
327
- "feat": "featA",
328
- "feat_emb": [0.1, 0.2, 0.3],
329
- "desc": "descA",
330
- "desc_emb": [0.1, 0.2, 0.3]},
331
- {"node_index": 1,
332
- "node_id": "id2",
333
- "node_name": "JAK2",
334
- "node_type": "gene/protein",
335
- "feat": "featB",
336
- "feat_emb": [0.4, 0.5, 0.6],
337
- "desc": "descB",
338
- "desc_emb": [0.4, 0.5, 0.6]}
374
+ {
375
+ "node_index": 0,
376
+ "node_id": "id1",
377
+ "node_name": "JAK1",
378
+ "node_type": "gene/protein",
379
+ "feat": "featA",
380
+ "feat_emb": [0.1, 0.2, 0.3],
381
+ "desc": "descA",
382
+ "desc_emb": [0.1, 0.2, 0.3],
383
+ },
384
+ {
385
+ "node_index": 1,
386
+ "node_id": "id2",
387
+ "node_name": "JAK2",
388
+ "node_type": "gene/protein",
389
+ "feat": "featB",
390
+ "feat_emb": [0.4, 0.5, 0.6],
391
+ "desc": "descB",
392
+ "desc_emb": [0.4, 0.5, 0.6],
393
+ },
339
394
  ]
340
395
  colls["nodes"].load.return_value = None
341
396
  colls["edges"] = MagicMock()
342
397
  colls["edges"].query.return_value = [
343
- {"triplet_index": 0,
344
- "head_id": "id1",
345
- "head_index": 0,
346
- "tail_id": "id2",
347
- "tail_index": 1,
348
- "edge_type": "gene/protein,ppi,gene/protein",
349
- "display_relation": "ppi",
350
- "feat": "featC",
351
- "feat_emb": [0.7, 0.8, 0.9]}
398
+ {
399
+ "triplet_index": 0,
400
+ "head_id": "id1",
401
+ "head_index": 0,
402
+ "tail_id": "id2",
403
+ "tail_index": 1,
404
+ "edge_type": "gene/protein,ppi,gene/protein",
405
+ "display_relation": "ppi",
406
+ "feat": "featC",
407
+ "feat_emb": [0.7, 0.8, 0.9],
408
+ }
352
409
  ]
353
410
  colls["edges"].load.return_value = None
411
+
354
412
  def collection_side_effect(name):
355
413
  if "nodes" in name:
356
414
  return colls["nodes"]
357
415
  if "edges" in name:
358
416
  return colls["edges"]
359
417
  return None
418
+
360
419
  mock_collection.side_effect = collection_side_effect
361
420
  mock_pcst_instance = MagicMock()
362
421
  mock_pcst_instance.extract_subgraph.return_value = {
363
422
  "nodes": pd.Series([1, 2]),
364
- "edges": pd.Series([0])
423
+ "edges": pd.Series([0]),
365
424
  }
366
425
  mock_pcst.return_value = mock_pcst_instance
367
426
  # Setup config mocks
368
- tool_cls = getattr(mod, "MultimodalSubgraphExtractionTool")
427
+ tool_cls = mod.MultimodalSubgraphExtractionTool
369
428
  tool = tool_cls()
370
429
 
371
430
  # Patch hydra.compose
372
- with patch(f"{module_name}.hydra.initialize"), \
373
- patch(f"{module_name}.hydra.compose") as mock_compose:
431
+ with (
432
+ patch(f"{module_name}.hydra.initialize"),
433
+ patch(f"{module_name}.hydra.compose") as mock_compose,
434
+ ):
374
435
  mock_compose.return_value = MagicMock()
375
436
  mock_compose.return_value.app.frontend = self.cfg_db
376
437
  mock_compose.return_value.tools.multimodal_subgraph_extraction = self.cfg
377
438
  self.state["embedding_model"].embed_query.return_value = [0.1, 0.2, 0.3]
378
439
  self.state["selections"] = {}
379
440
  response = tool.invoke(
380
- input={"prompt": self.prompt,
381
- "tool_call_id": "subgraph_extraction_tool",
382
- "state": self.state,
383
- "arg_data": self.arg_data}
441
+ input={
442
+ "prompt": self.prompt,
443
+ "tool_call_id": "subgraph_extraction_tool",
444
+ "state": self.state,
445
+ "arg_data": self.arg_data,
446
+ }
384
447
  )
385
448
  # Check tool message
386
- self.assertEqual(response.update["messages"][-1].tool_call_id,
387
- "subgraph_extraction_tool")
449
+ self.assertEqual(
450
+ response.update["messages"][-1].tool_call_id, "subgraph_extraction_tool"
451
+ )
388
452
  dic_extracted_graph = response.update["dic_extracted_graph"][0]
389
453
  self.assertIsInstance(dic_extracted_graph, dict)
390
454
  self.assertEqual(dic_extracted_graph["name"], self.arg_data["extraction_name"])
@@ -395,18 +459,25 @@ class TestMultimodalSubgraphExtractionTool(unittest.TestCase):
395
459
  self.assertGreater(len(dic_extracted_graph["graph_dict"]["nodes"]), 0)
396
460
  self.assertGreater(len(dic_extracted_graph["graph_dict"]["edges"]), 0)
397
461
  self.assertIsInstance(dic_extracted_graph["graph_text"], str)
398
- self.assertTrue(all(
399
- n[0] in dic_extracted_graph["graph_text"].replace('"', '')
400
- for subgraph_nodes in dic_extracted_graph["graph_dict"]["nodes"]
401
- for n in subgraph_nodes
402
- ))
403
- self.assertTrue(all(
404
- ",".join([str(e[0])] + str(e[2]['label'][0]).split(",") + [str(e[1])])
405
- in dic_extracted_graph["graph_text"].replace('"', '').\
406
- replace("[", "").replace("]", "").replace("'", "")
407
- for subgraph_edges in dic_extracted_graph["graph_dict"]["edges"]
408
- for e in subgraph_edges
409
- ))
462
+ self.assertTrue(
463
+ all(
464
+ n[0] in dic_extracted_graph["graph_text"].replace('"', "")
465
+ for subgraph_nodes in dic_extracted_graph["graph_dict"]["nodes"]
466
+ for n in subgraph_nodes
467
+ )
468
+ )
469
+ self.assertTrue(
470
+ all(
471
+ ",".join([str(e[0])] + str(e[2]["label"][0]).split(",") + [str(e[1])])
472
+ in dic_extracted_graph["graph_text"]
473
+ .replace('"', "")
474
+ .replace("[", "")
475
+ .replace("]", "")
476
+ .replace("'", "")
477
+ for subgraph_edges in dic_extracted_graph["graph_dict"]["edges"]
478
+ for e in subgraph_edges
479
+ )
480
+ )
410
481
 
411
482
  # Another test for unknown collection
412
483
  result = collection_side_effect("unknown")
@@ -439,15 +510,18 @@ class TestMultimodalSubgraphExtractionTool(unittest.TestCase):
439
510
  # In CPU mode, should return the input as-is
440
511
  self.assertEqual(result, [1.0, 2.0, 3.0])
441
512
 
442
- @patch("aiagents4pharma.talk2knowledgegraphs.tools."
443
- "milvus_multimodal_subgraph_extraction.Collection")
444
- @patch("aiagents4pharma.talk2knowledgegraphs.tools."
445
- "milvus_multimodal_subgraph_extraction.MultimodalPCSTPruning")
513
+ @patch(
514
+ "aiagents4pharma.talk2knowledgegraphs.tools."
515
+ "milvus_multimodal_subgraph_extraction.Collection"
516
+ )
517
+ @patch(
518
+ "aiagents4pharma.talk2knowledgegraphs.tools."
519
+ "milvus_multimodal_subgraph_extraction.MultimodalPCSTPruning"
520
+ )
446
521
  @patch("pymilvus.connections")
447
- def test_extract_multimodal_subgraph_no_vector_processing(self,
448
- mock_connections,
449
- mock_pcst,
450
- mock_collection):
522
+ def test_extract_multimodal_subgraph_no_vector_processing(
523
+ self, mock_connections, mock_pcst, mock_collection
524
+ ):
451
525
  """Test when vector_processing config is not present."""
452
526
  # Mock Milvus connection utilities
453
527
  mock_connections.has_connection.return_value = True
@@ -460,16 +534,27 @@ class TestMultimodalSubgraphExtractionTool(unittest.TestCase):
460
534
  colls = {}
461
535
  colls["nodes"] = MagicMock()
462
536
  colls["nodes"].query.return_value = [
463
- {"node_index": 0, "node_id": "id1", "node_name": "JAK1",
464
- "node_type": "gene/protein", "feat": "featA", "feat_emb": [0.1, 0.2, 0.3],
465
- "desc": "descA", "desc_emb": [0.1, 0.2, 0.3]}
537
+ {
538
+ "node_index": 0,
539
+ "node_id": "id1",
540
+ "node_name": "JAK1",
541
+ "node_type": "gene/protein",
542
+ "feat": "featA",
543
+ "feat_emb": [0.1, 0.2, 0.3],
544
+ "desc": "descA",
545
+ "desc_emb": [0.1, 0.2, 0.3],
546
+ }
466
547
  ]
467
548
  colls["nodes"].load.return_value = None
468
549
 
469
550
  colls["edges"] = MagicMock()
470
551
  colls["edges"].query.return_value = [
471
- {"triplet_index": 0, "head_id": "id1", "tail_id": "id2",
472
- "edge_type": "gene/protein,ppi,gene/protein"}
552
+ {
553
+ "triplet_index": 0,
554
+ "head_id": "id1",
555
+ "tail_id": "id2",
556
+ "edge_type": "gene/protein,ppi,gene/protein",
557
+ }
473
558
  ]
474
559
  colls["edges"].load.return_value = None
475
560
 
@@ -479,13 +564,14 @@ class TestMultimodalSubgraphExtractionTool(unittest.TestCase):
479
564
  if "edges" in name:
480
565
  return colls["edges"]
481
566
  return None
567
+
482
568
  mock_collection.side_effect = collection_side_effect
483
569
 
484
570
  # Mock MultimodalPCSTPruning
485
571
  mock_pcst_instance = MagicMock()
486
572
  mock_pcst_instance.extract_subgraph.return_value = {
487
573
  "nodes": pd.Series([1]),
488
- "edges": pd.Series([0])
574
+ "edges": pd.Series([0]),
489
575
  }
490
576
  mock_pcst.return_value = mock_pcst_instance
491
577
 
@@ -503,20 +589,29 @@ class TestMultimodalSubgraphExtractionTool(unittest.TestCase):
503
589
  del cfg_no_vector_processing.vector_processing
504
590
 
505
591
  # Patch hydra.compose to return config without vector_processing
506
- with patch("aiagents4pharma.talk2knowledgegraphs.tools."
507
- "milvus_multimodal_subgraph_extraction.hydra.initialize"), \
508
- patch("aiagents4pharma.talk2knowledgegraphs.tools."
509
- "milvus_multimodal_subgraph_extraction.hydra.compose") as mock_compose:
592
+ with (
593
+ patch(
594
+ "aiagents4pharma.talk2knowledgegraphs.tools."
595
+ "milvus_multimodal_subgraph_extraction.hydra.initialize"
596
+ ),
597
+ patch(
598
+ "aiagents4pharma.talk2knowledgegraphs.tools."
599
+ "milvus_multimodal_subgraph_extraction.hydra.compose"
600
+ ) as mock_compose,
601
+ ):
510
602
  mock_compose.return_value = MagicMock()
511
603
  mock_compose.return_value.app.frontend = self.cfg_db
512
- mock_compose.return_value.tools.multimodal_subgraph_extraction = \
604
+ mock_compose.return_value.tools.multimodal_subgraph_extraction = (
513
605
  cfg_no_vector_processing
606
+ )
514
607
 
515
608
  response = self.tool.invoke(
516
- input={"prompt": self.prompt,
517
- "tool_call_id": "subgraph_extraction_tool",
518
- "state": self.state,
519
- "arg_data": self.arg_data}
609
+ input={
610
+ "prompt": self.prompt,
611
+ "tool_call_id": "subgraph_extraction_tool",
612
+ "state": self.state,
613
+ "arg_data": self.arg_data,
614
+ }
520
615
  )
521
616
 
522
617
  # Verify the test completed successfully
@@ -530,15 +625,18 @@ class TestMultimodalSubgraphExtractionTool(unittest.TestCase):
530
625
  result = collection_side_effect("unknown_collection")
531
626
  self.assertIsNone(result)
532
627
 
533
- @patch("aiagents4pharma.talk2knowledgegraphs.tools."
534
- "milvus_multimodal_subgraph_extraction.Collection")
535
- @patch("aiagents4pharma.talk2knowledgegraphs.tools."
536
- "milvus_multimodal_subgraph_extraction.MultimodalPCSTPruning")
628
+ @patch(
629
+ "aiagents4pharma.talk2knowledgegraphs.tools."
630
+ "milvus_multimodal_subgraph_extraction.Collection"
631
+ )
632
+ @patch(
633
+ "aiagents4pharma.talk2knowledgegraphs.tools."
634
+ "milvus_multimodal_subgraph_extraction.MultimodalPCSTPruning"
635
+ )
537
636
  @patch("pymilvus.connections")
538
- def test_extract_multimodal_subgraph_dynamic_metrics_disabled(self,
539
- mock_connections,
540
- mock_pcst,
541
- mock_collection):
637
+ def test_extract_multimodal_subgraph_dynamic_metrics_disabled(
638
+ self, mock_connections, mock_pcst, mock_collection
639
+ ):
542
640
  """Test when dynamic_metrics is disabled."""
543
641
  # Mock Milvus connection utilities
544
642
  mock_connections.has_connection.return_value = True
@@ -551,16 +649,27 @@ class TestMultimodalSubgraphExtractionTool(unittest.TestCase):
551
649
  colls = {}
552
650
  colls["nodes"] = MagicMock()
553
651
  colls["nodes"].query.return_value = [
554
- {"node_index": 0, "node_id": "id1", "node_name": "JAK1",
555
- "node_type": "gene/protein", "feat": "featA", "feat_emb": [0.1, 0.2, 0.3],
556
- "desc": "descA", "desc_emb": [0.1, 0.2, 0.3]}
652
+ {
653
+ "node_index": 0,
654
+ "node_id": "id1",
655
+ "node_name": "JAK1",
656
+ "node_type": "gene/protein",
657
+ "feat": "featA",
658
+ "feat_emb": [0.1, 0.2, 0.3],
659
+ "desc": "descA",
660
+ "desc_emb": [0.1, 0.2, 0.3],
661
+ }
557
662
  ]
558
663
  colls["nodes"].load.return_value = None
559
664
 
560
665
  colls["edges"] = MagicMock()
561
666
  colls["edges"].query.return_value = [
562
- {"triplet_index": 0, "head_id": "id1", "tail_id": "id2",
563
- "edge_type": "gene/protein,ppi,gene/protein"}
667
+ {
668
+ "triplet_index": 0,
669
+ "head_id": "id1",
670
+ "tail_id": "id2",
671
+ "edge_type": "gene/protein,ppi,gene/protein",
672
+ }
564
673
  ]
565
674
  colls["edges"].load.return_value = None
566
675
 
@@ -570,13 +679,14 @@ class TestMultimodalSubgraphExtractionTool(unittest.TestCase):
570
679
  if "edges" in name:
571
680
  return colls["edges"]
572
681
  return None
682
+
573
683
  mock_collection.side_effect = collection_side_effect
574
684
 
575
685
  # Mock MultimodalPCSTPruning
576
686
  mock_pcst_instance = MagicMock()
577
687
  mock_pcst_instance.extract_subgraph.return_value = {
578
688
  "nodes": pd.Series([1]),
579
- "edges": pd.Series([0])
689
+ "edges": pd.Series([0]),
580
690
  }
581
691
  mock_pcst.return_value = mock_pcst_instance
582
692
 
@@ -595,19 +705,27 @@ class TestMultimodalSubgraphExtractionTool(unittest.TestCase):
595
705
  cfg_dynamic_disabled.vector_processing.dynamic_metrics = False
596
706
 
597
707
  # Patch hydra.compose to return config with dynamic_metrics disabled
598
- with patch("aiagents4pharma.talk2knowledgegraphs.tools."
599
- "milvus_multimodal_subgraph_extraction.hydra.initialize"), \
600
- patch("aiagents4pharma.talk2knowledgegraphs.tools."
601
- "milvus_multimodal_subgraph_extraction.hydra.compose") as mock_compose:
708
+ with (
709
+ patch(
710
+ "aiagents4pharma.talk2knowledgegraphs.tools."
711
+ "milvus_multimodal_subgraph_extraction.hydra.initialize"
712
+ ),
713
+ patch(
714
+ "aiagents4pharma.talk2knowledgegraphs.tools."
715
+ "milvus_multimodal_subgraph_extraction.hydra.compose"
716
+ ) as mock_compose,
717
+ ):
602
718
  mock_compose.return_value = MagicMock()
603
719
  mock_compose.return_value.app.frontend = self.cfg_db
604
720
  mock_compose.return_value.tools.multimodal_subgraph_extraction = cfg_dynamic_disabled
605
721
 
606
722
  response = self.tool.invoke(
607
- input={"prompt": self.prompt,
608
- "tool_call_id": "subgraph_extraction_tool",
609
- "state": self.state,
610
- "arg_data": self.arg_data}
723
+ input={
724
+ "prompt": self.prompt,
725
+ "tool_call_id": "subgraph_extraction_tool",
726
+ "state": self.state,
727
+ "arg_data": self.arg_data,
728
+ }
611
729
  )
612
730
 
613
731
  # Verify the test completed successfully