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
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",
|
@@ -4,7 +4,9 @@ Unit tests for Zotero path utility in zotero_path.py.
|
|
4
4
|
|
5
5
|
import unittest
|
6
6
|
from unittest.mock import MagicMock, patch
|
7
|
+
|
7
8
|
import pytest
|
9
|
+
|
8
10
|
from aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path import (
|
9
11
|
fetch_papers_for_save,
|
10
12
|
find_or_create_collection,
|
@@ -92,12 +94,8 @@ class TestFindOrCreateCollectionExtra(unittest.TestCase):
|
|
92
94
|
# Simulate no existing collections (so direct match fails)
|
93
95
|
self.fake_zot.collections.return_value = []
|
94
96
|
# Simulate create_collection returning a dict with a "success" key.
|
95
|
-
self.fake_zot.create_collection.return_value = {
|
96
|
-
|
97
|
-
}
|
98
|
-
result = find_or_create_collection(
|
99
|
-
self.fake_zot, "/NewCollection", create_missing=True
|
100
|
-
)
|
97
|
+
self.fake_zot.create_collection.return_value = {"success": {"0": "new_key_success"}}
|
98
|
+
result = find_or_create_collection(self.fake_zot, "/NewCollection", create_missing=True)
|
101
99
|
self.assertEqual(result, "new_key_success")
|
102
100
|
# Verify payload formatting: for a simple (non-nested) path, no parentCollection.
|
103
101
|
args, _ = self.fake_zot.create_collection.call_args
|
@@ -114,9 +112,7 @@ class TestFindOrCreateCollectionExtra(unittest.TestCase):
|
|
114
112
|
self.fake_zot.create_collection.return_value = {
|
115
113
|
"successful": {"0": {"data": {"key": "new_key_successful"}}}
|
116
114
|
}
|
117
|
-
result = find_or_create_collection(
|
118
|
-
self.fake_zot, "/NewCollection", create_missing=True
|
119
|
-
)
|
115
|
+
result = find_or_create_collection(self.fake_zot, "/NewCollection", create_missing=True)
|
120
116
|
self.assertEqual(result, "new_key_successful")
|
121
117
|
|
122
118
|
def test_create_collection_exception(self):
|
@@ -126,9 +122,7 @@ class TestFindOrCreateCollectionExtra(unittest.TestCase):
|
|
126
122
|
"""
|
127
123
|
self.fake_zot.collections.return_value = []
|
128
124
|
self.fake_zot.create_collection.side_effect = Exception("Creation error")
|
129
|
-
result = find_or_create_collection(
|
130
|
-
self.fake_zot, "/NewCollection", create_missing=True
|
131
|
-
)
|
125
|
+
result = find_or_create_collection(self.fake_zot, "/NewCollection", create_missing=True)
|
132
126
|
self.assertIsNone(result)
|
133
127
|
|
134
128
|
|
@@ -228,9 +222,7 @@ class TestZoteroPath:
|
|
228
222
|
mock_zotero.return_value = mock_zot
|
229
223
|
|
230
224
|
# Setup collections
|
231
|
-
collections = [
|
232
|
-
{"key": "abc123", "data": {"name": "Curiosity", "parentCollection": None}}
|
233
|
-
]
|
225
|
+
collections = [{"key": "abc123", "data": {"name": "Curiosity", "parentCollection": None}}]
|
234
226
|
mock_zot.collections.return_value = collections
|
235
227
|
|
236
228
|
# Setup create_collection response
|
@@ -249,9 +241,7 @@ class TestZoteroPath:
|
|
249
241
|
|
250
242
|
# Test creating nested "Curiosity/Curiosity2"
|
251
243
|
mock_zot.create_collection.reset_mock()
|
252
|
-
result = find_or_create_collection(
|
253
|
-
mock_zot, "/Curiosity/Curiosity2", create_missing=True
|
254
|
-
)
|
244
|
+
result = find_or_create_collection(mock_zot, "/Curiosity/Curiosity2", create_missing=True)
|
255
245
|
assert result == "new_key"
|
256
246
|
# Check that the call includes parentCollection
|
257
247
|
mock_zot.create_collection.assert_called_once()
|
@@ -314,11 +304,24 @@ class TestZoteroWrite:
|
|
314
304
|
mock_zot_class.return_value = mock_zot
|
315
305
|
yield mock_zot
|
316
306
|
|
317
|
-
@patch(
|
318
|
-
|
319
|
-
)
|
320
|
-
|
307
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.write_helper.fetch_papers_for_save")
|
308
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.write_helper.hydra.initialize")
|
309
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.write_helper.hydra.compose")
|
310
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.write_helper.zotero.Zotero")
|
311
|
+
def test_zotero_write_no_papers(self, mock_zotero_class, mock_compose, _, mock_fetch):
|
321
312
|
"""When no papers exist (even after approval), the function raises a ValueError."""
|
313
|
+
# Mock hydra configuration
|
314
|
+
cfg = MagicMock()
|
315
|
+
cfg.user_id = "test_user"
|
316
|
+
cfg.library_type = "user"
|
317
|
+
cfg.api_key = "test_key"
|
318
|
+
mock_compose.return_value = MagicMock()
|
319
|
+
mock_compose.return_value.tools.zotero_write = cfg
|
320
|
+
|
321
|
+
# Mock Zotero client
|
322
|
+
mock_zot = MagicMock()
|
323
|
+
mock_zotero_class.return_value = mock_zot
|
324
|
+
|
322
325
|
mock_fetch.return_value = None
|
323
326
|
|
324
327
|
state = {
|
@@ -338,22 +341,37 @@ class TestZoteroWrite:
|
|
338
341
|
)
|
339
342
|
assert "No fetched papers were found to save" in str(excinfo.value)
|
340
343
|
|
341
|
-
@patch(
|
342
|
-
"aiagents4pharma.talk2scholars.tools.zotero.utils.write_helper.fetch_papers_for_save"
|
343
|
-
)
|
344
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.write_helper.fetch_papers_for_save")
|
344
345
|
@patch(
|
345
346
|
"aiagents4pharma.talk2scholars.tools.zotero.utils.write_helper.find_or_create_collection"
|
346
347
|
)
|
347
|
-
|
348
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.write_helper.hydra.initialize")
|
349
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.write_helper.hydra.compose")
|
350
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.write_helper.zotero.Zotero")
|
351
|
+
def test_zotero_write_invalid_collection(
|
352
|
+
self, mock_zotero_class, mock_compose, _, mock_find, mock_fetch
|
353
|
+
):
|
348
354
|
"""Saving to a nonexistent Zotero collection returns an error Command."""
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
355
|
+
# Mock hydra configuration
|
356
|
+
cfg = MagicMock()
|
357
|
+
cfg.user_id = "test_user"
|
358
|
+
cfg.library_type = "user"
|
359
|
+
cfg.api_key = "test_key"
|
360
|
+
mock_compose.return_value = MagicMock()
|
361
|
+
mock_compose.return_value.tools.zotero_write = cfg
|
362
|
+
|
363
|
+
# Mock Zotero client
|
364
|
+
mock_zot = MagicMock()
|
365
|
+
mock_zotero_class.return_value = mock_zot
|
366
|
+
mock_zot.collections.return_value = [
|
353
367
|
{"key": "k1", "data": {"name": "Curiosity"}},
|
354
368
|
{"key": "k2", "data": {"name": "Random"}},
|
355
369
|
]
|
356
370
|
|
371
|
+
sample = {"paper1": {"Title": "Test Paper"}}
|
372
|
+
mock_fetch.return_value = sample
|
373
|
+
mock_find.return_value = None
|
374
|
+
|
357
375
|
state = {
|
358
376
|
"zotero_write_approval_status": {
|
359
377
|
"approved": True,
|
@@ -375,9 +393,7 @@ class TestZoteroWrite:
|
|
375
393
|
assert "does not exist in Zotero" in msg
|
376
394
|
assert "Curiosity, Random" in msg
|
377
395
|
|
378
|
-
@patch(
|
379
|
-
"aiagents4pharma.talk2scholars.tools.zotero.utils.write_helper.fetch_papers_for_save"
|
380
|
-
)
|
396
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.write_helper.fetch_papers_for_save")
|
381
397
|
@patch(
|
382
398
|
"aiagents4pharma.talk2scholars.tools.zotero.utils.write_helper.find_or_create_collection"
|
383
399
|
)
|
@@ -386,12 +402,8 @@ class TestZoteroWrite:
|
|
386
402
|
sample = {"paper1": {"Title": "Test Paper", "Authors": ["Test Author"]}}
|
387
403
|
mock_fetch.return_value = sample
|
388
404
|
mock_find.return_value = "abc123"
|
389
|
-
mock_zotero.collections.return_value = [
|
390
|
-
|
391
|
-
]
|
392
|
-
mock_zotero.create_items.return_value = {
|
393
|
-
"successful": {"0": {"key": "item123"}}
|
394
|
-
}
|
405
|
+
mock_zotero.collections.return_value = [{"key": "abc123", "data": {"name": "radiation"}}]
|
406
|
+
mock_zotero.create_items.return_value = {"successful": {"0": {"key": "item123"}}}
|
395
407
|
mock_hydra.tools.zotero_write.zotero.max_limit = 50
|
396
408
|
|
397
409
|
state = {
|
@@ -423,9 +435,7 @@ class TestZoteroRead:
|
|
423
435
|
def mock_hydra(self):
|
424
436
|
"""Fixture to mock hydra configuration."""
|
425
437
|
with (
|
426
|
-
patch(
|
427
|
-
"aiagents4pharma.talk2scholars.tools.zotero.utils.write_helper.hydra.initialize"
|
428
|
-
),
|
438
|
+
patch("aiagents4pharma.talk2scholars.tools.zotero.utils.write_helper.hydra.initialize"),
|
429
439
|
patch(
|
430
440
|
"aiagents4pharma.talk2scholars.tools.zotero.utils.write_helper.hydra.compose"
|
431
441
|
) as mock_compose,
|
@@ -453,9 +463,7 @@ class TestZoteroRead:
|
|
453
463
|
mock_zot_class.return_value = mock_zot
|
454
464
|
yield mock_zot
|
455
465
|
|
456
|
-
@patch(
|
457
|
-
"aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections"
|
458
|
-
)
|
466
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections")
|
459
467
|
def test_zotero_read_item_collections_error(
|
460
468
|
self, mock_get_collections, mock_hydra, mock_zotero
|
461
469
|
):
|