aiagents4pharma 1.43.0__py3-none-any.whl → 1.45.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 (290) 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/multimodal_subgraph_extraction/default.yaml +17 -2
  106. aiagents4pharma/talk2knowledgegraphs/configs/tools/subgraph_extraction/__init__.py +2 -2
  107. aiagents4pharma/talk2knowledgegraphs/configs/tools/subgraph_extraction/default.yaml +1 -1
  108. aiagents4pharma/talk2knowledgegraphs/configs/tools/subgraph_summarization/__init__.py +2 -2
  109. aiagents4pharma/talk2knowledgegraphs/configs/tools/subgraph_summarization/default.yaml +1 -1
  110. aiagents4pharma/talk2knowledgegraphs/configs/utils/enrichments/ols_terms/default.yaml +1 -1
  111. aiagents4pharma/talk2knowledgegraphs/configs/utils/enrichments/reactome_pathways/default.yaml +1 -1
  112. aiagents4pharma/talk2knowledgegraphs/configs/utils/enrichments/uniprot_proteins/default.yaml +1 -1
  113. aiagents4pharma/talk2knowledgegraphs/configs/utils/pubchem_utils/default.yaml +1 -1
  114. aiagents4pharma/talk2knowledgegraphs/datasets/__init__.py +4 -6
  115. aiagents4pharma/talk2knowledgegraphs/datasets/biobridge_primekg.py +115 -67
  116. aiagents4pharma/talk2knowledgegraphs/datasets/dataset.py +2 -0
  117. aiagents4pharma/talk2knowledgegraphs/datasets/primekg.py +35 -24
  118. aiagents4pharma/talk2knowledgegraphs/datasets/starkqa_primekg.py +29 -21
  119. aiagents4pharma/talk2knowledgegraphs/docker-compose/cpu/.env.example +23 -0
  120. aiagents4pharma/talk2knowledgegraphs/docker-compose/cpu/docker-compose.yml +93 -0
  121. aiagents4pharma/talk2knowledgegraphs/docker-compose/gpu/.env.example +23 -0
  122. aiagents4pharma/talk2knowledgegraphs/docker-compose/gpu/docker-compose.yml +108 -0
  123. aiagents4pharma/talk2knowledgegraphs/entrypoint.sh +190 -0
  124. aiagents4pharma/talk2knowledgegraphs/install.md +140 -0
  125. aiagents4pharma/talk2knowledgegraphs/milvus_data_dump.py +31 -65
  126. aiagents4pharma/talk2knowledgegraphs/states/__init__.py +3 -2
  127. aiagents4pharma/talk2knowledgegraphs/states/state_talk2knowledgegraphs.py +1 -0
  128. aiagents4pharma/talk2knowledgegraphs/tests/test_agents_t2kg_agent.py +65 -40
  129. aiagents4pharma/talk2knowledgegraphs/tests/test_datasets_biobridge_primekg.py +54 -48
  130. aiagents4pharma/talk2knowledgegraphs/tests/test_datasets_dataset.py +4 -0
  131. aiagents4pharma/talk2knowledgegraphs/tests/test_datasets_primekg.py +17 -4
  132. aiagents4pharma/talk2knowledgegraphs/tests/test_datasets_starkqa_primekg.py +33 -24
  133. aiagents4pharma/talk2knowledgegraphs/tests/test_tools_graphrag_reasoning.py +116 -69
  134. aiagents4pharma/talk2knowledgegraphs/tests/test_tools_milvus_multimodal_subgraph_extraction.py +736 -413
  135. aiagents4pharma/talk2knowledgegraphs/tests/test_tools_multimodal_subgraph_extraction.py +22 -15
  136. aiagents4pharma/talk2knowledgegraphs/tests/test_tools_subgraph_extraction.py +19 -12
  137. aiagents4pharma/talk2knowledgegraphs/tests/test_tools_subgraph_summarization.py +95 -48
  138. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_embeddings_embeddings.py +4 -0
  139. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_embeddings_huggingface.py +5 -0
  140. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_embeddings_nim_molmim.py +13 -18
  141. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_embeddings_ollama.py +10 -3
  142. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_enrichments_enrichments.py +4 -3
  143. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_enrichments_ollama.py +3 -2
  144. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_enrichments_ols.py +1 -0
  145. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_enrichments_pubchem.py +9 -4
  146. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_enrichments_reactome.py +6 -6
  147. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_enrichments_uniprot.py +4 -0
  148. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_extractions_milvus_multimodal_pcst.py +442 -42
  149. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_kg_utils.py +3 -4
  150. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_pubchem_utils.py +10 -6
  151. aiagents4pharma/talk2knowledgegraphs/tools/__init__.py +10 -7
  152. aiagents4pharma/talk2knowledgegraphs/tools/graphrag_reasoning.py +15 -20
  153. aiagents4pharma/talk2knowledgegraphs/tools/milvus_multimodal_subgraph_extraction.py +245 -205
  154. aiagents4pharma/talk2knowledgegraphs/tools/multimodal_subgraph_extraction.py +92 -90
  155. aiagents4pharma/talk2knowledgegraphs/tools/subgraph_extraction.py +25 -37
  156. aiagents4pharma/talk2knowledgegraphs/tools/subgraph_summarization.py +10 -13
  157. aiagents4pharma/talk2knowledgegraphs/utils/__init__.py +4 -7
  158. aiagents4pharma/talk2knowledgegraphs/utils/embeddings/__init__.py +4 -7
  159. aiagents4pharma/talk2knowledgegraphs/utils/embeddings/embeddings.py +4 -0
  160. aiagents4pharma/talk2knowledgegraphs/utils/embeddings/huggingface.py +11 -14
  161. aiagents4pharma/talk2knowledgegraphs/utils/embeddings/nim_molmim.py +7 -7
  162. aiagents4pharma/talk2knowledgegraphs/utils/embeddings/ollama.py +12 -6
  163. aiagents4pharma/talk2knowledgegraphs/utils/embeddings/sentence_transformer.py +8 -6
  164. aiagents4pharma/talk2knowledgegraphs/utils/enrichments/__init__.py +9 -6
  165. aiagents4pharma/talk2knowledgegraphs/utils/enrichments/enrichments.py +1 -0
  166. aiagents4pharma/talk2knowledgegraphs/utils/enrichments/ollama.py +15 -9
  167. aiagents4pharma/talk2knowledgegraphs/utils/enrichments/ols_terms.py +23 -20
  168. aiagents4pharma/talk2knowledgegraphs/utils/enrichments/pubchem_strings.py +12 -10
  169. aiagents4pharma/talk2knowledgegraphs/utils/enrichments/reactome_pathways.py +16 -10
  170. aiagents4pharma/talk2knowledgegraphs/utils/enrichments/uniprot_proteins.py +26 -18
  171. aiagents4pharma/talk2knowledgegraphs/utils/extractions/__init__.py +4 -5
  172. aiagents4pharma/talk2knowledgegraphs/utils/extractions/milvus_multimodal_pcst.py +218 -81
  173. aiagents4pharma/talk2knowledgegraphs/utils/extractions/multimodal_pcst.py +53 -47
  174. aiagents4pharma/talk2knowledgegraphs/utils/extractions/pcst.py +18 -14
  175. aiagents4pharma/talk2knowledgegraphs/utils/kg_utils.py +22 -23
  176. aiagents4pharma/talk2knowledgegraphs/utils/pubchem_utils.py +11 -10
  177. aiagents4pharma/talk2scholars/.dockerignore +13 -0
  178. aiagents4pharma/talk2scholars/Dockerfile +104 -0
  179. aiagents4pharma/talk2scholars/README.md +1 -0
  180. aiagents4pharma/talk2scholars/agents/__init__.py +1 -5
  181. aiagents4pharma/talk2scholars/agents/main_agent.py +6 -4
  182. aiagents4pharma/talk2scholars/agents/paper_download_agent.py +5 -4
  183. aiagents4pharma/talk2scholars/agents/pdf_agent.py +4 -2
  184. aiagents4pharma/talk2scholars/agents/s2_agent.py +2 -2
  185. aiagents4pharma/talk2scholars/agents/zotero_agent.py +10 -11
  186. aiagents4pharma/talk2scholars/configs/__init__.py +1 -3
  187. aiagents4pharma/talk2scholars/configs/agents/talk2scholars/__init__.py +1 -4
  188. aiagents4pharma/talk2scholars/configs/agents/talk2scholars/main_agent/default.yaml +1 -1
  189. aiagents4pharma/talk2scholars/configs/agents/talk2scholars/pdf_agent/default.yaml +1 -1
  190. aiagents4pharma/talk2scholars/configs/agents/talk2scholars/s2_agent/default.yaml +8 -8
  191. aiagents4pharma/talk2scholars/configs/agents/talk2scholars/zotero_agent/default.yaml +7 -7
  192. aiagents4pharma/talk2scholars/configs/tools/__init__.py +8 -6
  193. aiagents4pharma/talk2scholars/docker-compose/cpu/.env.example +21 -0
  194. aiagents4pharma/talk2scholars/docker-compose/cpu/docker-compose.yml +90 -0
  195. aiagents4pharma/talk2scholars/docker-compose/gpu/.env.example +21 -0
  196. aiagents4pharma/talk2scholars/docker-compose/gpu/docker-compose.yml +105 -0
  197. aiagents4pharma/talk2scholars/install.md +122 -0
  198. aiagents4pharma/talk2scholars/state/state_talk2scholars.py +8 -8
  199. aiagents4pharma/talk2scholars/tests/{test_main_agent.py → test_agents_main_agent.py} +41 -23
  200. aiagents4pharma/talk2scholars/tests/{test_paper_download_agent.py → test_agents_paper_agents_download_agent.py} +10 -16
  201. aiagents4pharma/talk2scholars/tests/{test_pdf_agent.py → test_agents_pdf_agent.py} +6 -10
  202. aiagents4pharma/talk2scholars/tests/{test_s2_agent.py → test_agents_s2_agent.py} +8 -16
  203. aiagents4pharma/talk2scholars/tests/{test_zotero_agent.py → test_agents_zotero_agent.py} +5 -7
  204. aiagents4pharma/talk2scholars/tests/{test_s2_display_dataframe.py → test_s2_tools_display_dataframe.py} +6 -7
  205. aiagents4pharma/talk2scholars/tests/{test_s2_query_dataframe.py → test_s2_tools_query_dataframe.py} +5 -15
  206. aiagents4pharma/talk2scholars/tests/{test_paper_downloader.py → test_tools_paper_downloader.py} +25 -63
  207. aiagents4pharma/talk2scholars/tests/{test_question_and_answer_tool.py → test_tools_question_and_answer_tool.py} +2 -6
  208. aiagents4pharma/talk2scholars/tests/{test_s2_multi.py → test_tools_s2_multi.py} +5 -5
  209. aiagents4pharma/talk2scholars/tests/{test_s2_retrieve.py → test_tools_s2_retrieve.py} +2 -1
  210. aiagents4pharma/talk2scholars/tests/{test_s2_search.py → test_tools_s2_search.py} +5 -5
  211. aiagents4pharma/talk2scholars/tests/{test_s2_single.py → test_tools_s2_single.py} +5 -5
  212. aiagents4pharma/talk2scholars/tests/{test_arxiv_downloader.py → test_utils_arxiv_downloader.py} +16 -25
  213. aiagents4pharma/talk2scholars/tests/{test_base_paper_downloader.py → test_utils_base_paper_downloader.py} +25 -47
  214. aiagents4pharma/talk2scholars/tests/{test_biorxiv_downloader.py → test_utils_biorxiv_downloader.py} +14 -42
  215. aiagents4pharma/talk2scholars/tests/{test_medrxiv_downloader.py → test_utils_medrxiv_downloader.py} +15 -49
  216. aiagents4pharma/talk2scholars/tests/{test_nvidia_nim_reranker.py → test_utils_nvidia_nim_reranker.py} +6 -16
  217. aiagents4pharma/talk2scholars/tests/{test_pdf_answer_formatter.py → test_utils_pdf_answer_formatter.py} +1 -0
  218. aiagents4pharma/talk2scholars/tests/{test_pdf_batch_processor.py → test_utils_pdf_batch_processor.py} +6 -15
  219. aiagents4pharma/talk2scholars/tests/{test_pdf_collection_manager.py → test_utils_pdf_collection_manager.py} +34 -11
  220. aiagents4pharma/talk2scholars/tests/{test_pdf_document_processor.py → test_utils_pdf_document_processor.py} +2 -3
  221. aiagents4pharma/talk2scholars/tests/{test_pdf_generate_answer.py → test_utils_pdf_generate_answer.py} +3 -6
  222. aiagents4pharma/talk2scholars/tests/{test_pdf_gpu_detection.py → test_utils_pdf_gpu_detection.py} +5 -16
  223. aiagents4pharma/talk2scholars/tests/{test_pdf_rag_pipeline.py → test_utils_pdf_rag_pipeline.py} +7 -17
  224. aiagents4pharma/talk2scholars/tests/{test_pdf_retrieve_chunks.py → test_utils_pdf_retrieve_chunks.py} +4 -11
  225. aiagents4pharma/talk2scholars/tests/{test_pdf_singleton_manager.py → test_utils_pdf_singleton_manager.py} +26 -23
  226. aiagents4pharma/talk2scholars/tests/{test_pdf_vector_normalization.py → test_utils_pdf_vector_normalization.py} +1 -1
  227. aiagents4pharma/talk2scholars/tests/{test_pdf_vector_store.py → test_utils_pdf_vector_store.py} +27 -55
  228. aiagents4pharma/talk2scholars/tests/{test_pubmed_downloader.py → test_utils_pubmed_downloader.py} +31 -91
  229. aiagents4pharma/talk2scholars/tests/{test_read_helper_utils.py → test_utils_read_helper_utils.py} +2 -6
  230. aiagents4pharma/talk2scholars/tests/{test_s2_utils_ext_ids.py → test_utils_s2_utils_ext_ids.py} +5 -15
  231. aiagents4pharma/talk2scholars/tests/{test_zotero_human_in_the_loop.py → test_utils_zotero_human_in_the_loop.py} +6 -13
  232. aiagents4pharma/talk2scholars/tests/{test_zotero_path.py → test_utils_zotero_path.py} +53 -45
  233. aiagents4pharma/talk2scholars/tests/{test_zotero_read.py → test_utils_zotero_read.py} +30 -91
  234. aiagents4pharma/talk2scholars/tests/{test_zotero_write.py → test_utils_zotero_write.py} +6 -16
  235. aiagents4pharma/talk2scholars/tools/__init__.py +1 -4
  236. aiagents4pharma/talk2scholars/tools/paper_download/paper_downloader.py +20 -35
  237. aiagents4pharma/talk2scholars/tools/paper_download/utils/__init__.py +7 -5
  238. aiagents4pharma/talk2scholars/tools/paper_download/utils/arxiv_downloader.py +9 -11
  239. aiagents4pharma/talk2scholars/tools/paper_download/utils/base_paper_downloader.py +14 -21
  240. aiagents4pharma/talk2scholars/tools/paper_download/utils/biorxiv_downloader.py +14 -22
  241. aiagents4pharma/talk2scholars/tools/paper_download/utils/medrxiv_downloader.py +11 -13
  242. aiagents4pharma/talk2scholars/tools/paper_download/utils/pubmed_downloader.py +14 -28
  243. aiagents4pharma/talk2scholars/tools/pdf/question_and_answer.py +4 -8
  244. aiagents4pharma/talk2scholars/tools/pdf/utils/__init__.py +16 -14
  245. aiagents4pharma/talk2scholars/tools/pdf/utils/answer_formatter.py +4 -4
  246. aiagents4pharma/talk2scholars/tools/pdf/utils/batch_processor.py +15 -17
  247. aiagents4pharma/talk2scholars/tools/pdf/utils/collection_manager.py +2 -2
  248. aiagents4pharma/talk2scholars/tools/pdf/utils/document_processor.py +5 -5
  249. aiagents4pharma/talk2scholars/tools/pdf/utils/generate_answer.py +4 -4
  250. aiagents4pharma/talk2scholars/tools/pdf/utils/get_vectorstore.py +2 -6
  251. aiagents4pharma/talk2scholars/tools/pdf/utils/gpu_detection.py +5 -9
  252. aiagents4pharma/talk2scholars/tools/pdf/utils/nvidia_nim_reranker.py +4 -4
  253. aiagents4pharma/talk2scholars/tools/pdf/utils/paper_loader.py +2 -2
  254. aiagents4pharma/talk2scholars/tools/pdf/utils/rag_pipeline.py +6 -15
  255. aiagents4pharma/talk2scholars/tools/pdf/utils/retrieve_chunks.py +7 -15
  256. aiagents4pharma/talk2scholars/tools/pdf/utils/singleton_manager.py +2 -2
  257. aiagents4pharma/talk2scholars/tools/pdf/utils/tool_helper.py +3 -4
  258. aiagents4pharma/talk2scholars/tools/pdf/utils/vector_normalization.py +8 -17
  259. aiagents4pharma/talk2scholars/tools/pdf/utils/vector_store.py +17 -33
  260. aiagents4pharma/talk2scholars/tools/s2/__init__.py +8 -6
  261. aiagents4pharma/talk2scholars/tools/s2/display_dataframe.py +3 -7
  262. aiagents4pharma/talk2scholars/tools/s2/multi_paper_rec.py +7 -6
  263. aiagents4pharma/talk2scholars/tools/s2/query_dataframe.py +5 -12
  264. aiagents4pharma/talk2scholars/tools/s2/retrieve_semantic_scholar_paper_id.py +2 -4
  265. aiagents4pharma/talk2scholars/tools/s2/search.py +6 -6
  266. aiagents4pharma/talk2scholars/tools/s2/single_paper_rec.py +5 -3
  267. aiagents4pharma/talk2scholars/tools/s2/utils/__init__.py +1 -3
  268. aiagents4pharma/talk2scholars/tools/s2/utils/multi_helper.py +12 -18
  269. aiagents4pharma/talk2scholars/tools/s2/utils/search_helper.py +11 -18
  270. aiagents4pharma/talk2scholars/tools/s2/utils/single_helper.py +11 -16
  271. aiagents4pharma/talk2scholars/tools/zotero/__init__.py +1 -4
  272. aiagents4pharma/talk2scholars/tools/zotero/utils/__init__.py +1 -4
  273. aiagents4pharma/talk2scholars/tools/zotero/utils/read_helper.py +21 -39
  274. aiagents4pharma/talk2scholars/tools/zotero/utils/review_helper.py +2 -6
  275. aiagents4pharma/talk2scholars/tools/zotero/utils/write_helper.py +8 -11
  276. aiagents4pharma/talk2scholars/tools/zotero/utils/zotero_path.py +4 -12
  277. aiagents4pharma/talk2scholars/tools/zotero/utils/zotero_pdf_downloader.py +13 -27
  278. aiagents4pharma/talk2scholars/tools/zotero/zotero_read.py +4 -7
  279. aiagents4pharma/talk2scholars/tools/zotero/zotero_review.py +8 -10
  280. aiagents4pharma/talk2scholars/tools/zotero/zotero_write.py +3 -2
  281. {aiagents4pharma-1.43.0.dist-info → aiagents4pharma-1.45.0.dist-info}/METADATA +115 -50
  282. aiagents4pharma-1.45.0.dist-info/RECORD +324 -0
  283. {aiagents4pharma-1.43.0.dist-info → aiagents4pharma-1.45.0.dist-info}/WHEEL +1 -2
  284. aiagents4pharma-1.43.0.dist-info/RECORD +0 -293
  285. aiagents4pharma-1.43.0.dist-info/top_level.txt +0 -1
  286. /aiagents4pharma/talk2scholars/tests/{test_state.py → test_states_state.py} +0 -0
  287. /aiagents4pharma/talk2scholars/tests/{test_pdf_paper_loader.py → test_utils_pdf_paper_loader.py} +0 -0
  288. /aiagents4pharma/talk2scholars/tests/{test_tool_helper_utils.py → test_utils_tool_helper_utils.py} +0 -0
  289. /aiagents4pharma/talk2scholars/tests/{test_zotero_pdf_downloader_utils.py → test_utils_zotero_pdf_downloader_utils.py} +0 -0
  290. {aiagents4pharma-1.43.0.dist-info → aiagents4pharma-1.45.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,12 +1,12 @@
1
1
  """collection_manager for managing Milvus collections for PDF chunks."""
2
2
 
3
- from unittest.mock import MagicMock, patch
4
3
  from dataclasses import dataclass, field
4
+ from unittest.mock import MagicMock, patch
5
+
5
6
  import pytest
6
7
 
7
8
  from aiagents4pharma.talk2scholars.tools.pdf.utils import collection_manager
8
9
 
9
-
10
10
  # -- Fixtures --
11
11
 
12
12
 
@@ -39,13 +39,20 @@ def index_params():
39
39
 
40
40
 
41
41
  def set_collection_cache(key, value):
42
- """Set a mocked collection into the cache."""
43
- getattr(collection_manager, "_collection_cache")[key] = value
42
+ """Set a mocked collection into the cache without replacing the whole attribute."""
43
+ cache = getattr(collection_manager, "_collection_cache", None)
44
+ if cache is None:
45
+ cache = {}
46
+ # Still need to attach it once if it doesn't exist
47
+ object.__setattr__(collection_manager, "_collection_cache", cache)
48
+ cache[key] = value
44
49
 
45
50
 
46
51
  def clear_collection_cache(key):
47
52
  """Remove a mocked collection from the cache."""
48
- getattr(collection_manager, "_collection_cache").pop(key, None)
53
+ cache = getattr(collection_manager, "_collection_cache", None)
54
+ if cache is not None:
55
+ cache.pop(key, None)
49
56
 
50
57
 
51
58
  # -- Tests --
@@ -124,9 +131,7 @@ def test_debug_collection_state_failure(mock_utility, mock_collection_cls, reque
124
131
  mock_collection.indexes = []
125
132
  mock_collection.num_entities = 10
126
133
 
127
- mock_collection.schema = property(
128
- lambda _: (_ for _ in ()).throw(Exception("bad schema"))
129
- )
134
+ mock_collection.schema = property(lambda _: (_ for _ in ()).throw(Exception("bad schema")))
130
135
 
131
136
  result = collection_manager.ensure_collection_exists(
132
137
  "bad_collection", config, index, has_gpu=True
@@ -145,6 +150,24 @@ def test_ensure_collection_exception(mock_utility, mock_collection_cls, request)
145
150
  mock_collection_cls.return_value = MagicMock()
146
151
 
147
152
  with pytest.raises(RuntimeError, match="milvus failure"):
148
- collection_manager.ensure_collection_exists(
149
- "fail_collection", config, index, has_gpu=False
150
- )
153
+ collection_manager.ensure_collection_exists("fail_collection", config, index, has_gpu=False)
154
+
155
+
156
+ def test_set_collection_cache_initializes_when_missing(monkeypatch):
157
+ """Ensure set_collection_cache initializes the cache when attribute is absent."""
158
+ # Remove the attribute if present (avoids W0212 and stays lint-clean)
159
+ monkeypatch.delattr(collection_manager, "_collection_cache", raising=False)
160
+
161
+ key = "init_case"
162
+ val = MagicMock()
163
+
164
+ # This should go through the None-branch and attach the cache via object.__setattr__
165
+ set_collection_cache(key, val)
166
+
167
+ # Verify cache got created and populated
168
+ cache = getattr(collection_manager, "_collection_cache", None)
169
+ assert isinstance(cache, dict)
170
+ assert cache.get(key) is val
171
+
172
+ # Cleanup
173
+ clear_collection_cache(key)
@@ -1,6 +1,7 @@
1
1
  """Unit tests for PDF document processing utilities."""
2
2
 
3
3
  from unittest.mock import MagicMock, patch
4
+
4
5
  import pytest
5
6
 
6
7
  from aiagents4pharma.talk2scholars.tools.pdf.utils.document_processor import (
@@ -26,9 +27,7 @@ def _base_args_params():
26
27
  "aiagents4pharma.talk2scholars.tools.pdf.utils.document_processor."
27
28
  "RecursiveCharacterTextSplitter"
28
29
  )
29
- def test_load_and_split_pdf_success(
30
- mock_splitter_cls, mock_loader_cls, base_args_params
31
- ):
30
+ def test_load_and_split_pdf_success(mock_splitter_cls, mock_loader_cls, base_args_params):
32
31
  """load_and_split_pdf should load and split PDF correctly."""
33
32
  mock_doc = MagicMock()
34
33
  mock_doc.metadata = {"page": 1}
@@ -1,6 +1,7 @@
1
1
  """generate_answer tests for the PDF tool"""
2
2
 
3
3
  from unittest.mock import MagicMock
4
+
4
5
  import pytest
5
6
 
6
7
  from aiagents4pharma.talk2scholars.tools.pdf.utils.generate_answer import (
@@ -60,16 +61,12 @@ def test_generate_answer_success(chunks_fixture):
60
61
  def test_generate_answer_raises_for_none_config(chunks_fixture):
61
62
  """generate_answer should raise ValueError for None config."""
62
63
  mock_llm = MagicMock()
63
- with pytest.raises(
64
- ValueError, match="Configuration for generate_answer is required."
65
- ):
64
+ with pytest.raises(ValueError, match="Configuration for generate_answer is required."):
66
65
  generate_answer("Why?", chunks_fixture, mock_llm, config=None)
67
66
 
68
67
 
69
68
  def test_generate_answer_raises_for_missing_template(chunks_fixture):
70
69
  """generate_answer should raise ValueError for missing prompt_template in config."""
71
70
  mock_llm = MagicMock()
72
- with pytest.raises(
73
- ValueError, match="The prompt_template is missing from the configuration."
74
- ):
71
+ with pytest.raises(ValueError, match="The prompt_template is missing from the configuration."):
75
72
  generate_answer("Why?", chunks_fixture, mock_llm, config={})
@@ -4,7 +4,6 @@ import subprocess
4
4
  from types import SimpleNamespace
5
5
  from unittest.mock import MagicMock, patch
6
6
 
7
-
8
7
  from aiagents4pharma.talk2scholars.tools.pdf.utils.gpu_detection import (
9
8
  detect_nvidia_gpu,
10
9
  get_optimal_index_config,
@@ -23,9 +22,7 @@ def test_detect_nvidia_gpu_force_cpu_from_config():
23
22
  @patch("aiagents4pharma.talk2scholars.tools.pdf.utils.gpu_detection.subprocess.run")
24
23
  def test_detect_nvidia_gpu_success(mock_run):
25
24
  """detect_nvidia_gpu should return True if NVIDIA GPUs are detected."""
26
- mock_run.return_value = MagicMock(
27
- returncode=0, stdout="NVIDIA A100\nNVIDIA RTX 3090"
28
- )
25
+ mock_run.return_value = MagicMock(returncode=0, stdout="NVIDIA A100\nNVIDIA RTX 3090")
29
26
 
30
27
  assert detect_nvidia_gpu() is True
31
28
  mock_run.assert_called_once()
@@ -44,9 +41,7 @@ def test_detect_nvidia_gpu_no_output(mock_run):
44
41
 
45
42
  def test_get_optimal_index_config_gpu():
46
43
  """get_optimal_index_config should return GPU_CAGRA for GPU setup."""
47
- index_params, search_params = get_optimal_index_config(
48
- has_gpu=True, embedding_dim=768
49
- )
44
+ index_params, search_params = get_optimal_index_config(has_gpu=True, embedding_dim=768)
50
45
 
51
46
  assert index_params["index_type"] == "GPU_CAGRA"
52
47
  assert "cache_dataset_on_device" in index_params["params"]
@@ -55,9 +50,7 @@ def test_get_optimal_index_config_gpu():
55
50
 
56
51
  def test_get_optimal_index_config_cpu():
57
52
  """get_optimal_index_config should return IVF_FLAT for CPU setup."""
58
- index_params, search_params = get_optimal_index_config(
59
- has_gpu=False, embedding_dim=768
60
- )
53
+ index_params, search_params = get_optimal_index_config(has_gpu=False, embedding_dim=768)
61
54
 
62
55
  assert index_params["index_type"] == "IVF_FLAT"
63
56
  assert index_params["params"]["nlist"] == 96 # 768 / 8 = 96
@@ -121,9 +114,7 @@ def test_detect_nvidia_gpu_timeout_raises_false(mock_run, mock_logger):
121
114
 
122
115
  result = detect_nvidia_gpu()
123
116
  assert result is False
124
- mock_logger.info.assert_called_with(
125
- "NVIDIA GPU detection failed: %s", mock_run.side_effect
126
- )
117
+ mock_logger.info.assert_called_with("NVIDIA GPU detection failed: %s", mock_run.side_effect)
127
118
 
128
119
 
129
120
  @patch("aiagents4pharma.talk2scholars.tools.pdf.utils.gpu_detection.logger")
@@ -135,6 +126,4 @@ def test_detect_nvidia_gpu_file_not_found_raises_false(mock_run, mock_logger):
135
126
 
136
127
  result = detect_nvidia_gpu()
137
128
  assert result is False
138
- mock_logger.info.assert_called_with(
139
- "NVIDIA GPU detection failed: %s", mock_run.side_effect
140
- )
129
+ mock_logger.info.assert_called_with("NVIDIA GPU detection failed: %s", mock_run.side_effect)
@@ -1,6 +1,7 @@
1
1
  """pdf rag pipeline tests."""
2
2
 
3
3
  from unittest.mock import MagicMock, patch
4
+
4
5
  import pytest
5
6
  from langchain_core.documents import Document
6
7
 
@@ -25,18 +26,13 @@ def _base_config_fixture():
25
26
  def _mock_docs_fixture():
26
27
  """Simulates PDF document chunks."""
27
28
  return [
28
- Document(page_content=f"chunk {i}", metadata={"paper_id": f"P{i % 2}"})
29
- for i in range(10)
29
+ Document(page_content=f"chunk {i}", metadata={"paper_id": f"P{i % 2}"}) for i in range(10)
30
30
  ]
31
31
 
32
32
 
33
33
  @patch("aiagents4pharma.talk2scholars.tools.pdf.utils.rag_pipeline.rerank_chunks")
34
- @patch(
35
- "aiagents4pharma.talk2scholars.tools.pdf.utils.rag_pipeline.retrieve_relevant_chunks"
36
- )
37
- def test_rag_pipeline_gpu_path(
38
- mock_retrieve, mock_rerank, base_config_fixture, mock_docs_fixture
39
- ):
34
+ @patch("aiagents4pharma.talk2scholars.tools.pdf.utils.rag_pipeline.retrieve_relevant_chunks")
35
+ def test_rag_pipeline_gpu_path(mock_retrieve, mock_rerank, base_config_fixture, mock_docs_fixture):
40
36
  """test RAG pipeline with GPU path."""
41
37
  mock_retrieve.return_value = mock_docs_fixture
42
38
  mock_rerank.return_value = mock_docs_fixture[:5]
@@ -55,12 +51,8 @@ def test_rag_pipeline_gpu_path(
55
51
 
56
52
 
57
53
  @patch("aiagents4pharma.talk2scholars.tools.pdf.utils.rag_pipeline.rerank_chunks")
58
- @patch(
59
- "aiagents4pharma.talk2scholars.tools.pdf.utils.rag_pipeline.retrieve_relevant_chunks"
60
- )
61
- def test_rag_pipeline_cpu_path(
62
- mock_retrieve, mock_rerank, base_config_fixture, mock_docs_fixture
63
- ):
54
+ @patch("aiagents4pharma.talk2scholars.tools.pdf.utils.rag_pipeline.retrieve_relevant_chunks")
55
+ def test_rag_pipeline_cpu_path(mock_retrieve, mock_rerank, base_config_fixture, mock_docs_fixture):
64
56
  """rag pipeline with CPU path."""
65
57
  mock_retrieve.return_value = mock_docs_fixture
66
58
  mock_rerank.return_value = mock_docs_fixture[:5]
@@ -79,9 +71,7 @@ def test_rag_pipeline_cpu_path(
79
71
 
80
72
 
81
73
  @patch("aiagents4pharma.talk2scholars.tools.pdf.utils.rag_pipeline.rerank_chunks")
82
- @patch(
83
- "aiagents4pharma.talk2scholars.tools.pdf.utils.rag_pipeline.retrieve_relevant_chunks"
84
- )
74
+ @patch("aiagents4pharma.talk2scholars.tools.pdf.utils.rag_pipeline.retrieve_relevant_chunks")
85
75
  def test_rag_pipeline_empty_results(mock_retrieve, mock_rerank, base_config_fixture):
86
76
  """rag pipeline with no results."""
87
77
  mock_retrieve.return_value = []
@@ -21,8 +21,7 @@ def mock_vector_store():
21
21
  def mock_chunks():
22
22
  """Fixture to simulate PDF chunks."""
23
23
  return [
24
- Document(page_content=f"chunk {i}", metadata={"paper_id": f"P{i%2}"})
25
- for i in range(5)
24
+ Document(page_content=f"chunk {i}", metadata={"paper_id": f"P{i % 2}"}) for i in range(5)
26
25
  ]
27
26
 
28
27
 
@@ -74,9 +73,7 @@ def test_retrieve_chunks_with_filter(mock_logger, request):
74
73
  mock_logger.debug = MagicMock()
75
74
  vector_store.max_marginal_relevance_search.return_value = chunks
76
75
 
77
- results = retrieve_relevant_chunks(
78
- vector_store, query="filter test", paper_ids=["P1"], top_k=3
79
- )
76
+ results = retrieve_relevant_chunks(vector_store, query="filter test", paper_ids=["P1"], top_k=3)
80
77
  assert results == chunks
81
78
  args, kwargs = vector_store.max_marginal_relevance_search.call_args
82
79
  assert len(args) == 0
@@ -115,9 +112,7 @@ def test_retrieve_chunks_default_search_params(mock_logger, request):
115
112
  )
116
113
 
117
114
  assert results == chunks
118
- mock_logger.debug.assert_any_call(
119
- "Using default search parameters (no hardware optimization)"
120
- )
115
+ mock_logger.debug.assert_any_call("Using default search parameters (no hardware optimization)")
121
116
 
122
117
 
123
118
  @patch("aiagents4pharma.talk2scholars.tools.pdf.utils.retrieve_chunks.logger")
@@ -191,7 +186,5 @@ def test_retrieve_chunks_with_scores_not_implemented(mock_logger, request):
191
186
  retrieve_relevant_chunks_with_scores(
192
187
  vector_store=vector_store, query="fail test", top_k=1, score_threshold=0.0
193
188
  )
194
- assert "Vector store does not support similarity_search_with_score" in str(
195
- excinfo.value
196
- )
189
+ assert "Vector store does not support similarity_search_with_score" in str(excinfo.value)
197
190
  mock_logger.debug.assert_called_with("GPU-accelerated similarity search enabled")
@@ -1,6 +1,9 @@
1
- """Tests for singleton_manager: manages vector store connections and event loops."""
1
+ """
2
+ Tests for singleton_manager: manages vector store connections and event loops.
3
+ """
2
4
 
3
5
  from unittest.mock import MagicMock, patch
6
+
4
7
  import pytest
5
8
  from pymilvus.exceptions import MilvusException
6
9
 
@@ -19,21 +22,21 @@ def test_singleton_instance_identity():
19
22
  assert a is b
20
23
 
21
24
 
22
- @patch(
23
- "aiagents4pharma.talk2scholars.tools.pdf.utils.singleton_manager.detect_nvidia_gpu"
24
- )
25
- def test_detect_gpu_once(mock_detect):
25
+ @patch("aiagents4pharma.talk2scholars.tools.pdf.utils.singleton_manager.detect_nvidia_gpu")
26
+ def test_detect_gpu_once(mock_detect, monkeypatch):
26
27
  """Ensure GPU detection is cached."""
27
28
  mock_detect.return_value = True
28
29
  singleton = VectorstoreSingleton()
29
- setattr(singleton, "_gpu_detected", None)
30
+
31
+ # Reset GPU detection cache safely
32
+ monkeypatch.setattr(VectorstoreSingleton, "_gpu_detected", None, raising=False)
30
33
 
31
34
  result = singleton.detect_gpu_once()
32
35
  assert result is True
33
36
 
37
+ # Second call should use cached value; detect_nvidia_gpu called only once
34
38
  result2 = singleton.detect_gpu_once()
35
39
  assert result2 is True
36
-
37
40
  mock_detect.assert_called_once()
38
41
 
39
42
 
@@ -63,20 +66,20 @@ def test_get_connection_creates_connection(_, mock_db, mock_conns):
63
66
 
64
67
 
65
68
  @patch("aiagents4pharma.talk2scholars.tools.pdf.utils.singleton_manager.Milvus")
66
- def test_get_vector_store_creates_if_missing(mock_milvus):
69
+ def test_get_vector_store_creates_if_missing(mock_milvus, monkeypatch):
67
70
  """get_vector_store should create a new vector store if missing."""
68
71
  singleton = VectorstoreSingleton()
69
- setattr(singleton, "_vector_stores", {})
70
- setattr(singleton, "_event_loops", {})
72
+
73
+ # Clear caches safely
74
+ monkeypatch.setattr(VectorstoreSingleton, "_vector_stores", {}, raising=False)
75
+ monkeypatch.setattr(VectorstoreSingleton, "_event_loops", {}, raising=False)
71
76
 
72
77
  mock_embed = MagicMock()
73
78
  connection_args = {"host": "localhost", "port": 19530}
74
79
 
75
80
  vs = singleton.get_vector_store("collection1", mock_embed, connection_args)
76
81
 
77
- vector_stores = getattr(singleton, "_vector_stores")
78
- assert vs is vector_stores["collection1"]
79
- assert "collection1" in vector_stores
82
+ assert vs is not None
80
83
  mock_milvus.assert_called_once()
81
84
 
82
85
 
@@ -114,17 +117,15 @@ def test_get_vectorstore_force_new(mock_vectorstore_cls):
114
117
  assert vs1 != vs2
115
118
 
116
119
 
117
- @patch(
118
- "aiagents4pharma.talk2scholars.tools.pdf.utils.singleton_manager.connections.connect"
119
- )
120
- @patch(
121
- "aiagents4pharma.talk2scholars.tools.pdf.utils.singleton_manager.connections.has_connection"
122
- )
120
+ @patch("aiagents4pharma.talk2scholars.tools.pdf.utils.singleton_manager.connections.connect")
121
+ @patch("aiagents4pharma.talk2scholars.tools.pdf.utils.singleton_manager.connections.has_connection")
123
122
  @patch("aiagents4pharma.talk2scholars.tools.pdf.utils.singleton_manager.db")
124
- def test_get_connection_milvus_error(_, mock_has_connection, mock_connect):
123
+ def test_get_connection_milvus_error(_, mock_has_connection, mock_connect, monkeypatch):
125
124
  """get_connection should raise MilvusException on connection failure."""
126
125
  manager = VectorstoreSingleton()
127
- setattr(manager, "_connections", {})
126
+
127
+ # Reset connections cache safely
128
+ monkeypatch.setattr(VectorstoreSingleton, "_connections", {}, raising=False)
128
129
 
129
130
  mock_has_connection.return_value = False
130
131
  mock_connect.side_effect = MilvusException("Connection failed")
@@ -133,10 +134,12 @@ def test_get_connection_milvus_error(_, mock_has_connection, mock_connect):
133
134
  manager.get_connection("localhost", 19530, "test_db")
134
135
 
135
136
 
136
- def test_get_event_loop_creates_new_loop_on_closed():
137
+ def test_get_event_loop_creates_new_loop_on_closed(monkeypatch):
137
138
  """Ensure get_event_loop creates a new loop if current one is closed."""
138
139
  manager = VectorstoreSingleton()
139
- setattr(manager, "_event_loops", {})
140
+
141
+ # Clear event loops safely
142
+ monkeypatch.setattr(VectorstoreSingleton, "_event_loops", {}, raising=False)
140
143
 
141
144
  mock_loop = MagicMock()
142
145
  mock_loop.is_closed.return_value = True
@@ -38,7 +38,7 @@ def test_normalize_vectors_batch_normal_case():
38
38
  [0.6, 0.8],
39
39
  [0.6, 0.8],
40
40
  ]
41
- for r, e in zip(result, expected):
41
+ for r, e in zip(result, expected, strict=False):
42
42
  assert pytest.approx(r) == e
43
43
 
44
44
 
@@ -180,29 +180,20 @@ def test_load_existing_papers_with_exception(mock_embedding, mock_config):
180
180
  patch(f"{MODULE}.log_index_configuration"),
181
181
  ):
182
182
  mock_singleton = MagicMock()
183
- safe_store = MagicMock()
184
- safe_collection = MagicMock()
185
- safe_collection.num_entities = 0
186
- safe_collection.flush.return_value = None
187
- safe_store.col = safe_collection
188
- safe_store.collection = safe_collection
189
- mock_singleton.get_vector_store.return_value = safe_store
190
- mock_singleton.get_connection.return_value = None
191
- singleton_cls.return_value = mock_singleton
192
-
193
- vs = Vectorstore(embedding_model=mock_embedding, config=mock_config)
194
-
195
- # now replace with failing store
183
+ # Set up failing store directly for initialization
196
184
  bad_collection = MagicMock()
197
185
  bad_collection.num_entities = 0
198
186
  bad_collection.flush.side_effect = Exception("flush failed")
199
187
  bad_store = MagicMock()
200
188
  bad_store.col = bad_collection
201
189
  bad_store.collection = bad_collection
202
- vs.vector_store = bad_store
190
+ mock_singleton.get_vector_store.return_value = bad_store
191
+ mock_singleton.get_connection.return_value = None
192
+ singleton_cls.return_value = mock_singleton
203
193
 
194
+ # Test error propagation through initialization that calls _load_existing_paper_ids
204
195
  with pytest.raises(Exception) as excinfo:
205
- getattr(vs, "_load_existing_paper_ids")()
196
+ Vectorstore(embedding_model=mock_embedding, config=mock_config)
206
197
  assert "flush failed" in str(excinfo.value)
207
198
 
208
199
 
@@ -232,10 +223,8 @@ def test_ensure_collection_loaded_with_entities(mock_embedding, mock_config):
232
223
  mock_singleton.get_connection.return_value = None
233
224
  singleton_cls.return_value = mock_singleton
234
225
 
235
- vs = Vectorstore(embedding_model=mock_embedding, config=mock_config)
236
- vs.vector_store = mock_store
237
- getattr(vs, "_ensure_collection_loaded")()
238
-
226
+ # Test through initialization which calls _ensure_collection_loaded
227
+ Vectorstore(embedding_model=mock_embedding, config=mock_config)
239
228
  assert mock_collection.load.called
240
229
 
241
230
 
@@ -255,29 +244,20 @@ def test_ensure_collection_loaded_handles_exception(mock_embedding, mock_config)
255
244
  patch(f"{MODULE}.log_index_configuration"),
256
245
  ):
257
246
  mock_singleton = MagicMock()
258
- safe_store = MagicMock()
259
- safe_collection = MagicMock()
260
- safe_collection.num_entities = 0
261
- safe_collection.flush.return_value = None
262
- safe_store.col = safe_collection
263
- safe_store.collection = safe_collection
264
- mock_singleton.get_vector_store.return_value = safe_store
265
- mock_singleton.get_connection.return_value = None
266
- singleton_cls.return_value = mock_singleton
267
-
268
- vs = Vectorstore(embedding_model=mock_embedding, config=mock_config)
269
-
270
- # override with failing store
247
+ # Set up failing store directly for initialization
271
248
  bad_collection = MagicMock()
272
249
  bad_collection.num_entities = 0
273
250
  bad_collection.flush.side_effect = Exception("flush error")
274
251
  bad_store = MagicMock()
275
252
  bad_store.col = bad_collection
276
253
  bad_store.collection = bad_collection
277
- vs.vector_store = bad_store
254
+ mock_singleton.get_vector_store.return_value = bad_store
255
+ mock_singleton.get_connection.return_value = None
256
+ singleton_cls.return_value = mock_singleton
278
257
 
258
+ # Test error propagation through initialization that calls _ensure_collection_loaded
279
259
  with pytest.raises(Exception) as excinfo:
280
- getattr(vs, "_ensure_collection_loaded")()
260
+ Vectorstore(embedding_model=mock_embedding, config=mock_config)
281
261
  assert "flush error" in str(excinfo.value)
282
262
 
283
263
 
@@ -313,9 +293,7 @@ def test_force_cpu_mode_logs_override(mock_config, mock_embedding):
313
293
  assert not vs.has_gpu
314
294
 
315
295
 
316
- def test_similarity_metric_override(
317
- dummy_embedding, dummy_config, dummy_vectorstore_components
318
- ):
296
+ def test_similarity_metric_override(dummy_embedding, dummy_config, dummy_vectorstore_components):
319
297
  """
320
298
  Test setting of use_cosine from config.similarity_metric.
321
299
  """
@@ -338,8 +316,7 @@ def test_load_existing_paper_ids_fallback_to_collection(
338
316
  delattr(mock_vector_store, attr)
339
317
 
340
318
  vs = Vectorstore(dummy_embedding, config=dummy_config)
341
- vs.vector_store = mock_vector_store
342
- getattr(vs, "_load_existing_paper_ids")()
319
+ # The loaded_papers is set during initialization via _load_existing_paper_ids
343
320
  assert isinstance(vs.loaded_papers, set)
344
321
 
345
322
 
@@ -356,8 +333,7 @@ def test_load_existing_papers_collection_empty_logs(
356
333
  mock_vector_store.col = mock_collection
357
334
 
358
335
  vs = Vectorstore(dummy_embedding, config=dummy_config)
359
- vs.vector_store = mock_vector_store
360
- getattr(vs, "_load_existing_paper_ids")()
336
+ # The loaded_papers is set during initialization via _load_existing_paper_ids
361
337
  assert len(vs.loaded_papers) == 0
362
338
 
363
339
 
@@ -382,16 +358,12 @@ def test_similarity_search_filter_paths(
382
358
  assert isinstance(result, list)
383
359
 
384
360
 
385
- def test_mmr_search_filter_paths(
386
- dummy_embedding, dummy_config, dummy_vectorstore_components
387
- ):
361
+ def test_mmr_search_filter_paths(dummy_embedding, dummy_config, dummy_vectorstore_components):
388
362
  """
389
363
  Test filter expression generation in max_marginal_relevance_search.
390
364
  """
391
365
  _, mock_vector_store = dummy_vectorstore_components
392
- mock_vector_store.max_marginal_relevance_search.return_value = [
393
- Document(page_content="test")
394
- ]
366
+ mock_vector_store.max_marginal_relevance_search.return_value = [Document(page_content="test")]
395
367
  vs = Vectorstore(dummy_embedding, config=dummy_config)
396
368
  vs.vector_store = mock_vector_store
397
369
 
@@ -411,10 +383,10 @@ def test_ensure_collection_loaded_no_col_and_no_collection(
411
383
  if hasattr(mock_vector_store, attr):
412
384
  delattr(mock_vector_store, attr)
413
385
 
414
- vs = Vectorstore(dummy_embedding, config=dummy_config)
415
- vs.vector_store = mock_vector_store
416
- getattr(vs, "_ensure_collection_loaded")()
417
- # no exception
386
+ # Test initialization succeeds without exception
387
+ Vectorstore(dummy_embedding, config=dummy_config)
388
+ # Collection loading is handled during initialization via _ensure_collection_loaded
389
+ # no exception if we got this far
418
390
 
419
391
 
420
392
  def test_ensure_collection_loaded_empty_logs(
@@ -428,7 +400,7 @@ def test_ensure_collection_loaded_empty_logs(
428
400
  mock_collection.num_entities = 0
429
401
  mock_vector_store.col = mock_collection
430
402
 
431
- vs = Vectorstore(dummy_embedding, config=dummy_config)
432
- vs.vector_store = mock_vector_store
433
- getattr(vs, "_ensure_collection_loaded")()
434
- # no exception
403
+ # Test initialization succeeds without exception
404
+ Vectorstore(dummy_embedding, config=dummy_config)
405
+ # Collection loading is handled during initialization via _ensure_collection_loaded
406
+ # no exception if we got this far