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,106 @@
1
+ """
2
+ Unit tests for Zotero read helper download branches.
3
+ """
4
+
5
+ import unittest
6
+ from types import SimpleNamespace
7
+ from unittest.mock import MagicMock, patch
8
+
9
+ from aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper import (
10
+ ZoteroSearchData,
11
+ )
12
+
13
+ # Dummy Hydra configuration for tests
14
+ dummy_zotero_read_config = SimpleNamespace(
15
+ user_id="dummy_user",
16
+ library_type="user",
17
+ api_key="dummy_api_key",
18
+ zotero=SimpleNamespace(
19
+ max_limit=5,
20
+ filter_item_types=["journalArticle", "conferencePaper"],
21
+ filter_excluded_types=["attachment", "note"],
22
+ ),
23
+ )
24
+ dummy_cfg = SimpleNamespace(tools=SimpleNamespace(zotero_read=dummy_zotero_read_config))
25
+
26
+
27
+ class TestReadHelperDownloadsFalse(unittest.TestCase):
28
+ """Tests for read_helper download_pdfs=False branches."""
29
+
30
+ @patch("aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections")
31
+ @patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.zotero.Zotero")
32
+ @patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.compose")
33
+ @patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.initialize")
34
+ def test_download_pdfs_false_branches(
35
+ self,
36
+ mock_hydra_init,
37
+ mock_hydra_compose,
38
+ mock_zotero_class,
39
+ mock_get_item_collections,
40
+ ):
41
+ """Ensure attachment_key and filename are set when download_pdfs=False."""
42
+ # Setup Hydra mocks
43
+ mock_hydra_compose.return_value = dummy_cfg
44
+ mock_hydra_init.return_value.__enter__.return_value = None
45
+
46
+ # Fake Zotero items: one paper with child PDF, one orphaned PDF
47
+ fake_zot = MagicMock()
48
+ fake_items = [
49
+ {
50
+ "data": {
51
+ "key": "paper1",
52
+ "title": "P1",
53
+ "abstractNote": "A1",
54
+ "date": "2021",
55
+ "url": "u1",
56
+ "itemType": "journalArticle",
57
+ }
58
+ },
59
+ {
60
+ "data": {
61
+ "key": "attach2",
62
+ "itemType": "attachment",
63
+ "contentType": "application/pdf",
64
+ "filename": "file2.pdf",
65
+ }
66
+ },
67
+ ]
68
+ fake_zot.items.return_value = fake_items
69
+ # children for paper1
70
+ fake_child = {
71
+ "data": {
72
+ "key": "attach1",
73
+ "filename": "file1.pdf",
74
+ "contentType": "application/pdf",
75
+ }
76
+ }
77
+
78
+ def children_side_effect(key):
79
+ return [fake_child] if key == "paper1" else []
80
+
81
+ fake_zot.children.side_effect = children_side_effect
82
+ mock_zotero_class.return_value = fake_zot
83
+ mock_get_item_collections.return_value = {"paper1": ["/C1"], "attach2": ["/C2"]}
84
+
85
+ # Instantiate with download_pdfs=False
86
+ search = ZoteroSearchData(
87
+ query="test",
88
+ only_articles=False,
89
+ limit=2,
90
+ tool_call_id="id",
91
+ download_pdfs=False,
92
+ )
93
+ search.process_search()
94
+ data = search.get_search_results()["article_data"]
95
+
96
+ # Regular paper1 should have attachment_key and filename, no pdf_url
97
+ self.assertIn("paper1", data)
98
+ self.assertEqual(data["paper1"]["attachment_key"], "attach1")
99
+ self.assertEqual(data["paper1"]["filename"], "file1.pdf")
100
+ self.assertNotIn("pdf_url", data["paper1"])
101
+
102
+ # Orphan attach2 should have attachment_key and filename, no pdf_url
103
+ self.assertIn("attach2", data)
104
+ self.assertEqual(data["attach2"]["attachment_key"], "attach2")
105
+ self.assertEqual(data["attach2"]["filename"], "file2.pdf")
106
+ self.assertNotIn("pdf_url", data["attach2"])
@@ -0,0 +1,403 @@
1
+ """
2
+ Unit tests for external ID handling in S2 helper modules.
3
+ """
4
+
5
+ from types import SimpleNamespace
6
+
7
+ import hydra
8
+ import pytest
9
+ import requests
10
+
11
+ from aiagents4pharma.talk2scholars.tools.s2.utils.multi_helper import MultiPaperRecData
12
+ from aiagents4pharma.talk2scholars.tools.s2.utils.search_helper import SearchData
13
+ from aiagents4pharma.talk2scholars.tools.s2.utils.single_helper import (
14
+ SinglePaperRecData,
15
+ )
16
+
17
+
18
+ @pytest.fixture(autouse=True)
19
+ def patch_hydra(monkeypatch):
20
+ """Patch Hydra's initialize and compose to provide dummy configs for tests."""
21
+
22
+ class DummyHydraContext:
23
+ """Dummy Hydra context manager to bypass config loading."""
24
+
25
+ def __enter__(self):
26
+ return None
27
+
28
+ def __exit__(self, exc_type, exc_val, traceback):
29
+ return False
30
+
31
+ # Dummy config with necessary fields for multi, search, and single helpers
32
+ dummy_cfg = SimpleNamespace(
33
+ tools=SimpleNamespace(
34
+ multi_paper_recommendation=SimpleNamespace(
35
+ api_endpoint="",
36
+ headers={},
37
+ api_fields=["paperId", "title", "authors", "externalIds"],
38
+ request_timeout=1,
39
+ ),
40
+ search=SimpleNamespace(
41
+ api_endpoint="",
42
+ api_fields=["paperId", "title", "authors", "externalIds"],
43
+ ),
44
+ single_paper_recommendation=SimpleNamespace(
45
+ api_endpoint="",
46
+ api_fields=["paperId", "title", "authors", "externalIds"],
47
+ request_timeout=1,
48
+ recommendation_params=SimpleNamespace(from_pool="test_pool"),
49
+ ),
50
+ )
51
+ )
52
+ monkeypatch.setattr(hydra, "initialize", lambda version_base, config_path: DummyHydraContext())
53
+ monkeypatch.setattr(hydra, "compose", lambda config_name, overrides: dummy_cfg)
54
+
55
+
56
+ def test_multi_helper_pmc_and_doi_ids(monkeypatch):
57
+ """Test PubMedCentral and DOI ID handling in MultiPaperRecData."""
58
+ rec = MultiPaperRecData(paper_ids=["p"], limit=1, year=None, tool_call_id="tid")
59
+ # Setup dummy API response
60
+ data = {
61
+ "recommendedPapers": [
62
+ {
63
+ "paperId": "p1",
64
+ "title": "Test",
65
+ "authors": [{"name": "A", "authorId": "A1"}],
66
+ "externalIds": {"PubMedCentral": "pmc1", "DOI": "doi1"},
67
+ }
68
+ ]
69
+ }
70
+ response = SimpleNamespace(status_code=200, json=lambda: data, raise_for_status=lambda: None)
71
+ monkeypatch.setattr(requests, "post", lambda *args, **kwargs: response)
72
+ results = rec.process_recommendations()
73
+ ids_list = results["papers"]["p1"]["paper_ids"]
74
+ assert ids_list == ["pmc:pmc1", "doi:doi1"]
75
+
76
+
77
+ def test_search_helper_pmc_and_doi_ids(monkeypatch):
78
+ """Test PubMedCentral and DOI ID handling in SearchData."""
79
+ sd = SearchData(query="q", limit=1, year=None, tool_call_id="tid")
80
+ data = {
81
+ "data": [
82
+ {
83
+ "paperId": "s1",
84
+ "title": "Test",
85
+ "authors": [{"name": "B", "authorId": "B1"}],
86
+ "externalIds": {"PubMedCentral": "pmc2", "DOI": "doi2"},
87
+ }
88
+ ]
89
+ }
90
+ response = SimpleNamespace(status_code=200, json=lambda: data, raise_for_status=lambda: None)
91
+ monkeypatch.setattr(requests, "get", lambda *args, **kwargs: response)
92
+ results = sd.process_search()
93
+ ids_list = results["papers"]["s1"]["paper_ids"]
94
+ assert ids_list == ["pmc:pmc2", "doi:doi2"]
95
+
96
+
97
+ def test_single_helper_pmc_and_doi_ids(monkeypatch):
98
+ """Test PubMedCentral and DOI ID handling in SinglePaperRecData."""
99
+ sp = SinglePaperRecData(paper_id="x", limit=1, year=None, tool_call_id="tid")
100
+ data = {
101
+ "recommendedPapers": [
102
+ {
103
+ "paperId": "x1",
104
+ "title": "Test",
105
+ "authors": [{"name": "C", "authorId": "C1"}],
106
+ "externalIds": {"PubMedCentral": "pmc3", "DOI": "doi3"},
107
+ }
108
+ ]
109
+ }
110
+ response = SimpleNamespace(status_code=200, json=lambda: data, raise_for_status=lambda: None)
111
+ monkeypatch.setattr(requests, "get", lambda *args, **kwargs: response)
112
+ results = sp.process_recommendations()
113
+ ids_list = results["papers"]["x1"]["paper_ids"]
114
+ assert ids_list == ["pmc:pmc3", "doi:doi3"]
115
+
116
+
117
+ def test_helpers_empty_when_no_external_ids(monkeypatch):
118
+ """Test that MultiPaperRecData, SearchData, and SinglePaperRecData
119
+ return empty lists when externalIds are missing or empty."""
120
+ # Test that no IDs are returned when externalIds is empty or missing
121
+ rec = MultiPaperRecData(paper_ids=["p"], limit=1, year=None, tool_call_id="tid")
122
+
123
+ # Simulate empty externalIds in API response
124
+ class DummyResp1:
125
+ """dummy response for multi-paper recommendation with empty externalIds"""
126
+
127
+ def __init__(self, data):
128
+ """initialize with data"""
129
+ self._data = data
130
+ self.status_code = 200
131
+
132
+ def json(self):
133
+ """json method to return data"""
134
+ return self._data
135
+
136
+ def raise_for_status(self):
137
+ """raise_for_status method to simulate successful response"""
138
+ return None
139
+
140
+ def dummy_post1(*_, **__):
141
+ """dummy response for multi-paper recommendation with empty externalIds"""
142
+ return DummyResp1(
143
+ {
144
+ "recommendedPapers": [
145
+ {
146
+ "paperId": "p2",
147
+ "title": "Test2",
148
+ "authors": [{"name": "D", "authorId": "D1"}],
149
+ "externalIds": {},
150
+ },
151
+ ]
152
+ }
153
+ )
154
+
155
+ monkeypatch.setattr(requests, "post", dummy_post1)
156
+ assert rec.process_recommendations()["papers"].get("p2", {}).get("paper_ids") == []
157
+ sd = SearchData(query="q2", limit=1, year=None, tool_call_id="tid2")
158
+
159
+ # Simulate empty externalIds in search API response
160
+ class DummyResp2:
161
+ """dummy response for search with empty externalIds"""
162
+
163
+ def __init__(self, data):
164
+ """initialize with data"""
165
+ self._data = data
166
+ self.status_code = 200
167
+
168
+ def json(self):
169
+ """json method to return data"""
170
+ return self._data
171
+
172
+ def raise_for_status(self):
173
+ """raise_for_status method to simulate successful response"""
174
+ return None
175
+
176
+ def dummy_get2(*_, **__):
177
+ """dummy response for search with empty externalIds"""
178
+ return DummyResp2(
179
+ {
180
+ "data": [
181
+ {
182
+ "paperId": "s2",
183
+ "title": "Test2",
184
+ "authors": [{"name": "E", "authorId": "E1"}],
185
+ "externalIds": {},
186
+ },
187
+ ]
188
+ }
189
+ )
190
+
191
+ monkeypatch.setattr(requests, "get", dummy_get2)
192
+ assert sd.process_search()["papers"].get("s2", {}).get("paper_ids") == []
193
+ sp = SinglePaperRecData(paper_id="y", limit=1, year=None, tool_call_id="tid3")
194
+
195
+ # Simulate empty externalIds in single-paper API response
196
+ class DummyResp3:
197
+ """dummy response for single paper recommendation with empty externalIds"""
198
+
199
+ def __init__(self, data):
200
+ """initialize with data"""
201
+ self._data = data
202
+ self.status_code = 200
203
+
204
+ def json(self):
205
+ """json method to return data"""
206
+ return self._data
207
+
208
+ def raise_for_status(self):
209
+ """raise_for_status method to simulate successful response"""
210
+ return None
211
+
212
+ def dummy_get3(*_, **__):
213
+ """dummy response for single paper recommendation with empty externalIds"""
214
+ return DummyResp3(
215
+ {
216
+ "recommendedPapers": [
217
+ {
218
+ "paperId": "y1",
219
+ "title": "Test3",
220
+ "authors": [{"name": "F", "authorId": "F1"}],
221
+ "externalIds": {},
222
+ },
223
+ ]
224
+ }
225
+ )
226
+
227
+ monkeypatch.setattr(requests, "get", dummy_get3)
228
+ assert sp.process_recommendations()["papers"].get("y1", {}).get("paper_ids") == []
229
+
230
+
231
+ def test_multi_helper_arxiv_and_pubmed_ids(monkeypatch):
232
+ """Test ArXiv and PubMed ID handling in MultiPaperRecData."""
233
+ rec = MultiPaperRecData(paper_ids=["p"], limit=1, year=None, tool_call_id="tid")
234
+
235
+ class DummyResp5:
236
+ """dummy response for multi-paper recommendation with ArXiv and PubMed IDs"""
237
+
238
+ def __init__(self, data):
239
+ """initialize with data"""
240
+ self._data = data
241
+ self.status_code = 200
242
+
243
+ def json(self):
244
+ """json method to return data"""
245
+ return self._data
246
+
247
+ def raise_for_status(self):
248
+ """raise_for_status method to simulate successful response"""
249
+ return None
250
+
251
+ def dummy_post5(*_, **__):
252
+ """dummy response for multi-paper recommendation with ArXiv and PubMed IDs"""
253
+ return DummyResp5(
254
+ {
255
+ "recommendedPapers": [
256
+ {
257
+ "paperId": "pX",
258
+ "title": "TestX",
259
+ "authors": [{"name": "A", "authorId": "A1"}],
260
+ "externalIds": {"ArXiv": "ax1", "PubMed": "pm1"},
261
+ },
262
+ ]
263
+ }
264
+ )
265
+
266
+ monkeypatch.setattr(requests, "post", dummy_post5)
267
+ ids_list = rec.process_recommendations()["papers"].get("pX", {}).get("paper_ids")
268
+ assert ids_list == ["arxiv:ax1", "pubmed:pm1"]
269
+
270
+
271
+ def test_search_helper_arxiv_and_pubmed_ids(monkeypatch):
272
+ """Test ArXiv and PubMed ID handling in SearchData."""
273
+ sd = SearchData(query="q", limit=1, year=None, tool_call_id="tid")
274
+
275
+ class DummyResp6:
276
+ """dummy response for search with ArXiv and PubMed IDs"""
277
+
278
+ def __init__(self, data):
279
+ """initialize with data"""
280
+ self._data = data
281
+ self.status_code = 200
282
+
283
+ def json(self):
284
+ """json method to return data"""
285
+ return self._data
286
+
287
+ def raise_for_status(self):
288
+ """ "raise_for_status method to simulate successful response"""
289
+ return None
290
+
291
+ def dummy_get6(*_, **__):
292
+ """dummy response for search with ArXiv and PubMed IDs"""
293
+ return DummyResp6(
294
+ {
295
+ "data": [
296
+ {
297
+ "paperId": "sX",
298
+ "title": "TestS",
299
+ "authors": [{"name": "B", "authorId": "B1"}],
300
+ "externalIds": {"ArXiv": "ax2", "PubMed": "pm2"},
301
+ },
302
+ ]
303
+ }
304
+ )
305
+
306
+ monkeypatch.setattr(requests, "get", dummy_get6)
307
+ ids_list = sd.process_search()["papers"].get("sX", {}).get("paper_ids")
308
+ assert ids_list == ["arxiv:ax2", "pubmed:pm2"]
309
+
310
+
311
+ def test_single_helper_arxiv_and_pubmed_ids(monkeypatch):
312
+ """Test ArXiv and PubMed ID handling in SinglePaperRecData."""
313
+ sp = SinglePaperRecData(paper_id="x", limit=1, year=None, tool_call_id="tid")
314
+
315
+ class DummyResp7:
316
+ """dummy response for single paper recommendation with ArXiv and PubMed IDs"""
317
+
318
+ def __init__(self, data):
319
+ """initialize with data"""
320
+ self._data = data
321
+ self.status_code = 200
322
+
323
+ def json(self):
324
+ """json method to return data"""
325
+ return self._data
326
+
327
+ def raise_for_status(self):
328
+ """raise_for_status method to simulate successful response"""
329
+ return None
330
+
331
+ def dummy_get7(*_, **__):
332
+ """dummy response for single paper recommendation with ArXiv and PubMed IDs"""
333
+ return DummyResp7(
334
+ {
335
+ "recommendedPapers": [
336
+ {
337
+ "paperId": "xY",
338
+ "title": "TestY",
339
+ "authors": [{"name": "C", "authorId": "C1"}],
340
+ "externalIds": {"ArXiv": "ax3", "PubMed": "pm3"},
341
+ },
342
+ ]
343
+ }
344
+ )
345
+
346
+ monkeypatch.setattr(requests, "get", dummy_get7)
347
+ ids_list = sp.process_recommendations()["papers"].get("xY", {}).get("paper_ids")
348
+ assert ids_list == ["arxiv:ax3", "pubmed:pm3"]
349
+
350
+
351
+ def test_search_helper_create_content_snippet(monkeypatch):
352
+ """Test that SearchData._create_content includes snippets appropriately."""
353
+ sd = SearchData(query="QueryX", limit=3, year="2022", tool_call_id="tid")
354
+ sd.filtered_papers = {
355
+ "p1": {"Title": "Title1", "Year": "2021", "Abstract": "First. Second. Third."},
356
+ "p2": {"Title": "Title2", "Year": "2020", "Abstract": ""},
357
+ }
358
+ # Stub out network fetch/filter to rely on preset filtered_papers
359
+ monkeypatch.setattr(SearchData, "_fetch_papers", lambda self: None)
360
+ monkeypatch.setattr(SearchData, "_filter_papers", lambda self: None)
361
+ results = sd.process_search()
362
+ content = results["content"]
363
+ assert "1. Title1 (2021)" in content
364
+ assert "Abstract snippet: First. Second." in content
365
+ assert "2. Title2 (2020)" in content
366
+ # Only one snippet present
367
+ assert content.count("Abstract snippet:") == 1
368
+
369
+
370
+ def test_single_helper_create_content_snippet(monkeypatch):
371
+ """Test that SinglePaperRecData._create_content includes snippets appropriately."""
372
+ sp = SinglePaperRecData(paper_id="pid", limit=2, year=None, tool_call_id="tid")
373
+ sp.filtered_papers = {
374
+ "x1": {"Title": "STitle1", "Year": "2019", "Abstract": "SOne. STwo. SThree."},
375
+ "x2": {"Title": "STitle2", "Year": "2018", "Abstract": ""},
376
+ }
377
+ # Stub out network fetch/filter to rely on preset filtered_papers
378
+ monkeypatch.setattr(SinglePaperRecData, "_fetch_recommendations", lambda self: None)
379
+ monkeypatch.setattr(SinglePaperRecData, "_filter_papers", lambda self: None)
380
+ results = sp.process_recommendations()
381
+ content = results["content"]
382
+ assert "1. STitle1 (2019)" in content
383
+ assert "Abstract snippet: SOne. STwo." in content
384
+ assert "2. STitle2 (2018)" in content
385
+ assert content.count("Abstract snippet:") == 1
386
+
387
+
388
+ def test_multi_helper_create_content_snippet(monkeypatch):
389
+ """Test that MultiPaperRecData._create_content includes snippets appropriately."""
390
+ mr = MultiPaperRecData(paper_ids=["a", "b"], limit=2, year="2021", tool_call_id="tid")
391
+ mr.filtered_papers = {
392
+ "m1": {"Title": "MTitle1", "Year": "2017", "Abstract": "MOne. MTwo. MThree."},
393
+ "m2": {"Title": "MTitle2", "Year": "2016", "Abstract": ""},
394
+ }
395
+ # Stub out network fetch/filter to rely on preset filtered_papers
396
+ monkeypatch.setattr(MultiPaperRecData, "_fetch_recommendations", lambda self: None)
397
+ monkeypatch.setattr(MultiPaperRecData, "_filter_papers", lambda self: None)
398
+ results = mr.process_recommendations()
399
+ content = results["content"]
400
+ assert "1. MTitle1 (2017)" in content
401
+ assert "Abstract snippet: MOne. MTwo." in content
402
+ assert "2. MTitle2 (2016)" in content
403
+ assert content.count("Abstract snippet:") == 1
@@ -0,0 +1,85 @@
1
+ """
2
+ Unit tests for QAToolHelper routines in tool_helper.py
3
+ """
4
+
5
+ import unittest
6
+ from types import SimpleNamespace
7
+ from unittest.mock import MagicMock, patch
8
+
9
+ from aiagents4pharma.talk2scholars.tools.pdf.utils.tool_helper import QAToolHelper
10
+
11
+
12
+ class TestQAToolHelper(unittest.TestCase):
13
+ """tests for QAToolHelper routines"""
14
+
15
+ def setUp(self):
16
+ """setup for each test"""
17
+ self.helper = QAToolHelper()
18
+
19
+ def test_start_call_sets_config_and_call_id(self):
20
+ """start_call should set config and call_id"""
21
+ cfg = SimpleNamespace(foo="bar")
22
+ self.helper.start_call(cfg, "call123")
23
+ self.assertIs(self.helper.config, cfg)
24
+ self.assertEqual(self.helper.call_id, "call123")
25
+
26
+ @patch("aiagents4pharma.talk2scholars.tools.pdf.utils.tool_helper.get_vectorstore")
27
+ def test_init_vector_store_reuse(self, mock_get_vectorstore):
28
+ """Mock vector store reuse test"""
29
+ emb_model = MagicMock()
30
+ mock_instance = MagicMock()
31
+ mock_get_vectorstore.return_value = mock_instance
32
+
33
+ first = self.helper.init_vector_store(emb_model)
34
+ second = self.helper.init_vector_store(emb_model)
35
+
36
+ self.assertIs(first, second)
37
+ self.assertIs(second, mock_instance)
38
+
39
+ def test_get_state_models_and_data_success(self):
40
+ """get_state_models_and_data should return models and data from state"""
41
+ emb = MagicMock()
42
+ llm = MagicMock()
43
+ articles = {"p": {}}
44
+ state = {
45
+ "text_embedding_model": emb,
46
+ "llm_model": llm,
47
+ "article_data": articles,
48
+ }
49
+ ret_emb, ret_llm, ret_articles = self.helper.get_state_models_and_data(state)
50
+ self.assertIs(ret_emb, emb)
51
+ self.assertIs(ret_llm, llm)
52
+ self.assertIs(ret_articles, articles)
53
+
54
+ def test_get_state_models_and_data_missing_text_embedding(self):
55
+ """get_state_models_and_data should raise ValueError if text_embedding_model is missing"""
56
+ state = {"llm_model": MagicMock(), "article_data": {"p": {}}}
57
+ with self.assertRaises(ValueError):
58
+ self.helper.get_state_models_and_data(state)
59
+
60
+ def test_get_state_models_and_data_missing_llm(self):
61
+ """should raise ValueError if llm_model is missing"""
62
+ state = {"text_embedding_model": MagicMock(), "article_data": {"p": {}}}
63
+ with self.assertRaises(ValueError):
64
+ self.helper.get_state_models_and_data(state)
65
+
66
+ def test_get_state_models_and_data_missing_article_data(self):
67
+ """get_state_models_and_data should raise ValueError if article_data is missing"""
68
+ state = {"text_embedding_model": MagicMock(), "llm_model": MagicMock()}
69
+ with self.assertRaises(ValueError):
70
+ self.helper.get_state_models_and_data(state)
71
+
72
+ def test_get_hardware_stats(self):
73
+ """get_hardware_stats should return correct GPU and hardware mode"""
74
+ helper = QAToolHelper()
75
+ helper.call_id = "test_call"
76
+
77
+ helper.has_gpu = False
78
+ stats = helper.get_hardware_stats()
79
+ self.assertEqual(stats["gpu_available"], False)
80
+ self.assertEqual(stats["hardware_mode"], "CPU-only")
81
+
82
+ helper.has_gpu = True
83
+ stats = helper.get_hardware_stats()
84
+ self.assertEqual(stats["gpu_available"], True)
85
+ self.assertEqual(stats["hardware_mode"], "GPU-accelerated")