aiagents4pharma 0.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- aiagents4pharma/__init__.py +11 -0
- aiagents4pharma/talk2aiagents4pharma/.dockerignore +13 -0
- aiagents4pharma/talk2aiagents4pharma/Dockerfile +133 -0
- aiagents4pharma/talk2aiagents4pharma/README.md +1 -0
- aiagents4pharma/talk2aiagents4pharma/__init__.py +5 -0
- aiagents4pharma/talk2aiagents4pharma/agents/__init__.py +6 -0
- aiagents4pharma/talk2aiagents4pharma/agents/main_agent.py +70 -0
- aiagents4pharma/talk2aiagents4pharma/configs/__init__.py +5 -0
- aiagents4pharma/talk2aiagents4pharma/configs/agents/__init__.py +5 -0
- aiagents4pharma/talk2aiagents4pharma/configs/agents/main_agent/default.yaml +29 -0
- aiagents4pharma/talk2aiagents4pharma/configs/app/__init__.py +0 -0
- aiagents4pharma/talk2aiagents4pharma/configs/app/frontend/__init__.py +0 -0
- aiagents4pharma/talk2aiagents4pharma/configs/app/frontend/default.yaml +102 -0
- aiagents4pharma/talk2aiagents4pharma/configs/config.yaml +4 -0
- 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 +154 -0
- aiagents4pharma/talk2aiagents4pharma/states/__init__.py +5 -0
- aiagents4pharma/talk2aiagents4pharma/states/state_talk2aiagents4pharma.py +18 -0
- aiagents4pharma/talk2aiagents4pharma/tests/__init__.py +3 -0
- aiagents4pharma/talk2aiagents4pharma/tests/test_main_agent.py +312 -0
- aiagents4pharma/talk2biomodels/.dockerignore +13 -0
- aiagents4pharma/talk2biomodels/Dockerfile +104 -0
- aiagents4pharma/talk2biomodels/README.md +1 -0
- aiagents4pharma/talk2biomodels/__init__.py +5 -0
- aiagents4pharma/talk2biomodels/agents/__init__.py +6 -0
- aiagents4pharma/talk2biomodels/agents/t2b_agent.py +104 -0
- aiagents4pharma/talk2biomodels/api/__init__.py +5 -0
- aiagents4pharma/talk2biomodels/api/ols.py +75 -0
- aiagents4pharma/talk2biomodels/api/uniprot.py +36 -0
- aiagents4pharma/talk2biomodels/configs/__init__.py +5 -0
- aiagents4pharma/talk2biomodels/configs/agents/__init__.py +5 -0
- aiagents4pharma/talk2biomodels/configs/agents/t2b_agent/__init__.py +3 -0
- aiagents4pharma/talk2biomodels/configs/agents/t2b_agent/default.yaml +14 -0
- aiagents4pharma/talk2biomodels/configs/app/__init__.py +0 -0
- aiagents4pharma/talk2biomodels/configs/app/frontend/__init__.py +0 -0
- aiagents4pharma/talk2biomodels/configs/app/frontend/default.yaml +72 -0
- aiagents4pharma/talk2biomodels/configs/config.yaml +7 -0
- aiagents4pharma/talk2biomodels/configs/tools/__init__.py +5 -0
- aiagents4pharma/talk2biomodels/configs/tools/ask_question/__init__.py +3 -0
- aiagents4pharma/talk2biomodels/configs/tools/ask_question/default.yaml +30 -0
- aiagents4pharma/talk2biomodels/configs/tools/custom_plotter/__init__.py +3 -0
- aiagents4pharma/talk2biomodels/configs/tools/custom_plotter/default.yaml +8 -0
- aiagents4pharma/talk2biomodels/configs/tools/get_annotation/__init__.py +3 -0
- aiagents4pharma/talk2biomodels/configs/tools/get_annotation/default.yaml +8 -0
- aiagents4pharma/talk2biomodels/install.md +63 -0
- aiagents4pharma/talk2biomodels/models/__init__.py +5 -0
- aiagents4pharma/talk2biomodels/models/basico_model.py +125 -0
- aiagents4pharma/talk2biomodels/models/sys_bio_model.py +60 -0
- aiagents4pharma/talk2biomodels/states/__init__.py +6 -0
- aiagents4pharma/talk2biomodels/states/state_talk2biomodels.py +49 -0
- aiagents4pharma/talk2biomodels/tests/BIOMD0000000449_url.xml +1585 -0
- aiagents4pharma/talk2biomodels/tests/__init__.py +3 -0
- aiagents4pharma/talk2biomodels/tests/article_on_model_537.pdf +0 -0
- aiagents4pharma/talk2biomodels/tests/test_api.py +31 -0
- aiagents4pharma/talk2biomodels/tests/test_ask_question.py +42 -0
- aiagents4pharma/talk2biomodels/tests/test_basico_model.py +67 -0
- aiagents4pharma/talk2biomodels/tests/test_get_annotation.py +190 -0
- aiagents4pharma/talk2biomodels/tests/test_getmodelinfo.py +92 -0
- aiagents4pharma/talk2biomodels/tests/test_integration.py +116 -0
- aiagents4pharma/talk2biomodels/tests/test_load_biomodel.py +35 -0
- aiagents4pharma/talk2biomodels/tests/test_param_scan.py +71 -0
- aiagents4pharma/talk2biomodels/tests/test_query_article.py +184 -0
- aiagents4pharma/talk2biomodels/tests/test_save_model.py +47 -0
- aiagents4pharma/talk2biomodels/tests/test_search_models.py +35 -0
- aiagents4pharma/talk2biomodels/tests/test_simulate_model.py +44 -0
- aiagents4pharma/talk2biomodels/tests/test_steady_state.py +86 -0
- aiagents4pharma/talk2biomodels/tests/test_sys_bio_model.py +67 -0
- aiagents4pharma/talk2biomodels/tools/__init__.py +17 -0
- aiagents4pharma/talk2biomodels/tools/ask_question.py +125 -0
- aiagents4pharma/talk2biomodels/tools/custom_plotter.py +165 -0
- aiagents4pharma/talk2biomodels/tools/get_annotation.py +342 -0
- aiagents4pharma/talk2biomodels/tools/get_modelinfo.py +159 -0
- aiagents4pharma/talk2biomodels/tools/load_arguments.py +134 -0
- aiagents4pharma/talk2biomodels/tools/load_biomodel.py +44 -0
- aiagents4pharma/talk2biomodels/tools/parameter_scan.py +310 -0
- aiagents4pharma/talk2biomodels/tools/query_article.py +64 -0
- aiagents4pharma/talk2biomodels/tools/save_model.py +98 -0
- aiagents4pharma/talk2biomodels/tools/search_models.py +96 -0
- aiagents4pharma/talk2biomodels/tools/simulate_model.py +137 -0
- aiagents4pharma/talk2biomodels/tools/steady_state.py +187 -0
- aiagents4pharma/talk2biomodels/tools/utils.py +23 -0
- aiagents4pharma/talk2cells/README.md +1 -0
- aiagents4pharma/talk2cells/__init__.py +5 -0
- aiagents4pharma/talk2cells/agents/__init__.py +6 -0
- aiagents4pharma/talk2cells/agents/scp_agent.py +87 -0
- aiagents4pharma/talk2cells/states/__init__.py +6 -0
- aiagents4pharma/talk2cells/states/state_talk2cells.py +15 -0
- aiagents4pharma/talk2cells/tests/scp_agent/test_scp_agent.py +22 -0
- aiagents4pharma/talk2cells/tools/__init__.py +6 -0
- aiagents4pharma/talk2cells/tools/scp_agent/__init__.py +6 -0
- aiagents4pharma/talk2cells/tools/scp_agent/display_studies.py +27 -0
- aiagents4pharma/talk2cells/tools/scp_agent/search_studies.py +78 -0
- aiagents4pharma/talk2knowledgegraphs/.dockerignore +13 -0
- aiagents4pharma/talk2knowledgegraphs/Dockerfile +131 -0
- aiagents4pharma/talk2knowledgegraphs/README.md +1 -0
- aiagents4pharma/talk2knowledgegraphs/__init__.py +5 -0
- aiagents4pharma/talk2knowledgegraphs/agents/__init__.py +5 -0
- aiagents4pharma/talk2knowledgegraphs/agents/t2kg_agent.py +99 -0
- aiagents4pharma/talk2knowledgegraphs/configs/__init__.py +5 -0
- aiagents4pharma/talk2knowledgegraphs/configs/agents/t2kg_agent/__init__.py +3 -0
- aiagents4pharma/talk2knowledgegraphs/configs/agents/t2kg_agent/default.yaml +62 -0
- aiagents4pharma/talk2knowledgegraphs/configs/app/__init__.py +5 -0
- aiagents4pharma/talk2knowledgegraphs/configs/app/frontend/__init__.py +3 -0
- aiagents4pharma/talk2knowledgegraphs/configs/app/frontend/default.yaml +79 -0
- aiagents4pharma/talk2knowledgegraphs/configs/config.yaml +13 -0
- aiagents4pharma/talk2knowledgegraphs/configs/tools/__init__.py +5 -0
- aiagents4pharma/talk2knowledgegraphs/configs/tools/graphrag_reasoning/__init__.py +3 -0
- aiagents4pharma/talk2knowledgegraphs/configs/tools/graphrag_reasoning/default.yaml +24 -0
- aiagents4pharma/talk2knowledgegraphs/configs/tools/multimodal_subgraph_extraction/__init__.py +0 -0
- aiagents4pharma/talk2knowledgegraphs/configs/tools/multimodal_subgraph_extraction/default.yaml +33 -0
- aiagents4pharma/talk2knowledgegraphs/configs/tools/subgraph_extraction/__init__.py +3 -0
- aiagents4pharma/talk2knowledgegraphs/configs/tools/subgraph_extraction/default.yaml +43 -0
- aiagents4pharma/talk2knowledgegraphs/configs/tools/subgraph_summarization/__init__.py +3 -0
- aiagents4pharma/talk2knowledgegraphs/configs/tools/subgraph_summarization/default.yaml +9 -0
- aiagents4pharma/talk2knowledgegraphs/configs/utils/database/milvus/__init__.py +3 -0
- aiagents4pharma/talk2knowledgegraphs/configs/utils/database/milvus/default.yaml +61 -0
- aiagents4pharma/talk2knowledgegraphs/configs/utils/enrichments/ols_terms/default.yaml +3 -0
- aiagents4pharma/talk2knowledgegraphs/configs/utils/enrichments/reactome_pathways/default.yaml +3 -0
- aiagents4pharma/talk2knowledgegraphs/configs/utils/enrichments/uniprot_proteins/default.yaml +6 -0
- aiagents4pharma/talk2knowledgegraphs/configs/utils/pubchem_utils/default.yaml +5 -0
- aiagents4pharma/talk2knowledgegraphs/datasets/__init__.py +5 -0
- aiagents4pharma/talk2knowledgegraphs/datasets/biobridge_primekg.py +607 -0
- aiagents4pharma/talk2knowledgegraphs/datasets/dataset.py +25 -0
- aiagents4pharma/talk2knowledgegraphs/datasets/primekg.py +212 -0
- aiagents4pharma/talk2knowledgegraphs/datasets/starkqa_primekg.py +210 -0
- 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 +180 -0
- aiagents4pharma/talk2knowledgegraphs/install.md +165 -0
- aiagents4pharma/talk2knowledgegraphs/milvus_data_dump.py +886 -0
- aiagents4pharma/talk2knowledgegraphs/states/__init__.py +5 -0
- aiagents4pharma/talk2knowledgegraphs/states/state_talk2knowledgegraphs.py +40 -0
- aiagents4pharma/talk2knowledgegraphs/tests/__init__.py +0 -0
- aiagents4pharma/talk2knowledgegraphs/tests/test_agents_t2kg_agent.py +318 -0
- aiagents4pharma/talk2knowledgegraphs/tests/test_datasets_biobridge_primekg.py +248 -0
- aiagents4pharma/talk2knowledgegraphs/tests/test_datasets_dataset.py +33 -0
- aiagents4pharma/talk2knowledgegraphs/tests/test_datasets_primekg.py +86 -0
- aiagents4pharma/talk2knowledgegraphs/tests/test_datasets_starkqa_primekg.py +125 -0
- aiagents4pharma/talk2knowledgegraphs/tests/test_tools_graphrag_reasoning.py +257 -0
- aiagents4pharma/talk2knowledgegraphs/tests/test_tools_milvus_multimodal_subgraph_extraction.py +1444 -0
- aiagents4pharma/talk2knowledgegraphs/tests/test_tools_multimodal_subgraph_extraction.py +159 -0
- aiagents4pharma/talk2knowledgegraphs/tests/test_tools_subgraph_extraction.py +152 -0
- aiagents4pharma/talk2knowledgegraphs/tests/test_tools_subgraph_summarization.py +201 -0
- aiagents4pharma/talk2knowledgegraphs/tests/test_utils_database_milvus_connection_manager.py +812 -0
- aiagents4pharma/talk2knowledgegraphs/tests/test_utils_embeddings_embeddings.py +51 -0
- aiagents4pharma/talk2knowledgegraphs/tests/test_utils_embeddings_huggingface.py +49 -0
- aiagents4pharma/talk2knowledgegraphs/tests/test_utils_embeddings_nim_molmim.py +59 -0
- aiagents4pharma/talk2knowledgegraphs/tests/test_utils_embeddings_ollama.py +63 -0
- aiagents4pharma/talk2knowledgegraphs/tests/test_utils_embeddings_sentencetransformer.py +47 -0
- aiagents4pharma/talk2knowledgegraphs/tests/test_utils_enrichments_enrichments.py +40 -0
- aiagents4pharma/talk2knowledgegraphs/tests/test_utils_enrichments_ollama.py +94 -0
- aiagents4pharma/talk2knowledgegraphs/tests/test_utils_enrichments_ols.py +70 -0
- aiagents4pharma/talk2knowledgegraphs/tests/test_utils_enrichments_pubchem.py +45 -0
- aiagents4pharma/talk2knowledgegraphs/tests/test_utils_enrichments_reactome.py +44 -0
- aiagents4pharma/talk2knowledgegraphs/tests/test_utils_enrichments_uniprot.py +48 -0
- aiagents4pharma/talk2knowledgegraphs/tests/test_utils_extractions_milvus_multimodal_pcst.py +759 -0
- aiagents4pharma/talk2knowledgegraphs/tests/test_utils_kg_utils.py +78 -0
- aiagents4pharma/talk2knowledgegraphs/tests/test_utils_pubchem_utils.py +123 -0
- aiagents4pharma/talk2knowledgegraphs/tools/__init__.py +11 -0
- aiagents4pharma/talk2knowledgegraphs/tools/graphrag_reasoning.py +138 -0
- aiagents4pharma/talk2knowledgegraphs/tools/load_arguments.py +22 -0
- aiagents4pharma/talk2knowledgegraphs/tools/milvus_multimodal_subgraph_extraction.py +965 -0
- aiagents4pharma/talk2knowledgegraphs/tools/multimodal_subgraph_extraction.py +374 -0
- aiagents4pharma/talk2knowledgegraphs/tools/subgraph_extraction.py +291 -0
- aiagents4pharma/talk2knowledgegraphs/tools/subgraph_summarization.py +123 -0
- aiagents4pharma/talk2knowledgegraphs/utils/__init__.py +5 -0
- aiagents4pharma/talk2knowledgegraphs/utils/database/__init__.py +5 -0
- aiagents4pharma/talk2knowledgegraphs/utils/database/milvus_connection_manager.py +586 -0
- aiagents4pharma/talk2knowledgegraphs/utils/embeddings/__init__.py +5 -0
- aiagents4pharma/talk2knowledgegraphs/utils/embeddings/embeddings.py +81 -0
- aiagents4pharma/talk2knowledgegraphs/utils/embeddings/huggingface.py +111 -0
- aiagents4pharma/talk2knowledgegraphs/utils/embeddings/nim_molmim.py +54 -0
- aiagents4pharma/talk2knowledgegraphs/utils/embeddings/ollama.py +87 -0
- aiagents4pharma/talk2knowledgegraphs/utils/embeddings/sentence_transformer.py +73 -0
- aiagents4pharma/talk2knowledgegraphs/utils/enrichments/__init__.py +12 -0
- aiagents4pharma/talk2knowledgegraphs/utils/enrichments/enrichments.py +37 -0
- aiagents4pharma/talk2knowledgegraphs/utils/enrichments/ollama.py +129 -0
- aiagents4pharma/talk2knowledgegraphs/utils/enrichments/ols_terms.py +89 -0
- aiagents4pharma/talk2knowledgegraphs/utils/enrichments/pubchem_strings.py +78 -0
- aiagents4pharma/talk2knowledgegraphs/utils/enrichments/reactome_pathways.py +71 -0
- aiagents4pharma/talk2knowledgegraphs/utils/enrichments/uniprot_proteins.py +98 -0
- aiagents4pharma/talk2knowledgegraphs/utils/extractions/__init__.py +5 -0
- aiagents4pharma/talk2knowledgegraphs/utils/extractions/milvus_multimodal_pcst.py +762 -0
- aiagents4pharma/talk2knowledgegraphs/utils/extractions/multimodal_pcst.py +298 -0
- aiagents4pharma/talk2knowledgegraphs/utils/extractions/pcst.py +229 -0
- aiagents4pharma/talk2knowledgegraphs/utils/kg_utils.py +67 -0
- aiagents4pharma/talk2knowledgegraphs/utils/pubchem_utils.py +104 -0
- aiagents4pharma/talk2scholars/.dockerignore +13 -0
- aiagents4pharma/talk2scholars/Dockerfile +104 -0
- aiagents4pharma/talk2scholars/README.md +1 -0
- aiagents4pharma/talk2scholars/__init__.py +7 -0
- aiagents4pharma/talk2scholars/agents/__init__.py +13 -0
- aiagents4pharma/talk2scholars/agents/main_agent.py +89 -0
- aiagents4pharma/talk2scholars/agents/paper_download_agent.py +96 -0
- aiagents4pharma/talk2scholars/agents/pdf_agent.py +101 -0
- aiagents4pharma/talk2scholars/agents/s2_agent.py +135 -0
- aiagents4pharma/talk2scholars/agents/zotero_agent.py +127 -0
- aiagents4pharma/talk2scholars/configs/__init__.py +7 -0
- aiagents4pharma/talk2scholars/configs/agents/__init__.py +7 -0
- aiagents4pharma/talk2scholars/configs/agents/talk2scholars/__init__.py +7 -0
- aiagents4pharma/talk2scholars/configs/agents/talk2scholars/main_agent/__init__.py +3 -0
- aiagents4pharma/talk2scholars/configs/agents/talk2scholars/main_agent/default.yaml +52 -0
- aiagents4pharma/talk2scholars/configs/agents/talk2scholars/paper_download_agent/__init__.py +3 -0
- aiagents4pharma/talk2scholars/configs/agents/talk2scholars/paper_download_agent/default.yaml +19 -0
- aiagents4pharma/talk2scholars/configs/agents/talk2scholars/pdf_agent/__init__.py +3 -0
- aiagents4pharma/talk2scholars/configs/agents/talk2scholars/pdf_agent/default.yaml +19 -0
- aiagents4pharma/talk2scholars/configs/agents/talk2scholars/s2_agent/__init__.py +3 -0
- aiagents4pharma/talk2scholars/configs/agents/talk2scholars/s2_agent/default.yaml +44 -0
- aiagents4pharma/talk2scholars/configs/agents/talk2scholars/zotero_agent/__init__.py +3 -0
- aiagents4pharma/talk2scholars/configs/agents/talk2scholars/zotero_agent/default.yaml +19 -0
- aiagents4pharma/talk2scholars/configs/app/__init__.py +7 -0
- aiagents4pharma/talk2scholars/configs/app/frontend/__init__.py +3 -0
- aiagents4pharma/talk2scholars/configs/app/frontend/default.yaml +72 -0
- aiagents4pharma/talk2scholars/configs/config.yaml +16 -0
- aiagents4pharma/talk2scholars/configs/tools/__init__.py +21 -0
- aiagents4pharma/talk2scholars/configs/tools/multi_paper_recommendation/__init__.py +3 -0
- aiagents4pharma/talk2scholars/configs/tools/multi_paper_recommendation/default.yaml +26 -0
- aiagents4pharma/talk2scholars/configs/tools/paper_download/__init__.py +3 -0
- aiagents4pharma/talk2scholars/configs/tools/paper_download/default.yaml +124 -0
- aiagents4pharma/talk2scholars/configs/tools/question_and_answer/__init__.py +3 -0
- aiagents4pharma/talk2scholars/configs/tools/question_and_answer/default.yaml +62 -0
- aiagents4pharma/talk2scholars/configs/tools/retrieve_semantic_scholar_paper_id/__init__.py +3 -0
- aiagents4pharma/talk2scholars/configs/tools/retrieve_semantic_scholar_paper_id/default.yaml +12 -0
- aiagents4pharma/talk2scholars/configs/tools/search/__init__.py +3 -0
- aiagents4pharma/talk2scholars/configs/tools/search/default.yaml +26 -0
- aiagents4pharma/talk2scholars/configs/tools/single_paper_recommendation/__init__.py +3 -0
- aiagents4pharma/talk2scholars/configs/tools/single_paper_recommendation/default.yaml +26 -0
- aiagents4pharma/talk2scholars/configs/tools/zotero_read/__init__.py +3 -0
- aiagents4pharma/talk2scholars/configs/tools/zotero_read/default.yaml +57 -0
- aiagents4pharma/talk2scholars/configs/tools/zotero_write/__inti__.py +3 -0
- aiagents4pharma/talk2scholars/configs/tools/zotero_write/default.yaml +55 -0
- 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/__init__.py +7 -0
- aiagents4pharma/talk2scholars/state/state_talk2scholars.py +98 -0
- aiagents4pharma/talk2scholars/tests/__init__.py +3 -0
- aiagents4pharma/talk2scholars/tests/test_agents_main_agent.py +256 -0
- aiagents4pharma/talk2scholars/tests/test_agents_paper_agents_download_agent.py +139 -0
- aiagents4pharma/talk2scholars/tests/test_agents_pdf_agent.py +114 -0
- aiagents4pharma/talk2scholars/tests/test_agents_s2_agent.py +198 -0
- aiagents4pharma/talk2scholars/tests/test_agents_zotero_agent.py +160 -0
- aiagents4pharma/talk2scholars/tests/test_s2_tools_display_dataframe.py +91 -0
- aiagents4pharma/talk2scholars/tests/test_s2_tools_query_dataframe.py +191 -0
- aiagents4pharma/talk2scholars/tests/test_states_state.py +38 -0
- aiagents4pharma/talk2scholars/tests/test_tools_paper_downloader.py +507 -0
- aiagents4pharma/talk2scholars/tests/test_tools_question_and_answer_tool.py +105 -0
- aiagents4pharma/talk2scholars/tests/test_tools_s2_multi.py +307 -0
- aiagents4pharma/talk2scholars/tests/test_tools_s2_retrieve.py +67 -0
- aiagents4pharma/talk2scholars/tests/test_tools_s2_search.py +286 -0
- aiagents4pharma/talk2scholars/tests/test_tools_s2_single.py +298 -0
- aiagents4pharma/talk2scholars/tests/test_utils_arxiv_downloader.py +469 -0
- aiagents4pharma/talk2scholars/tests/test_utils_base_paper_downloader.py +598 -0
- aiagents4pharma/talk2scholars/tests/test_utils_biorxiv_downloader.py +669 -0
- aiagents4pharma/talk2scholars/tests/test_utils_medrxiv_downloader.py +500 -0
- aiagents4pharma/talk2scholars/tests/test_utils_nvidia_nim_reranker.py +117 -0
- aiagents4pharma/talk2scholars/tests/test_utils_pdf_answer_formatter.py +67 -0
- aiagents4pharma/talk2scholars/tests/test_utils_pdf_batch_processor.py +92 -0
- aiagents4pharma/talk2scholars/tests/test_utils_pdf_collection_manager.py +173 -0
- aiagents4pharma/talk2scholars/tests/test_utils_pdf_document_processor.py +68 -0
- aiagents4pharma/talk2scholars/tests/test_utils_pdf_generate_answer.py +72 -0
- aiagents4pharma/talk2scholars/tests/test_utils_pdf_gpu_detection.py +129 -0
- aiagents4pharma/talk2scholars/tests/test_utils_pdf_paper_loader.py +116 -0
- aiagents4pharma/talk2scholars/tests/test_utils_pdf_rag_pipeline.py +88 -0
- aiagents4pharma/talk2scholars/tests/test_utils_pdf_retrieve_chunks.py +190 -0
- aiagents4pharma/talk2scholars/tests/test_utils_pdf_singleton_manager.py +159 -0
- aiagents4pharma/talk2scholars/tests/test_utils_pdf_vector_normalization.py +121 -0
- aiagents4pharma/talk2scholars/tests/test_utils_pdf_vector_store.py +406 -0
- aiagents4pharma/talk2scholars/tests/test_utils_pubmed_downloader.py +1007 -0
- aiagents4pharma/talk2scholars/tests/test_utils_read_helper_utils.py +106 -0
- aiagents4pharma/talk2scholars/tests/test_utils_s2_utils_ext_ids.py +403 -0
- aiagents4pharma/talk2scholars/tests/test_utils_tool_helper_utils.py +85 -0
- aiagents4pharma/talk2scholars/tests/test_utils_zotero_human_in_the_loop.py +266 -0
- aiagents4pharma/talk2scholars/tests/test_utils_zotero_path.py +496 -0
- aiagents4pharma/talk2scholars/tests/test_utils_zotero_pdf_downloader_utils.py +46 -0
- aiagents4pharma/talk2scholars/tests/test_utils_zotero_read.py +743 -0
- aiagents4pharma/talk2scholars/tests/test_utils_zotero_write.py +151 -0
- aiagents4pharma/talk2scholars/tools/__init__.py +9 -0
- aiagents4pharma/talk2scholars/tools/paper_download/__init__.py +12 -0
- aiagents4pharma/talk2scholars/tools/paper_download/paper_downloader.py +442 -0
- aiagents4pharma/talk2scholars/tools/paper_download/utils/__init__.py +22 -0
- aiagents4pharma/talk2scholars/tools/paper_download/utils/arxiv_downloader.py +207 -0
- aiagents4pharma/talk2scholars/tools/paper_download/utils/base_paper_downloader.py +336 -0
- aiagents4pharma/talk2scholars/tools/paper_download/utils/biorxiv_downloader.py +313 -0
- aiagents4pharma/talk2scholars/tools/paper_download/utils/medrxiv_downloader.py +196 -0
- aiagents4pharma/talk2scholars/tools/paper_download/utils/pubmed_downloader.py +323 -0
- aiagents4pharma/talk2scholars/tools/pdf/__init__.py +7 -0
- aiagents4pharma/talk2scholars/tools/pdf/question_and_answer.py +170 -0
- aiagents4pharma/talk2scholars/tools/pdf/utils/__init__.py +37 -0
- aiagents4pharma/talk2scholars/tools/pdf/utils/answer_formatter.py +62 -0
- aiagents4pharma/talk2scholars/tools/pdf/utils/batch_processor.py +198 -0
- aiagents4pharma/talk2scholars/tools/pdf/utils/collection_manager.py +172 -0
- aiagents4pharma/talk2scholars/tools/pdf/utils/document_processor.py +76 -0
- aiagents4pharma/talk2scholars/tools/pdf/utils/generate_answer.py +97 -0
- aiagents4pharma/talk2scholars/tools/pdf/utils/get_vectorstore.py +59 -0
- aiagents4pharma/talk2scholars/tools/pdf/utils/gpu_detection.py +150 -0
- aiagents4pharma/talk2scholars/tools/pdf/utils/nvidia_nim_reranker.py +97 -0
- aiagents4pharma/talk2scholars/tools/pdf/utils/paper_loader.py +123 -0
- aiagents4pharma/talk2scholars/tools/pdf/utils/rag_pipeline.py +113 -0
- aiagents4pharma/talk2scholars/tools/pdf/utils/retrieve_chunks.py +197 -0
- aiagents4pharma/talk2scholars/tools/pdf/utils/singleton_manager.py +140 -0
- aiagents4pharma/talk2scholars/tools/pdf/utils/tool_helper.py +86 -0
- aiagents4pharma/talk2scholars/tools/pdf/utils/vector_normalization.py +150 -0
- aiagents4pharma/talk2scholars/tools/pdf/utils/vector_store.py +327 -0
- aiagents4pharma/talk2scholars/tools/s2/__init__.py +21 -0
- aiagents4pharma/talk2scholars/tools/s2/display_dataframe.py +110 -0
- aiagents4pharma/talk2scholars/tools/s2/multi_paper_rec.py +111 -0
- aiagents4pharma/talk2scholars/tools/s2/query_dataframe.py +233 -0
- aiagents4pharma/talk2scholars/tools/s2/retrieve_semantic_scholar_paper_id.py +128 -0
- aiagents4pharma/talk2scholars/tools/s2/search.py +101 -0
- aiagents4pharma/talk2scholars/tools/s2/single_paper_rec.py +102 -0
- aiagents4pharma/talk2scholars/tools/s2/utils/__init__.py +5 -0
- aiagents4pharma/talk2scholars/tools/s2/utils/multi_helper.py +223 -0
- aiagents4pharma/talk2scholars/tools/s2/utils/search_helper.py +205 -0
- aiagents4pharma/talk2scholars/tools/s2/utils/single_helper.py +216 -0
- aiagents4pharma/talk2scholars/tools/zotero/__init__.py +7 -0
- aiagents4pharma/talk2scholars/tools/zotero/utils/__init__.py +7 -0
- aiagents4pharma/talk2scholars/tools/zotero/utils/read_helper.py +270 -0
- aiagents4pharma/talk2scholars/tools/zotero/utils/review_helper.py +74 -0
- aiagents4pharma/talk2scholars/tools/zotero/utils/write_helper.py +194 -0
- aiagents4pharma/talk2scholars/tools/zotero/utils/zotero_path.py +180 -0
- aiagents4pharma/talk2scholars/tools/zotero/utils/zotero_pdf_downloader.py +133 -0
- aiagents4pharma/talk2scholars/tools/zotero/zotero_read.py +105 -0
- aiagents4pharma/talk2scholars/tools/zotero/zotero_review.py +162 -0
- aiagents4pharma/talk2scholars/tools/zotero/zotero_write.py +91 -0
- aiagents4pharma-0.0.0.dist-info/METADATA +335 -0
- aiagents4pharma-0.0.0.dist-info/RECORD +336 -0
- aiagents4pharma-0.0.0.dist-info/WHEEL +4 -0
- aiagents4pharma-0.0.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Unit tests for Zotero read helper download branches.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import unittest
|
|
6
|
+
from types import SimpleNamespace
|
|
7
|
+
from unittest.mock import MagicMock, patch
|
|
8
|
+
|
|
9
|
+
from aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper import (
|
|
10
|
+
ZoteroSearchData,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
# Dummy Hydra configuration for tests
|
|
14
|
+
dummy_zotero_read_config = SimpleNamespace(
|
|
15
|
+
user_id="dummy_user",
|
|
16
|
+
library_type="user",
|
|
17
|
+
api_key="dummy_api_key",
|
|
18
|
+
zotero=SimpleNamespace(
|
|
19
|
+
max_limit=5,
|
|
20
|
+
filter_item_types=["journalArticle", "conferencePaper"],
|
|
21
|
+
filter_excluded_types=["attachment", "note"],
|
|
22
|
+
),
|
|
23
|
+
)
|
|
24
|
+
dummy_cfg = SimpleNamespace(tools=SimpleNamespace(zotero_read=dummy_zotero_read_config))
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class TestReadHelperDownloadsFalse(unittest.TestCase):
|
|
28
|
+
"""Tests for read_helper download_pdfs=False branches."""
|
|
29
|
+
|
|
30
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections")
|
|
31
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.zotero.Zotero")
|
|
32
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.compose")
|
|
33
|
+
@patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.initialize")
|
|
34
|
+
def test_download_pdfs_false_branches(
|
|
35
|
+
self,
|
|
36
|
+
mock_hydra_init,
|
|
37
|
+
mock_hydra_compose,
|
|
38
|
+
mock_zotero_class,
|
|
39
|
+
mock_get_item_collections,
|
|
40
|
+
):
|
|
41
|
+
"""Ensure attachment_key and filename are set when download_pdfs=False."""
|
|
42
|
+
# Setup Hydra mocks
|
|
43
|
+
mock_hydra_compose.return_value = dummy_cfg
|
|
44
|
+
mock_hydra_init.return_value.__enter__.return_value = None
|
|
45
|
+
|
|
46
|
+
# Fake Zotero items: one paper with child PDF, one orphaned PDF
|
|
47
|
+
fake_zot = MagicMock()
|
|
48
|
+
fake_items = [
|
|
49
|
+
{
|
|
50
|
+
"data": {
|
|
51
|
+
"key": "paper1",
|
|
52
|
+
"title": "P1",
|
|
53
|
+
"abstractNote": "A1",
|
|
54
|
+
"date": "2021",
|
|
55
|
+
"url": "u1",
|
|
56
|
+
"itemType": "journalArticle",
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"data": {
|
|
61
|
+
"key": "attach2",
|
|
62
|
+
"itemType": "attachment",
|
|
63
|
+
"contentType": "application/pdf",
|
|
64
|
+
"filename": "file2.pdf",
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
]
|
|
68
|
+
fake_zot.items.return_value = fake_items
|
|
69
|
+
# children for paper1
|
|
70
|
+
fake_child = {
|
|
71
|
+
"data": {
|
|
72
|
+
"key": "attach1",
|
|
73
|
+
"filename": "file1.pdf",
|
|
74
|
+
"contentType": "application/pdf",
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
def children_side_effect(key):
|
|
79
|
+
return [fake_child] if key == "paper1" else []
|
|
80
|
+
|
|
81
|
+
fake_zot.children.side_effect = children_side_effect
|
|
82
|
+
mock_zotero_class.return_value = fake_zot
|
|
83
|
+
mock_get_item_collections.return_value = {"paper1": ["/C1"], "attach2": ["/C2"]}
|
|
84
|
+
|
|
85
|
+
# Instantiate with download_pdfs=False
|
|
86
|
+
search = ZoteroSearchData(
|
|
87
|
+
query="test",
|
|
88
|
+
only_articles=False,
|
|
89
|
+
limit=2,
|
|
90
|
+
tool_call_id="id",
|
|
91
|
+
download_pdfs=False,
|
|
92
|
+
)
|
|
93
|
+
search.process_search()
|
|
94
|
+
data = search.get_search_results()["article_data"]
|
|
95
|
+
|
|
96
|
+
# Regular paper1 should have attachment_key and filename, no pdf_url
|
|
97
|
+
self.assertIn("paper1", data)
|
|
98
|
+
self.assertEqual(data["paper1"]["attachment_key"], "attach1")
|
|
99
|
+
self.assertEqual(data["paper1"]["filename"], "file1.pdf")
|
|
100
|
+
self.assertNotIn("pdf_url", data["paper1"])
|
|
101
|
+
|
|
102
|
+
# Orphan attach2 should have attachment_key and filename, no pdf_url
|
|
103
|
+
self.assertIn("attach2", data)
|
|
104
|
+
self.assertEqual(data["attach2"]["attachment_key"], "attach2")
|
|
105
|
+
self.assertEqual(data["attach2"]["filename"], "file2.pdf")
|
|
106
|
+
self.assertNotIn("pdf_url", data["attach2"])
|
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Unit tests for external ID handling in S2 helper modules.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from types import SimpleNamespace
|
|
6
|
+
|
|
7
|
+
import hydra
|
|
8
|
+
import pytest
|
|
9
|
+
import requests
|
|
10
|
+
|
|
11
|
+
from aiagents4pharma.talk2scholars.tools.s2.utils.multi_helper import MultiPaperRecData
|
|
12
|
+
from aiagents4pharma.talk2scholars.tools.s2.utils.search_helper import SearchData
|
|
13
|
+
from aiagents4pharma.talk2scholars.tools.s2.utils.single_helper import (
|
|
14
|
+
SinglePaperRecData,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@pytest.fixture(autouse=True)
|
|
19
|
+
def patch_hydra(monkeypatch):
|
|
20
|
+
"""Patch Hydra's initialize and compose to provide dummy configs for tests."""
|
|
21
|
+
|
|
22
|
+
class DummyHydraContext:
|
|
23
|
+
"""Dummy Hydra context manager to bypass config loading."""
|
|
24
|
+
|
|
25
|
+
def __enter__(self):
|
|
26
|
+
return None
|
|
27
|
+
|
|
28
|
+
def __exit__(self, exc_type, exc_val, traceback):
|
|
29
|
+
return False
|
|
30
|
+
|
|
31
|
+
# Dummy config with necessary fields for multi, search, and single helpers
|
|
32
|
+
dummy_cfg = SimpleNamespace(
|
|
33
|
+
tools=SimpleNamespace(
|
|
34
|
+
multi_paper_recommendation=SimpleNamespace(
|
|
35
|
+
api_endpoint="",
|
|
36
|
+
headers={},
|
|
37
|
+
api_fields=["paperId", "title", "authors", "externalIds"],
|
|
38
|
+
request_timeout=1,
|
|
39
|
+
),
|
|
40
|
+
search=SimpleNamespace(
|
|
41
|
+
api_endpoint="",
|
|
42
|
+
api_fields=["paperId", "title", "authors", "externalIds"],
|
|
43
|
+
),
|
|
44
|
+
single_paper_recommendation=SimpleNamespace(
|
|
45
|
+
api_endpoint="",
|
|
46
|
+
api_fields=["paperId", "title", "authors", "externalIds"],
|
|
47
|
+
request_timeout=1,
|
|
48
|
+
recommendation_params=SimpleNamespace(from_pool="test_pool"),
|
|
49
|
+
),
|
|
50
|
+
)
|
|
51
|
+
)
|
|
52
|
+
monkeypatch.setattr(hydra, "initialize", lambda version_base, config_path: DummyHydraContext())
|
|
53
|
+
monkeypatch.setattr(hydra, "compose", lambda config_name, overrides: dummy_cfg)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def test_multi_helper_pmc_and_doi_ids(monkeypatch):
|
|
57
|
+
"""Test PubMedCentral and DOI ID handling in MultiPaperRecData."""
|
|
58
|
+
rec = MultiPaperRecData(paper_ids=["p"], limit=1, year=None, tool_call_id="tid")
|
|
59
|
+
# Setup dummy API response
|
|
60
|
+
data = {
|
|
61
|
+
"recommendedPapers": [
|
|
62
|
+
{
|
|
63
|
+
"paperId": "p1",
|
|
64
|
+
"title": "Test",
|
|
65
|
+
"authors": [{"name": "A", "authorId": "A1"}],
|
|
66
|
+
"externalIds": {"PubMedCentral": "pmc1", "DOI": "doi1"},
|
|
67
|
+
}
|
|
68
|
+
]
|
|
69
|
+
}
|
|
70
|
+
response = SimpleNamespace(status_code=200, json=lambda: data, raise_for_status=lambda: None)
|
|
71
|
+
monkeypatch.setattr(requests, "post", lambda *args, **kwargs: response)
|
|
72
|
+
results = rec.process_recommendations()
|
|
73
|
+
ids_list = results["papers"]["p1"]["paper_ids"]
|
|
74
|
+
assert ids_list == ["pmc:pmc1", "doi:doi1"]
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def test_search_helper_pmc_and_doi_ids(monkeypatch):
|
|
78
|
+
"""Test PubMedCentral and DOI ID handling in SearchData."""
|
|
79
|
+
sd = SearchData(query="q", limit=1, year=None, tool_call_id="tid")
|
|
80
|
+
data = {
|
|
81
|
+
"data": [
|
|
82
|
+
{
|
|
83
|
+
"paperId": "s1",
|
|
84
|
+
"title": "Test",
|
|
85
|
+
"authors": [{"name": "B", "authorId": "B1"}],
|
|
86
|
+
"externalIds": {"PubMedCentral": "pmc2", "DOI": "doi2"},
|
|
87
|
+
}
|
|
88
|
+
]
|
|
89
|
+
}
|
|
90
|
+
response = SimpleNamespace(status_code=200, json=lambda: data, raise_for_status=lambda: None)
|
|
91
|
+
monkeypatch.setattr(requests, "get", lambda *args, **kwargs: response)
|
|
92
|
+
results = sd.process_search()
|
|
93
|
+
ids_list = results["papers"]["s1"]["paper_ids"]
|
|
94
|
+
assert ids_list == ["pmc:pmc2", "doi:doi2"]
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def test_single_helper_pmc_and_doi_ids(monkeypatch):
|
|
98
|
+
"""Test PubMedCentral and DOI ID handling in SinglePaperRecData."""
|
|
99
|
+
sp = SinglePaperRecData(paper_id="x", limit=1, year=None, tool_call_id="tid")
|
|
100
|
+
data = {
|
|
101
|
+
"recommendedPapers": [
|
|
102
|
+
{
|
|
103
|
+
"paperId": "x1",
|
|
104
|
+
"title": "Test",
|
|
105
|
+
"authors": [{"name": "C", "authorId": "C1"}],
|
|
106
|
+
"externalIds": {"PubMedCentral": "pmc3", "DOI": "doi3"},
|
|
107
|
+
}
|
|
108
|
+
]
|
|
109
|
+
}
|
|
110
|
+
response = SimpleNamespace(status_code=200, json=lambda: data, raise_for_status=lambda: None)
|
|
111
|
+
monkeypatch.setattr(requests, "get", lambda *args, **kwargs: response)
|
|
112
|
+
results = sp.process_recommendations()
|
|
113
|
+
ids_list = results["papers"]["x1"]["paper_ids"]
|
|
114
|
+
assert ids_list == ["pmc:pmc3", "doi:doi3"]
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def test_helpers_empty_when_no_external_ids(monkeypatch):
|
|
118
|
+
"""Test that MultiPaperRecData, SearchData, and SinglePaperRecData
|
|
119
|
+
return empty lists when externalIds are missing or empty."""
|
|
120
|
+
# Test that no IDs are returned when externalIds is empty or missing
|
|
121
|
+
rec = MultiPaperRecData(paper_ids=["p"], limit=1, year=None, tool_call_id="tid")
|
|
122
|
+
|
|
123
|
+
# Simulate empty externalIds in API response
|
|
124
|
+
class DummyResp1:
|
|
125
|
+
"""dummy response for multi-paper recommendation with empty externalIds"""
|
|
126
|
+
|
|
127
|
+
def __init__(self, data):
|
|
128
|
+
"""initialize with data"""
|
|
129
|
+
self._data = data
|
|
130
|
+
self.status_code = 200
|
|
131
|
+
|
|
132
|
+
def json(self):
|
|
133
|
+
"""json method to return data"""
|
|
134
|
+
return self._data
|
|
135
|
+
|
|
136
|
+
def raise_for_status(self):
|
|
137
|
+
"""raise_for_status method to simulate successful response"""
|
|
138
|
+
return None
|
|
139
|
+
|
|
140
|
+
def dummy_post1(*_, **__):
|
|
141
|
+
"""dummy response for multi-paper recommendation with empty externalIds"""
|
|
142
|
+
return DummyResp1(
|
|
143
|
+
{
|
|
144
|
+
"recommendedPapers": [
|
|
145
|
+
{
|
|
146
|
+
"paperId": "p2",
|
|
147
|
+
"title": "Test2",
|
|
148
|
+
"authors": [{"name": "D", "authorId": "D1"}],
|
|
149
|
+
"externalIds": {},
|
|
150
|
+
},
|
|
151
|
+
]
|
|
152
|
+
}
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
monkeypatch.setattr(requests, "post", dummy_post1)
|
|
156
|
+
assert rec.process_recommendations()["papers"].get("p2", {}).get("paper_ids") == []
|
|
157
|
+
sd = SearchData(query="q2", limit=1, year=None, tool_call_id="tid2")
|
|
158
|
+
|
|
159
|
+
# Simulate empty externalIds in search API response
|
|
160
|
+
class DummyResp2:
|
|
161
|
+
"""dummy response for search with empty externalIds"""
|
|
162
|
+
|
|
163
|
+
def __init__(self, data):
|
|
164
|
+
"""initialize with data"""
|
|
165
|
+
self._data = data
|
|
166
|
+
self.status_code = 200
|
|
167
|
+
|
|
168
|
+
def json(self):
|
|
169
|
+
"""json method to return data"""
|
|
170
|
+
return self._data
|
|
171
|
+
|
|
172
|
+
def raise_for_status(self):
|
|
173
|
+
"""raise_for_status method to simulate successful response"""
|
|
174
|
+
return None
|
|
175
|
+
|
|
176
|
+
def dummy_get2(*_, **__):
|
|
177
|
+
"""dummy response for search with empty externalIds"""
|
|
178
|
+
return DummyResp2(
|
|
179
|
+
{
|
|
180
|
+
"data": [
|
|
181
|
+
{
|
|
182
|
+
"paperId": "s2",
|
|
183
|
+
"title": "Test2",
|
|
184
|
+
"authors": [{"name": "E", "authorId": "E1"}],
|
|
185
|
+
"externalIds": {},
|
|
186
|
+
},
|
|
187
|
+
]
|
|
188
|
+
}
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
monkeypatch.setattr(requests, "get", dummy_get2)
|
|
192
|
+
assert sd.process_search()["papers"].get("s2", {}).get("paper_ids") == []
|
|
193
|
+
sp = SinglePaperRecData(paper_id="y", limit=1, year=None, tool_call_id="tid3")
|
|
194
|
+
|
|
195
|
+
# Simulate empty externalIds in single-paper API response
|
|
196
|
+
class DummyResp3:
|
|
197
|
+
"""dummy response for single paper recommendation with empty externalIds"""
|
|
198
|
+
|
|
199
|
+
def __init__(self, data):
|
|
200
|
+
"""initialize with data"""
|
|
201
|
+
self._data = data
|
|
202
|
+
self.status_code = 200
|
|
203
|
+
|
|
204
|
+
def json(self):
|
|
205
|
+
"""json method to return data"""
|
|
206
|
+
return self._data
|
|
207
|
+
|
|
208
|
+
def raise_for_status(self):
|
|
209
|
+
"""raise_for_status method to simulate successful response"""
|
|
210
|
+
return None
|
|
211
|
+
|
|
212
|
+
def dummy_get3(*_, **__):
|
|
213
|
+
"""dummy response for single paper recommendation with empty externalIds"""
|
|
214
|
+
return DummyResp3(
|
|
215
|
+
{
|
|
216
|
+
"recommendedPapers": [
|
|
217
|
+
{
|
|
218
|
+
"paperId": "y1",
|
|
219
|
+
"title": "Test3",
|
|
220
|
+
"authors": [{"name": "F", "authorId": "F1"}],
|
|
221
|
+
"externalIds": {},
|
|
222
|
+
},
|
|
223
|
+
]
|
|
224
|
+
}
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
monkeypatch.setattr(requests, "get", dummy_get3)
|
|
228
|
+
assert sp.process_recommendations()["papers"].get("y1", {}).get("paper_ids") == []
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def test_multi_helper_arxiv_and_pubmed_ids(monkeypatch):
|
|
232
|
+
"""Test ArXiv and PubMed ID handling in MultiPaperRecData."""
|
|
233
|
+
rec = MultiPaperRecData(paper_ids=["p"], limit=1, year=None, tool_call_id="tid")
|
|
234
|
+
|
|
235
|
+
class DummyResp5:
|
|
236
|
+
"""dummy response for multi-paper recommendation with ArXiv and PubMed IDs"""
|
|
237
|
+
|
|
238
|
+
def __init__(self, data):
|
|
239
|
+
"""initialize with data"""
|
|
240
|
+
self._data = data
|
|
241
|
+
self.status_code = 200
|
|
242
|
+
|
|
243
|
+
def json(self):
|
|
244
|
+
"""json method to return data"""
|
|
245
|
+
return self._data
|
|
246
|
+
|
|
247
|
+
def raise_for_status(self):
|
|
248
|
+
"""raise_for_status method to simulate successful response"""
|
|
249
|
+
return None
|
|
250
|
+
|
|
251
|
+
def dummy_post5(*_, **__):
|
|
252
|
+
"""dummy response for multi-paper recommendation with ArXiv and PubMed IDs"""
|
|
253
|
+
return DummyResp5(
|
|
254
|
+
{
|
|
255
|
+
"recommendedPapers": [
|
|
256
|
+
{
|
|
257
|
+
"paperId": "pX",
|
|
258
|
+
"title": "TestX",
|
|
259
|
+
"authors": [{"name": "A", "authorId": "A1"}],
|
|
260
|
+
"externalIds": {"ArXiv": "ax1", "PubMed": "pm1"},
|
|
261
|
+
},
|
|
262
|
+
]
|
|
263
|
+
}
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
monkeypatch.setattr(requests, "post", dummy_post5)
|
|
267
|
+
ids_list = rec.process_recommendations()["papers"].get("pX", {}).get("paper_ids")
|
|
268
|
+
assert ids_list == ["arxiv:ax1", "pubmed:pm1"]
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
def test_search_helper_arxiv_and_pubmed_ids(monkeypatch):
|
|
272
|
+
"""Test ArXiv and PubMed ID handling in SearchData."""
|
|
273
|
+
sd = SearchData(query="q", limit=1, year=None, tool_call_id="tid")
|
|
274
|
+
|
|
275
|
+
class DummyResp6:
|
|
276
|
+
"""dummy response for search with ArXiv and PubMed IDs"""
|
|
277
|
+
|
|
278
|
+
def __init__(self, data):
|
|
279
|
+
"""initialize with data"""
|
|
280
|
+
self._data = data
|
|
281
|
+
self.status_code = 200
|
|
282
|
+
|
|
283
|
+
def json(self):
|
|
284
|
+
"""json method to return data"""
|
|
285
|
+
return self._data
|
|
286
|
+
|
|
287
|
+
def raise_for_status(self):
|
|
288
|
+
""" "raise_for_status method to simulate successful response"""
|
|
289
|
+
return None
|
|
290
|
+
|
|
291
|
+
def dummy_get6(*_, **__):
|
|
292
|
+
"""dummy response for search with ArXiv and PubMed IDs"""
|
|
293
|
+
return DummyResp6(
|
|
294
|
+
{
|
|
295
|
+
"data": [
|
|
296
|
+
{
|
|
297
|
+
"paperId": "sX",
|
|
298
|
+
"title": "TestS",
|
|
299
|
+
"authors": [{"name": "B", "authorId": "B1"}],
|
|
300
|
+
"externalIds": {"ArXiv": "ax2", "PubMed": "pm2"},
|
|
301
|
+
},
|
|
302
|
+
]
|
|
303
|
+
}
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
monkeypatch.setattr(requests, "get", dummy_get6)
|
|
307
|
+
ids_list = sd.process_search()["papers"].get("sX", {}).get("paper_ids")
|
|
308
|
+
assert ids_list == ["arxiv:ax2", "pubmed:pm2"]
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
def test_single_helper_arxiv_and_pubmed_ids(monkeypatch):
|
|
312
|
+
"""Test ArXiv and PubMed ID handling in SinglePaperRecData."""
|
|
313
|
+
sp = SinglePaperRecData(paper_id="x", limit=1, year=None, tool_call_id="tid")
|
|
314
|
+
|
|
315
|
+
class DummyResp7:
|
|
316
|
+
"""dummy response for single paper recommendation with ArXiv and PubMed IDs"""
|
|
317
|
+
|
|
318
|
+
def __init__(self, data):
|
|
319
|
+
"""initialize with data"""
|
|
320
|
+
self._data = data
|
|
321
|
+
self.status_code = 200
|
|
322
|
+
|
|
323
|
+
def json(self):
|
|
324
|
+
"""json method to return data"""
|
|
325
|
+
return self._data
|
|
326
|
+
|
|
327
|
+
def raise_for_status(self):
|
|
328
|
+
"""raise_for_status method to simulate successful response"""
|
|
329
|
+
return None
|
|
330
|
+
|
|
331
|
+
def dummy_get7(*_, **__):
|
|
332
|
+
"""dummy response for single paper recommendation with ArXiv and PubMed IDs"""
|
|
333
|
+
return DummyResp7(
|
|
334
|
+
{
|
|
335
|
+
"recommendedPapers": [
|
|
336
|
+
{
|
|
337
|
+
"paperId": "xY",
|
|
338
|
+
"title": "TestY",
|
|
339
|
+
"authors": [{"name": "C", "authorId": "C1"}],
|
|
340
|
+
"externalIds": {"ArXiv": "ax3", "PubMed": "pm3"},
|
|
341
|
+
},
|
|
342
|
+
]
|
|
343
|
+
}
|
|
344
|
+
)
|
|
345
|
+
|
|
346
|
+
monkeypatch.setattr(requests, "get", dummy_get7)
|
|
347
|
+
ids_list = sp.process_recommendations()["papers"].get("xY", {}).get("paper_ids")
|
|
348
|
+
assert ids_list == ["arxiv:ax3", "pubmed:pm3"]
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
def test_search_helper_create_content_snippet(monkeypatch):
|
|
352
|
+
"""Test that SearchData._create_content includes snippets appropriately."""
|
|
353
|
+
sd = SearchData(query="QueryX", limit=3, year="2022", tool_call_id="tid")
|
|
354
|
+
sd.filtered_papers = {
|
|
355
|
+
"p1": {"Title": "Title1", "Year": "2021", "Abstract": "First. Second. Third."},
|
|
356
|
+
"p2": {"Title": "Title2", "Year": "2020", "Abstract": ""},
|
|
357
|
+
}
|
|
358
|
+
# Stub out network fetch/filter to rely on preset filtered_papers
|
|
359
|
+
monkeypatch.setattr(SearchData, "_fetch_papers", lambda self: None)
|
|
360
|
+
monkeypatch.setattr(SearchData, "_filter_papers", lambda self: None)
|
|
361
|
+
results = sd.process_search()
|
|
362
|
+
content = results["content"]
|
|
363
|
+
assert "1. Title1 (2021)" in content
|
|
364
|
+
assert "Abstract snippet: First. Second." in content
|
|
365
|
+
assert "2. Title2 (2020)" in content
|
|
366
|
+
# Only one snippet present
|
|
367
|
+
assert content.count("Abstract snippet:") == 1
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
def test_single_helper_create_content_snippet(monkeypatch):
|
|
371
|
+
"""Test that SinglePaperRecData._create_content includes snippets appropriately."""
|
|
372
|
+
sp = SinglePaperRecData(paper_id="pid", limit=2, year=None, tool_call_id="tid")
|
|
373
|
+
sp.filtered_papers = {
|
|
374
|
+
"x1": {"Title": "STitle1", "Year": "2019", "Abstract": "SOne. STwo. SThree."},
|
|
375
|
+
"x2": {"Title": "STitle2", "Year": "2018", "Abstract": ""},
|
|
376
|
+
}
|
|
377
|
+
# Stub out network fetch/filter to rely on preset filtered_papers
|
|
378
|
+
monkeypatch.setattr(SinglePaperRecData, "_fetch_recommendations", lambda self: None)
|
|
379
|
+
monkeypatch.setattr(SinglePaperRecData, "_filter_papers", lambda self: None)
|
|
380
|
+
results = sp.process_recommendations()
|
|
381
|
+
content = results["content"]
|
|
382
|
+
assert "1. STitle1 (2019)" in content
|
|
383
|
+
assert "Abstract snippet: SOne. STwo." in content
|
|
384
|
+
assert "2. STitle2 (2018)" in content
|
|
385
|
+
assert content.count("Abstract snippet:") == 1
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
def test_multi_helper_create_content_snippet(monkeypatch):
|
|
389
|
+
"""Test that MultiPaperRecData._create_content includes snippets appropriately."""
|
|
390
|
+
mr = MultiPaperRecData(paper_ids=["a", "b"], limit=2, year="2021", tool_call_id="tid")
|
|
391
|
+
mr.filtered_papers = {
|
|
392
|
+
"m1": {"Title": "MTitle1", "Year": "2017", "Abstract": "MOne. MTwo. MThree."},
|
|
393
|
+
"m2": {"Title": "MTitle2", "Year": "2016", "Abstract": ""},
|
|
394
|
+
}
|
|
395
|
+
# Stub out network fetch/filter to rely on preset filtered_papers
|
|
396
|
+
monkeypatch.setattr(MultiPaperRecData, "_fetch_recommendations", lambda self: None)
|
|
397
|
+
monkeypatch.setattr(MultiPaperRecData, "_filter_papers", lambda self: None)
|
|
398
|
+
results = mr.process_recommendations()
|
|
399
|
+
content = results["content"]
|
|
400
|
+
assert "1. MTitle1 (2017)" in content
|
|
401
|
+
assert "Abstract snippet: MOne. MTwo." in content
|
|
402
|
+
assert "2. MTitle2 (2016)" in content
|
|
403
|
+
assert content.count("Abstract snippet:") == 1
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Unit tests for QAToolHelper routines in tool_helper.py
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import unittest
|
|
6
|
+
from types import SimpleNamespace
|
|
7
|
+
from unittest.mock import MagicMock, patch
|
|
8
|
+
|
|
9
|
+
from aiagents4pharma.talk2scholars.tools.pdf.utils.tool_helper import QAToolHelper
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class TestQAToolHelper(unittest.TestCase):
|
|
13
|
+
"""tests for QAToolHelper routines"""
|
|
14
|
+
|
|
15
|
+
def setUp(self):
|
|
16
|
+
"""setup for each test"""
|
|
17
|
+
self.helper = QAToolHelper()
|
|
18
|
+
|
|
19
|
+
def test_start_call_sets_config_and_call_id(self):
|
|
20
|
+
"""start_call should set config and call_id"""
|
|
21
|
+
cfg = SimpleNamespace(foo="bar")
|
|
22
|
+
self.helper.start_call(cfg, "call123")
|
|
23
|
+
self.assertIs(self.helper.config, cfg)
|
|
24
|
+
self.assertEqual(self.helper.call_id, "call123")
|
|
25
|
+
|
|
26
|
+
@patch("aiagents4pharma.talk2scholars.tools.pdf.utils.tool_helper.get_vectorstore")
|
|
27
|
+
def test_init_vector_store_reuse(self, mock_get_vectorstore):
|
|
28
|
+
"""Mock vector store reuse test"""
|
|
29
|
+
emb_model = MagicMock()
|
|
30
|
+
mock_instance = MagicMock()
|
|
31
|
+
mock_get_vectorstore.return_value = mock_instance
|
|
32
|
+
|
|
33
|
+
first = self.helper.init_vector_store(emb_model)
|
|
34
|
+
second = self.helper.init_vector_store(emb_model)
|
|
35
|
+
|
|
36
|
+
self.assertIs(first, second)
|
|
37
|
+
self.assertIs(second, mock_instance)
|
|
38
|
+
|
|
39
|
+
def test_get_state_models_and_data_success(self):
|
|
40
|
+
"""get_state_models_and_data should return models and data from state"""
|
|
41
|
+
emb = MagicMock()
|
|
42
|
+
llm = MagicMock()
|
|
43
|
+
articles = {"p": {}}
|
|
44
|
+
state = {
|
|
45
|
+
"text_embedding_model": emb,
|
|
46
|
+
"llm_model": llm,
|
|
47
|
+
"article_data": articles,
|
|
48
|
+
}
|
|
49
|
+
ret_emb, ret_llm, ret_articles = self.helper.get_state_models_and_data(state)
|
|
50
|
+
self.assertIs(ret_emb, emb)
|
|
51
|
+
self.assertIs(ret_llm, llm)
|
|
52
|
+
self.assertIs(ret_articles, articles)
|
|
53
|
+
|
|
54
|
+
def test_get_state_models_and_data_missing_text_embedding(self):
|
|
55
|
+
"""get_state_models_and_data should raise ValueError if text_embedding_model is missing"""
|
|
56
|
+
state = {"llm_model": MagicMock(), "article_data": {"p": {}}}
|
|
57
|
+
with self.assertRaises(ValueError):
|
|
58
|
+
self.helper.get_state_models_and_data(state)
|
|
59
|
+
|
|
60
|
+
def test_get_state_models_and_data_missing_llm(self):
|
|
61
|
+
"""should raise ValueError if llm_model is missing"""
|
|
62
|
+
state = {"text_embedding_model": MagicMock(), "article_data": {"p": {}}}
|
|
63
|
+
with self.assertRaises(ValueError):
|
|
64
|
+
self.helper.get_state_models_and_data(state)
|
|
65
|
+
|
|
66
|
+
def test_get_state_models_and_data_missing_article_data(self):
|
|
67
|
+
"""get_state_models_and_data should raise ValueError if article_data is missing"""
|
|
68
|
+
state = {"text_embedding_model": MagicMock(), "llm_model": MagicMock()}
|
|
69
|
+
with self.assertRaises(ValueError):
|
|
70
|
+
self.helper.get_state_models_and_data(state)
|
|
71
|
+
|
|
72
|
+
def test_get_hardware_stats(self):
|
|
73
|
+
"""get_hardware_stats should return correct GPU and hardware mode"""
|
|
74
|
+
helper = QAToolHelper()
|
|
75
|
+
helper.call_id = "test_call"
|
|
76
|
+
|
|
77
|
+
helper.has_gpu = False
|
|
78
|
+
stats = helper.get_hardware_stats()
|
|
79
|
+
self.assertEqual(stats["gpu_available"], False)
|
|
80
|
+
self.assertEqual(stats["hardware_mode"], "CPU-only")
|
|
81
|
+
|
|
82
|
+
helper.has_gpu = True
|
|
83
|
+
stats = helper.get_hardware_stats()
|
|
84
|
+
self.assertEqual(stats["gpu_available"], True)
|
|
85
|
+
self.assertEqual(stats["hardware_mode"], "GPU-accelerated")
|