aiagents4pharma 1.43.0__py3-none-any.whl → 1.45.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- aiagents4pharma/__init__.py +2 -2
- aiagents4pharma/talk2aiagents4pharma/.dockerignore +13 -0
- aiagents4pharma/talk2aiagents4pharma/Dockerfile +105 -0
- aiagents4pharma/talk2aiagents4pharma/README.md +1 -0
- aiagents4pharma/talk2aiagents4pharma/__init__.py +4 -5
- aiagents4pharma/talk2aiagents4pharma/agents/__init__.py +3 -2
- aiagents4pharma/talk2aiagents4pharma/agents/main_agent.py +24 -23
- aiagents4pharma/talk2aiagents4pharma/configs/__init__.py +2 -2
- aiagents4pharma/talk2aiagents4pharma/configs/agents/__init__.py +2 -2
- aiagents4pharma/talk2aiagents4pharma/configs/agents/main_agent/default.yaml +2 -2
- aiagents4pharma/talk2aiagents4pharma/configs/config.yaml +1 -1
- aiagents4pharma/talk2aiagents4pharma/docker-compose/cpu/.env.example +23 -0
- aiagents4pharma/talk2aiagents4pharma/docker-compose/cpu/docker-compose.yml +93 -0
- aiagents4pharma/talk2aiagents4pharma/docker-compose/gpu/.env.example +23 -0
- aiagents4pharma/talk2aiagents4pharma/docker-compose/gpu/docker-compose.yml +108 -0
- aiagents4pharma/talk2aiagents4pharma/install.md +127 -0
- aiagents4pharma/talk2aiagents4pharma/states/__init__.py +3 -2
- aiagents4pharma/talk2aiagents4pharma/states/state_talk2aiagents4pharma.py +5 -3
- aiagents4pharma/talk2aiagents4pharma/tests/__init__.py +2 -2
- aiagents4pharma/talk2aiagents4pharma/tests/test_main_agent.py +72 -50
- aiagents4pharma/talk2biomodels/.dockerignore +13 -0
- aiagents4pharma/talk2biomodels/Dockerfile +104 -0
- aiagents4pharma/talk2biomodels/README.md +1 -0
- aiagents4pharma/talk2biomodels/__init__.py +4 -8
- aiagents4pharma/talk2biomodels/agents/__init__.py +3 -2
- aiagents4pharma/talk2biomodels/agents/t2b_agent.py +47 -42
- aiagents4pharma/talk2biomodels/api/__init__.py +4 -5
- aiagents4pharma/talk2biomodels/api/kegg.py +14 -10
- aiagents4pharma/talk2biomodels/api/ols.py +13 -10
- aiagents4pharma/talk2biomodels/api/uniprot.py +7 -6
- aiagents4pharma/talk2biomodels/configs/__init__.py +3 -4
- aiagents4pharma/talk2biomodels/configs/agents/__init__.py +2 -2
- aiagents4pharma/talk2biomodels/configs/agents/t2b_agent/__init__.py +2 -2
- aiagents4pharma/talk2biomodels/configs/agents/t2b_agent/default.yaml +1 -1
- aiagents4pharma/talk2biomodels/configs/config.yaml +1 -1
- aiagents4pharma/talk2biomodels/configs/tools/__init__.py +4 -5
- aiagents4pharma/talk2biomodels/configs/tools/ask_question/__init__.py +2 -2
- aiagents4pharma/talk2biomodels/configs/tools/ask_question/default.yaml +1 -2
- aiagents4pharma/talk2biomodels/configs/tools/custom_plotter/__init__.py +2 -2
- aiagents4pharma/talk2biomodels/configs/tools/custom_plotter/default.yaml +1 -1
- aiagents4pharma/talk2biomodels/configs/tools/get_annotation/__init__.py +2 -2
- aiagents4pharma/talk2biomodels/configs/tools/get_annotation/default.yaml +1 -1
- aiagents4pharma/talk2biomodels/install.md +63 -0
- aiagents4pharma/talk2biomodels/models/__init__.py +4 -4
- aiagents4pharma/talk2biomodels/models/basico_model.py +36 -28
- aiagents4pharma/talk2biomodels/models/sys_bio_model.py +13 -10
- aiagents4pharma/talk2biomodels/states/__init__.py +3 -2
- aiagents4pharma/talk2biomodels/states/state_talk2biomodels.py +12 -8
- aiagents4pharma/talk2biomodels/tests/BIOMD0000000449_url.xml +1585 -0
- aiagents4pharma/talk2biomodels/tests/__init__.py +2 -2
- aiagents4pharma/talk2biomodels/tests/article_on_model_537.pdf +0 -0
- aiagents4pharma/talk2biomodels/tests/test_api.py +18 -14
- aiagents4pharma/talk2biomodels/tests/test_ask_question.py +8 -9
- aiagents4pharma/talk2biomodels/tests/test_basico_model.py +15 -9
- aiagents4pharma/talk2biomodels/tests/test_get_annotation.py +54 -55
- aiagents4pharma/talk2biomodels/tests/test_getmodelinfo.py +28 -27
- aiagents4pharma/talk2biomodels/tests/test_integration.py +21 -33
- aiagents4pharma/talk2biomodels/tests/test_load_biomodel.py +14 -11
- aiagents4pharma/talk2biomodels/tests/test_param_scan.py +21 -20
- aiagents4pharma/talk2biomodels/tests/test_query_article.py +129 -29
- aiagents4pharma/talk2biomodels/tests/test_search_models.py +9 -13
- aiagents4pharma/talk2biomodels/tests/test_simulate_model.py +16 -15
- aiagents4pharma/talk2biomodels/tests/test_steady_state.py +12 -22
- aiagents4pharma/talk2biomodels/tests/test_sys_bio_model.py +33 -29
- aiagents4pharma/talk2biomodels/tools/__init__.py +15 -12
- aiagents4pharma/talk2biomodels/tools/ask_question.py +42 -32
- aiagents4pharma/talk2biomodels/tools/custom_plotter.py +51 -43
- aiagents4pharma/talk2biomodels/tools/get_annotation.py +99 -75
- aiagents4pharma/talk2biomodels/tools/get_modelinfo.py +57 -51
- aiagents4pharma/talk2biomodels/tools/load_arguments.py +52 -32
- aiagents4pharma/talk2biomodels/tools/load_biomodel.py +8 -2
- aiagents4pharma/talk2biomodels/tools/parameter_scan.py +107 -90
- aiagents4pharma/talk2biomodels/tools/query_article.py +14 -13
- aiagents4pharma/talk2biomodels/tools/search_models.py +37 -26
- aiagents4pharma/talk2biomodels/tools/simulate_model.py +47 -37
- aiagents4pharma/talk2biomodels/tools/steady_state.py +76 -58
- aiagents4pharma/talk2biomodels/tools/utils.py +4 -3
- aiagents4pharma/talk2cells/README.md +1 -0
- aiagents4pharma/talk2cells/__init__.py +4 -5
- aiagents4pharma/talk2cells/agents/__init__.py +3 -2
- aiagents4pharma/talk2cells/agents/scp_agent.py +21 -19
- aiagents4pharma/talk2cells/states/__init__.py +3 -2
- aiagents4pharma/talk2cells/states/state_talk2cells.py +4 -2
- aiagents4pharma/talk2cells/tests/scp_agent/test_scp_agent.py +8 -9
- aiagents4pharma/talk2cells/tools/__init__.py +3 -2
- aiagents4pharma/talk2cells/tools/scp_agent/__init__.py +4 -4
- aiagents4pharma/talk2cells/tools/scp_agent/display_studies.py +5 -3
- aiagents4pharma/talk2cells/tools/scp_agent/search_studies.py +21 -22
- aiagents4pharma/talk2knowledgegraphs/.dockerignore +13 -0
- aiagents4pharma/talk2knowledgegraphs/Dockerfile +103 -0
- aiagents4pharma/talk2knowledgegraphs/README.md +1 -0
- aiagents4pharma/talk2knowledgegraphs/__init__.py +4 -7
- aiagents4pharma/talk2knowledgegraphs/agents/__init__.py +3 -2
- aiagents4pharma/talk2knowledgegraphs/agents/t2kg_agent.py +40 -30
- aiagents4pharma/talk2knowledgegraphs/configs/__init__.py +3 -6
- aiagents4pharma/talk2knowledgegraphs/configs/agents/t2kg_agent/__init__.py +2 -2
- aiagents4pharma/talk2knowledgegraphs/configs/agents/t2kg_agent/default.yaml +8 -8
- aiagents4pharma/talk2knowledgegraphs/configs/app/__init__.py +3 -2
- aiagents4pharma/talk2knowledgegraphs/configs/app/frontend/__init__.py +2 -2
- aiagents4pharma/talk2knowledgegraphs/configs/app/frontend/default.yaml +1 -1
- aiagents4pharma/talk2knowledgegraphs/configs/config.yaml +1 -1
- aiagents4pharma/talk2knowledgegraphs/configs/tools/__init__.py +4 -5
- aiagents4pharma/talk2knowledgegraphs/configs/tools/graphrag_reasoning/__init__.py +2 -2
- aiagents4pharma/talk2knowledgegraphs/configs/tools/graphrag_reasoning/default.yaml +1 -1
- aiagents4pharma/talk2knowledgegraphs/configs/tools/multimodal_subgraph_extraction/default.yaml +17 -2
- aiagents4pharma/talk2knowledgegraphs/configs/tools/subgraph_extraction/__init__.py +2 -2
- aiagents4pharma/talk2knowledgegraphs/configs/tools/subgraph_extraction/default.yaml +1 -1
- aiagents4pharma/talk2knowledgegraphs/configs/tools/subgraph_summarization/__init__.py +2 -2
- aiagents4pharma/talk2knowledgegraphs/configs/tools/subgraph_summarization/default.yaml +1 -1
- aiagents4pharma/talk2knowledgegraphs/configs/utils/enrichments/ols_terms/default.yaml +1 -1
- aiagents4pharma/talk2knowledgegraphs/configs/utils/enrichments/reactome_pathways/default.yaml +1 -1
- aiagents4pharma/talk2knowledgegraphs/configs/utils/enrichments/uniprot_proteins/default.yaml +1 -1
- aiagents4pharma/talk2knowledgegraphs/configs/utils/pubchem_utils/default.yaml +1 -1
- aiagents4pharma/talk2knowledgegraphs/datasets/__init__.py +4 -6
- aiagents4pharma/talk2knowledgegraphs/datasets/biobridge_primekg.py +115 -67
- aiagents4pharma/talk2knowledgegraphs/datasets/dataset.py +2 -0
- aiagents4pharma/talk2knowledgegraphs/datasets/primekg.py +35 -24
- aiagents4pharma/talk2knowledgegraphs/datasets/starkqa_primekg.py +29 -21
- aiagents4pharma/talk2knowledgegraphs/docker-compose/cpu/.env.example +23 -0
- aiagents4pharma/talk2knowledgegraphs/docker-compose/cpu/docker-compose.yml +93 -0
- aiagents4pharma/talk2knowledgegraphs/docker-compose/gpu/.env.example +23 -0
- aiagents4pharma/talk2knowledgegraphs/docker-compose/gpu/docker-compose.yml +108 -0
- aiagents4pharma/talk2knowledgegraphs/entrypoint.sh +190 -0
- aiagents4pharma/talk2knowledgegraphs/install.md +140 -0
- aiagents4pharma/talk2knowledgegraphs/milvus_data_dump.py +31 -65
- aiagents4pharma/talk2knowledgegraphs/states/__init__.py +3 -2
- aiagents4pharma/talk2knowledgegraphs/states/state_talk2knowledgegraphs.py +1 -0
- aiagents4pharma/talk2knowledgegraphs/tests/test_agents_t2kg_agent.py +65 -40
- aiagents4pharma/talk2knowledgegraphs/tests/test_datasets_biobridge_primekg.py +54 -48
- aiagents4pharma/talk2knowledgegraphs/tests/test_datasets_dataset.py +4 -0
- aiagents4pharma/talk2knowledgegraphs/tests/test_datasets_primekg.py +17 -4
- aiagents4pharma/talk2knowledgegraphs/tests/test_datasets_starkqa_primekg.py +33 -24
- aiagents4pharma/talk2knowledgegraphs/tests/test_tools_graphrag_reasoning.py +116 -69
- aiagents4pharma/talk2knowledgegraphs/tests/test_tools_milvus_multimodal_subgraph_extraction.py +736 -413
- aiagents4pharma/talk2knowledgegraphs/tests/test_tools_multimodal_subgraph_extraction.py +22 -15
- aiagents4pharma/talk2knowledgegraphs/tests/test_tools_subgraph_extraction.py +19 -12
- aiagents4pharma/talk2knowledgegraphs/tests/test_tools_subgraph_summarization.py +95 -48
- aiagents4pharma/talk2knowledgegraphs/tests/test_utils_embeddings_embeddings.py +4 -0
- aiagents4pharma/talk2knowledgegraphs/tests/test_utils_embeddings_huggingface.py +5 -0
- aiagents4pharma/talk2knowledgegraphs/tests/test_utils_embeddings_nim_molmim.py +13 -18
- aiagents4pharma/talk2knowledgegraphs/tests/test_utils_embeddings_ollama.py +10 -3
- aiagents4pharma/talk2knowledgegraphs/tests/test_utils_enrichments_enrichments.py +4 -3
- aiagents4pharma/talk2knowledgegraphs/tests/test_utils_enrichments_ollama.py +3 -2
- aiagents4pharma/talk2knowledgegraphs/tests/test_utils_enrichments_ols.py +1 -0
- aiagents4pharma/talk2knowledgegraphs/tests/test_utils_enrichments_pubchem.py +9 -4
- aiagents4pharma/talk2knowledgegraphs/tests/test_utils_enrichments_reactome.py +6 -6
- aiagents4pharma/talk2knowledgegraphs/tests/test_utils_enrichments_uniprot.py +4 -0
- aiagents4pharma/talk2knowledgegraphs/tests/test_utils_extractions_milvus_multimodal_pcst.py +442 -42
- aiagents4pharma/talk2knowledgegraphs/tests/test_utils_kg_utils.py +3 -4
- aiagents4pharma/talk2knowledgegraphs/tests/test_utils_pubchem_utils.py +10 -6
- aiagents4pharma/talk2knowledgegraphs/tools/__init__.py +10 -7
- aiagents4pharma/talk2knowledgegraphs/tools/graphrag_reasoning.py +15 -20
- aiagents4pharma/talk2knowledgegraphs/tools/milvus_multimodal_subgraph_extraction.py +245 -205
- aiagents4pharma/talk2knowledgegraphs/tools/multimodal_subgraph_extraction.py +92 -90
- aiagents4pharma/talk2knowledgegraphs/tools/subgraph_extraction.py +25 -37
- aiagents4pharma/talk2knowledgegraphs/tools/subgraph_summarization.py +10 -13
- aiagents4pharma/talk2knowledgegraphs/utils/__init__.py +4 -7
- aiagents4pharma/talk2knowledgegraphs/utils/embeddings/__init__.py +4 -7
- aiagents4pharma/talk2knowledgegraphs/utils/embeddings/embeddings.py +4 -0
- aiagents4pharma/talk2knowledgegraphs/utils/embeddings/huggingface.py +11 -14
- aiagents4pharma/talk2knowledgegraphs/utils/embeddings/nim_molmim.py +7 -7
- aiagents4pharma/talk2knowledgegraphs/utils/embeddings/ollama.py +12 -6
- aiagents4pharma/talk2knowledgegraphs/utils/embeddings/sentence_transformer.py +8 -6
- aiagents4pharma/talk2knowledgegraphs/utils/enrichments/__init__.py +9 -6
- aiagents4pharma/talk2knowledgegraphs/utils/enrichments/enrichments.py +1 -0
- aiagents4pharma/talk2knowledgegraphs/utils/enrichments/ollama.py +15 -9
- aiagents4pharma/talk2knowledgegraphs/utils/enrichments/ols_terms.py +23 -20
- aiagents4pharma/talk2knowledgegraphs/utils/enrichments/pubchem_strings.py +12 -10
- aiagents4pharma/talk2knowledgegraphs/utils/enrichments/reactome_pathways.py +16 -10
- aiagents4pharma/talk2knowledgegraphs/utils/enrichments/uniprot_proteins.py +26 -18
- aiagents4pharma/talk2knowledgegraphs/utils/extractions/__init__.py +4 -5
- aiagents4pharma/talk2knowledgegraphs/utils/extractions/milvus_multimodal_pcst.py +218 -81
- aiagents4pharma/talk2knowledgegraphs/utils/extractions/multimodal_pcst.py +53 -47
- aiagents4pharma/talk2knowledgegraphs/utils/extractions/pcst.py +18 -14
- aiagents4pharma/talk2knowledgegraphs/utils/kg_utils.py +22 -23
- aiagents4pharma/talk2knowledgegraphs/utils/pubchem_utils.py +11 -10
- aiagents4pharma/talk2scholars/.dockerignore +13 -0
- aiagents4pharma/talk2scholars/Dockerfile +104 -0
- aiagents4pharma/talk2scholars/README.md +1 -0
- aiagents4pharma/talk2scholars/agents/__init__.py +1 -5
- aiagents4pharma/talk2scholars/agents/main_agent.py +6 -4
- aiagents4pharma/talk2scholars/agents/paper_download_agent.py +5 -4
- aiagents4pharma/talk2scholars/agents/pdf_agent.py +4 -2
- aiagents4pharma/talk2scholars/agents/s2_agent.py +2 -2
- aiagents4pharma/talk2scholars/agents/zotero_agent.py +10 -11
- aiagents4pharma/talk2scholars/configs/__init__.py +1 -3
- aiagents4pharma/talk2scholars/configs/agents/talk2scholars/__init__.py +1 -4
- aiagents4pharma/talk2scholars/configs/agents/talk2scholars/main_agent/default.yaml +1 -1
- aiagents4pharma/talk2scholars/configs/agents/talk2scholars/pdf_agent/default.yaml +1 -1
- aiagents4pharma/talk2scholars/configs/agents/talk2scholars/s2_agent/default.yaml +8 -8
- aiagents4pharma/talk2scholars/configs/agents/talk2scholars/zotero_agent/default.yaml +7 -7
- aiagents4pharma/talk2scholars/configs/tools/__init__.py +8 -6
- aiagents4pharma/talk2scholars/docker-compose/cpu/.env.example +21 -0
- aiagents4pharma/talk2scholars/docker-compose/cpu/docker-compose.yml +90 -0
- aiagents4pharma/talk2scholars/docker-compose/gpu/.env.example +21 -0
- aiagents4pharma/talk2scholars/docker-compose/gpu/docker-compose.yml +105 -0
- aiagents4pharma/talk2scholars/install.md +122 -0
- aiagents4pharma/talk2scholars/state/state_talk2scholars.py +8 -8
- aiagents4pharma/talk2scholars/tests/{test_main_agent.py → test_agents_main_agent.py} +41 -23
- aiagents4pharma/talk2scholars/tests/{test_paper_download_agent.py → test_agents_paper_agents_download_agent.py} +10 -16
- aiagents4pharma/talk2scholars/tests/{test_pdf_agent.py → test_agents_pdf_agent.py} +6 -10
- aiagents4pharma/talk2scholars/tests/{test_s2_agent.py → test_agents_s2_agent.py} +8 -16
- aiagents4pharma/talk2scholars/tests/{test_zotero_agent.py → test_agents_zotero_agent.py} +5 -7
- aiagents4pharma/talk2scholars/tests/{test_s2_display_dataframe.py → test_s2_tools_display_dataframe.py} +6 -7
- aiagents4pharma/talk2scholars/tests/{test_s2_query_dataframe.py → test_s2_tools_query_dataframe.py} +5 -15
- aiagents4pharma/talk2scholars/tests/{test_paper_downloader.py → test_tools_paper_downloader.py} +25 -63
- aiagents4pharma/talk2scholars/tests/{test_question_and_answer_tool.py → test_tools_question_and_answer_tool.py} +2 -6
- aiagents4pharma/talk2scholars/tests/{test_s2_multi.py → test_tools_s2_multi.py} +5 -5
- aiagents4pharma/talk2scholars/tests/{test_s2_retrieve.py → test_tools_s2_retrieve.py} +2 -1
- aiagents4pharma/talk2scholars/tests/{test_s2_search.py → test_tools_s2_search.py} +5 -5
- aiagents4pharma/talk2scholars/tests/{test_s2_single.py → test_tools_s2_single.py} +5 -5
- aiagents4pharma/talk2scholars/tests/{test_arxiv_downloader.py → test_utils_arxiv_downloader.py} +16 -25
- aiagents4pharma/talk2scholars/tests/{test_base_paper_downloader.py → test_utils_base_paper_downloader.py} +25 -47
- aiagents4pharma/talk2scholars/tests/{test_biorxiv_downloader.py → test_utils_biorxiv_downloader.py} +14 -42
- aiagents4pharma/talk2scholars/tests/{test_medrxiv_downloader.py → test_utils_medrxiv_downloader.py} +15 -49
- aiagents4pharma/talk2scholars/tests/{test_nvidia_nim_reranker.py → test_utils_nvidia_nim_reranker.py} +6 -16
- aiagents4pharma/talk2scholars/tests/{test_pdf_answer_formatter.py → test_utils_pdf_answer_formatter.py} +1 -0
- aiagents4pharma/talk2scholars/tests/{test_pdf_batch_processor.py → test_utils_pdf_batch_processor.py} +6 -15
- aiagents4pharma/talk2scholars/tests/{test_pdf_collection_manager.py → test_utils_pdf_collection_manager.py} +34 -11
- aiagents4pharma/talk2scholars/tests/{test_pdf_document_processor.py → test_utils_pdf_document_processor.py} +2 -3
- aiagents4pharma/talk2scholars/tests/{test_pdf_generate_answer.py → test_utils_pdf_generate_answer.py} +3 -6
- aiagents4pharma/talk2scholars/tests/{test_pdf_gpu_detection.py → test_utils_pdf_gpu_detection.py} +5 -16
- aiagents4pharma/talk2scholars/tests/{test_pdf_rag_pipeline.py → test_utils_pdf_rag_pipeline.py} +7 -17
- aiagents4pharma/talk2scholars/tests/{test_pdf_retrieve_chunks.py → test_utils_pdf_retrieve_chunks.py} +4 -11
- aiagents4pharma/talk2scholars/tests/{test_pdf_singleton_manager.py → test_utils_pdf_singleton_manager.py} +26 -23
- aiagents4pharma/talk2scholars/tests/{test_pdf_vector_normalization.py → test_utils_pdf_vector_normalization.py} +1 -1
- aiagents4pharma/talk2scholars/tests/{test_pdf_vector_store.py → test_utils_pdf_vector_store.py} +27 -55
- aiagents4pharma/talk2scholars/tests/{test_pubmed_downloader.py → test_utils_pubmed_downloader.py} +31 -91
- aiagents4pharma/talk2scholars/tests/{test_read_helper_utils.py → test_utils_read_helper_utils.py} +2 -6
- aiagents4pharma/talk2scholars/tests/{test_s2_utils_ext_ids.py → test_utils_s2_utils_ext_ids.py} +5 -15
- aiagents4pharma/talk2scholars/tests/{test_zotero_human_in_the_loop.py → test_utils_zotero_human_in_the_loop.py} +6 -13
- aiagents4pharma/talk2scholars/tests/{test_zotero_path.py → test_utils_zotero_path.py} +53 -45
- aiagents4pharma/talk2scholars/tests/{test_zotero_read.py → test_utils_zotero_read.py} +30 -91
- aiagents4pharma/talk2scholars/tests/{test_zotero_write.py → test_utils_zotero_write.py} +6 -16
- aiagents4pharma/talk2scholars/tools/__init__.py +1 -4
- aiagents4pharma/talk2scholars/tools/paper_download/paper_downloader.py +20 -35
- aiagents4pharma/talk2scholars/tools/paper_download/utils/__init__.py +7 -5
- aiagents4pharma/talk2scholars/tools/paper_download/utils/arxiv_downloader.py +9 -11
- aiagents4pharma/talk2scholars/tools/paper_download/utils/base_paper_downloader.py +14 -21
- aiagents4pharma/talk2scholars/tools/paper_download/utils/biorxiv_downloader.py +14 -22
- aiagents4pharma/talk2scholars/tools/paper_download/utils/medrxiv_downloader.py +11 -13
- aiagents4pharma/talk2scholars/tools/paper_download/utils/pubmed_downloader.py +14 -28
- aiagents4pharma/talk2scholars/tools/pdf/question_and_answer.py +4 -8
- aiagents4pharma/talk2scholars/tools/pdf/utils/__init__.py +16 -14
- aiagents4pharma/talk2scholars/tools/pdf/utils/answer_formatter.py +4 -4
- aiagents4pharma/talk2scholars/tools/pdf/utils/batch_processor.py +15 -17
- aiagents4pharma/talk2scholars/tools/pdf/utils/collection_manager.py +2 -2
- aiagents4pharma/talk2scholars/tools/pdf/utils/document_processor.py +5 -5
- aiagents4pharma/talk2scholars/tools/pdf/utils/generate_answer.py +4 -4
- aiagents4pharma/talk2scholars/tools/pdf/utils/get_vectorstore.py +2 -6
- aiagents4pharma/talk2scholars/tools/pdf/utils/gpu_detection.py +5 -9
- aiagents4pharma/talk2scholars/tools/pdf/utils/nvidia_nim_reranker.py +4 -4
- aiagents4pharma/talk2scholars/tools/pdf/utils/paper_loader.py +2 -2
- aiagents4pharma/talk2scholars/tools/pdf/utils/rag_pipeline.py +6 -15
- aiagents4pharma/talk2scholars/tools/pdf/utils/retrieve_chunks.py +7 -15
- aiagents4pharma/talk2scholars/tools/pdf/utils/singleton_manager.py +2 -2
- aiagents4pharma/talk2scholars/tools/pdf/utils/tool_helper.py +3 -4
- aiagents4pharma/talk2scholars/tools/pdf/utils/vector_normalization.py +8 -17
- aiagents4pharma/talk2scholars/tools/pdf/utils/vector_store.py +17 -33
- aiagents4pharma/talk2scholars/tools/s2/__init__.py +8 -6
- aiagents4pharma/talk2scholars/tools/s2/display_dataframe.py +3 -7
- aiagents4pharma/talk2scholars/tools/s2/multi_paper_rec.py +7 -6
- aiagents4pharma/talk2scholars/tools/s2/query_dataframe.py +5 -12
- aiagents4pharma/talk2scholars/tools/s2/retrieve_semantic_scholar_paper_id.py +2 -4
- aiagents4pharma/talk2scholars/tools/s2/search.py +6 -6
- aiagents4pharma/talk2scholars/tools/s2/single_paper_rec.py +5 -3
- aiagents4pharma/talk2scholars/tools/s2/utils/__init__.py +1 -3
- aiagents4pharma/talk2scholars/tools/s2/utils/multi_helper.py +12 -18
- aiagents4pharma/talk2scholars/tools/s2/utils/search_helper.py +11 -18
- aiagents4pharma/talk2scholars/tools/s2/utils/single_helper.py +11 -16
- aiagents4pharma/talk2scholars/tools/zotero/__init__.py +1 -4
- aiagents4pharma/talk2scholars/tools/zotero/utils/__init__.py +1 -4
- aiagents4pharma/talk2scholars/tools/zotero/utils/read_helper.py +21 -39
- aiagents4pharma/talk2scholars/tools/zotero/utils/review_helper.py +2 -6
- aiagents4pharma/talk2scholars/tools/zotero/utils/write_helper.py +8 -11
- aiagents4pharma/talk2scholars/tools/zotero/utils/zotero_path.py +4 -12
- aiagents4pharma/talk2scholars/tools/zotero/utils/zotero_pdf_downloader.py +13 -27
- aiagents4pharma/talk2scholars/tools/zotero/zotero_read.py +4 -7
- aiagents4pharma/talk2scholars/tools/zotero/zotero_review.py +8 -10
- aiagents4pharma/talk2scholars/tools/zotero/zotero_write.py +3 -2
- {aiagents4pharma-1.43.0.dist-info → aiagents4pharma-1.45.0.dist-info}/METADATA +115 -50
- aiagents4pharma-1.45.0.dist-info/RECORD +324 -0
- {aiagents4pharma-1.43.0.dist-info → aiagents4pharma-1.45.0.dist-info}/WHEEL +1 -2
- aiagents4pharma-1.43.0.dist-info/RECORD +0 -293
- aiagents4pharma-1.43.0.dist-info/top_level.txt +0 -1
- /aiagents4pharma/talk2scholars/tests/{test_state.py → test_states_state.py} +0 -0
- /aiagents4pharma/talk2scholars/tests/{test_pdf_paper_loader.py → test_utils_pdf_paper_loader.py} +0 -0
- /aiagents4pharma/talk2scholars/tests/{test_tool_helper_utils.py → test_utils_tool_helper_utils.py} +0 -0
- /aiagents4pharma/talk2scholars/tests/{test_zotero_pdf_downloader_utils.py → test_utils_zotero_pdf_downloader_utils.py} +0 -0
- {aiagents4pharma-1.43.0.dist-info → aiagents4pharma-1.45.0.dist-info}/licenses/LICENSE +0 -0
@@ -17,7 +17,6 @@ from aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_pdf_downloader impo
|
|
17
17
|
)
|
18
18
|
from aiagents4pharma.talk2scholars.tools.zotero.zotero_read import zotero_read
|
19
19
|
|
20
|
-
|
21
20
|
# Dummy Hydra configuration to be used in tests
|
22
21
|
dummy_zotero_read_config = SimpleNamespace(
|
23
22
|
user_id="dummy_user",
|
@@ -34,14 +33,10 @@ dummy_cfg = SimpleNamespace(tools=SimpleNamespace(zotero_read=dummy_zotero_read_
|
|
34
33
|
class TestZoteroSearchTool(unittest.TestCase):
|
35
34
|
"""Tests for Zotero search tool."""
|
36
35
|
|
37
|
-
@patch(
|
38
|
-
"aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections"
|
39
|
-
)
|
36
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections")
|
40
37
|
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.zotero.Zotero")
|
41
38
|
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.compose")
|
42
|
-
@patch(
|
43
|
-
"aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.initialize"
|
44
|
-
)
|
39
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.initialize")
|
45
40
|
def test_valid_query(
|
46
41
|
self,
|
47
42
|
mock_hydra_init,
|
@@ -111,14 +106,10 @@ class TestZoteroSearchTool(unittest.TestCase):
|
|
111
106
|
self.assertIn("Query: test", message_content)
|
112
107
|
self.assertIn("Number of papers found: 2", message_content)
|
113
108
|
|
114
|
-
@patch(
|
115
|
-
"aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections"
|
116
|
-
)
|
109
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections")
|
117
110
|
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.zotero.Zotero")
|
118
111
|
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.compose")
|
119
|
-
@patch(
|
120
|
-
"aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.initialize"
|
121
|
-
)
|
112
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.initialize")
|
122
113
|
def test_empty_query_fetch_all_items(
|
123
114
|
self,
|
124
115
|
mock_hydra_init,
|
@@ -159,18 +150,12 @@ class TestZoteroSearchTool(unittest.TestCase):
|
|
159
150
|
update = result.update
|
160
151
|
filtered_papers = update["article_data"]
|
161
152
|
self.assertIn("paper1", filtered_papers)
|
162
|
-
fake_zot.items.assert_called_with(
|
163
|
-
limit=dummy_cfg.tools.zotero_read.zotero.max_limit
|
164
|
-
)
|
153
|
+
fake_zot.items.assert_called_with(limit=dummy_cfg.tools.zotero_read.zotero.max_limit)
|
165
154
|
|
166
|
-
@patch(
|
167
|
-
"aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections"
|
168
|
-
)
|
155
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections")
|
169
156
|
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.zotero.Zotero")
|
170
157
|
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.compose")
|
171
|
-
@patch(
|
172
|
-
"aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.initialize"
|
173
|
-
)
|
158
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.initialize")
|
174
159
|
def test_no_items_returned(
|
175
160
|
self,
|
176
161
|
mock_hydra_init,
|
@@ -198,17 +183,11 @@ class TestZoteroSearchTool(unittest.TestCase):
|
|
198
183
|
zotero_read.run(tool_input)
|
199
184
|
self.assertIn("No items returned from Zotero", str(context.exception))
|
200
185
|
|
201
|
-
@patch(
|
202
|
-
"aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections"
|
203
|
-
)
|
186
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections")
|
204
187
|
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.zotero.Zotero")
|
205
188
|
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.compose")
|
206
|
-
@patch(
|
207
|
-
|
208
|
-
)
|
209
|
-
@patch(
|
210
|
-
"aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.download_pdfs_in_parallel"
|
211
|
-
)
|
189
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.initialize")
|
190
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.download_pdfs_in_parallel")
|
212
191
|
def test_filtering_no_matching_papers(self, *mocks):
|
213
192
|
"""Testing filtering when no paper matching"""
|
214
193
|
(
|
@@ -274,14 +253,10 @@ class TestZoteroSearchTool(unittest.TestCase):
|
|
274
253
|
self.assertEqual(filtered_papers["paper1"]["pdf_url"], "/tmp/fake_path.pdf")
|
275
254
|
self.assertEqual(filtered_papers["paper1"]["source"], "zotero")
|
276
255
|
|
277
|
-
@patch(
|
278
|
-
"aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections"
|
279
|
-
)
|
256
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections")
|
280
257
|
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.zotero.Zotero")
|
281
258
|
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.compose")
|
282
|
-
@patch(
|
283
|
-
"aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.initialize"
|
284
|
-
)
|
259
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.initialize")
|
285
260
|
def test_items_api_exception(
|
286
261
|
self,
|
287
262
|
mock_hydra_init,
|
@@ -309,14 +284,10 @@ class TestZoteroSearchTool(unittest.TestCase):
|
|
309
284
|
zotero_read.run(tool_input)
|
310
285
|
self.assertIn("Failed to fetch items from Zotero", str(context.exception))
|
311
286
|
|
312
|
-
@patch(
|
313
|
-
"aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections"
|
314
|
-
)
|
287
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections")
|
315
288
|
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.zotero.Zotero")
|
316
289
|
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.compose")
|
317
|
-
@patch(
|
318
|
-
"aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.initialize"
|
319
|
-
)
|
290
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.initialize")
|
320
291
|
def test_missing_key_in_item(
|
321
292
|
self,
|
322
293
|
mock_hydra_init,
|
@@ -370,14 +341,10 @@ class TestZoteroSearchTool(unittest.TestCase):
|
|
370
341
|
self.assertIn("paper_valid", filtered_papers)
|
371
342
|
self.assertEqual(len(filtered_papers), 1)
|
372
343
|
|
373
|
-
@patch(
|
374
|
-
"aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections"
|
375
|
-
)
|
344
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections")
|
376
345
|
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.zotero.Zotero")
|
377
346
|
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.compose")
|
378
|
-
@patch(
|
379
|
-
"aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.initialize"
|
380
|
-
)
|
347
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.initialize")
|
381
348
|
def test_item_not_dict(
|
382
349
|
self,
|
383
350
|
mock_hydra_init,
|
@@ -410,14 +377,10 @@ class TestZoteroSearchTool(unittest.TestCase):
|
|
410
377
|
zotero_read.run(tool_input)
|
411
378
|
self.assertIn("No matching papers returned from Zotero", str(context.exception))
|
412
379
|
|
413
|
-
@patch(
|
414
|
-
"aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections"
|
415
|
-
)
|
380
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections")
|
416
381
|
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.zotero.Zotero")
|
417
382
|
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.compose")
|
418
|
-
@patch(
|
419
|
-
"aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.initialize"
|
420
|
-
)
|
383
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.initialize")
|
421
384
|
def test_data_not_dict(
|
422
385
|
self,
|
423
386
|
mock_hydra_init,
|
@@ -447,17 +410,11 @@ class TestZoteroSearchTool(unittest.TestCase):
|
|
447
410
|
zotero_read.run(tool_input)
|
448
411
|
self.assertIn("No matching papers returned from Zotero", str(context.exception))
|
449
412
|
|
450
|
-
@patch(
|
451
|
-
"aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections"
|
452
|
-
)
|
413
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections")
|
453
414
|
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.zotero.Zotero")
|
454
415
|
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.compose")
|
455
|
-
@patch(
|
456
|
-
|
457
|
-
)
|
458
|
-
@patch(
|
459
|
-
"aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.requests.Session.get"
|
460
|
-
)
|
416
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.initialize")
|
417
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.requests.Session.get")
|
461
418
|
def test_pdf_attachment_success(self, *mocks):
|
462
419
|
"""Test for pdf attachment success"""
|
463
420
|
(
|
@@ -506,9 +463,7 @@ class TestZoteroSearchTool(unittest.TestCase):
|
|
506
463
|
mock_response = MagicMock()
|
507
464
|
mock_response.status_code = 200
|
508
465
|
mock_response.iter_content = lambda chunk_size: [b"fake pdf content"]
|
509
|
-
mock_response.headers = {
|
510
|
-
"Content-Disposition": 'attachment; filename="file1.pdf"'
|
511
|
-
}
|
466
|
+
mock_response.headers = {"Content-Disposition": 'attachment; filename="file1.pdf"'}
|
512
467
|
mock_response.raise_for_status = lambda: None
|
513
468
|
mock_session_get.return_value = mock_response
|
514
469
|
|
@@ -528,14 +483,10 @@ class TestZoteroSearchTool(unittest.TestCase):
|
|
528
483
|
self.assertEqual(paper["filename"], "file1.pdf")
|
529
484
|
self.assertEqual(paper["attachment_key"], "attachment1")
|
530
485
|
|
531
|
-
@patch(
|
532
|
-
"aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections"
|
533
|
-
)
|
486
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections")
|
534
487
|
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.zotero.Zotero")
|
535
488
|
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.compose")
|
536
|
-
@patch(
|
537
|
-
"aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.initialize"
|
538
|
-
)
|
489
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.initialize")
|
539
490
|
def test_pdf_attachment_children_exception(
|
540
491
|
self,
|
541
492
|
mock_hydra_init,
|
@@ -590,14 +541,10 @@ class TestZoteroSearchTool(unittest.TestCase):
|
|
590
541
|
self.assertNotIn("filename", filtered_papers["paper1"])
|
591
542
|
self.assertNotIn("attachment_key", filtered_papers["paper1"])
|
592
543
|
|
593
|
-
@patch(
|
594
|
-
"aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections"
|
595
|
-
)
|
544
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections")
|
596
545
|
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.zotero.Zotero")
|
597
546
|
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.compose")
|
598
|
-
@patch(
|
599
|
-
"aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.initialize"
|
600
|
-
)
|
547
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.initialize")
|
601
548
|
def test_pdf_attachment_missing_key(
|
602
549
|
self,
|
603
550
|
mock_hydra_init,
|
@@ -653,14 +600,10 @@ class TestZoteroSearchTool(unittest.TestCase):
|
|
653
600
|
self.assertNotIn("pdf_url", paper)
|
654
601
|
self.assertNotIn("attachment_key", paper)
|
655
602
|
|
656
|
-
@patch(
|
657
|
-
"aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections"
|
658
|
-
)
|
603
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections")
|
659
604
|
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.zotero.Zotero")
|
660
605
|
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.compose")
|
661
|
-
@patch(
|
662
|
-
"aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.initialize"
|
663
|
-
)
|
606
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.initialize")
|
664
607
|
def test_pdf_attachment_outer_exception(
|
665
608
|
self,
|
666
609
|
mock_hydra_init,
|
@@ -739,14 +682,10 @@ class TestZoteroSearchTool(unittest.TestCase):
|
|
739
682
|
# Should return None on failure
|
740
683
|
self.assertIsNone(result)
|
741
684
|
|
742
|
-
@patch(
|
743
|
-
"aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections"
|
744
|
-
)
|
685
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections")
|
745
686
|
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.zotero.Zotero")
|
746
687
|
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.compose")
|
747
|
-
@patch(
|
748
|
-
"aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.initialize"
|
749
|
-
)
|
688
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.initialize")
|
750
689
|
def test_download_pdf_exception_logging(
|
751
690
|
self,
|
752
691
|
mock_hydra_init,
|
@@ -4,16 +4,12 @@ Unit tests for Zotero write tool in zotero_write.py.
|
|
4
4
|
|
5
5
|
import unittest
|
6
6
|
from types import SimpleNamespace
|
7
|
-
from unittest.mock import
|
7
|
+
from unittest.mock import MagicMock, patch
|
8
8
|
|
9
9
|
from aiagents4pharma.talk2scholars.tools.zotero.zotero_write import zotero_write
|
10
10
|
|
11
|
-
dummy_zotero_write_config = SimpleNamespace(
|
12
|
-
|
13
|
-
)
|
14
|
-
dummy_cfg = SimpleNamespace(
|
15
|
-
tools=SimpleNamespace(zotero_write=dummy_zotero_write_config)
|
16
|
-
)
|
11
|
+
dummy_zotero_write_config = SimpleNamespace(user_id="dummy", library_type="user", api_key="dummy")
|
12
|
+
dummy_cfg = SimpleNamespace(tools=SimpleNamespace(zotero_write=dummy_zotero_write_config))
|
17
13
|
|
18
14
|
|
19
15
|
class TestZoteroSaveTool(unittest.TestCase):
|
@@ -49,9 +45,7 @@ class TestZoteroSaveTool(unittest.TestCase):
|
|
49
45
|
}
|
50
46
|
if papers is not None:
|
51
47
|
# When papers is provided as dict, use it directly.
|
52
|
-
state["last_displayed_papers"] = (
|
53
|
-
papers if isinstance(papers, dict) else "papers"
|
54
|
-
)
|
48
|
+
state["last_displayed_papers"] = papers if isinstance(papers, dict) else "papers"
|
55
49
|
if isinstance(papers, dict):
|
56
50
|
state["papers"] = papers
|
57
51
|
return state
|
@@ -83,9 +77,7 @@ class TestZoteroSaveTool(unittest.TestCase):
|
|
83
77
|
)
|
84
78
|
def test_invalid_collection(self, mock_find, mock_fetch):
|
85
79
|
"""Test when collection path is invalid"""
|
86
|
-
self.fake_zot.collections.return_value = [
|
87
|
-
{"key": "k1", "data": {"name": "Existing"}}
|
88
|
-
]
|
80
|
+
self.fake_zot.collections.return_value = [{"key": "k1", "data": {"name": "Existing"}}]
|
89
81
|
# Provide a valid papers dict so we don't hit the no-papers error.
|
90
82
|
state = self.make_state({"p1": {"Title": "X"}}, True)
|
91
83
|
result = zotero_write.run(
|
@@ -143,9 +135,7 @@ class TestZoteroSaveTool(unittest.TestCase):
|
|
143
135
|
self.fake_zot.collections.return_value = [
|
144
136
|
{"key": "colKey", "data": {"name": "Test Collection"}}
|
145
137
|
]
|
146
|
-
self.fake_zot.create_items.return_value = {
|
147
|
-
"successful": {"0": {"key": "item1"}}
|
148
|
-
}
|
138
|
+
self.fake_zot.create_items.return_value = {"successful": {"0": {"key": "item1"}}}
|
149
139
|
mock_fetch.return_value = {"p1": {"Title": "X"}}
|
150
140
|
mock_find.return_value = "colKey"
|
151
141
|
|
@@ -6,16 +6,17 @@ Supports downloading papers from arXiv, medRxiv, bioRxiv, and PubMed through a s
|
|
6
6
|
|
7
7
|
import logging
|
8
8
|
import threading
|
9
|
-
from typing import Annotated, Any,
|
9
|
+
from typing import Annotated, Any, Literal
|
10
10
|
|
11
11
|
import hydra
|
12
12
|
from hydra.core.global_hydra import GlobalHydra
|
13
|
-
from omegaconf import OmegaConf
|
14
13
|
from langchain_core.messages import ToolMessage
|
15
14
|
from langchain_core.tools import tool
|
16
15
|
from langchain_core.tools.base import InjectedToolCallId
|
17
16
|
from langgraph.types import Command
|
17
|
+
from omegaconf import OmegaConf
|
18
18
|
from pydantic import BaseModel, Field
|
19
|
+
|
19
20
|
from .utils.arxiv_downloader import ArxivDownloader
|
20
21
|
from .utils.base_paper_downloader import BasePaperDownloader
|
21
22
|
from .utils.biorxiv_downloader import BiorxivDownloader
|
@@ -30,14 +31,14 @@ logger = logging.getLogger(__name__)
|
|
30
31
|
class UnifiedPaperDownloadInput(BaseModel):
|
31
32
|
"""Input schema for the unified paper download tool."""
|
32
33
|
|
33
|
-
service:
|
34
|
+
service: Literal["arxiv", "medrxiv", "biorxiv", "pubmed"] | None = Field(
|
34
35
|
default=None,
|
35
36
|
description=(
|
36
37
|
"Paper service to download from: 'arxiv', 'medrxiv', 'biorxiv', or 'pubmed'. "
|
37
38
|
"If not specified, uses the configured default service."
|
38
39
|
),
|
39
40
|
)
|
40
|
-
identifiers:
|
41
|
+
identifiers: list[str] = Field(
|
41
42
|
description=(
|
42
43
|
"List of paper identifiers. Format depends on service:\n"
|
43
44
|
"- arxiv: arXiv IDs (e.g., ['1234.5678', '2301.12345'])\n"
|
@@ -140,12 +141,9 @@ class PaperDownloaderFactory:
|
|
140
141
|
return PaperDownloaderFactory._cached_config
|
141
142
|
|
142
143
|
try:
|
143
|
-
|
144
144
|
# Clear if already initialized
|
145
145
|
if GlobalHydra().is_initialized():
|
146
|
-
logger.info(
|
147
|
-
"GlobalHydra already initialized, clearing for config load"
|
148
|
-
)
|
146
|
+
logger.info("GlobalHydra already initialized, clearing for config load")
|
149
147
|
GlobalHydra.instance().clear()
|
150
148
|
|
151
149
|
# Load configuration
|
@@ -156,16 +154,12 @@ class PaperDownloaderFactory:
|
|
156
154
|
|
157
155
|
# Cache the configuration
|
158
156
|
PaperDownloaderFactory._cached_config = cfg.tools.paper_download
|
159
|
-
logger.info(
|
160
|
-
"Successfully loaded and cached paper download configuration"
|
161
|
-
)
|
157
|
+
logger.info("Successfully loaded and cached paper download configuration")
|
162
158
|
|
163
159
|
return PaperDownloaderFactory._cached_config
|
164
160
|
|
165
161
|
except Exception as e:
|
166
|
-
logger.error(
|
167
|
-
"Failed to load unified paper download configuration: %s", e
|
168
|
-
)
|
162
|
+
logger.error("Failed to load unified paper download configuration: %s", e)
|
169
163
|
raise RuntimeError(f"Configuration loading failed: {e}") from e
|
170
164
|
|
171
165
|
@staticmethod
|
@@ -181,10 +175,7 @@ class PaperDownloaderFactory:
|
|
181
175
|
Returns:
|
182
176
|
Service-specific configuration object
|
183
177
|
"""
|
184
|
-
if (
|
185
|
-
not hasattr(unified_config, "services")
|
186
|
-
or service not in unified_config.services
|
187
|
-
):
|
178
|
+
if not hasattr(unified_config, "services") or service not in unified_config.services:
|
188
179
|
raise ValueError(f"Service '{service}' not found in configuration")
|
189
180
|
|
190
181
|
# Create a simple config object that combines common and service-specific settings
|
@@ -202,14 +193,10 @@ class PaperDownloaderFactory:
|
|
202
193
|
config_obj = ServiceConfig()
|
203
194
|
|
204
195
|
# Handle common config (using helper method to reduce branches)
|
205
|
-
PaperDownloaderFactory._apply_config(
|
206
|
-
config_obj, unified_config.common, "common"
|
207
|
-
)
|
196
|
+
PaperDownloaderFactory._apply_config(config_obj, unified_config.common, "common")
|
208
197
|
|
209
198
|
# Handle service-specific config (using helper method to reduce branches)
|
210
|
-
PaperDownloaderFactory._apply_config(
|
211
|
-
config_obj, unified_config.services[service], service
|
212
|
-
)
|
199
|
+
PaperDownloaderFactory._apply_config(config_obj, unified_config.services[service], service)
|
213
200
|
|
214
201
|
return config_obj
|
215
202
|
|
@@ -239,9 +226,7 @@ class PaperDownloaderFactory:
|
|
239
226
|
|
240
227
|
# Method 2: Try direct attribute access
|
241
228
|
if hasattr(source_config, "__dict__"):
|
242
|
-
PaperDownloaderFactory._extract_from_dict(
|
243
|
-
config_obj, source_config.__dict__
|
244
|
-
)
|
229
|
+
PaperDownloaderFactory._extract_from_dict(config_obj, source_config.__dict__)
|
245
230
|
return
|
246
231
|
|
247
232
|
# Method 3: Try items() method
|
@@ -290,8 +275,8 @@ class PaperDownloaderFactory:
|
|
290
275
|
parse_docstring=True,
|
291
276
|
)
|
292
277
|
def download_papers(
|
293
|
-
service:
|
294
|
-
identifiers:
|
278
|
+
service: Literal["arxiv", "medrxiv", "biorxiv", "pubmed"] | None,
|
279
|
+
identifiers: list[str],
|
295
280
|
tool_call_id: Annotated[str, InjectedToolCallId],
|
296
281
|
) -> Command[Any]:
|
297
282
|
"""
|
@@ -334,36 +319,36 @@ def download_papers(
|
|
334
319
|
# Convenience functions for backward compatibility (optional)
|
335
320
|
# These functions explicitly specify the service, bypassing the default service config
|
336
321
|
def download_arxiv_papers(
|
337
|
-
arxiv_ids:
|
322
|
+
arxiv_ids: list[str], tool_call_id: Annotated[str, InjectedToolCallId]
|
338
323
|
) -> Command[Any]:
|
339
324
|
"""Convenience function for downloading arXiv papers (explicitly uses arXiv service)."""
|
340
325
|
return _download_papers_impl("arxiv", arxiv_ids, tool_call_id)
|
341
326
|
|
342
327
|
|
343
328
|
def download_medrxiv_papers(
|
344
|
-
dois:
|
329
|
+
dois: list[str], tool_call_id: Annotated[str, InjectedToolCallId]
|
345
330
|
) -> Command[Any]:
|
346
331
|
"""Convenience function for downloading medRxiv papers (explicitly uses medRxiv service)."""
|
347
332
|
return _download_papers_impl("medrxiv", dois, tool_call_id)
|
348
333
|
|
349
334
|
|
350
335
|
def download_biorxiv_papers(
|
351
|
-
dois:
|
336
|
+
dois: list[str], tool_call_id: Annotated[str, InjectedToolCallId]
|
352
337
|
) -> Command[Any]:
|
353
338
|
"""Convenience function for downloading bioRxiv papers (explicitly uses bioRxiv service)."""
|
354
339
|
return _download_papers_impl("biorxiv", dois, tool_call_id)
|
355
340
|
|
356
341
|
|
357
342
|
def download_pubmed_papers(
|
358
|
-
pmids:
|
343
|
+
pmids: list[str], tool_call_id: Annotated[str, InjectedToolCallId]
|
359
344
|
) -> Command[Any]:
|
360
345
|
"""Convenience function for downloading PubMed papers (explicitly uses PubMed service)."""
|
361
346
|
return _download_papers_impl("pubmed", pmids, tool_call_id)
|
362
347
|
|
363
348
|
|
364
349
|
def _download_papers_impl(
|
365
|
-
service:
|
366
|
-
identifiers:
|
350
|
+
service: Literal["arxiv", "medrxiv", "biorxiv", "pubmed"] | None,
|
351
|
+
identifiers: list[str],
|
367
352
|
tool_call_id: str,
|
368
353
|
) -> Command[Any]:
|
369
354
|
"""
|
@@ -5,11 +5,13 @@ biorxiv and medrxiv.
|
|
5
5
|
"""
|
6
6
|
|
7
7
|
# Import modules
|
8
|
-
from . import
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
from . import (
|
9
|
+
arxiv_downloader,
|
10
|
+
base_paper_downloader,
|
11
|
+
biorxiv_downloader,
|
12
|
+
medrxiv_downloader,
|
13
|
+
pubmed_downloader,
|
14
|
+
)
|
13
15
|
|
14
16
|
__all__ = [
|
15
17
|
"arxiv_downloader",
|
@@ -5,7 +5,7 @@ ArXiv paper downloader implementation.
|
|
5
5
|
|
6
6
|
import logging
|
7
7
|
import xml.etree.ElementTree as ET
|
8
|
-
from typing import Any
|
8
|
+
from typing import Any
|
9
9
|
|
10
10
|
import requests
|
11
11
|
|
@@ -92,8 +92,8 @@ class ArxivDownloader(BasePaperDownloader):
|
|
92
92
|
self,
|
93
93
|
metadata: ET.Element,
|
94
94
|
identifier: str,
|
95
|
-
pdf_result:
|
96
|
-
) ->
|
95
|
+
pdf_result: tuple[str, str] | None,
|
96
|
+
) -> dict[str, Any]:
|
97
97
|
"""
|
98
98
|
Extract structured metadata from arXiv API response.
|
99
99
|
|
@@ -124,7 +124,7 @@ class ArxivDownloader(BasePaperDownloader):
|
|
124
124
|
"arxiv_id": identifier,
|
125
125
|
}
|
126
126
|
|
127
|
-
def _extract_basic_metadata(self, entry: ET.Element, ns: dict) ->
|
127
|
+
def _extract_basic_metadata(self, entry: ET.Element, ns: dict) -> dict[str, Any]:
|
128
128
|
"""Extract basic metadata (title, authors, abstract, date) from entry."""
|
129
129
|
title = self._extract_title(entry, ns)
|
130
130
|
authors = self._extract_authors(entry, ns)
|
@@ -160,13 +160,11 @@ class ArxivDownloader(BasePaperDownloader):
|
|
160
160
|
def _extract_publication_date(self, entry: ET.Element, ns: dict) -> str:
|
161
161
|
"""Extract publication date from entry."""
|
162
162
|
published_elem = entry.find("atom:published", ns)
|
163
|
-
return (
|
164
|
-
(published_elem.text or "").strip() if published_elem is not None else "N/A"
|
165
|
-
)
|
163
|
+
return (published_elem.text or "").strip() if published_elem is not None else "N/A"
|
166
164
|
|
167
165
|
def _extract_pdf_metadata(
|
168
|
-
self, pdf_result:
|
169
|
-
) ->
|
166
|
+
self, pdf_result: tuple[str, str] | None, identifier: str
|
167
|
+
) -> dict[str, Any]:
|
170
168
|
"""Extract PDF-related metadata."""
|
171
169
|
if pdf_result:
|
172
170
|
temp_file_path, filename = pdf_result
|
@@ -198,12 +196,12 @@ class ArxivDownloader(BasePaperDownloader):
|
|
198
196
|
"""Generate default filename for arXiv paper."""
|
199
197
|
return f"{identifier}.pdf"
|
200
198
|
|
201
|
-
def _get_paper_identifier_info(self, paper:
|
199
|
+
def _get_paper_identifier_info(self, paper: dict[str, Any]) -> str:
|
202
200
|
"""Get arXiv-specific identifier info for paper summary."""
|
203
201
|
arxiv_id = paper.get("arxiv_id", "N/A")
|
204
202
|
pub_date = paper.get("Publication Date", "N/A")
|
205
203
|
return f" (arXiv:{arxiv_id}, {pub_date})"
|
206
204
|
|
207
|
-
def _add_service_identifier(self, entry:
|
205
|
+
def _add_service_identifier(self, entry: dict[str, Any], identifier: str) -> None:
|
208
206
|
"""Add arXiv ID field to entry."""
|
209
207
|
entry["arxiv_id"] = identifier
|