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,150 @@
1
+ """
2
+ GPU Detection Utility for Milvus Index Selection
3
+ Handle COSINE -> IP conversion for GPU indexes
4
+ """
5
+
6
+ import logging
7
+ import subprocess
8
+ from typing import Any
9
+
10
+ logger = logging.getLogger(__name__)
11
+
12
+
13
+ def detect_nvidia_gpu(config=None) -> bool:
14
+ """
15
+ Detect if NVIDIA GPU is available and should be used.
16
+
17
+ Args:
18
+ config: Hydra config object that may contain force_cpu_mode flag
19
+
20
+ Returns:
21
+ bool: True if GPU should be used, False if CPU should be used
22
+ """
23
+
24
+ # Check for force CPU mode in config
25
+ if config and hasattr(config, "gpu_detection"):
26
+ force_cpu = getattr(config.gpu_detection, "force_cpu_mode", False)
27
+ if force_cpu:
28
+ logger.info(
29
+ "Force CPU mode enabled in config - using CPU even though GPU may be available"
30
+ )
31
+ return False
32
+
33
+ # Normal GPU detection logic
34
+ try:
35
+ result = subprocess.run(
36
+ ["nvidia-smi", "--query-gpu=name", "--format=csv,noheader"],
37
+ capture_output=True,
38
+ text=True,
39
+ timeout=10,
40
+ check=False,
41
+ )
42
+
43
+ if result.returncode == 0 and result.stdout.strip():
44
+ gpu_names = result.stdout.strip().split("\n")
45
+ logger.info("Detected NVIDIA GPU(s): %s", gpu_names)
46
+ logger.info("To force CPU mode, set 'force_cpu_mode: true' in config")
47
+ return True
48
+
49
+ logger.info("nvidia-smi command failed or no GPUs detected")
50
+ return False
51
+
52
+ except (subprocess.TimeoutExpired, FileNotFoundError) as e:
53
+ logger.info("NVIDIA GPU detection failed: %s", e)
54
+ return False
55
+
56
+
57
+ def get_optimal_index_config(
58
+ has_gpu: bool, embedding_dim: int = 768, use_cosine: bool = True
59
+ ) -> tuple[dict[str, Any], dict[str, Any]]:
60
+ """
61
+ Get optimal index and search parameters based on GPU availability.
62
+
63
+ IMPORTANT: GPU indexes don't support COSINE distance. When using GPU with COSINE,
64
+ vectors must be normalized and IP distance used instead.
65
+
66
+ Args:
67
+ has_gpu (bool): Whether NVIDIA GPU is available
68
+ embedding_dim (int): Dimension of embeddings
69
+ use_cosine (bool): Whether to use cosine similarity (will be converted to IP for GPU)
70
+
71
+ Returns:
72
+ Tuple[Dict[str, Any], Dict[str, Any]]: (index_params, search_params)
73
+ """
74
+ if has_gpu:
75
+ logger.info("Configuring GPU_CAGRA index for NVIDIA GPU")
76
+
77
+ # For GPU: COSINE is not supported, must use IP with normalized vectors
78
+ if use_cosine:
79
+ logger.warning(
80
+ "GPU indexes don't support COSINE distance. "
81
+ "Vectors will be normalized and IP distance will be used instead."
82
+ )
83
+ metric_type = "IP" # Inner Product for normalized vectors = cosine similarity
84
+ else:
85
+ metric_type = "IP" # Default to IP for GPU
86
+
87
+ # GPU_CAGRA index parameters - optimized for performance
88
+ index_params = {
89
+ "index_type": "GPU_CAGRA",
90
+ "metric_type": metric_type,
91
+ "params": {
92
+ "intermediate_graph_degree": 64, # Higher for better recall
93
+ "graph_degree": 32, # Balanced performance/recall
94
+ "build_algo": "IVF_PQ", # Higher quality build
95
+ "cache_dataset_on_device": "true", # Cache for better recall
96
+ "adapt_for_cpu": "false", # Pure GPU mode
97
+ },
98
+ }
99
+
100
+ # GPU_CAGRA search parameters
101
+ search_params = {
102
+ "metric_type": metric_type,
103
+ "params": {
104
+ "itopk_size": 128, # Power of 2, good for intermediate results
105
+ "search_width": 16, # Balanced entry points
106
+ "team_size": 16, # Optimize for typical vector dimensions
107
+ },
108
+ }
109
+
110
+ else:
111
+ logger.info("Configuring CPU index (IVF_FLAT) - no NVIDIA GPU detected")
112
+
113
+ # CPU supports COSINE directly
114
+ metric_type = "COSINE" if use_cosine else "IP"
115
+
116
+ # CPU IVF_FLAT index parameters
117
+ index_params = {
118
+ "index_type": "IVF_FLAT",
119
+ "metric_type": metric_type,
120
+ "params": {
121
+ "nlist": min(1024, max(64, embedding_dim // 8)) # Dynamic nlist based on dimension
122
+ },
123
+ }
124
+
125
+ # CPU search parameters
126
+ search_params = {
127
+ "metric_type": metric_type,
128
+ "params": {"nprobe": 16}, # Slightly higher than original for better recall
129
+ }
130
+
131
+ return index_params, search_params
132
+
133
+
134
+ def log_index_configuration(
135
+ index_params: dict[str, Any], search_params: dict[str, Any], use_cosine: bool = True
136
+ ) -> None:
137
+ """Log the selected index configuration for debugging."""
138
+ index_type = index_params.get("index_type", "Unknown")
139
+ metric_type = index_params.get("metric_type", "Unknown")
140
+
141
+ logger.info("=== Milvus Index Configuration ===")
142
+ logger.info("Index Type: %s", index_type)
143
+ logger.info("Metric Type: %s", metric_type)
144
+
145
+ if index_type == "GPU_CAGRA" and use_cosine and metric_type == "IP":
146
+ logger.info("NOTE: Using IP with normalized vectors to simulate COSINE for GPU")
147
+
148
+ logger.info("Index Params: %s", index_params.get("params", {}))
149
+ logger.info("Search Params: %s", search_params.get("params", {}))
150
+ logger.info("===================================")
@@ -0,0 +1,97 @@
1
+ """
2
+ NVIDIA NIM Reranker Utility for Milvus Integration
3
+ Rerank chunks instead of papers following traditional RAG pipeline
4
+ """
5
+
6
+ import logging
7
+ import os
8
+ from typing import Any
9
+
10
+ from langchain_core.documents import Document
11
+ from langchain_nvidia_ai_endpoints import NVIDIARerank
12
+
13
+ # Set up logging with configurable level
14
+ log_level = os.environ.get("LOG_LEVEL", "INFO")
15
+ logging.basicConfig(level=getattr(logging, log_level))
16
+ logger = logging.getLogger(__name__)
17
+ logger.setLevel(getattr(logging, log_level))
18
+
19
+
20
+ def rerank_chunks(
21
+ chunks: list[Document], query: str, config: Any, top_k: int = 25
22
+ ) -> list[Document]:
23
+ """
24
+ Rerank chunks by relevance to the query using NVIDIA's reranker.
25
+
26
+ This follows the traditional RAG pipeline: first retrieve chunks, then rerank them.
27
+
28
+ Args:
29
+ chunks (List[Document]): List of chunks to rerank
30
+ query (str): The query string
31
+ config (Any): Configuration containing reranker settings
32
+ top_k (int): Number of top chunks to return after reranking
33
+
34
+ Returns:
35
+ List[Document]: Reranked chunks (top_k most relevant)
36
+ """
37
+ logger.info(
38
+ "Starting NVIDIA chunk reranker for query: '%s' with %d chunks, top_k=%d",
39
+ query[:50] + "..." if len(query) > 50 else query,
40
+ len(chunks),
41
+ top_k,
42
+ )
43
+
44
+ # If we have fewer chunks than top_k, just return all
45
+ if len(chunks) <= top_k:
46
+ logger.info(
47
+ "Number of chunks (%d) <= top_k (%d), returning all chunks without reranking",
48
+ len(chunks),
49
+ top_k,
50
+ )
51
+ return chunks
52
+
53
+ # Get API key from config
54
+ api_key = config.reranker.api_key
55
+ if not api_key:
56
+ logger.error("No NVIDIA API key found in configuration for reranking")
57
+ raise ValueError("Configuration 'reranker.api_key' must be set for reranking")
58
+
59
+ logger.info("Using NVIDIA reranker model: %s", config.reranker.model)
60
+
61
+ # Initialize reranker with truncation to handle long chunks
62
+ reranker = NVIDIARerank(
63
+ model=config.reranker.model,
64
+ api_key=api_key,
65
+ truncate="END", # Truncate at the end if too long
66
+ )
67
+
68
+ # Log chunk metadata for debugging
69
+ logger.debug(
70
+ "Reranking chunks from papers: %s",
71
+ list({chunk.metadata.get("paper_id", "unknown") for chunk in chunks})[:5],
72
+ )
73
+
74
+ # Rerank the chunks
75
+ logger.info("Calling NVIDIA reranker API with %d chunks...", len(chunks))
76
+ reranked_chunks = reranker.compress_documents(query=query, documents=chunks)
77
+
78
+ for i, doc in enumerate(reranked_chunks[:top_k]):
79
+ score = doc.metadata.get("relevance_score", "N/A")
80
+ source = doc.metadata.get("paper_id", "unknown")
81
+ logger.info("Rank %d | Score: %.4f | Source: %s", i + 1, score, source)
82
+
83
+ logger.info(
84
+ "Successfully reranked chunks. Returning top %d chunks",
85
+ min(top_k, len(reranked_chunks)),
86
+ )
87
+
88
+ # Log which papers the top chunks come from
89
+ if reranked_chunks and logger.isEnabledFor(logging.DEBUG):
90
+ top_papers = {}
91
+ for chunk in reranked_chunks[:top_k]:
92
+ paper_id = chunk.metadata.get("paper_id", "unknown")
93
+ top_papers[paper_id] = top_papers.get(paper_id, 0) + 1
94
+ logger.debug("Top %d chunks distribution by paper: %s", top_k, top_papers)
95
+
96
+ # Return only top_k chunks (convert to list to match return type)
97
+ return list(reranked_chunks[:top_k])
@@ -0,0 +1,123 @@
1
+ """
2
+ Paper loading utilities for managing PDF documents in vector store.
3
+ """
4
+
5
+ import logging
6
+ from typing import Any
7
+
8
+ from .batch_processor import add_papers_batch
9
+
10
+ logger = logging.getLogger(__name__)
11
+
12
+
13
+ def load_all_papers(
14
+ vector_store: Any, # The Vectorstore instance
15
+ articles: dict[str, Any],
16
+ call_id: str,
17
+ config: Any,
18
+ has_gpu: bool,
19
+ ) -> None:
20
+ """
21
+ Ensure all papers from article_data are loaded into the Milvus vector store.
22
+ Optimized for GPU/CPU processing.
23
+
24
+ Args:
25
+ vector_store: The Vectorstore instance
26
+ articles: Dictionary of article data
27
+ call_id: Call identifier for logging
28
+ config: Configuration object
29
+ has_gpu: Whether GPU is available
30
+ """
31
+ papers_to_load = []
32
+ skipped_papers = []
33
+ already_loaded = []
34
+
35
+ # Check which papers need to be loaded
36
+ for pid, article_info in articles.items():
37
+ if pid not in vector_store.loaded_papers:
38
+ pdf_url = article_info.get("pdf_url")
39
+ if pdf_url:
40
+ # Prepare tuple for batch loading
41
+ papers_to_load.append((pid, pdf_url, article_info))
42
+ else:
43
+ skipped_papers.append(pid)
44
+ else:
45
+ already_loaded.append(pid)
46
+
47
+ # Log summary of papers status with hardware info
48
+ hardware_info = f" (GPU acceleration: {'enabled' if has_gpu else 'disabled'})"
49
+ logger.info(
50
+ "%s: Paper loading summary%s - Total: %d, Already loaded: %d, To load: %d, No PDF: %d",
51
+ call_id,
52
+ hardware_info,
53
+ len(articles),
54
+ len(already_loaded),
55
+ len(papers_to_load),
56
+ len(skipped_papers),
57
+ )
58
+
59
+ if skipped_papers:
60
+ logger.warning(
61
+ "%s: Skipping %d papers without PDF URLs: %s%s",
62
+ call_id,
63
+ len(skipped_papers),
64
+ skipped_papers[:5], # Show first 5
65
+ "..." if len(skipped_papers) > 5 else "",
66
+ )
67
+
68
+ if not papers_to_load:
69
+ logger.info("%s: All papers with PDFs are already loaded in Milvus", call_id)
70
+ return
71
+
72
+ # Use batch loading with parallel processing for ALL papers at once
73
+ # Adjust parameters based on hardware capabilities
74
+ if has_gpu:
75
+ # GPU can handle more parallel processing
76
+ max_workers = min(12, max(4, len(papers_to_load))) # More workers for GPU
77
+ batch_size = config.get("embedding_batch_size", 2000) # Larger batches for GPU
78
+ logger.info(
79
+ "%s: Using GPU-optimized loading parameters: %d workers, batch size %d",
80
+ call_id,
81
+ max_workers,
82
+ batch_size,
83
+ )
84
+ else:
85
+ # CPU - more conservative parameters
86
+ max_workers = min(8, max(3, len(papers_to_load))) # Conservative for CPU
87
+ batch_size = config.get("embedding_batch_size", 1000) # Smaller batches for CPU
88
+ logger.info(
89
+ "%s: Using CPU-optimized loading parameters: %d workers, batch size %d",
90
+ call_id,
91
+ max_workers,
92
+ batch_size,
93
+ )
94
+
95
+ logger.info(
96
+ "%s: Loading %d papers in ONE BATCH using %d parallel workers (batch size: %d, %s)",
97
+ call_id,
98
+ len(papers_to_load),
99
+ max_workers,
100
+ batch_size,
101
+ "GPU accelerated" if has_gpu else "CPU processing",
102
+ )
103
+
104
+ # This should process ALL papers at once with hardware optimization
105
+ add_papers_batch(
106
+ papers_to_add=papers_to_load,
107
+ vector_store=vector_store.vector_store, # Pass the LangChain vector store
108
+ loaded_papers=vector_store.loaded_papers,
109
+ paper_metadata=vector_store.paper_metadata,
110
+ documents=vector_store.documents,
111
+ config=vector_store.config,
112
+ metadata_fields=vector_store.metadata_fields,
113
+ has_gpu=vector_store.has_gpu,
114
+ max_workers=max_workers,
115
+ batch_size=batch_size,
116
+ )
117
+
118
+ logger.info(
119
+ "%s: Successfully completed batch loading of all %d papers with %s",
120
+ call_id,
121
+ len(papers_to_load),
122
+ "GPU acceleration" if has_gpu else "CPU processing",
123
+ )
@@ -0,0 +1,113 @@
1
+ """
2
+ RAG pipeline for retrieving and reranking chunks from a vector store.
3
+ """
4
+
5
+ import logging
6
+ from typing import Any
7
+
8
+ # Import our GPU detection utility
9
+ from .nvidia_nim_reranker import rerank_chunks
10
+ from .retrieve_chunks import retrieve_relevant_chunks
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+
15
+ def retrieve_and_rerank_chunks(
16
+ vector_store: Any, query: str, config: Any, call_id: str, has_gpu: bool
17
+ ) -> list[Any]:
18
+ """
19
+ Traditional RAG pipeline: retrieve chunks from all papers, then rerank.
20
+ Optimized for GPU/CPU hardware.
21
+
22
+ Args:
23
+ vs: Vector store instance
24
+ query: User query
25
+
26
+ Returns:
27
+ List of reranked chunks
28
+ """
29
+ hardware_mode = "GPU-accelerated" if has_gpu else "CPU-optimized"
30
+ logger.info(
31
+ "%s: Starting traditional RAG pipeline - retrieve then rerank (%s)",
32
+ call_id,
33
+ hardware_mode,
34
+ )
35
+
36
+ # Step 1: Retrieve chunks from ALL papers (cast wide net)
37
+ # Adjust initial retrieval count based on hardware
38
+ if has_gpu:
39
+ # GPU can handle larger initial retrieval efficiently
40
+ initial_chunks_count = config.get("initial_retrieval_k", 150) # Increased for GPU
41
+ mmr_diversity = config.get("mmr_diversity", 0.75) # Slightly more diverse for larger sets
42
+ else:
43
+ # CPU - use conservative settings
44
+ initial_chunks_count = config.get("initial_retrieval_k", 100) # Original
45
+ mmr_diversity = config.get("mmr_diversity", 0.8) # Original
46
+
47
+ logger.info(
48
+ "%s: Step 1 - Retrieving top %d chunks from ALL papers (%s mode)",
49
+ call_id,
50
+ initial_chunks_count,
51
+ hardware_mode,
52
+ )
53
+
54
+ retrieved_chunks = retrieve_relevant_chunks(
55
+ vector_store,
56
+ query=query,
57
+ paper_ids=None, # No filter - retrieve from all papers
58
+ top_k=initial_chunks_count,
59
+ mmr_diversity=mmr_diversity,
60
+ )
61
+
62
+ if not retrieved_chunks:
63
+ logger.warning("%s: No chunks retrieved from vector store", call_id)
64
+ return []
65
+
66
+ logger.info(
67
+ "%s: Retrieved %d chunks from %d unique papers using %s",
68
+ call_id,
69
+ len(retrieved_chunks),
70
+ len({chunk.metadata.get("paper_id", "unknown") for chunk in retrieved_chunks}),
71
+ hardware_mode,
72
+ )
73
+
74
+ # Step 2: Rerank the retrieved chunks
75
+ final_chunk_count = config.top_k_chunks
76
+ logger.info(
77
+ "%s: Step 2 - Reranking %d chunks to get top %d",
78
+ call_id,
79
+ len(retrieved_chunks),
80
+ final_chunk_count,
81
+ )
82
+
83
+ reranked_chunks = rerank_chunks(
84
+ chunks=retrieved_chunks,
85
+ query=query,
86
+ config=config,
87
+ top_k=final_chunk_count,
88
+ )
89
+
90
+ # Log final results with hardware info
91
+ final_papers = len({chunk.metadata.get("paper_id", "unknown") for chunk in reranked_chunks})
92
+
93
+ logger.info(
94
+ "%s: Reranking complete using %s. Final %d chunks from %d unique papers",
95
+ call_id,
96
+ hardware_mode,
97
+ len(reranked_chunks),
98
+ final_papers,
99
+ )
100
+
101
+ # Log performance insights
102
+ if len(retrieved_chunks) > 0:
103
+ efficiency = len(reranked_chunks) / len(retrieved_chunks) * 100
104
+ logger.debug(
105
+ "%s: Pipeline efficiency: %.1f%% (%d final / %d initial chunks) - %s",
106
+ call_id,
107
+ efficiency,
108
+ len(reranked_chunks),
109
+ len(retrieved_chunks),
110
+ hardware_mode,
111
+ )
112
+
113
+ return reranked_chunks
@@ -0,0 +1,197 @@
1
+ """
2
+ Retrieve relevant chunks from a Milvus vector store using MMR (Maximal Marginal Relevance).
3
+ Follows traditional RAG pipeline - retrieve first, then rerank.
4
+ With automatic GPU/CPU search parameter optimization.
5
+ """
6
+
7
+ import logging
8
+ import os
9
+
10
+ from langchain_core.documents import Document
11
+
12
+ # Set up logging with configurable level
13
+ log_level = os.environ.get("LOG_LEVEL", "INFO")
14
+ logging.basicConfig(level=getattr(logging, log_level))
15
+ logger = logging.getLogger(__name__)
16
+ logger.setLevel(getattr(logging, log_level))
17
+
18
+
19
+ def retrieve_relevant_chunks(
20
+ vector_store,
21
+ query: str,
22
+ paper_ids: list[str] | None = None,
23
+ top_k: int = 100, # Increased default to cast wider net before reranking
24
+ mmr_diversity: float = 0.8, # Slightly reduced for better diversity
25
+ ) -> list[Document]:
26
+ """
27
+ Retrieve the most relevant chunks for a query using maximal marginal relevance.
28
+ Automatically uses GPU-optimized search parameters if GPU is available.
29
+
30
+ In the traditional RAG pipeline, this should retrieve chunks from ALL available papers,
31
+ not just pre-selected ones. The reranker will then select the best chunks.
32
+
33
+ Args:
34
+ vector_store: The Milvus vector store instance
35
+ query: Query string
36
+ paper_ids: Optional list of paper IDs to filter by (default: None - search all papers)
37
+ top_k: Number of chunks to retrieve (default: 100 for reranking pipeline)
38
+ mmr_diversity: Diversity parameter for MMR (0=max diversity, 1=max relevance)
39
+
40
+ Returns:
41
+ List of document chunks
42
+ """
43
+ if not vector_store:
44
+ logger.error("Vector store is not initialized")
45
+ return []
46
+
47
+ # Check if vector store has GPU capabilities
48
+ has_gpu = getattr(vector_store, "has_gpu", False)
49
+ search_mode = "GPU-accelerated" if has_gpu else "CPU"
50
+
51
+ # Prepare filter for paper_ids if provided
52
+ filter_dict = None
53
+ if paper_ids:
54
+ logger.warning(
55
+ "Paper IDs filter provided. Traditional RAG pipeline typically"
56
+ "retrieves from ALL papers first. "
57
+ "Consider removing paper_ids filter for better results."
58
+ )
59
+ logger.info("Filtering retrieval to papers: %s", paper_ids)
60
+ filter_dict = {"paper_id": paper_ids}
61
+ else:
62
+ logger.info(
63
+ "Retrieving chunks from ALL papers (traditional RAG approach) using %s search",
64
+ search_mode,
65
+ )
66
+
67
+ # Use Milvus's built-in MMR search with optimized parameters
68
+ logger.info(
69
+ "Performing %s MMR search with query: '%s', k=%d, diversity=%.2f",
70
+ search_mode,
71
+ query[:50] + "..." if len(query) > 50 else query,
72
+ top_k,
73
+ mmr_diversity,
74
+ )
75
+
76
+ # Fetch more candidates for better MMR results
77
+ # Adjust fetch_k based on available hardware
78
+ if has_gpu:
79
+ # GPU can handle larger candidate sets efficiently
80
+ fetch_k = min(top_k * 6, 800) # Increased for GPU
81
+ logger.debug("Using GPU-optimized fetch_k: %d", fetch_k)
82
+ else:
83
+ # CPU - more conservative to avoid performance issues
84
+ fetch_k = min(top_k * 4, 500) # Original conservative approach
85
+ logger.debug("Using CPU-optimized fetch_k: %d", fetch_k)
86
+
87
+ # Get search parameters from vector store if available
88
+ search_params = getattr(vector_store, "search_params", None)
89
+
90
+ if search_params:
91
+ logger.debug("Using hardware-optimized search parameters: %s", search_params)
92
+ else:
93
+ logger.debug("Using default search parameters (no hardware optimization)")
94
+
95
+ # Perform MMR search - let the vector store handle search_params internally
96
+ # Don't pass search_params explicitly to avoid conflicts
97
+ results = vector_store.max_marginal_relevance_search(
98
+ query=query,
99
+ k=top_k,
100
+ fetch_k=fetch_k,
101
+ lambda_mult=mmr_diversity,
102
+ filter=filter_dict,
103
+ )
104
+
105
+ logger.info("Retrieved %d chunks using %s MMR from Milvus", len(results), search_mode)
106
+
107
+ # Log some details about retrieved chunks for debugging
108
+ if results and logger.isEnabledFor(logging.DEBUG):
109
+ paper_counts = {}
110
+ for doc in results:
111
+ paper_id = doc.metadata.get("paper_id", "unknown")
112
+ paper_counts[paper_id] = paper_counts.get(paper_id, 0) + 1
113
+
114
+ logger.debug(
115
+ "%s retrieval - chunks per paper: %s",
116
+ search_mode,
117
+ dict(sorted(paper_counts.items(), key=lambda x: x[1], reverse=True)[:10]),
118
+ )
119
+ logger.debug(
120
+ "%s retrieval - total papers represented: %d",
121
+ search_mode,
122
+ len(paper_counts),
123
+ )
124
+
125
+ return results
126
+
127
+
128
+ def retrieve_relevant_chunks_with_scores(
129
+ vector_store,
130
+ query: str,
131
+ paper_ids: list[str] | None = None,
132
+ top_k: int = 100,
133
+ score_threshold: float = 0.0,
134
+ ) -> list[tuple[Document, float]]:
135
+ """
136
+ Retrieve chunks with similarity scores, optimized for GPU/CPU.
137
+
138
+ Args:
139
+ vector_store: The Milvus vector store instance
140
+ query: Query string
141
+ paper_ids: Optional list of paper IDs to filter by
142
+ top_k: Number of chunks to retrieve
143
+ score_threshold: Minimum similarity score threshold
144
+
145
+ Returns:
146
+ List of (document, score) tuples
147
+ """
148
+ if not vector_store:
149
+ logger.error("Vector store is not initialized")
150
+ return []
151
+
152
+ has_gpu = getattr(vector_store, "has_gpu", False)
153
+ search_mode = "GPU-accelerated" if has_gpu else "CPU"
154
+
155
+ # Prepare filter
156
+ filter_dict = None
157
+ if paper_ids:
158
+ filter_dict = {"paper_id": paper_ids}
159
+
160
+ logger.info(
161
+ "Performing %s similarity search with scores: query='%s', k=%d, threshold=%.3f",
162
+ search_mode,
163
+ query[:50] + "..." if len(query) > 50 else query,
164
+ top_k,
165
+ score_threshold,
166
+ )
167
+
168
+ # Check hardware optimization status instead of unused search_params
169
+ has_optimization = hasattr(vector_store, "has_gpu") and vector_store.has_gpu
170
+
171
+ if has_optimization:
172
+ logger.debug("GPU-accelerated similarity search enabled")
173
+ else:
174
+ logger.debug("Standard CPU similarity search")
175
+
176
+ if hasattr(vector_store, "similarity_search_with_score"):
177
+ # Don't pass search_params to avoid conflicts
178
+ results = vector_store.similarity_search_with_score(
179
+ query=query,
180
+ k=top_k,
181
+ filter=filter_dict,
182
+ )
183
+
184
+ # Filter by score threshold
185
+ filtered_results = [(doc, score) for doc, score in results if score >= score_threshold]
186
+
187
+ logger.info(
188
+ "%s search with scores retrieved %d/%d chunks above threshold %.3f",
189
+ search_mode,
190
+ len(filtered_results),
191
+ len(results),
192
+ score_threshold,
193
+ )
194
+
195
+ return filtered_results
196
+
197
+ raise NotImplementedError("Vector store does not support similarity_search_with_score")