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.
- 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/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 +334 -216
- 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 +160 -97
- aiagents4pharma/talk2knowledgegraphs/tests/test_utils_kg_utils.py +3 -4
- aiagents4pharma/talk2knowledgegraphs/tests/test_utils_pubchem_utils.py +87 -13
- aiagents4pharma/talk2knowledgegraphs/tools/__init__.py +10 -7
- aiagents4pharma/talk2knowledgegraphs/tools/graphrag_reasoning.py +15 -20
- aiagents4pharma/talk2knowledgegraphs/tools/milvus_multimodal_subgraph_extraction.py +145 -142
- 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 +14 -34
- 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.44.0.dist-info → aiagents4pharma-1.45.1.dist-info}/METADATA +115 -51
- aiagents4pharma-1.45.1.dist-info/RECORD +324 -0
- {aiagents4pharma-1.44.0.dist-info → aiagents4pharma-1.45.1.dist-info}/WHEEL +1 -2
- aiagents4pharma-1.44.0.dist-info/RECORD +0 -293
- aiagents4pharma-1.44.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.44.0.dist-info → aiagents4pharma-1.45.1.dist-info}/licenses/LICENSE +0 -0
aiagents4pharma/talk2scholars/tests/{test_pdf_vector_store.py → test_utils_pdf_vector_store.py}
RENAMED
@@ -180,29 +180,20 @@ def test_load_existing_papers_with_exception(mock_embedding, mock_config):
|
|
180
180
|
patch(f"{MODULE}.log_index_configuration"),
|
181
181
|
):
|
182
182
|
mock_singleton = MagicMock()
|
183
|
-
|
184
|
-
safe_collection = MagicMock()
|
185
|
-
safe_collection.num_entities = 0
|
186
|
-
safe_collection.flush.return_value = None
|
187
|
-
safe_store.col = safe_collection
|
188
|
-
safe_store.collection = safe_collection
|
189
|
-
mock_singleton.get_vector_store.return_value = safe_store
|
190
|
-
mock_singleton.get_connection.return_value = None
|
191
|
-
singleton_cls.return_value = mock_singleton
|
192
|
-
|
193
|
-
vs = Vectorstore(embedding_model=mock_embedding, config=mock_config)
|
194
|
-
|
195
|
-
# now replace with failing store
|
183
|
+
# Set up failing store directly for initialization
|
196
184
|
bad_collection = MagicMock()
|
197
185
|
bad_collection.num_entities = 0
|
198
186
|
bad_collection.flush.side_effect = Exception("flush failed")
|
199
187
|
bad_store = MagicMock()
|
200
188
|
bad_store.col = bad_collection
|
201
189
|
bad_store.collection = bad_collection
|
202
|
-
|
190
|
+
mock_singleton.get_vector_store.return_value = bad_store
|
191
|
+
mock_singleton.get_connection.return_value = None
|
192
|
+
singleton_cls.return_value = mock_singleton
|
203
193
|
|
194
|
+
# Test error propagation through initialization that calls _load_existing_paper_ids
|
204
195
|
with pytest.raises(Exception) as excinfo:
|
205
|
-
|
196
|
+
Vectorstore(embedding_model=mock_embedding, config=mock_config)
|
206
197
|
assert "flush failed" in str(excinfo.value)
|
207
198
|
|
208
199
|
|
@@ -232,10 +223,8 @@ def test_ensure_collection_loaded_with_entities(mock_embedding, mock_config):
|
|
232
223
|
mock_singleton.get_connection.return_value = None
|
233
224
|
singleton_cls.return_value = mock_singleton
|
234
225
|
|
235
|
-
|
236
|
-
|
237
|
-
getattr(vs, "_ensure_collection_loaded")()
|
238
|
-
|
226
|
+
# Test through initialization which calls _ensure_collection_loaded
|
227
|
+
Vectorstore(embedding_model=mock_embedding, config=mock_config)
|
239
228
|
assert mock_collection.load.called
|
240
229
|
|
241
230
|
|
@@ -255,29 +244,20 @@ def test_ensure_collection_loaded_handles_exception(mock_embedding, mock_config)
|
|
255
244
|
patch(f"{MODULE}.log_index_configuration"),
|
256
245
|
):
|
257
246
|
mock_singleton = MagicMock()
|
258
|
-
|
259
|
-
safe_collection = MagicMock()
|
260
|
-
safe_collection.num_entities = 0
|
261
|
-
safe_collection.flush.return_value = None
|
262
|
-
safe_store.col = safe_collection
|
263
|
-
safe_store.collection = safe_collection
|
264
|
-
mock_singleton.get_vector_store.return_value = safe_store
|
265
|
-
mock_singleton.get_connection.return_value = None
|
266
|
-
singleton_cls.return_value = mock_singleton
|
267
|
-
|
268
|
-
vs = Vectorstore(embedding_model=mock_embedding, config=mock_config)
|
269
|
-
|
270
|
-
# override with failing store
|
247
|
+
# Set up failing store directly for initialization
|
271
248
|
bad_collection = MagicMock()
|
272
249
|
bad_collection.num_entities = 0
|
273
250
|
bad_collection.flush.side_effect = Exception("flush error")
|
274
251
|
bad_store = MagicMock()
|
275
252
|
bad_store.col = bad_collection
|
276
253
|
bad_store.collection = bad_collection
|
277
|
-
|
254
|
+
mock_singleton.get_vector_store.return_value = bad_store
|
255
|
+
mock_singleton.get_connection.return_value = None
|
256
|
+
singleton_cls.return_value = mock_singleton
|
278
257
|
|
258
|
+
# Test error propagation through initialization that calls _ensure_collection_loaded
|
279
259
|
with pytest.raises(Exception) as excinfo:
|
280
|
-
|
260
|
+
Vectorstore(embedding_model=mock_embedding, config=mock_config)
|
281
261
|
assert "flush error" in str(excinfo.value)
|
282
262
|
|
283
263
|
|
@@ -313,9 +293,7 @@ def test_force_cpu_mode_logs_override(mock_config, mock_embedding):
|
|
313
293
|
assert not vs.has_gpu
|
314
294
|
|
315
295
|
|
316
|
-
def test_similarity_metric_override(
|
317
|
-
dummy_embedding, dummy_config, dummy_vectorstore_components
|
318
|
-
):
|
296
|
+
def test_similarity_metric_override(dummy_embedding, dummy_config, dummy_vectorstore_components):
|
319
297
|
"""
|
320
298
|
Test setting of use_cosine from config.similarity_metric.
|
321
299
|
"""
|
@@ -338,8 +316,7 @@ def test_load_existing_paper_ids_fallback_to_collection(
|
|
338
316
|
delattr(mock_vector_store, attr)
|
339
317
|
|
340
318
|
vs = Vectorstore(dummy_embedding, config=dummy_config)
|
341
|
-
|
342
|
-
getattr(vs, "_load_existing_paper_ids")()
|
319
|
+
# The loaded_papers is set during initialization via _load_existing_paper_ids
|
343
320
|
assert isinstance(vs.loaded_papers, set)
|
344
321
|
|
345
322
|
|
@@ -356,8 +333,7 @@ def test_load_existing_papers_collection_empty_logs(
|
|
356
333
|
mock_vector_store.col = mock_collection
|
357
334
|
|
358
335
|
vs = Vectorstore(dummy_embedding, config=dummy_config)
|
359
|
-
|
360
|
-
getattr(vs, "_load_existing_paper_ids")()
|
336
|
+
# The loaded_papers is set during initialization via _load_existing_paper_ids
|
361
337
|
assert len(vs.loaded_papers) == 0
|
362
338
|
|
363
339
|
|
@@ -382,16 +358,12 @@ def test_similarity_search_filter_paths(
|
|
382
358
|
assert isinstance(result, list)
|
383
359
|
|
384
360
|
|
385
|
-
def test_mmr_search_filter_paths(
|
386
|
-
dummy_embedding, dummy_config, dummy_vectorstore_components
|
387
|
-
):
|
361
|
+
def test_mmr_search_filter_paths(dummy_embedding, dummy_config, dummy_vectorstore_components):
|
388
362
|
"""
|
389
363
|
Test filter expression generation in max_marginal_relevance_search.
|
390
364
|
"""
|
391
365
|
_, mock_vector_store = dummy_vectorstore_components
|
392
|
-
mock_vector_store.max_marginal_relevance_search.return_value = [
|
393
|
-
Document(page_content="test")
|
394
|
-
]
|
366
|
+
mock_vector_store.max_marginal_relevance_search.return_value = [Document(page_content="test")]
|
395
367
|
vs = Vectorstore(dummy_embedding, config=dummy_config)
|
396
368
|
vs.vector_store = mock_vector_store
|
397
369
|
|
@@ -411,10 +383,10 @@ def test_ensure_collection_loaded_no_col_and_no_collection(
|
|
411
383
|
if hasattr(mock_vector_store, attr):
|
412
384
|
delattr(mock_vector_store, attr)
|
413
385
|
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
# no exception
|
386
|
+
# Test initialization succeeds without exception
|
387
|
+
Vectorstore(dummy_embedding, config=dummy_config)
|
388
|
+
# Collection loading is handled during initialization via _ensure_collection_loaded
|
389
|
+
# no exception if we got this far
|
418
390
|
|
419
391
|
|
420
392
|
def test_ensure_collection_loaded_empty_logs(
|
@@ -428,7 +400,7 @@ def test_ensure_collection_loaded_empty_logs(
|
|
428
400
|
mock_collection.num_entities = 0
|
429
401
|
mock_vector_store.col = mock_collection
|
430
402
|
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
# no exception
|
403
|
+
# Test initialization succeeds without exception
|
404
|
+
Vectorstore(dummy_embedding, config=dummy_config)
|
405
|
+
# Collection loading is handled during initialization via _ensure_collection_loaded
|
406
|
+
# no exception if we got this far
|
aiagents4pharma/talk2scholars/tests/{test_pubmed_downloader.py → test_utils_pubmed_downloader.py}
RENAMED
@@ -139,8 +139,7 @@ class TestPubmedDownloaderBasics(unittest.TestCase):
|
|
139
139
|
"""<error> node -> return empty string."""
|
140
140
|
resp = Mock()
|
141
141
|
resp.text = (
|
142
|
-
'<?xml version="1.0"?><OA><error code="idDoesNotExist">'
|
143
|
-
"Invalid PMC ID</error></OA>"
|
142
|
+
'<?xml version="1.0"?><OA><error code="idDoesNotExist">Invalid PMC ID</error></OA>'
|
144
143
|
)
|
145
144
|
resp.raise_for_status = Mock()
|
146
145
|
mock_get.return_value = resp
|
@@ -299,10 +298,7 @@ class TestPubmedDownloaderEuropePMC(unittest.TestCase):
|
|
299
298
|
resp.status_code = 200
|
300
299
|
mock_head.return_value = resp
|
301
300
|
result = self.downloader.try_europe_pmc_public("PMC123456")
|
302
|
-
expected =
|
303
|
-
"https://www.ebi.ac.uk/europepmc/webservices/rest"
|
304
|
-
"?accid=PMC123456&blobtype=pdf"
|
305
|
-
)
|
301
|
+
expected = "https://www.ebi.ac.uk/europepmc/webservices/rest?accid=PMC123456&blobtype=pdf"
|
306
302
|
mock_head.assert_called_once_with(expected, timeout=30)
|
307
303
|
self.assertEqual(result, expected)
|
308
304
|
|
@@ -356,18 +352,14 @@ class TestPubmedDownloaderPMCScrape(unittest.TestCase):
|
|
356
352
|
|
357
353
|
expected_url = "https://www.ncbi.nlm.nih.gov/pmc/articles/PMC123456/"
|
358
354
|
expected_headers = {"User-Agent": "Mozilla/5.0 (compatible; test-agent)"}
|
359
|
-
mock_get.assert_called_once_with(
|
360
|
-
|
361
|
-
)
|
362
|
-
self.assertEqual(
|
363
|
-
result, "https://www.ncbi.nlm.nih.gov/pmc/articles/PMC123456/pdf/test.pdf"
|
364
|
-
)
|
355
|
+
mock_get.assert_called_once_with(expected_url, headers=expected_headers, timeout=30)
|
356
|
+
self.assertEqual(result, "https://www.ncbi.nlm.nih.gov/pmc/articles/PMC123456/pdf/test.pdf")
|
365
357
|
|
366
358
|
@patch("requests.get")
|
367
359
|
def test_try_pmc_page_scraping_no_pdf(self, mock_get):
|
368
360
|
"""Test PMC page scraping with no PDF found."""
|
369
361
|
resp = Mock()
|
370
|
-
resp.content = "<html><head></head></html>"
|
362
|
+
resp.content = b"<html><head></head></html>"
|
371
363
|
resp.raise_for_status = Mock()
|
372
364
|
mock_get.return_value = resp
|
373
365
|
self.assertEqual(self.downloader.try_pmc_page_scraping_public("PMC123456"), "")
|
@@ -486,17 +478,13 @@ class TestPubmedDownloaderConstructAndFallbacks(unittest.TestCase):
|
|
486
478
|
"""Test fallback chain through multiple sources."""
|
487
479
|
with (
|
488
480
|
patch.object(self.downloader, "try_oa_api_public", return_value="") as m_oa,
|
489
|
-
patch.object(
|
490
|
-
self.downloader, "try_europe_pmc_public", return_value=""
|
491
|
-
) as m_eu,
|
481
|
+
patch.object(self.downloader, "try_europe_pmc_public", return_value="") as m_eu,
|
492
482
|
patch.object(
|
493
483
|
self.downloader,
|
494
484
|
"try_pmc_page_scraping_public",
|
495
485
|
return_value="http://test.pdf",
|
496
486
|
) as m_scr,
|
497
|
-
patch.object(
|
498
|
-
self.downloader, "try_direct_pmc_url_public", return_value=""
|
499
|
-
) as m_dir,
|
487
|
+
patch.object(self.downloader, "try_direct_pmc_url_public", return_value="") as m_dir,
|
500
488
|
):
|
501
489
|
out = self.downloader.fetch_pdf_url_with_fallbacks_public("PMC123456")
|
502
490
|
self.assertEqual(out, "http://test.pdf")
|
@@ -509,12 +497,8 @@ class TestPubmedDownloaderConstructAndFallbacks(unittest.TestCase):
|
|
509
497
|
"""Test fallback chain with direct PMC success."""
|
510
498
|
with (
|
511
499
|
patch.object(self.downloader, "try_oa_api_public", return_value="") as m_oa,
|
512
|
-
patch.object(
|
513
|
-
|
514
|
-
) as m_eu,
|
515
|
-
patch.object(
|
516
|
-
self.downloader, "try_pmc_page_scraping_public", return_value=""
|
517
|
-
) as m_scr,
|
500
|
+
patch.object(self.downloader, "try_europe_pmc_public", return_value="") as m_eu,
|
501
|
+
patch.object(self.downloader, "try_pmc_page_scraping_public", return_value="") as m_scr,
|
518
502
|
patch.object(
|
519
503
|
self.downloader,
|
520
504
|
"try_direct_pmc_url_public",
|
@@ -532,15 +516,9 @@ class TestPubmedDownloaderConstructAndFallbacks(unittest.TestCase):
|
|
532
516
|
"""Test fallback chain when all sources fail."""
|
533
517
|
with (
|
534
518
|
patch.object(self.downloader, "try_oa_api_public", return_value="") as m_oa,
|
535
|
-
patch.object(
|
536
|
-
|
537
|
-
) as
|
538
|
-
patch.object(
|
539
|
-
self.downloader, "try_pmc_page_scraping_public", return_value=""
|
540
|
-
) as m_scr,
|
541
|
-
patch.object(
|
542
|
-
self.downloader, "try_direct_pmc_url_public", return_value=""
|
543
|
-
) as m_dir,
|
519
|
+
patch.object(self.downloader, "try_europe_pmc_public", return_value="") as m_eu,
|
520
|
+
patch.object(self.downloader, "try_pmc_page_scraping_public", return_value="") as m_scr,
|
521
|
+
patch.object(self.downloader, "try_direct_pmc_url_public", return_value="") as m_dir,
|
544
522
|
):
|
545
523
|
out = self.downloader.fetch_pdf_url_with_fallbacks_public("PMC123456")
|
546
524
|
self.assertEqual(out, "")
|
@@ -587,9 +565,7 @@ class TestPubmedDownloaderIntegration(unittest.TestCase):
|
|
587
565
|
"""Test full workflow from PMID to PDF URL."""
|
588
566
|
metadata_response = Mock()
|
589
567
|
metadata_response.json.return_value = {
|
590
|
-
"records": [
|
591
|
-
{"pmid": "12345678", "pmcid": "PMC123456", "doi": "10.1234/test"}
|
592
|
-
]
|
568
|
+
"records": [{"pmid": "12345678", "pmcid": "PMC123456", "doi": "10.1234/test"}]
|
593
569
|
}
|
594
570
|
metadata_response.raise_for_status = Mock()
|
595
571
|
|
@@ -631,9 +607,7 @@ class TestPubmedDownloaderIntegration(unittest.TestCase):
|
|
631
607
|
"""Test workflow with fallback to alternative sources."""
|
632
608
|
metadata_response = Mock()
|
633
609
|
metadata_response.json.return_value = {
|
634
|
-
"records": [
|
635
|
-
{"pmid": "12345678", "pmcid": "PMC123456", "doi": "10.1234/test"}
|
636
|
-
]
|
610
|
+
"records": [{"pmid": "12345678", "pmcid": "PMC123456", "doi": "10.1234/test"}]
|
637
611
|
}
|
638
612
|
metadata_response.raise_for_status = Mock()
|
639
613
|
|
@@ -780,9 +754,7 @@ class TestPubmedDownloaderHelpers(unittest.TestCase):
|
|
780
754
|
"""Test that placeholder abstracts return empty snippets."""
|
781
755
|
self.assertEqual(self.downloader.get_snippet(""), "")
|
782
756
|
self.assertEqual(self.downloader.get_snippet("N/A"), "")
|
783
|
-
self.assertEqual(
|
784
|
-
self.downloader.get_snippet("Abstract available in PubMed"), ""
|
785
|
-
)
|
757
|
+
self.assertEqual(self.downloader.get_snippet("Abstract available in PubMed"), "")
|
786
758
|
|
787
759
|
def test_get_snippet_non_placeholder_delegates_to_base(self):
|
788
760
|
"""Test that non-placeholder abstracts delegate to base class."""
|
@@ -793,9 +765,7 @@ class TestPubmedDownloaderHelpers(unittest.TestCase):
|
|
793
765
|
|
794
766
|
def test_get_paper_identifier_info_without_pmcid_line(self):
|
795
767
|
"""Test paper identifier info formatting without PMCID."""
|
796
|
-
info = self.downloader.get_paper_identifier_info_public(
|
797
|
-
{"PMID": "999", "PMCID": "N/A"}
|
798
|
-
)
|
768
|
+
info = self.downloader.get_paper_identifier_info_public({"PMID": "999", "PMCID": "N/A"})
|
799
769
|
self.assertIn("(PMID: 999)", info)
|
800
770
|
self.assertNotIn("PMCID:", info)
|
801
771
|
|
@@ -861,14 +831,10 @@ class TestPubmedDownloaderMissingLineCoverage(unittest.TestCase):
|
|
861
831
|
patch.object(self.downloader, "_try_pmc_page_scraping", return_value=""),
|
862
832
|
patch.object(self.downloader, "_try_direct_pmc_url", return_value=""),
|
863
833
|
patch(
|
864
|
-
"aiagents4pharma.talk2scholars.tools.paper_download.utils."
|
865
|
-
"pubmed_downloader.logger"
|
834
|
+
"aiagents4pharma.talk2scholars.tools.paper_download.utils.pubmed_downloader.logger"
|
866
835
|
) as mock_logger,
|
867
836
|
):
|
868
|
-
|
869
|
-
result = self.downloader.fetch_pdf_url_with_fallbacks_production(
|
870
|
-
"PMC123456"
|
871
|
-
)
|
837
|
+
result = self.downloader.fetch_pdf_url_with_fallbacks_production("PMC123456")
|
872
838
|
|
873
839
|
self.assertEqual(result, "")
|
874
840
|
# Verify the warning log is called
|
@@ -879,21 +845,15 @@ class TestPubmedDownloaderMissingLineCoverage(unittest.TestCase):
|
|
879
845
|
def test_fetch_pdf_url_with_fallbacks_oa_api_success_early_return(self):
|
880
846
|
"""Test _fetch_pdf_url_with_fallbacks when OA API succeeds on first try."""
|
881
847
|
with (
|
882
|
-
patch.object(
|
883
|
-
self.downloader, "_try_oa_api", return_value="http://oa.pdf"
|
884
|
-
) as mock_oa,
|
848
|
+
patch.object(self.downloader, "_try_oa_api", return_value="http://oa.pdf") as mock_oa,
|
885
849
|
patch.object(self.downloader, "_try_europe_pmc") as mock_eu,
|
886
850
|
patch.object(self.downloader, "_try_pmc_page_scraping") as mock_scr,
|
887
851
|
patch.object(self.downloader, "_try_direct_pmc_url") as mock_dir,
|
888
852
|
patch(
|
889
|
-
"aiagents4pharma.talk2scholars.tools.paper_download.utils."
|
890
|
-
"pubmed_downloader.logger"
|
853
|
+
"aiagents4pharma.talk2scholars.tools.paper_download.utils.pubmed_downloader.logger"
|
891
854
|
) as mock_logger,
|
892
855
|
):
|
893
|
-
|
894
|
-
result = self.downloader.fetch_pdf_url_with_fallbacks_production(
|
895
|
-
"PMC123456"
|
896
|
-
)
|
856
|
+
result = self.downloader.fetch_pdf_url_with_fallbacks_production("PMC123456")
|
897
857
|
|
898
858
|
self.assertEqual(result, "http://oa.pdf")
|
899
859
|
mock_oa.assert_called_once_with("PMC123456")
|
@@ -901,9 +861,7 @@ class TestPubmedDownloaderMissingLineCoverage(unittest.TestCase):
|
|
901
861
|
mock_scr.assert_not_called()
|
902
862
|
mock_dir.assert_not_called()
|
903
863
|
# Verify the initial info log is called
|
904
|
-
mock_logger.info.assert_called_with(
|
905
|
-
"Fetching PDF URL for PMCID: %s", "PMC123456"
|
906
|
-
)
|
864
|
+
mock_logger.info.assert_called_with("Fetching PDF URL for PMCID: %s", "PMC123456")
|
907
865
|
|
908
866
|
def test_fetch_pdf_url_with_fallbacks_europe_pmc_success_after_oa_fail(self):
|
909
867
|
"""Test _fetch_pdf_url_with_fallbacks when Europe PMC succeeds after OA API fails."""
|
@@ -915,10 +873,7 @@ class TestPubmedDownloaderMissingLineCoverage(unittest.TestCase):
|
|
915
873
|
patch.object(self.downloader, "_try_pmc_page_scraping") as mock_scr,
|
916
874
|
patch.object(self.downloader, "_try_direct_pmc_url") as mock_dir,
|
917
875
|
):
|
918
|
-
|
919
|
-
result = self.downloader.fetch_pdf_url_with_fallbacks_production(
|
920
|
-
"PMC123456"
|
921
|
-
)
|
876
|
+
result = self.downloader.fetch_pdf_url_with_fallbacks_production("PMC123456")
|
922
877
|
|
923
878
|
self.assertEqual(result, "http://eu.pdf")
|
924
879
|
mock_oa.assert_called_once_with("PMC123456")
|
@@ -932,18 +887,13 @@ class TestPubmedDownloaderMissingLineCoverage(unittest.TestCase):
|
|
932
887
|
"""Test _fetch_pdf_url_with_fallbacks when PMC scraping succeeds."""
|
933
888
|
with (
|
934
889
|
patch.object(self.downloader, "_try_oa_api", return_value="") as mock_oa,
|
935
|
-
patch.object(
|
936
|
-
self.downloader, "_try_europe_pmc", return_value=""
|
937
|
-
) as mock_eu,
|
890
|
+
patch.object(self.downloader, "_try_europe_pmc", return_value="") as mock_eu,
|
938
891
|
patch.object(
|
939
892
|
self.downloader, "_try_pmc_page_scraping", return_value="http://scr.pdf"
|
940
893
|
) as mock_scr,
|
941
894
|
patch.object(self.downloader, "_try_direct_pmc_url") as mock_dir,
|
942
895
|
):
|
943
|
-
|
944
|
-
result = self.downloader.fetch_pdf_url_with_fallbacks_production(
|
945
|
-
"PMC123456"
|
946
|
-
)
|
896
|
+
result = self.downloader.fetch_pdf_url_with_fallbacks_production("PMC123456")
|
947
897
|
|
948
898
|
self.assertEqual(result, "http://scr.pdf")
|
949
899
|
mock_oa.assert_called_once_with("PMC123456")
|
@@ -955,20 +905,13 @@ class TestPubmedDownloaderMissingLineCoverage(unittest.TestCase):
|
|
955
905
|
"""Test _fetch_pdf_url_with_fallbacks when direct PMC succeeds as last resort."""
|
956
906
|
with (
|
957
907
|
patch.object(self.downloader, "_try_oa_api", return_value="") as mock_oa,
|
958
|
-
patch.object(
|
959
|
-
|
960
|
-
) as mock_eu,
|
961
|
-
patch.object(
|
962
|
-
self.downloader, "_try_pmc_page_scraping", return_value=""
|
963
|
-
) as mock_scr,
|
908
|
+
patch.object(self.downloader, "_try_europe_pmc", return_value="") as mock_eu,
|
909
|
+
patch.object(self.downloader, "_try_pmc_page_scraping", return_value="") as mock_scr,
|
964
910
|
patch.object(
|
965
911
|
self.downloader, "_try_direct_pmc_url", return_value="http://dir.pdf"
|
966
912
|
) as mock_dir,
|
967
913
|
):
|
968
|
-
|
969
|
-
result = self.downloader.fetch_pdf_url_with_fallbacks_production(
|
970
|
-
"PMC123456"
|
971
|
-
)
|
914
|
+
result = self.downloader.fetch_pdf_url_with_fallbacks_production("PMC123456")
|
972
915
|
|
973
916
|
self.assertEqual(result, "http://dir.pdf")
|
974
917
|
mock_oa.assert_called_once_with("PMC123456")
|
@@ -1012,8 +955,7 @@ class TestPubmedDownloaderProductionConstructPdfUrl(unittest.TestCase):
|
|
1012
955
|
"""Test production construct_pdf_url with missing pmcid key."""
|
1013
956
|
metadata = {"records": [{"doi": "10.1/x"}]}
|
1014
957
|
with patch(
|
1015
|
-
"aiagents4pharma.talk2scholars.tools.paper_download.utils."
|
1016
|
-
"pubmed_downloader.logger"
|
958
|
+
"aiagents4pharma.talk2scholars.tools.paper_download.utils.pubmed_downloader.logger"
|
1017
959
|
) as mock_logger:
|
1018
960
|
result = self.downloader.construct_pdf_url(metadata, "12345678")
|
1019
961
|
|
@@ -1027,8 +969,7 @@ class TestPubmedDownloaderProductionConstructPdfUrl(unittest.TestCase):
|
|
1027
969
|
"""Test production construct_pdf_url with empty pmcid."""
|
1028
970
|
metadata = {"records": [{"pmcid": "", "doi": "10.1/x"}]}
|
1029
971
|
with patch(
|
1030
|
-
"aiagents4pharma.talk2scholars.tools.paper_download.utils."
|
1031
|
-
"pubmed_downloader.logger"
|
972
|
+
"aiagents4pharma.talk2scholars.tools.paper_download.utils.pubmed_downloader.logger"
|
1032
973
|
) as mock_logger:
|
1033
974
|
result = self.downloader.construct_pdf_url(metadata, "12345678")
|
1034
975
|
|
@@ -1042,8 +983,7 @@ class TestPubmedDownloaderProductionConstructPdfUrl(unittest.TestCase):
|
|
1042
983
|
"""Test production construct_pdf_url with N/A pmcid."""
|
1043
984
|
metadata = {"records": [{"pmcid": "N/A", "doi": "10.1/x"}]}
|
1044
985
|
with patch(
|
1045
|
-
"aiagents4pharma.talk2scholars.tools.paper_download.utils."
|
1046
|
-
"pubmed_downloader.logger"
|
986
|
+
"aiagents4pharma.talk2scholars.tools.paper_download.utils.pubmed_downloader.logger"
|
1047
987
|
) as mock_logger:
|
1048
988
|
result = self.downloader.construct_pdf_url(metadata, "12345678")
|
1049
989
|
|
aiagents4pharma/talk2scholars/tests/{test_read_helper_utils.py → test_utils_read_helper_utils.py}
RENAMED
@@ -27,14 +27,10 @@ dummy_cfg = SimpleNamespace(tools=SimpleNamespace(zotero_read=dummy_zotero_read_
|
|
27
27
|
class TestReadHelperDownloadsFalse(unittest.TestCase):
|
28
28
|
"""Tests for read_helper download_pdfs=False branches."""
|
29
29
|
|
30
|
-
@patch(
|
31
|
-
"aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections"
|
32
|
-
)
|
30
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections")
|
33
31
|
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.zotero.Zotero")
|
34
32
|
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.compose")
|
35
|
-
@patch(
|
36
|
-
"aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.initialize"
|
37
|
-
)
|
33
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.initialize")
|
38
34
|
def test_download_pdfs_false_branches(
|
39
35
|
self,
|
40
36
|
mock_hydra_init,
|
aiagents4pharma/talk2scholars/tests/{test_s2_utils_ext_ids.py → test_utils_s2_utils_ext_ids.py}
RENAMED
@@ -49,9 +49,7 @@ def patch_hydra(monkeypatch):
|
|
49
49
|
),
|
50
50
|
)
|
51
51
|
)
|
52
|
-
monkeypatch.setattr(
|
53
|
-
hydra, "initialize", lambda version_base, config_path: DummyHydraContext()
|
54
|
-
)
|
52
|
+
monkeypatch.setattr(hydra, "initialize", lambda version_base, config_path: DummyHydraContext())
|
55
53
|
monkeypatch.setattr(hydra, "compose", lambda config_name, overrides: dummy_cfg)
|
56
54
|
|
57
55
|
|
@@ -69,9 +67,7 @@ def test_multi_helper_pmc_and_doi_ids(monkeypatch):
|
|
69
67
|
}
|
70
68
|
]
|
71
69
|
}
|
72
|
-
response = SimpleNamespace(
|
73
|
-
status_code=200, json=lambda: data, raise_for_status=lambda: None
|
74
|
-
)
|
70
|
+
response = SimpleNamespace(status_code=200, json=lambda: data, raise_for_status=lambda: None)
|
75
71
|
monkeypatch.setattr(requests, "post", lambda *args, **kwargs: response)
|
76
72
|
results = rec.process_recommendations()
|
77
73
|
ids_list = results["papers"]["p1"]["paper_ids"]
|
@@ -91,9 +87,7 @@ def test_search_helper_pmc_and_doi_ids(monkeypatch):
|
|
91
87
|
}
|
92
88
|
]
|
93
89
|
}
|
94
|
-
response = SimpleNamespace(
|
95
|
-
status_code=200, json=lambda: data, raise_for_status=lambda: None
|
96
|
-
)
|
90
|
+
response = SimpleNamespace(status_code=200, json=lambda: data, raise_for_status=lambda: None)
|
97
91
|
monkeypatch.setattr(requests, "get", lambda *args, **kwargs: response)
|
98
92
|
results = sd.process_search()
|
99
93
|
ids_list = results["papers"]["s1"]["paper_ids"]
|
@@ -113,9 +107,7 @@ def test_single_helper_pmc_and_doi_ids(monkeypatch):
|
|
113
107
|
}
|
114
108
|
]
|
115
109
|
}
|
116
|
-
response = SimpleNamespace(
|
117
|
-
status_code=200, json=lambda: data, raise_for_status=lambda: None
|
118
|
-
)
|
110
|
+
response = SimpleNamespace(status_code=200, json=lambda: data, raise_for_status=lambda: None)
|
119
111
|
monkeypatch.setattr(requests, "get", lambda *args, **kwargs: response)
|
120
112
|
results = sp.process_recommendations()
|
121
113
|
ids_list = results["papers"]["x1"]["paper_ids"]
|
@@ -395,9 +387,7 @@ def test_single_helper_create_content_snippet(monkeypatch):
|
|
395
387
|
|
396
388
|
def test_multi_helper_create_content_snippet(monkeypatch):
|
397
389
|
"""Test that MultiPaperRecData._create_content includes snippets appropriately."""
|
398
|
-
mr = MultiPaperRecData(
|
399
|
-
paper_ids=["a", "b"], limit=2, year="2021", tool_call_id="tid"
|
400
|
-
)
|
390
|
+
mr = MultiPaperRecData(paper_ids=["a", "b"], limit=2, year="2021", tool_call_id="tid")
|
401
391
|
mr.filtered_papers = {
|
402
392
|
"m1": {"Title": "MTitle1", "Year": "2017", "Abstract": "MOne. MTwo. MThree."},
|
403
393
|
"m2": {"Title": "MTitle2", "Year": "2016", "Abstract": ""},
|
@@ -3,7 +3,8 @@ Unit tests for Zotero human in the loop in zotero_review.py with structured outp
|
|
3
3
|
"""
|
4
4
|
|
5
5
|
import unittest
|
6
|
-
from unittest.mock import
|
6
|
+
from unittest.mock import MagicMock, patch
|
7
|
+
|
7
8
|
from aiagents4pharma.talk2scholars.tools.zotero.zotero_review import zotero_review
|
8
9
|
|
9
10
|
|
@@ -185,22 +186,16 @@ class TestZoteroReviewTool(unittest.TestCase):
|
|
185
186
|
|
186
187
|
upd = result.update
|
187
188
|
self.assertEqual(upd["zotero_write_approval_status"], {"approved": False})
|
188
|
-
self.assertIn(
|
189
|
-
"Human rejected saving papers to Zotero", upd["messages"][0].content
|
190
|
-
)
|
189
|
+
self.assertIn("Human rejected saving papers to Zotero", upd["messages"][0].content)
|
191
190
|
mock_fetch.assert_called_once()
|
192
191
|
mock_interrupt.assert_called_once()
|
193
192
|
|
194
|
-
@patch(
|
195
|
-
"aiagents4pharma.talk2scholars.tools.zotero.zotero_review.fetch_papers_for_save"
|
196
|
-
)
|
193
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.zotero_review.fetch_papers_for_save")
|
197
194
|
@patch("aiagents4pharma.talk2scholars.tools.zotero.zotero_review.interrupt")
|
198
195
|
def test_structured_processing_failure(self, mock_interrupt, mock_fetch):
|
199
196
|
"""Test fallback when structured review processing fails."""
|
200
197
|
# Simulate valid fetched papers with multiple entries.
|
201
|
-
papers = {
|
202
|
-
f"p{i}": {"Title": f"Title{i}", "Authors": [f"A{i}"]} for i in range(1, 8)
|
203
|
-
}
|
198
|
+
papers = {f"p{i}": {"Title": f"Title{i}", "Authors": [f"A{i}"]} for i in range(1, 8)}
|
204
199
|
mock_fetch.return_value = papers
|
205
200
|
mock_interrupt.return_value = "dummy_response"
|
206
201
|
# Provide a fake llm_model whose invoke() raises an exception.
|
@@ -234,9 +229,7 @@ class TestZoteroReviewTool(unittest.TestCase):
|
|
234
229
|
|
235
230
|
@patch(
|
236
231
|
"aiagents4pharma.talk2scholars.tools.zotero.zotero_review.fetch_papers_for_save",
|
237
|
-
return_value={
|
238
|
-
"p1": {"Title": "Test Paper", "Authors": ["Alice", "Bob", "Charlie"]}
|
239
|
-
},
|
232
|
+
return_value={"p1": {"Title": "Test Paper", "Authors": ["Alice", "Bob", "Charlie"]}},
|
240
233
|
)
|
241
234
|
@patch(
|
242
235
|
"aiagents4pharma.talk2scholars.tools.zotero.zotero_review.interrupt",
|