aiagents4pharma 1.44.0__py3-none-any.whl → 1.45.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (289) hide show
  1. aiagents4pharma/__init__.py +2 -2
  2. aiagents4pharma/talk2aiagents4pharma/.dockerignore +13 -0
  3. aiagents4pharma/talk2aiagents4pharma/Dockerfile +105 -0
  4. aiagents4pharma/talk2aiagents4pharma/README.md +1 -0
  5. aiagents4pharma/talk2aiagents4pharma/__init__.py +4 -5
  6. aiagents4pharma/talk2aiagents4pharma/agents/__init__.py +3 -2
  7. aiagents4pharma/talk2aiagents4pharma/agents/main_agent.py +24 -23
  8. aiagents4pharma/talk2aiagents4pharma/configs/__init__.py +2 -2
  9. aiagents4pharma/talk2aiagents4pharma/configs/agents/__init__.py +2 -2
  10. aiagents4pharma/talk2aiagents4pharma/configs/agents/main_agent/default.yaml +2 -2
  11. aiagents4pharma/talk2aiagents4pharma/configs/config.yaml +1 -1
  12. aiagents4pharma/talk2aiagents4pharma/docker-compose/cpu/.env.example +23 -0
  13. aiagents4pharma/talk2aiagents4pharma/docker-compose/cpu/docker-compose.yml +93 -0
  14. aiagents4pharma/talk2aiagents4pharma/docker-compose/gpu/.env.example +23 -0
  15. aiagents4pharma/talk2aiagents4pharma/docker-compose/gpu/docker-compose.yml +108 -0
  16. aiagents4pharma/talk2aiagents4pharma/install.md +127 -0
  17. aiagents4pharma/talk2aiagents4pharma/states/__init__.py +3 -2
  18. aiagents4pharma/talk2aiagents4pharma/states/state_talk2aiagents4pharma.py +5 -3
  19. aiagents4pharma/talk2aiagents4pharma/tests/__init__.py +2 -2
  20. aiagents4pharma/talk2aiagents4pharma/tests/test_main_agent.py +72 -50
  21. aiagents4pharma/talk2biomodels/.dockerignore +13 -0
  22. aiagents4pharma/talk2biomodels/Dockerfile +104 -0
  23. aiagents4pharma/talk2biomodels/README.md +1 -0
  24. aiagents4pharma/talk2biomodels/__init__.py +4 -8
  25. aiagents4pharma/talk2biomodels/agents/__init__.py +3 -2
  26. aiagents4pharma/talk2biomodels/agents/t2b_agent.py +47 -42
  27. aiagents4pharma/talk2biomodels/api/__init__.py +4 -5
  28. aiagents4pharma/talk2biomodels/api/kegg.py +14 -10
  29. aiagents4pharma/talk2biomodels/api/ols.py +13 -10
  30. aiagents4pharma/talk2biomodels/api/uniprot.py +7 -6
  31. aiagents4pharma/talk2biomodels/configs/__init__.py +3 -4
  32. aiagents4pharma/talk2biomodels/configs/agents/__init__.py +2 -2
  33. aiagents4pharma/talk2biomodels/configs/agents/t2b_agent/__init__.py +2 -2
  34. aiagents4pharma/talk2biomodels/configs/agents/t2b_agent/default.yaml +1 -1
  35. aiagents4pharma/talk2biomodels/configs/config.yaml +1 -1
  36. aiagents4pharma/talk2biomodels/configs/tools/__init__.py +4 -5
  37. aiagents4pharma/talk2biomodels/configs/tools/ask_question/__init__.py +2 -2
  38. aiagents4pharma/talk2biomodels/configs/tools/ask_question/default.yaml +1 -2
  39. aiagents4pharma/talk2biomodels/configs/tools/custom_plotter/__init__.py +2 -2
  40. aiagents4pharma/talk2biomodels/configs/tools/custom_plotter/default.yaml +1 -1
  41. aiagents4pharma/talk2biomodels/configs/tools/get_annotation/__init__.py +2 -2
  42. aiagents4pharma/talk2biomodels/configs/tools/get_annotation/default.yaml +1 -1
  43. aiagents4pharma/talk2biomodels/install.md +63 -0
  44. aiagents4pharma/talk2biomodels/models/__init__.py +4 -4
  45. aiagents4pharma/talk2biomodels/models/basico_model.py +36 -28
  46. aiagents4pharma/talk2biomodels/models/sys_bio_model.py +13 -10
  47. aiagents4pharma/talk2biomodels/states/__init__.py +3 -2
  48. aiagents4pharma/talk2biomodels/states/state_talk2biomodels.py +12 -8
  49. aiagents4pharma/talk2biomodels/tests/BIOMD0000000449_url.xml +1585 -0
  50. aiagents4pharma/talk2biomodels/tests/__init__.py +2 -2
  51. aiagents4pharma/talk2biomodels/tests/article_on_model_537.pdf +0 -0
  52. aiagents4pharma/talk2biomodels/tests/test_api.py +18 -14
  53. aiagents4pharma/talk2biomodels/tests/test_ask_question.py +8 -9
  54. aiagents4pharma/talk2biomodels/tests/test_basico_model.py +15 -9
  55. aiagents4pharma/talk2biomodels/tests/test_get_annotation.py +54 -55
  56. aiagents4pharma/talk2biomodels/tests/test_getmodelinfo.py +28 -27
  57. aiagents4pharma/talk2biomodels/tests/test_integration.py +21 -33
  58. aiagents4pharma/talk2biomodels/tests/test_load_biomodel.py +14 -11
  59. aiagents4pharma/talk2biomodels/tests/test_param_scan.py +21 -20
  60. aiagents4pharma/talk2biomodels/tests/test_query_article.py +129 -29
  61. aiagents4pharma/talk2biomodels/tests/test_search_models.py +9 -13
  62. aiagents4pharma/talk2biomodels/tests/test_simulate_model.py +16 -15
  63. aiagents4pharma/talk2biomodels/tests/test_steady_state.py +12 -22
  64. aiagents4pharma/talk2biomodels/tests/test_sys_bio_model.py +33 -29
  65. aiagents4pharma/talk2biomodels/tools/__init__.py +15 -12
  66. aiagents4pharma/talk2biomodels/tools/ask_question.py +42 -32
  67. aiagents4pharma/talk2biomodels/tools/custom_plotter.py +51 -43
  68. aiagents4pharma/talk2biomodels/tools/get_annotation.py +99 -75
  69. aiagents4pharma/talk2biomodels/tools/get_modelinfo.py +57 -51
  70. aiagents4pharma/talk2biomodels/tools/load_arguments.py +52 -32
  71. aiagents4pharma/talk2biomodels/tools/load_biomodel.py +8 -2
  72. aiagents4pharma/talk2biomodels/tools/parameter_scan.py +107 -90
  73. aiagents4pharma/talk2biomodels/tools/query_article.py +14 -13
  74. aiagents4pharma/talk2biomodels/tools/search_models.py +37 -26
  75. aiagents4pharma/talk2biomodels/tools/simulate_model.py +47 -37
  76. aiagents4pharma/talk2biomodels/tools/steady_state.py +76 -58
  77. aiagents4pharma/talk2biomodels/tools/utils.py +4 -3
  78. aiagents4pharma/talk2cells/README.md +1 -0
  79. aiagents4pharma/talk2cells/__init__.py +4 -5
  80. aiagents4pharma/talk2cells/agents/__init__.py +3 -2
  81. aiagents4pharma/talk2cells/agents/scp_agent.py +21 -19
  82. aiagents4pharma/talk2cells/states/__init__.py +3 -2
  83. aiagents4pharma/talk2cells/states/state_talk2cells.py +4 -2
  84. aiagents4pharma/talk2cells/tests/scp_agent/test_scp_agent.py +8 -9
  85. aiagents4pharma/talk2cells/tools/__init__.py +3 -2
  86. aiagents4pharma/talk2cells/tools/scp_agent/__init__.py +4 -4
  87. aiagents4pharma/talk2cells/tools/scp_agent/display_studies.py +5 -3
  88. aiagents4pharma/talk2cells/tools/scp_agent/search_studies.py +21 -22
  89. aiagents4pharma/talk2knowledgegraphs/.dockerignore +13 -0
  90. aiagents4pharma/talk2knowledgegraphs/Dockerfile +103 -0
  91. aiagents4pharma/talk2knowledgegraphs/README.md +1 -0
  92. aiagents4pharma/talk2knowledgegraphs/__init__.py +4 -7
  93. aiagents4pharma/talk2knowledgegraphs/agents/__init__.py +3 -2
  94. aiagents4pharma/talk2knowledgegraphs/agents/t2kg_agent.py +40 -30
  95. aiagents4pharma/talk2knowledgegraphs/configs/__init__.py +3 -6
  96. aiagents4pharma/talk2knowledgegraphs/configs/agents/t2kg_agent/__init__.py +2 -2
  97. aiagents4pharma/talk2knowledgegraphs/configs/agents/t2kg_agent/default.yaml +8 -8
  98. aiagents4pharma/talk2knowledgegraphs/configs/app/__init__.py +3 -2
  99. aiagents4pharma/talk2knowledgegraphs/configs/app/frontend/__init__.py +2 -2
  100. aiagents4pharma/talk2knowledgegraphs/configs/app/frontend/default.yaml +1 -1
  101. aiagents4pharma/talk2knowledgegraphs/configs/config.yaml +1 -1
  102. aiagents4pharma/talk2knowledgegraphs/configs/tools/__init__.py +4 -5
  103. aiagents4pharma/talk2knowledgegraphs/configs/tools/graphrag_reasoning/__init__.py +2 -2
  104. aiagents4pharma/talk2knowledgegraphs/configs/tools/graphrag_reasoning/default.yaml +1 -1
  105. aiagents4pharma/talk2knowledgegraphs/configs/tools/subgraph_extraction/__init__.py +2 -2
  106. aiagents4pharma/talk2knowledgegraphs/configs/tools/subgraph_extraction/default.yaml +1 -1
  107. aiagents4pharma/talk2knowledgegraphs/configs/tools/subgraph_summarization/__init__.py +2 -2
  108. aiagents4pharma/talk2knowledgegraphs/configs/tools/subgraph_summarization/default.yaml +1 -1
  109. aiagents4pharma/talk2knowledgegraphs/configs/utils/enrichments/ols_terms/default.yaml +1 -1
  110. aiagents4pharma/talk2knowledgegraphs/configs/utils/enrichments/reactome_pathways/default.yaml +1 -1
  111. aiagents4pharma/talk2knowledgegraphs/configs/utils/enrichments/uniprot_proteins/default.yaml +1 -1
  112. aiagents4pharma/talk2knowledgegraphs/configs/utils/pubchem_utils/default.yaml +1 -1
  113. aiagents4pharma/talk2knowledgegraphs/datasets/__init__.py +4 -6
  114. aiagents4pharma/talk2knowledgegraphs/datasets/biobridge_primekg.py +115 -67
  115. aiagents4pharma/talk2knowledgegraphs/datasets/dataset.py +2 -0
  116. aiagents4pharma/talk2knowledgegraphs/datasets/primekg.py +35 -24
  117. aiagents4pharma/talk2knowledgegraphs/datasets/starkqa_primekg.py +29 -21
  118. aiagents4pharma/talk2knowledgegraphs/docker-compose/cpu/.env.example +23 -0
  119. aiagents4pharma/talk2knowledgegraphs/docker-compose/cpu/docker-compose.yml +93 -0
  120. aiagents4pharma/talk2knowledgegraphs/docker-compose/gpu/.env.example +23 -0
  121. aiagents4pharma/talk2knowledgegraphs/docker-compose/gpu/docker-compose.yml +108 -0
  122. aiagents4pharma/talk2knowledgegraphs/entrypoint.sh +190 -0
  123. aiagents4pharma/talk2knowledgegraphs/install.md +140 -0
  124. aiagents4pharma/talk2knowledgegraphs/milvus_data_dump.py +31 -65
  125. aiagents4pharma/talk2knowledgegraphs/states/__init__.py +3 -2
  126. aiagents4pharma/talk2knowledgegraphs/states/state_talk2knowledgegraphs.py +1 -0
  127. aiagents4pharma/talk2knowledgegraphs/tests/test_agents_t2kg_agent.py +65 -40
  128. aiagents4pharma/talk2knowledgegraphs/tests/test_datasets_biobridge_primekg.py +54 -48
  129. aiagents4pharma/talk2knowledgegraphs/tests/test_datasets_dataset.py +4 -0
  130. aiagents4pharma/talk2knowledgegraphs/tests/test_datasets_primekg.py +17 -4
  131. aiagents4pharma/talk2knowledgegraphs/tests/test_datasets_starkqa_primekg.py +33 -24
  132. aiagents4pharma/talk2knowledgegraphs/tests/test_tools_graphrag_reasoning.py +116 -69
  133. aiagents4pharma/talk2knowledgegraphs/tests/test_tools_milvus_multimodal_subgraph_extraction.py +334 -216
  134. aiagents4pharma/talk2knowledgegraphs/tests/test_tools_multimodal_subgraph_extraction.py +22 -15
  135. aiagents4pharma/talk2knowledgegraphs/tests/test_tools_subgraph_extraction.py +19 -12
  136. aiagents4pharma/talk2knowledgegraphs/tests/test_tools_subgraph_summarization.py +95 -48
  137. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_embeddings_embeddings.py +4 -0
  138. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_embeddings_huggingface.py +5 -0
  139. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_embeddings_nim_molmim.py +13 -18
  140. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_embeddings_ollama.py +10 -3
  141. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_enrichments_enrichments.py +4 -3
  142. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_enrichments_ollama.py +3 -2
  143. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_enrichments_ols.py +1 -0
  144. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_enrichments_pubchem.py +9 -4
  145. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_enrichments_reactome.py +6 -6
  146. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_enrichments_uniprot.py +4 -0
  147. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_extractions_milvus_multimodal_pcst.py +160 -97
  148. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_kg_utils.py +3 -4
  149. aiagents4pharma/talk2knowledgegraphs/tests/test_utils_pubchem_utils.py +87 -13
  150. aiagents4pharma/talk2knowledgegraphs/tools/__init__.py +10 -7
  151. aiagents4pharma/talk2knowledgegraphs/tools/graphrag_reasoning.py +15 -20
  152. aiagents4pharma/talk2knowledgegraphs/tools/milvus_multimodal_subgraph_extraction.py +145 -142
  153. aiagents4pharma/talk2knowledgegraphs/tools/multimodal_subgraph_extraction.py +92 -90
  154. aiagents4pharma/talk2knowledgegraphs/tools/subgraph_extraction.py +25 -37
  155. aiagents4pharma/talk2knowledgegraphs/tools/subgraph_summarization.py +10 -13
  156. aiagents4pharma/talk2knowledgegraphs/utils/__init__.py +4 -7
  157. aiagents4pharma/talk2knowledgegraphs/utils/embeddings/__init__.py +4 -7
  158. aiagents4pharma/talk2knowledgegraphs/utils/embeddings/embeddings.py +4 -0
  159. aiagents4pharma/talk2knowledgegraphs/utils/embeddings/huggingface.py +11 -14
  160. aiagents4pharma/talk2knowledgegraphs/utils/embeddings/nim_molmim.py +7 -7
  161. aiagents4pharma/talk2knowledgegraphs/utils/embeddings/ollama.py +12 -6
  162. aiagents4pharma/talk2knowledgegraphs/utils/embeddings/sentence_transformer.py +8 -6
  163. aiagents4pharma/talk2knowledgegraphs/utils/enrichments/__init__.py +9 -6
  164. aiagents4pharma/talk2knowledgegraphs/utils/enrichments/enrichments.py +1 -0
  165. aiagents4pharma/talk2knowledgegraphs/utils/enrichments/ollama.py +15 -9
  166. aiagents4pharma/talk2knowledgegraphs/utils/enrichments/ols_terms.py +23 -20
  167. aiagents4pharma/talk2knowledgegraphs/utils/enrichments/pubchem_strings.py +12 -10
  168. aiagents4pharma/talk2knowledgegraphs/utils/enrichments/reactome_pathways.py +16 -10
  169. aiagents4pharma/talk2knowledgegraphs/utils/enrichments/uniprot_proteins.py +26 -18
  170. aiagents4pharma/talk2knowledgegraphs/utils/extractions/__init__.py +4 -5
  171. aiagents4pharma/talk2knowledgegraphs/utils/extractions/milvus_multimodal_pcst.py +14 -34
  172. aiagents4pharma/talk2knowledgegraphs/utils/extractions/multimodal_pcst.py +53 -47
  173. aiagents4pharma/talk2knowledgegraphs/utils/extractions/pcst.py +18 -14
  174. aiagents4pharma/talk2knowledgegraphs/utils/kg_utils.py +22 -23
  175. aiagents4pharma/talk2knowledgegraphs/utils/pubchem_utils.py +11 -10
  176. aiagents4pharma/talk2scholars/.dockerignore +13 -0
  177. aiagents4pharma/talk2scholars/Dockerfile +104 -0
  178. aiagents4pharma/talk2scholars/README.md +1 -0
  179. aiagents4pharma/talk2scholars/agents/__init__.py +1 -5
  180. aiagents4pharma/talk2scholars/agents/main_agent.py +6 -4
  181. aiagents4pharma/talk2scholars/agents/paper_download_agent.py +5 -4
  182. aiagents4pharma/talk2scholars/agents/pdf_agent.py +4 -2
  183. aiagents4pharma/talk2scholars/agents/s2_agent.py +2 -2
  184. aiagents4pharma/talk2scholars/agents/zotero_agent.py +10 -11
  185. aiagents4pharma/talk2scholars/configs/__init__.py +1 -3
  186. aiagents4pharma/talk2scholars/configs/agents/talk2scholars/__init__.py +1 -4
  187. aiagents4pharma/talk2scholars/configs/agents/talk2scholars/main_agent/default.yaml +1 -1
  188. aiagents4pharma/talk2scholars/configs/agents/talk2scholars/pdf_agent/default.yaml +1 -1
  189. aiagents4pharma/talk2scholars/configs/agents/talk2scholars/s2_agent/default.yaml +8 -8
  190. aiagents4pharma/talk2scholars/configs/agents/talk2scholars/zotero_agent/default.yaml +7 -7
  191. aiagents4pharma/talk2scholars/configs/tools/__init__.py +8 -6
  192. aiagents4pharma/talk2scholars/docker-compose/cpu/.env.example +21 -0
  193. aiagents4pharma/talk2scholars/docker-compose/cpu/docker-compose.yml +90 -0
  194. aiagents4pharma/talk2scholars/docker-compose/gpu/.env.example +21 -0
  195. aiagents4pharma/talk2scholars/docker-compose/gpu/docker-compose.yml +105 -0
  196. aiagents4pharma/talk2scholars/install.md +122 -0
  197. aiagents4pharma/talk2scholars/state/state_talk2scholars.py +8 -8
  198. aiagents4pharma/talk2scholars/tests/{test_main_agent.py → test_agents_main_agent.py} +41 -23
  199. aiagents4pharma/talk2scholars/tests/{test_paper_download_agent.py → test_agents_paper_agents_download_agent.py} +10 -16
  200. aiagents4pharma/talk2scholars/tests/{test_pdf_agent.py → test_agents_pdf_agent.py} +6 -10
  201. aiagents4pharma/talk2scholars/tests/{test_s2_agent.py → test_agents_s2_agent.py} +8 -16
  202. aiagents4pharma/talk2scholars/tests/{test_zotero_agent.py → test_agents_zotero_agent.py} +5 -7
  203. aiagents4pharma/talk2scholars/tests/{test_s2_display_dataframe.py → test_s2_tools_display_dataframe.py} +6 -7
  204. aiagents4pharma/talk2scholars/tests/{test_s2_query_dataframe.py → test_s2_tools_query_dataframe.py} +5 -15
  205. aiagents4pharma/talk2scholars/tests/{test_paper_downloader.py → test_tools_paper_downloader.py} +25 -63
  206. aiagents4pharma/talk2scholars/tests/{test_question_and_answer_tool.py → test_tools_question_and_answer_tool.py} +2 -6
  207. aiagents4pharma/talk2scholars/tests/{test_s2_multi.py → test_tools_s2_multi.py} +5 -5
  208. aiagents4pharma/talk2scholars/tests/{test_s2_retrieve.py → test_tools_s2_retrieve.py} +2 -1
  209. aiagents4pharma/talk2scholars/tests/{test_s2_search.py → test_tools_s2_search.py} +5 -5
  210. aiagents4pharma/talk2scholars/tests/{test_s2_single.py → test_tools_s2_single.py} +5 -5
  211. aiagents4pharma/talk2scholars/tests/{test_arxiv_downloader.py → test_utils_arxiv_downloader.py} +16 -25
  212. aiagents4pharma/talk2scholars/tests/{test_base_paper_downloader.py → test_utils_base_paper_downloader.py} +25 -47
  213. aiagents4pharma/talk2scholars/tests/{test_biorxiv_downloader.py → test_utils_biorxiv_downloader.py} +14 -42
  214. aiagents4pharma/talk2scholars/tests/{test_medrxiv_downloader.py → test_utils_medrxiv_downloader.py} +15 -49
  215. aiagents4pharma/talk2scholars/tests/{test_nvidia_nim_reranker.py → test_utils_nvidia_nim_reranker.py} +6 -16
  216. aiagents4pharma/talk2scholars/tests/{test_pdf_answer_formatter.py → test_utils_pdf_answer_formatter.py} +1 -0
  217. aiagents4pharma/talk2scholars/tests/{test_pdf_batch_processor.py → test_utils_pdf_batch_processor.py} +6 -15
  218. aiagents4pharma/talk2scholars/tests/{test_pdf_collection_manager.py → test_utils_pdf_collection_manager.py} +34 -11
  219. aiagents4pharma/talk2scholars/tests/{test_pdf_document_processor.py → test_utils_pdf_document_processor.py} +2 -3
  220. aiagents4pharma/talk2scholars/tests/{test_pdf_generate_answer.py → test_utils_pdf_generate_answer.py} +3 -6
  221. aiagents4pharma/talk2scholars/tests/{test_pdf_gpu_detection.py → test_utils_pdf_gpu_detection.py} +5 -16
  222. aiagents4pharma/talk2scholars/tests/{test_pdf_rag_pipeline.py → test_utils_pdf_rag_pipeline.py} +7 -17
  223. aiagents4pharma/talk2scholars/tests/{test_pdf_retrieve_chunks.py → test_utils_pdf_retrieve_chunks.py} +4 -11
  224. aiagents4pharma/talk2scholars/tests/{test_pdf_singleton_manager.py → test_utils_pdf_singleton_manager.py} +26 -23
  225. aiagents4pharma/talk2scholars/tests/{test_pdf_vector_normalization.py → test_utils_pdf_vector_normalization.py} +1 -1
  226. aiagents4pharma/talk2scholars/tests/{test_pdf_vector_store.py → test_utils_pdf_vector_store.py} +27 -55
  227. aiagents4pharma/talk2scholars/tests/{test_pubmed_downloader.py → test_utils_pubmed_downloader.py} +31 -91
  228. aiagents4pharma/talk2scholars/tests/{test_read_helper_utils.py → test_utils_read_helper_utils.py} +2 -6
  229. aiagents4pharma/talk2scholars/tests/{test_s2_utils_ext_ids.py → test_utils_s2_utils_ext_ids.py} +5 -15
  230. aiagents4pharma/talk2scholars/tests/{test_zotero_human_in_the_loop.py → test_utils_zotero_human_in_the_loop.py} +6 -13
  231. aiagents4pharma/talk2scholars/tests/{test_zotero_path.py → test_utils_zotero_path.py} +53 -45
  232. aiagents4pharma/talk2scholars/tests/{test_zotero_read.py → test_utils_zotero_read.py} +30 -91
  233. aiagents4pharma/talk2scholars/tests/{test_zotero_write.py → test_utils_zotero_write.py} +6 -16
  234. aiagents4pharma/talk2scholars/tools/__init__.py +1 -4
  235. aiagents4pharma/talk2scholars/tools/paper_download/paper_downloader.py +20 -35
  236. aiagents4pharma/talk2scholars/tools/paper_download/utils/__init__.py +7 -5
  237. aiagents4pharma/talk2scholars/tools/paper_download/utils/arxiv_downloader.py +9 -11
  238. aiagents4pharma/talk2scholars/tools/paper_download/utils/base_paper_downloader.py +14 -21
  239. aiagents4pharma/talk2scholars/tools/paper_download/utils/biorxiv_downloader.py +14 -22
  240. aiagents4pharma/talk2scholars/tools/paper_download/utils/medrxiv_downloader.py +11 -13
  241. aiagents4pharma/talk2scholars/tools/paper_download/utils/pubmed_downloader.py +14 -28
  242. aiagents4pharma/talk2scholars/tools/pdf/question_and_answer.py +4 -8
  243. aiagents4pharma/talk2scholars/tools/pdf/utils/__init__.py +16 -14
  244. aiagents4pharma/talk2scholars/tools/pdf/utils/answer_formatter.py +4 -4
  245. aiagents4pharma/talk2scholars/tools/pdf/utils/batch_processor.py +15 -17
  246. aiagents4pharma/talk2scholars/tools/pdf/utils/collection_manager.py +2 -2
  247. aiagents4pharma/talk2scholars/tools/pdf/utils/document_processor.py +5 -5
  248. aiagents4pharma/talk2scholars/tools/pdf/utils/generate_answer.py +4 -4
  249. aiagents4pharma/talk2scholars/tools/pdf/utils/get_vectorstore.py +2 -6
  250. aiagents4pharma/talk2scholars/tools/pdf/utils/gpu_detection.py +5 -9
  251. aiagents4pharma/talk2scholars/tools/pdf/utils/nvidia_nim_reranker.py +4 -4
  252. aiagents4pharma/talk2scholars/tools/pdf/utils/paper_loader.py +2 -2
  253. aiagents4pharma/talk2scholars/tools/pdf/utils/rag_pipeline.py +6 -15
  254. aiagents4pharma/talk2scholars/tools/pdf/utils/retrieve_chunks.py +7 -15
  255. aiagents4pharma/talk2scholars/tools/pdf/utils/singleton_manager.py +2 -2
  256. aiagents4pharma/talk2scholars/tools/pdf/utils/tool_helper.py +3 -4
  257. aiagents4pharma/talk2scholars/tools/pdf/utils/vector_normalization.py +8 -17
  258. aiagents4pharma/talk2scholars/tools/pdf/utils/vector_store.py +17 -33
  259. aiagents4pharma/talk2scholars/tools/s2/__init__.py +8 -6
  260. aiagents4pharma/talk2scholars/tools/s2/display_dataframe.py +3 -7
  261. aiagents4pharma/talk2scholars/tools/s2/multi_paper_rec.py +7 -6
  262. aiagents4pharma/talk2scholars/tools/s2/query_dataframe.py +5 -12
  263. aiagents4pharma/talk2scholars/tools/s2/retrieve_semantic_scholar_paper_id.py +2 -4
  264. aiagents4pharma/talk2scholars/tools/s2/search.py +6 -6
  265. aiagents4pharma/talk2scholars/tools/s2/single_paper_rec.py +5 -3
  266. aiagents4pharma/talk2scholars/tools/s2/utils/__init__.py +1 -3
  267. aiagents4pharma/talk2scholars/tools/s2/utils/multi_helper.py +12 -18
  268. aiagents4pharma/talk2scholars/tools/s2/utils/search_helper.py +11 -18
  269. aiagents4pharma/talk2scholars/tools/s2/utils/single_helper.py +11 -16
  270. aiagents4pharma/talk2scholars/tools/zotero/__init__.py +1 -4
  271. aiagents4pharma/talk2scholars/tools/zotero/utils/__init__.py +1 -4
  272. aiagents4pharma/talk2scholars/tools/zotero/utils/read_helper.py +21 -39
  273. aiagents4pharma/talk2scholars/tools/zotero/utils/review_helper.py +2 -6
  274. aiagents4pharma/talk2scholars/tools/zotero/utils/write_helper.py +8 -11
  275. aiagents4pharma/talk2scholars/tools/zotero/utils/zotero_path.py +4 -12
  276. aiagents4pharma/talk2scholars/tools/zotero/utils/zotero_pdf_downloader.py +13 -27
  277. aiagents4pharma/talk2scholars/tools/zotero/zotero_read.py +4 -7
  278. aiagents4pharma/talk2scholars/tools/zotero/zotero_review.py +8 -10
  279. aiagents4pharma/talk2scholars/tools/zotero/zotero_write.py +3 -2
  280. {aiagents4pharma-1.44.0.dist-info → aiagents4pharma-1.45.1.dist-info}/METADATA +115 -51
  281. aiagents4pharma-1.45.1.dist-info/RECORD +324 -0
  282. {aiagents4pharma-1.44.0.dist-info → aiagents4pharma-1.45.1.dist-info}/WHEEL +1 -2
  283. aiagents4pharma-1.44.0.dist-info/RECORD +0 -293
  284. aiagents4pharma-1.44.0.dist-info/top_level.txt +0 -1
  285. /aiagents4pharma/talk2scholars/tests/{test_state.py → test_states_state.py} +0 -0
  286. /aiagents4pharma/talk2scholars/tests/{test_pdf_paper_loader.py → test_utils_pdf_paper_loader.py} +0 -0
  287. /aiagents4pharma/talk2scholars/tests/{test_tool_helper_utils.py → test_utils_tool_helper_utils.py} +0 -0
  288. /aiagents4pharma/talk2scholars/tests/{test_zotero_pdf_downloader_utils.py → test_utils_zotero_pdf_downloader_utils.py} +0 -0
  289. {aiagents4pharma-1.44.0.dist-info → aiagents4pharma-1.45.1.dist-info}/licenses/LICENSE +0 -0
@@ -2,12 +2,14 @@
2
2
  This file is used to import all the modules in the package.
3
3
  """
4
4
 
5
- from . import display_dataframe
6
- from . import multi_paper_rec
7
- from . import search
8
- from . import single_paper_rec
9
- from . import query_dataframe
10
- from . import retrieve_semantic_scholar_paper_id
5
+ from . import (
6
+ display_dataframe,
7
+ multi_paper_rec,
8
+ query_dataframe,
9
+ retrieve_semantic_scholar_paper_id,
10
+ search,
11
+ single_paper_rec,
12
+ )
11
13
 
12
14
  __all__ = [
13
15
  "display_dataframe",
@@ -12,17 +12,15 @@ only displays the existing list. If no papers are available, it raises NoPapersF
12
12
  to signal that a search or recommendation must be executed first.
13
13
  """
14
14
 
15
-
16
15
  import logging
17
-
18
16
  from typing import Annotated
19
- from pydantic import BaseModel, Field
17
+
20
18
  from langchain_core.messages import ToolMessage
21
19
  from langchain_core.tools import tool
22
20
  from langchain_core.tools.base import InjectedToolCallId
23
21
  from langgraph.prebuilt import InjectedState
24
22
  from langgraph.types import Command
25
-
23
+ from pydantic import BaseModel, Field
26
24
 
27
25
  # Configure logging
28
26
  logging.basicConfig(level=logging.INFO)
@@ -97,9 +95,7 @@ def display_dataframe(
97
95
  artifact = state.get(context_val)
98
96
  if not artifact:
99
97
  logger.info("No papers found in state, raising NoPapersFoundError")
100
- raise NoPapersFoundError(
101
- "No papers found. A search/rec needs to be performed first."
102
- )
98
+ raise NoPapersFoundError("No papers found. A search/rec needs to be performed first.")
103
99
  content = f"{len(artifact)} papers found. Papers are attached as an artifact."
104
100
  return Command(
105
101
  update={
@@ -9,14 +9,15 @@ of recommended papers.
9
9
  """
10
10
 
11
11
  import logging
12
- from typing import Annotated, Any, List, Optional
12
+ from typing import Annotated, Any
13
+
13
14
  from langchain_core.messages import ToolMessage
14
15
  from langchain_core.tools import tool
15
16
  from langchain_core.tools.base import InjectedToolCallId
16
17
  from langgraph.types import Command
17
18
  from pydantic import BaseModel, Field
18
- from .utils.multi_helper import MultiPaperRecData
19
19
 
20
+ from .utils.multi_helper import MultiPaperRecData
20
21
 
21
22
  # Configure logging
22
23
  logging.basicConfig(level=logging.INFO)
@@ -34,7 +35,7 @@ class MultiPaperRecInput(BaseModel):
34
35
  tool_call_id: Internal tool call identifier injected by the system.
35
36
  """
36
37
 
37
- paper_ids: List[str] = Field(
38
+ paper_ids: list[str] = Field(
38
39
  description="List of 40-character Semantic Scholar Paper IDs"
39
40
  "(at least two) to base recommendations on"
40
41
  )
@@ -44,7 +45,7 @@ class MultiPaperRecInput(BaseModel):
44
45
  ge=1,
45
46
  le=500,
46
47
  )
47
- year: Optional[str] = Field(
48
+ year: str | None = Field(
48
49
  default=None,
49
50
  description="Publication year filter; supports formats:"
50
51
  "'YYYY', 'YYYY-', '-YYYY', 'YYYY:YYYY'",
@@ -59,10 +60,10 @@ class MultiPaperRecInput(BaseModel):
59
60
  parse_docstring=True,
60
61
  )
61
62
  def get_multi_paper_recommendations(
62
- paper_ids: List[str],
63
+ paper_ids: list[str],
63
64
  tool_call_id: Annotated[str, InjectedToolCallId],
64
65
  limit: int = 10,
65
- year: Optional[str] = None,
66
+ year: str | None = None,
66
67
  ) -> Command[Any]:
67
68
  """
68
69
  Recommend related research papers using the Semantic Scholar API.
@@ -26,9 +26,8 @@ Notes
26
26
  first identifier is returned; otherwise a list is returned from all rows that have values.
27
27
  """
28
28
 
29
-
30
29
  import logging
31
- from typing import Annotated, Optional, Any
30
+ from typing import Annotated, Any
32
31
 
33
32
  import pandas as pd
34
33
  from langchain_core.messages import ToolMessage
@@ -99,7 +98,7 @@ class QueryDataFrameInput(BaseModel):
99
98
  "extract when extract_ids=True."
100
99
  ),
101
100
  )
102
- row_number: Optional[int] = Field(
101
+ row_number: int | None = Field(
103
102
  default=None,
104
103
  description=(
105
104
  "1-based index of the ID to extract from the list; if provided, returns only"
@@ -180,9 +179,7 @@ def query_dataframe(
180
179
  context_val = state.get("last_displayed_papers")
181
180
  if not context_val:
182
181
  logger.info("No papers displayed so far, raising NoPapersFoundError")
183
- raise NoPapersFoundError(
184
- "No papers found. A search needs to be performed first."
185
- )
182
+ raise NoPapersFoundError("No papers found. A search needs to be performed first.")
186
183
 
187
184
  # Resolve the paper dictionary
188
185
  if isinstance(context_val, dict):
@@ -205,14 +202,10 @@ def query_dataframe(
205
202
  if not id_column:
206
203
  raise ValueError("Must specify 'id_column' when extract_ids=True.")
207
204
  if row_number is not None:
208
- question_to_agent = (
209
- f"df['{id_column}'].dropna().str[0].tolist()[{row_number-1}]"
210
- )
205
+ question_to_agent = f"df['{id_column}'].dropna().str[0].tolist()[{row_number - 1}]"
211
206
  else:
212
207
  question_to_agent = f"df['{id_column}'].dropna().str[0].tolist()"
213
- logger.info(
214
- "extract_ids enabled: asking agent to run expression: %s", question_to_agent
215
- )
208
+ logger.info("extract_ids enabled: asking agent to run expression: %s", question_to_agent)
216
209
 
217
210
  df_agent = create_pandas_dataframe_agent(
218
211
  llm_model,
@@ -10,6 +10,7 @@ Configuration is loaded via Hydra and the top ranked result is returned.
10
10
 
11
11
  import logging
12
12
  from typing import Annotated, Any
13
+
13
14
  import hydra
14
15
  import requests
15
16
  from langchain_core.messages import ToolMessage
@@ -18,7 +19,6 @@ from langchain_core.tools.base import InjectedToolCallId
18
19
  from langgraph.types import Command
19
20
  from pydantic import BaseModel, Field
20
21
 
21
-
22
22
  # Configure logging
23
23
  logging.basicConfig(level=logging.INFO)
24
24
  logger = logging.getLogger(__name__)
@@ -36,9 +36,7 @@ class RetrieveSemanticScholarPaperIdInput(BaseModel):
36
36
  Runtime-injected identifier for tracing the tool invocation.
37
37
  """
38
38
 
39
- paper_title: str = Field(
40
- ..., description="The paper title to search for on Semantic Scholar."
41
- )
39
+ paper_title: str = Field(..., description="The paper title to search for on Semantic Scholar.")
42
40
  tool_call_id: Annotated[str, InjectedToolCallId]
43
41
 
44
42
 
@@ -8,12 +8,14 @@ optionally filtered by publication year.
8
8
  """
9
9
 
10
10
  import logging
11
- from typing import Annotated, Any, Optional
11
+ from typing import Annotated, Any
12
+
12
13
  from langchain_core.messages import ToolMessage
13
14
  from langchain_core.tools import tool
14
15
  from langchain_core.tools.base import InjectedToolCallId
15
16
  from langgraph.types import Command
16
17
  from pydantic import BaseModel, Field
18
+
17
19
  from .utils.search_helper import SearchData
18
20
 
19
21
  # Configure logging
@@ -32,16 +34,14 @@ class SearchInput(BaseModel):
32
34
  tool_call_id: Internal tool call identifier injected by the system.
33
35
  """
34
36
 
35
- query: str = Field(
36
- description="Full or partial paper title or keywords to search for"
37
- )
37
+ query: str = Field(description="Full or partial paper title or keywords to search for")
38
38
  limit: int = Field(
39
39
  default=10,
40
40
  description="Maximum number of search results to return (1-100)",
41
41
  ge=1,
42
42
  le=100,
43
43
  )
44
- year: Optional[str] = Field(
44
+ year: str | None = Field(
45
45
  default=None,
46
46
  description="Publication year filter; supports formats:"
47
47
  "'YYYY', 'YYYY-', '-YYYY', 'YYYY:YYYY'",
@@ -58,7 +58,7 @@ def search_tool(
58
58
  query: str,
59
59
  tool_call_id: Annotated[str, InjectedToolCallId],
60
60
  limit: int = 10,
61
- year: Optional[str] = None,
61
+ year: str | None = None,
62
62
  ) -> Command[Any]:
63
63
  """
64
64
  Return academic papers from Semantic Scholar matching a title or keyword query.
@@ -8,12 +8,14 @@ Given a Semantic Scholar paper ID, this tool retrieves related works
8
8
  """
9
9
 
10
10
  import logging
11
- from typing import Annotated, Any, Optional
11
+ from typing import Annotated, Any
12
+
12
13
  from langchain_core.messages import ToolMessage
13
14
  from langchain_core.tools import tool
14
15
  from langchain_core.tools.base import InjectedToolCallId
15
16
  from langgraph.types import Command
16
17
  from pydantic import BaseModel, Field
18
+
17
19
  from .utils.single_helper import SinglePaperRecData
18
20
 
19
21
  # Configure logging
@@ -40,7 +42,7 @@ class SinglePaperRecInput(BaseModel):
40
42
  ge=1,
41
43
  le=500,
42
44
  )
43
- year: Optional[str] = Field(
45
+ year: str | None = Field(
44
46
  default=None,
45
47
  description="Publication year filter; supports formats::"
46
48
  "'YYYY', 'YYYY-', '-YYYY', 'YYYY:YYYY'",
@@ -57,7 +59,7 @@ def get_single_paper_recommendations(
57
59
  paper_id: str,
58
60
  tool_call_id: Annotated[str, InjectedToolCallId],
59
61
  limit: int = 10,
60
- year: Optional[str] = None,
62
+ year: str | None = None,
61
63
  ) -> Command[Any]:
62
64
  """
63
65
  Recommend related research papers using the Semantic Scholar API for a single paper ID.
@@ -1,7 +1,5 @@
1
1
  """This module contains utility functions for the Semantic Scholar search tool."""
2
2
 
3
- from . import search_helper
4
- from . import single_helper
5
- from . import multi_helper
3
+ from . import multi_helper, search_helper, single_helper
6
4
 
7
5
  __all__ = ["search_helper", "single_helper", "multi_helper"]
@@ -6,11 +6,11 @@ Utility for fetching recommendations based on multiple papers.
6
6
 
7
7
  import json
8
8
  import logging
9
- from typing import Any, List, Optional, Dict
9
+ from typing import Any
10
+
10
11
  import hydra
11
12
  import requests
12
13
 
13
-
14
14
  # Configure logging
15
15
  logging.basicConfig(level=logging.INFO)
16
16
  logger = logging.getLogger(__name__)
@@ -21,9 +21,9 @@ class MultiPaperRecData:
21
21
 
22
22
  def __init__(
23
23
  self,
24
- paper_ids: List[str],
24
+ paper_ids: list[str],
25
25
  limit: int,
26
- year: Optional[str],
26
+ year: str | None,
27
27
  tool_call_id: str,
28
28
  ):
29
29
  self.paper_ids = paper_ids
@@ -51,7 +51,7 @@ class MultiPaperRecData:
51
51
  logger.info("Loaded configuration for multi-paper recommendation tool")
52
52
  return cfg.tools.multi_paper_recommendation
53
53
 
54
- def _create_params(self) -> Dict[str, Any]:
54
+ def _create_params(self) -> dict[str, Any]:
55
55
  """Create parameters for the API request."""
56
56
  params = {
57
57
  "limit": min(self.limit, 500),
@@ -94,9 +94,7 @@ class MultiPaperRecData:
94
94
  ) from e
95
95
 
96
96
  if self.response is None:
97
- raise RuntimeError(
98
- "Failed to obtain a response from the Semantic Scholar API."
99
- )
97
+ raise RuntimeError("Failed to obtain a response from the Semantic Scholar API.")
100
98
 
101
99
  logger.info(
102
100
  "API Response Status for multi-paper recommendations: %s",
@@ -117,9 +115,7 @@ class MultiPaperRecData:
117
115
 
118
116
  self.recommendations = self.data.get("recommendedPapers", [])
119
117
  if not self.recommendations:
120
- logger.error(
121
- "No recommendations returned from API for paper IDs: %s", self.paper_ids
122
- )
118
+ logger.error("No recommendations returned from API for paper IDs: %s", self.paper_ids)
123
119
  raise RuntimeError(
124
120
  "No recommendations were found for your query. Consider refining your search "
125
121
  "by using more specific keywords or different terms."
@@ -128,12 +124,12 @@ class MultiPaperRecData:
128
124
  def _filter_papers(self) -> None:
129
125
  """Filter and format papers."""
130
126
  # Build filtered recommendations with unified paper_ids
131
- filtered: Dict[str, Any] = {}
127
+ filtered: dict[str, Any] = {}
132
128
  for paper in self.recommendations:
133
129
  if not paper.get("title") or not paper.get("authors"):
134
130
  continue
135
131
  ext = paper.get("externalIds", {}) or {}
136
- ids: List[str] = []
132
+ ids: list[str] = []
137
133
  arxiv = ext.get("ArXiv")
138
134
  if arxiv:
139
135
  ids.append(f"arxiv:{arxiv}")
@@ -191,7 +187,7 @@ class MultiPaperRecData:
191
187
  title = paper.get("Title", "N/A")
192
188
  year = paper.get("Year", "N/A")
193
189
  snippet = self._get_snippet(paper.get("Abstract", ""))
194
- entry = f"{i+1}. {title} ({year})"
190
+ entry = f"{i + 1}. {title} ({year})"
195
191
  if snippet:
196
192
  entry += f"\n Abstract snippet: {snippet}"
197
193
  entries.append(entry)
@@ -202,14 +198,12 @@ class MultiPaperRecData:
202
198
  "Papers are attached as an artifact."
203
199
  )
204
200
  self.content += " Here is a summary of the recommendations:\n"
205
- self.content += (
206
- f"Number of recommended papers found: {self.get_paper_count()}\n"
207
- )
201
+ self.content += f"Number of recommended papers found: {self.get_paper_count()}\n"
208
202
  self.content += f"Query Paper IDs: {', '.join(self.paper_ids)}\n"
209
203
  self.content += f"Year: {self.year}\n" if self.year else ""
210
204
  self.content += "Here are a few of these papers:\n" + top_papers_info
211
205
 
212
- def process_recommendations(self) -> Dict[str, Any]:
206
+ def process_recommendations(self) -> dict[str, Any]:
213
207
  """Process the recommendations request and return results."""
214
208
  self._fetch_recommendations()
215
209
  self._filter_papers()
@@ -5,7 +5,8 @@ Utility for fetching recommendations based on a single paper.
5
5
  """
6
6
 
7
7
  import logging
8
- from typing import Any, Optional, Dict
8
+ from typing import Any
9
+
9
10
  import hydra
10
11
  import requests
11
12
 
@@ -21,7 +22,7 @@ class SearchData:
21
22
  self,
22
23
  query: str,
23
24
  limit: int,
24
- year: Optional[str],
25
+ year: str | None,
25
26
  tool_call_id: str,
26
27
  ):
27
28
  self.query = query
@@ -40,13 +41,11 @@ class SearchData:
40
41
  def _load_config(self) -> Any:
41
42
  """Load hydra configuration."""
42
43
  with hydra.initialize(version_base=None, config_path="../../../configs"):
43
- cfg = hydra.compose(
44
- config_name="config", overrides=["tools/search=default"]
45
- )
44
+ cfg = hydra.compose(config_name="config", overrides=["tools/search=default"])
46
45
  logger.info("Loaded configuration for search tool")
47
46
  return cfg.tools.search
48
47
 
49
- def _create_params(self) -> Dict[str, Any]:
48
+ def _create_params(self) -> dict[str, Any]:
50
49
  """Create parameters for the API request."""
51
50
  params = {
52
51
  "query": self.query,
@@ -64,9 +63,7 @@ class SearchData:
64
63
  # Wrap API call in try/except to catch connectivity issues
65
64
  for attempt in range(10):
66
65
  try:
67
- self.response = requests.get(
68
- self.endpoint, params=self.params, timeout=10
69
- )
66
+ self.response = requests.get(self.endpoint, params=self.params, timeout=10)
70
67
  self.response.raise_for_status() # Raises HTTPError for bad responses
71
68
  break # Exit loop if request is successful
72
69
  except requests.exceptions.RequestException as e:
@@ -82,9 +79,7 @@ class SearchData:
82
79
  ) from e
83
80
 
84
81
  if self.response is None:
85
- raise RuntimeError(
86
- "Failed to obtain a response from the Semantic Scholar API."
87
- )
82
+ raise RuntimeError("Failed to obtain a response from the Semantic Scholar API.")
88
83
 
89
84
  self.data = self.response.json()
90
85
 
@@ -99,9 +94,7 @@ class SearchData:
99
94
 
100
95
  self.papers = self.data.get("data", [])
101
96
  if not self.papers:
102
- logger.error(
103
- "No papers returned from Semantic Scholar API for query: %s", self.query
104
- )
97
+ logger.error("No papers returned from Semantic Scholar API for query: %s", self.query)
105
98
  raise RuntimeError(
106
99
  "No papers were found for your query. Consider refining your search "
107
100
  "by using more specific keywords or different terms."
@@ -110,7 +103,7 @@ class SearchData:
110
103
  def _filter_papers(self) -> None:
111
104
  """Filter and format papers."""
112
105
  # Build filtered papers mapping with unified paper_ids list
113
- filtered: Dict[str, Any] = {}
106
+ filtered: dict[str, Any] = {}
114
107
  for paper in self.papers:
115
108
  if not paper.get("title") or not paper.get("authors"):
116
109
  continue
@@ -175,7 +168,7 @@ class SearchData:
175
168
  title = paper.get("Title", "N/A")
176
169
  year = paper.get("Year", "N/A")
177
170
  snippet = self._get_snippet(paper.get("Abstract", ""))
178
- entry = f"{i+1}. {title} ({year})"
171
+ entry = f"{i + 1}. {title} ({year})"
179
172
  if snippet:
180
173
  entry += f"\n Abstract snippet: {snippet}"
181
174
  entries.append(entry)
@@ -192,7 +185,7 @@ class SearchData:
192
185
  self.content += f"Year: {self.year}\n" if self.year else ""
193
186
  self.content += "Top 3 papers:\n" + top_papers_info
194
187
 
195
- def process_search(self) -> Dict[str, Any]:
188
+ def process_search(self) -> dict[str, Any]:
196
189
  """Process the search request and return results."""
197
190
  self._fetch_papers()
198
191
  self._filter_papers()
@@ -5,7 +5,8 @@ Utility for fetching recommendations based on a single paper.
5
5
  """
6
6
 
7
7
  import logging
8
- from typing import Any, Optional, Dict, List
8
+ from typing import Any
9
+
9
10
  import hydra
10
11
  import requests
11
12
 
@@ -21,7 +22,7 @@ class SinglePaperRecData:
21
22
  self,
22
23
  paper_id: str,
23
24
  limit: int,
24
- year: Optional[str],
25
+ year: str | None,
25
26
  tool_call_id: str,
26
27
  ):
27
28
  self.paper_id = paper_id
@@ -47,7 +48,7 @@ class SinglePaperRecData:
47
48
  logger.info("Loaded configuration for single paper recommendation tool")
48
49
  return cfg.tools.single_paper_recommendation
49
50
 
50
- def _create_params(self) -> Dict[str, Any]:
51
+ def _create_params(self) -> dict[str, Any]:
51
52
  """Create parameters for the API request."""
52
53
  params = {
53
54
  "limit": min(self.limit, 500), # Max 500 per API docs
@@ -86,9 +87,7 @@ class SinglePaperRecData:
86
87
  ) from e
87
88
 
88
89
  if self.response is None:
89
- raise RuntimeError(
90
- "Failed to obtain a response from the Semantic Scholar API."
91
- )
90
+ raise RuntimeError("Failed to obtain a response from the Semantic Scholar API.")
92
91
 
93
92
  logger.info(
94
93
  "API Response Status for recommendations of paper %s: %s",
@@ -110,9 +109,7 @@ class SinglePaperRecData:
110
109
 
111
110
  self.recommendations = self.data.get("recommendedPapers", [])
112
111
  if not self.recommendations:
113
- logger.error(
114
- "No recommendations returned from API for paper: %s", self.paper_id
115
- )
112
+ logger.error("No recommendations returned from API for paper: %s", self.paper_id)
116
113
  raise RuntimeError(
117
114
  "No recommendations were found for your query. Consider refining your search "
118
115
  "by using more specific keywords or different terms."
@@ -121,12 +118,12 @@ class SinglePaperRecData:
121
118
  def _filter_papers(self) -> None:
122
119
  """Filter and format papers."""
123
120
  # Build filtered recommendations with unified paper_ids
124
- filtered: Dict[str, Any] = {}
121
+ filtered: dict[str, Any] = {}
125
122
  for paper in self.recommendations:
126
123
  if not paper.get("title") or not paper.get("authors"):
127
124
  continue
128
125
  ext = paper.get("externalIds", {}) or {}
129
- ids: List[str] = []
126
+ ids: list[str] = []
130
127
  arxiv = ext.get("ArXiv")
131
128
  if arxiv:
132
129
  ids.append(f"arxiv:{arxiv}")
@@ -184,7 +181,7 @@ class SinglePaperRecData:
184
181
  title = paper.get("Title", "N/A")
185
182
  year = paper.get("Year", "N/A")
186
183
  snippet = self._get_snippet(paper.get("Abstract", ""))
187
- entry = f"{i+1}. {title} ({year})"
184
+ entry = f"{i + 1}. {title} ({year})"
188
185
  if snippet:
189
186
  entry += f"\n Abstract snippet: {snippet}"
190
187
  entries.append(entry)
@@ -195,13 +192,11 @@ class SinglePaperRecData:
195
192
  "Papers are attached as an artifact. "
196
193
  "Here is a summary of the recommendations:\n"
197
194
  )
198
- self.content += (
199
- f"Number of recommended papers found: {self.get_paper_count()}\n"
200
- )
195
+ self.content += f"Number of recommended papers found: {self.get_paper_count()}\n"
201
196
  self.content += f"Query Paper ID: {self.paper_id}\n"
202
197
  self.content += "Here are a few of these papers:\n" + top_papers_info
203
198
 
204
- def process_recommendations(self) -> Dict[str, Any]:
199
+ def process_recommendations(self) -> dict[str, Any]:
205
200
  """Process the recommendations request and return results."""
206
201
  self._fetch_recommendations()
207
202
  self._filter_papers()
@@ -2,9 +2,6 @@
2
2
  Import statements
3
3
  """
4
4
 
5
- from . import zotero_read
6
- from . import zotero_write
7
- from . import utils
8
- from . import zotero_review
5
+ from . import utils, zotero_read, zotero_review, zotero_write
9
6
 
10
7
  __all__ = ["zotero_read", "zotero_write", "utils", "zotero_review"]
@@ -2,9 +2,6 @@
2
2
  Import statements
3
3
  """
4
4
 
5
- from . import zotero_path
6
- from . import read_helper
7
- from . import write_helper
8
- from . import review_helper
5
+ from . import read_helper, review_helper, write_helper, zotero_path
9
6
 
10
7
  __all__ = ["zotero_path", "read_helper", "write_helper", "review_helper"]