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,165 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Tool for plotting a custom y-axis of a simulation plot.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
from typing import Annotated, Literal
|
|
9
|
+
|
|
10
|
+
import hydra
|
|
11
|
+
import pandas as pd
|
|
12
|
+
from langchain_core.prompts import ChatPromptTemplate
|
|
13
|
+
from langchain_core.tools import BaseTool
|
|
14
|
+
from langgraph.prebuilt import InjectedState
|
|
15
|
+
from pydantic import BaseModel, Field
|
|
16
|
+
|
|
17
|
+
from .load_biomodel import ModelData, load_biomodel
|
|
18
|
+
from .utils import get_model_units
|
|
19
|
+
|
|
20
|
+
# Initialize logger
|
|
21
|
+
logging.basicConfig(level=logging.INFO)
|
|
22
|
+
logger = logging.getLogger(__name__)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def extract_relevant_species(question, species_names, state):
|
|
26
|
+
"""
|
|
27
|
+
Extract the relevant species from the user question.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
question (str): The user question.
|
|
31
|
+
species_names (list): The species names available in the simulation results.
|
|
32
|
+
state (dict): The state of the graph.
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
CustomHeader: The relevant species
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
# In the following code, we extract the species
|
|
39
|
+
# from the user question. We use Literal to restrict
|
|
40
|
+
# the species names to the ones available in the
|
|
41
|
+
# simulation results.
|
|
42
|
+
class CustomHeader(BaseModel):
|
|
43
|
+
"""
|
|
44
|
+
A list of species based on user question.
|
|
45
|
+
|
|
46
|
+
This is a Pydantic model that restricts the species
|
|
47
|
+
names to the ones available in the simulation results.
|
|
48
|
+
|
|
49
|
+
If no species is relevant, set the attribute
|
|
50
|
+
`relevant_species` to None.
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
relevant_species: None | list[Literal[*species_names,]] = Field(
|
|
54
|
+
description="This is a list of species based on the user question."
|
|
55
|
+
"It is restricted to the species available in the simulation results."
|
|
56
|
+
"If no species is relevant, set this attribute to None."
|
|
57
|
+
"If the user asks for very specific species (for example, using the"
|
|
58
|
+
"keyword `only` in the question), set this attribute to correspond "
|
|
59
|
+
"to the species available in the simulation results, otherwise set it to None."
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
# Load hydra configuration
|
|
63
|
+
with hydra.initialize(version_base=None, config_path="../configs"):
|
|
64
|
+
cfg = hydra.compose(config_name="config", overrides=["tools/custom_plotter=default"])
|
|
65
|
+
cfg = cfg.tools.custom_plotter
|
|
66
|
+
# Get the system prompt
|
|
67
|
+
system_prompt = cfg.system_prompt_custom_header
|
|
68
|
+
# Create an instance of the LLM model
|
|
69
|
+
logging.log(logging.INFO, "LLM model: %s", state["llm_model"])
|
|
70
|
+
llm = state["llm_model"]
|
|
71
|
+
llm_with_structured_output = llm.with_structured_output(CustomHeader)
|
|
72
|
+
prompt = ChatPromptTemplate.from_messages([("system", system_prompt), ("human", "{input}")])
|
|
73
|
+
few_shot_structured_llm = prompt | llm_with_structured_output
|
|
74
|
+
return few_shot_structured_llm.invoke(question)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class CustomPlotterInput(BaseModel):
|
|
78
|
+
"""
|
|
79
|
+
Input schema for the custom plotter tool.
|
|
80
|
+
"""
|
|
81
|
+
|
|
82
|
+
question: str = Field(description="Description of the plot")
|
|
83
|
+
sys_bio_model: ModelData = Field(description="model data", default=None)
|
|
84
|
+
simulation_name: str = Field(description="Name assigned to the simulation")
|
|
85
|
+
state: Annotated[dict, InjectedState]
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
# Note: It's important that every field has type hints.
|
|
89
|
+
# BaseTool is a Pydantic class and not having type hints
|
|
90
|
+
# can lead to unexpected behavior.
|
|
91
|
+
# Note: It's important that every field has type hints.
|
|
92
|
+
# BaseTool is a Pydantic class and not having type hints
|
|
93
|
+
# can lead to unexpected behavior.
|
|
94
|
+
class CustomPlotterTool(BaseTool):
|
|
95
|
+
"""
|
|
96
|
+
Tool for custom plotting the y-axis of a plot.
|
|
97
|
+
"""
|
|
98
|
+
|
|
99
|
+
name: str = "custom_plotter"
|
|
100
|
+
description: str = """A visualization tool designed to extract and display a subset
|
|
101
|
+
of the larger simulation plot generated by the simulate_model tool.
|
|
102
|
+
It allows users to specify particular species for the y-axis,
|
|
103
|
+
providing a more targeted view of key species without the clutter
|
|
104
|
+
of the full plot."""
|
|
105
|
+
args_schema: type[BaseModel] = CustomPlotterInput
|
|
106
|
+
response_format: str = "content_and_artifact"
|
|
107
|
+
|
|
108
|
+
def _run(
|
|
109
|
+
self,
|
|
110
|
+
question: str,
|
|
111
|
+
sys_bio_model: ModelData,
|
|
112
|
+
simulation_name: str,
|
|
113
|
+
state: Annotated[dict, InjectedState],
|
|
114
|
+
) -> tuple[str, None | list[str]]:
|
|
115
|
+
"""
|
|
116
|
+
Run the tool.
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
question (str): The question about the custom plot.
|
|
120
|
+
sys_bio_model (ModelData): The model data.
|
|
121
|
+
simulation_name (str): The name assigned to the simulation.
|
|
122
|
+
state (dict): The state of the graph.
|
|
123
|
+
|
|
124
|
+
Returns:
|
|
125
|
+
str: The answer to the question
|
|
126
|
+
"""
|
|
127
|
+
logger.log(logging.INFO, "Calling custom_plotter tool %s, %s", question, sys_bio_model)
|
|
128
|
+
# Load the model
|
|
129
|
+
sbml_file_path = state["sbml_file_path"][-1] if len(state["sbml_file_path"]) > 0 else None
|
|
130
|
+
model_object = load_biomodel(sys_bio_model, sbml_file_path=sbml_file_path)
|
|
131
|
+
dic_simulated_data = {}
|
|
132
|
+
for data in state["dic_simulated_data"]:
|
|
133
|
+
for key in data:
|
|
134
|
+
if key not in dic_simulated_data:
|
|
135
|
+
dic_simulated_data[key] = []
|
|
136
|
+
dic_simulated_data[key] += [data[key]]
|
|
137
|
+
# Create a pandas dataframe from the dictionary
|
|
138
|
+
df = pd.DataFrame.from_dict(dic_simulated_data)
|
|
139
|
+
# Get the simulated data for the current tool call
|
|
140
|
+
df = pd.DataFrame(df[df["name"] == simulation_name]["data"].iloc[0])
|
|
141
|
+
# df = pd.DataFrame.from_dict(state['dic_simulated_data'])
|
|
142
|
+
species_names = df.columns.tolist()
|
|
143
|
+
# Exclude the time column
|
|
144
|
+
species_names.remove("Time")
|
|
145
|
+
logging.log(logging.INFO, "Species names: %s", species_names)
|
|
146
|
+
# Extract the relevant species from the user question
|
|
147
|
+
results = extract_relevant_species(question, species_names, state)
|
|
148
|
+
print(results)
|
|
149
|
+
if results.relevant_species is None:
|
|
150
|
+
raise ValueError(
|
|
151
|
+
"No species found in the simulation results \
|
|
152
|
+
that matches the user prompt."
|
|
153
|
+
)
|
|
154
|
+
extracted_species = []
|
|
155
|
+
# Extract the species from the results
|
|
156
|
+
# that are available in the simulation results
|
|
157
|
+
for species in results.relevant_species:
|
|
158
|
+
if species in species_names:
|
|
159
|
+
extracted_species.append(species)
|
|
160
|
+
logging.info("Extracted species: %s", extracted_species)
|
|
161
|
+
# Include the time column
|
|
162
|
+
extracted_species.insert(0, "Time")
|
|
163
|
+
return f"Custom plot {simulation_name}", {
|
|
164
|
+
"dic_data": df[extracted_species].to_dict(orient="records")
|
|
165
|
+
} | get_model_units(model_object)
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
This module contains the `GetAnnotationTool` for fetching species annotations
|
|
5
|
+
based on the provided model and species names.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import logging
|
|
9
|
+
import math
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
from typing import Annotated, Literal
|
|
12
|
+
|
|
13
|
+
import basico
|
|
14
|
+
import hydra
|
|
15
|
+
import pandas as pd
|
|
16
|
+
from langchain_core.messages import ToolMessage
|
|
17
|
+
from langchain_core.tools.base import BaseTool, InjectedToolCallId
|
|
18
|
+
from langgraph.prebuilt import InjectedState
|
|
19
|
+
from langgraph.types import Command
|
|
20
|
+
from pydantic import BaseModel, Field
|
|
21
|
+
|
|
22
|
+
from ..api.ols import search_ols_labels
|
|
23
|
+
from ..api.uniprot import search_uniprot_labels
|
|
24
|
+
|
|
25
|
+
# from langchain_openai import ChatOpenAI
|
|
26
|
+
from .load_biomodel import ModelData, load_biomodel
|
|
27
|
+
|
|
28
|
+
# Initialize logger
|
|
29
|
+
logging.basicConfig(level=logging.INFO)
|
|
30
|
+
logger = logging.getLogger(__name__)
|
|
31
|
+
|
|
32
|
+
ols_ontology_abbreviations = {"pato", "chebi", "sbo", "fma", "pr", "go"}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def extract_relevant_species_names(model_object, arg_data, state):
|
|
36
|
+
"""
|
|
37
|
+
Extract relevant species names based on the user question.
|
|
38
|
+
"""
|
|
39
|
+
# Load hydra configuration
|
|
40
|
+
with hydra.initialize(version_base=None, config_path="../configs"):
|
|
41
|
+
cfg = hydra.compose(config_name="config", overrides=["tools/get_annotation=default"])
|
|
42
|
+
cfg = cfg.tools.get_annotation
|
|
43
|
+
logger.info(
|
|
44
|
+
"Loaded the following system prompt for the LLM to get a structured output: %s",
|
|
45
|
+
cfg.prompt,
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
# Extract all the species names from the model
|
|
49
|
+
df_species = basico.model_info.get_species(model=model_object.copasi_model)
|
|
50
|
+
if df_species is None:
|
|
51
|
+
raise ValueError("Unable to extract species from the model.")
|
|
52
|
+
# Get all the species names
|
|
53
|
+
all_species_names = df_species.index.tolist()
|
|
54
|
+
|
|
55
|
+
# Define a structured output for the LLM model
|
|
56
|
+
class CustomHeader(BaseModel):
|
|
57
|
+
"""
|
|
58
|
+
A list of species based on user question.
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
relevant_species: None | list[Literal[*all_species_names,]] = Field(
|
|
62
|
+
description="""List of species based on user question.
|
|
63
|
+
If no relevant species are found, it must be None."""
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
# Create an instance of the LLM model
|
|
67
|
+
llm = state["llm_model"]
|
|
68
|
+
# Get the structured output from the LLM model
|
|
69
|
+
llm_with_structured_output = llm.with_structured_output(CustomHeader)
|
|
70
|
+
# Define the question for the LLM model using the prompt
|
|
71
|
+
question = cfg.prompt
|
|
72
|
+
question += f"Here is the user question: {arg_data.user_question}"
|
|
73
|
+
# Invoke the LLM model with the user question
|
|
74
|
+
results = llm_with_structured_output.invoke(question)
|
|
75
|
+
logging.info("Results from the LLM model: %s", results)
|
|
76
|
+
# Check if the returned species names are empty
|
|
77
|
+
if not results.relevant_species:
|
|
78
|
+
raise ValueError("Model does not contain the requested species.")
|
|
79
|
+
extracted_species = []
|
|
80
|
+
# Extract all the species names from the model
|
|
81
|
+
for species in results.relevant_species:
|
|
82
|
+
if species in all_species_names:
|
|
83
|
+
extracted_species.append(species)
|
|
84
|
+
logger.info("Extracted species: %s", extracted_species)
|
|
85
|
+
return extracted_species
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def prepare_content_msg(species_without_description: list[str]):
|
|
89
|
+
"""
|
|
90
|
+
Prepare the content message.
|
|
91
|
+
"""
|
|
92
|
+
content = "Successfully extracted annotations for the species."
|
|
93
|
+
if species_without_description:
|
|
94
|
+
content += f"""The descriptions for the following species
|
|
95
|
+
were not found:
|
|
96
|
+
{", ".join(species_without_description)}."""
|
|
97
|
+
return content
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
@dataclass
|
|
101
|
+
class ArgumentData:
|
|
102
|
+
"""
|
|
103
|
+
Dataclass for storing the argument data.
|
|
104
|
+
"""
|
|
105
|
+
|
|
106
|
+
experiment_name: Annotated[
|
|
107
|
+
str,
|
|
108
|
+
"An AI assigned _ separated name of"
|
|
109
|
+
" the experiment based on human query"
|
|
110
|
+
" and the context of the experiment."
|
|
111
|
+
" This must be set before the experiment is run.",
|
|
112
|
+
]
|
|
113
|
+
user_question: Annotated[str, "Description of the user question"]
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class GetAnnotationInput(BaseModel):
|
|
117
|
+
"""
|
|
118
|
+
Input schema for annotation tool.
|
|
119
|
+
"""
|
|
120
|
+
|
|
121
|
+
arg_data: ArgumentData = Field(description="argument data")
|
|
122
|
+
sys_bio_model: ModelData = Field(description="model data")
|
|
123
|
+
tool_call_id: Annotated[str, InjectedToolCallId]
|
|
124
|
+
state: Annotated[dict, InjectedState]
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
class GetAnnotationTool(BaseTool):
|
|
128
|
+
"""
|
|
129
|
+
Tool for fetching species annotations based on the provided model and species names.
|
|
130
|
+
"""
|
|
131
|
+
|
|
132
|
+
name: str = "get_annotation"
|
|
133
|
+
description: str = """A tool to extract annotations for a list of species names
|
|
134
|
+
based on the provided model. Annotations include
|
|
135
|
+
the species name, description, database, ID, link,
|
|
136
|
+
and qualifier. The tool can handle multiple species
|
|
137
|
+
in a single invoke."""
|
|
138
|
+
args_schema: type[BaseModel] = GetAnnotationInput
|
|
139
|
+
return_direct: bool = False
|
|
140
|
+
|
|
141
|
+
def _run(
|
|
142
|
+
self,
|
|
143
|
+
arg_data: ArgumentData,
|
|
144
|
+
tool_call_id: Annotated[str, InjectedToolCallId],
|
|
145
|
+
state: Annotated[dict, InjectedState],
|
|
146
|
+
sys_bio_model: ModelData = None,
|
|
147
|
+
) -> str:
|
|
148
|
+
"""
|
|
149
|
+
Run the tool.
|
|
150
|
+
"""
|
|
151
|
+
logger.info(
|
|
152
|
+
"Running the GetAnnotationTool tool for species %s, %s",
|
|
153
|
+
arg_data.user_question,
|
|
154
|
+
arg_data.experiment_name,
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
# Prepare the model object
|
|
158
|
+
sbml_file_path = state["sbml_file_path"][-1] if state["sbml_file_path"] else None
|
|
159
|
+
model_object = load_biomodel(sys_bio_model, sbml_file_path=sbml_file_path)
|
|
160
|
+
|
|
161
|
+
# Extract relevant species names based on the user question
|
|
162
|
+
list_species_names = extract_relevant_species_names(model_object, arg_data, state)
|
|
163
|
+
print(list_species_names)
|
|
164
|
+
|
|
165
|
+
(annotations_df, species_without_description) = self._fetch_annotations(list_species_names)
|
|
166
|
+
|
|
167
|
+
# Process annotations
|
|
168
|
+
annotations_df = self._process_annotations(annotations_df)
|
|
169
|
+
|
|
170
|
+
# Prepare the simulated data
|
|
171
|
+
dic_annotations_data = {
|
|
172
|
+
"name": arg_data.experiment_name,
|
|
173
|
+
"source": (sys_bio_model.biomodel_id if sys_bio_model.biomodel_id else "upload"),
|
|
174
|
+
"tool_call_id": tool_call_id,
|
|
175
|
+
"data": annotations_df.to_dict(),
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
# Update the state with the annotations data
|
|
179
|
+
dic_updated_state_for_model = {}
|
|
180
|
+
for key, value in {
|
|
181
|
+
"model_id": [sys_bio_model.biomodel_id],
|
|
182
|
+
"sbml_file_path": [sbml_file_path],
|
|
183
|
+
"dic_annotations_data": [dic_annotations_data],
|
|
184
|
+
}.items():
|
|
185
|
+
if value:
|
|
186
|
+
dic_updated_state_for_model[key] = value
|
|
187
|
+
|
|
188
|
+
return Command(
|
|
189
|
+
update=dic_updated_state_for_model
|
|
190
|
+
| {
|
|
191
|
+
"messages": [
|
|
192
|
+
ToolMessage(
|
|
193
|
+
content=prepare_content_msg(species_without_description),
|
|
194
|
+
artifact=True,
|
|
195
|
+
tool_call_id=tool_call_id,
|
|
196
|
+
)
|
|
197
|
+
]
|
|
198
|
+
}
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
def _fetch_annotations(self, list_species_names: list[str]) -> tuple:
|
|
202
|
+
"""
|
|
203
|
+
Fetch annotations for the given species names from the model.
|
|
204
|
+
In this method, we fetch the MIRIAM annotations for the species names.
|
|
205
|
+
If the annotation is not found, we add the species to the list of
|
|
206
|
+
species not found. If the annotation is found, we extract the descriptions
|
|
207
|
+
from the annotation and add them to the data list.
|
|
208
|
+
|
|
209
|
+
Args:
|
|
210
|
+
list_species_names (List[str]): List of species names to fetch annotations for.
|
|
211
|
+
|
|
212
|
+
Returns:
|
|
213
|
+
tuple: A tuple containing the annotations dataframe, species not found list,
|
|
214
|
+
and description not found list.
|
|
215
|
+
"""
|
|
216
|
+
description_not_found = []
|
|
217
|
+
data = []
|
|
218
|
+
|
|
219
|
+
# Loop through the species names
|
|
220
|
+
for species in list_species_names:
|
|
221
|
+
# Get the MIRIAM annotation for the species
|
|
222
|
+
annotation = basico.get_miriam_annotation(name=species)
|
|
223
|
+
|
|
224
|
+
# Extract the descriptions from the annotation
|
|
225
|
+
descriptions = annotation.get("descriptions", [])
|
|
226
|
+
|
|
227
|
+
if descriptions == []:
|
|
228
|
+
description_not_found.append(species)
|
|
229
|
+
continue
|
|
230
|
+
|
|
231
|
+
# Loop through the descriptions and add them to the data list
|
|
232
|
+
for desc in descriptions:
|
|
233
|
+
data.append(
|
|
234
|
+
{
|
|
235
|
+
"Species Name": species,
|
|
236
|
+
"Link": desc["id"],
|
|
237
|
+
"Qualifier": desc["qualifier"],
|
|
238
|
+
}
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
# Create a dataframe from the data list
|
|
242
|
+
annotations_df = pd.DataFrame(data)
|
|
243
|
+
|
|
244
|
+
# Return the annotations dataframe and the species not found list
|
|
245
|
+
return annotations_df, description_not_found
|
|
246
|
+
|
|
247
|
+
def _process_annotations(self, annotations_df: pd.DataFrame) -> pd.DataFrame:
|
|
248
|
+
"""
|
|
249
|
+
Process annotations dataframe to add additional information.
|
|
250
|
+
In this method, we add a new column for the ID, a new column for the database,
|
|
251
|
+
and a new column for the description. We then reorder the columns and process
|
|
252
|
+
the link to format it correctly.
|
|
253
|
+
|
|
254
|
+
Args:
|
|
255
|
+
annotations_df (pd.DataFrame): Annotations dataframe to process.
|
|
256
|
+
|
|
257
|
+
Returns:
|
|
258
|
+
pd.DataFrame: Processed annotations dataframe
|
|
259
|
+
"""
|
|
260
|
+
logger.info("Processing annotations.")
|
|
261
|
+
# Add a new column for the ID
|
|
262
|
+
# Get the ID from the link key
|
|
263
|
+
annotations_df["Id"] = annotations_df["Link"].str.split("/").str[-1]
|
|
264
|
+
|
|
265
|
+
# Add a new column for the database
|
|
266
|
+
# Get the database from the link key
|
|
267
|
+
annotations_df["Database"] = annotations_df["Link"].str.split("/").str[-2]
|
|
268
|
+
|
|
269
|
+
# Fetch descriptions for the IDs based on the database type
|
|
270
|
+
# by qyerying the respective APIs
|
|
271
|
+
identifiers = annotations_df[["Id", "Database"]].to_dict(orient="records")
|
|
272
|
+
descriptions = self._fetch_descriptions(identifiers)
|
|
273
|
+
|
|
274
|
+
# Add a new column for the description
|
|
275
|
+
# Get the description from the descriptions dictionary
|
|
276
|
+
# based on the ID. If the description is not found, use '-'
|
|
277
|
+
annotations_df["Description"] = annotations_df["Id"].apply(
|
|
278
|
+
lambda x: descriptions.get(x, "-")
|
|
279
|
+
)
|
|
280
|
+
# annotations_df.index = annotations_df.index + 1
|
|
281
|
+
|
|
282
|
+
# Reorder the columns
|
|
283
|
+
annotations_df = annotations_df[
|
|
284
|
+
["Species Name", "Description", "Database", "Id", "Link", "Qualifier"]
|
|
285
|
+
]
|
|
286
|
+
|
|
287
|
+
# Process the link to format it correctly
|
|
288
|
+
annotations_df["Link"] = annotations_df["Link"].apply(self._process_link)
|
|
289
|
+
|
|
290
|
+
# Return the processed annotations dataframe
|
|
291
|
+
return annotations_df
|
|
292
|
+
|
|
293
|
+
def _process_link(self, link: str) -> str:
|
|
294
|
+
"""
|
|
295
|
+
Process link to format it correctly.
|
|
296
|
+
"""
|
|
297
|
+
for ols_ontology_abbreviation in ols_ontology_abbreviations:
|
|
298
|
+
if ols_ontology_abbreviation + "/" in link:
|
|
299
|
+
link = link.replace(f"{ols_ontology_abbreviation}/", "")
|
|
300
|
+
return link
|
|
301
|
+
|
|
302
|
+
def _fetch_descriptions(self, data: list[dict[str, str]]) -> dict[str, str]:
|
|
303
|
+
"""
|
|
304
|
+
Fetch protein names or labels based on the database type.
|
|
305
|
+
"""
|
|
306
|
+
logger.info("Fetching descriptions for the IDs.")
|
|
307
|
+
results = {}
|
|
308
|
+
grouped_data = {}
|
|
309
|
+
|
|
310
|
+
# In the following loop, we create a dictionary with database as the key
|
|
311
|
+
# and a list of identifiers as the value. If either the database or the
|
|
312
|
+
# identifier is NaN, we set it to None.
|
|
313
|
+
for entry in data:
|
|
314
|
+
identifier = entry.get("Id")
|
|
315
|
+
database = entry.get("Database")
|
|
316
|
+
# Check if database is NaN
|
|
317
|
+
if isinstance(database, float):
|
|
318
|
+
if math.isnan(database):
|
|
319
|
+
database = None
|
|
320
|
+
results[identifier or "unknown"] = "-"
|
|
321
|
+
else:
|
|
322
|
+
database = database.lower()
|
|
323
|
+
grouped_data.setdefault(database, []).append(identifier)
|
|
324
|
+
|
|
325
|
+
# In the following loop, we fetch the descriptions for the identifiers
|
|
326
|
+
# based on the database type.
|
|
327
|
+
# Constants
|
|
328
|
+
|
|
329
|
+
for database, identifiers in grouped_data.items():
|
|
330
|
+
if database == "uniprot":
|
|
331
|
+
results.update(search_uniprot_labels(identifiers))
|
|
332
|
+
elif database in ols_ontology_abbreviations:
|
|
333
|
+
annotations = search_ols_labels(
|
|
334
|
+
[{"Id": id_, "Database": database} for id_ in identifiers]
|
|
335
|
+
)
|
|
336
|
+
for identifier in identifiers:
|
|
337
|
+
results[identifier] = annotations.get(database, {}).get(identifier, "-")
|
|
338
|
+
else:
|
|
339
|
+
# For any other database types, do not fetch; mark as unknown
|
|
340
|
+
for identifier in identifiers:
|
|
341
|
+
results[identifier] = "-"
|
|
342
|
+
return results
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Tool for get model information.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
from dataclasses import dataclass
|
|
9
|
+
from typing import Annotated
|
|
10
|
+
|
|
11
|
+
import basico
|
|
12
|
+
from langchain_core.messages import ToolMessage
|
|
13
|
+
from langchain_core.tools import BaseTool
|
|
14
|
+
from langchain_core.tools.base import InjectedToolCallId
|
|
15
|
+
from langgraph.prebuilt import InjectedState
|
|
16
|
+
from langgraph.types import Command
|
|
17
|
+
from pydantic import BaseModel, Field
|
|
18
|
+
|
|
19
|
+
from .load_biomodel import ModelData, load_biomodel
|
|
20
|
+
|
|
21
|
+
# Initialize logger
|
|
22
|
+
logging.basicConfig(level=logging.INFO)
|
|
23
|
+
logger = logging.getLogger(__name__)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass
|
|
27
|
+
class RequestedModelInfo:
|
|
28
|
+
"""
|
|
29
|
+
Dataclass for storing the requested model information.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
species: bool = Field(description="Get species from the model.", default=False)
|
|
33
|
+
parameters: bool = Field(description="Get parameters from the model.", default=False)
|
|
34
|
+
compartments: bool = Field(description="Get compartments from the model.", default=False)
|
|
35
|
+
units: bool = Field(description="Get units from the model.", default=False)
|
|
36
|
+
description: bool = Field(description="Get description from the model.", default=False)
|
|
37
|
+
name: bool = Field(description="Get name from the model.", default=False)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class GetModelInfoInput(BaseModel):
|
|
41
|
+
"""
|
|
42
|
+
Input schema for the GetModelInfo tool.
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
requested_model_info: RequestedModelInfo = Field(description="requested model information")
|
|
46
|
+
sys_bio_model: ModelData = Field(description="model data")
|
|
47
|
+
tool_call_id: Annotated[str, InjectedToolCallId]
|
|
48
|
+
state: Annotated[dict, InjectedState]
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
# Note: It's important that every field has type hints. BaseTool is a
|
|
52
|
+
# Pydantic class and not having type hints can lead to unexpected behavior.
|
|
53
|
+
class GetModelInfoTool(BaseTool):
|
|
54
|
+
"""
|
|
55
|
+
This tool ise used extract model information.
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
name: str = "get_modelinfo"
|
|
59
|
+
description: str = """A tool for extracting name,
|
|
60
|
+
description, species, parameters,
|
|
61
|
+
compartments, and units from a model."""
|
|
62
|
+
args_schema: type[BaseModel] = GetModelInfoInput
|
|
63
|
+
|
|
64
|
+
def _run(
|
|
65
|
+
self,
|
|
66
|
+
requested_model_info: RequestedModelInfo,
|
|
67
|
+
tool_call_id: Annotated[str, InjectedToolCallId],
|
|
68
|
+
state: Annotated[dict, InjectedState],
|
|
69
|
+
sys_bio_model: ModelData | None = None,
|
|
70
|
+
) -> Command:
|
|
71
|
+
"""
|
|
72
|
+
Run the tool.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
requested_model_info (RequestedModelInfo): The requested model information.
|
|
76
|
+
tool_call_id (str): The tool call ID. This is injected by the system.
|
|
77
|
+
state (dict): The state of the tool.
|
|
78
|
+
sys_bio_model (ModelData): The model data.
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
Command: The updated state of the tool.
|
|
82
|
+
"""
|
|
83
|
+
logger.log(
|
|
84
|
+
logging.INFO,
|
|
85
|
+
"Calling get_modelinfo tool %s, %s",
|
|
86
|
+
sys_bio_model,
|
|
87
|
+
requested_model_info,
|
|
88
|
+
)
|
|
89
|
+
# print (state, 'state')
|
|
90
|
+
sbml_file_path = state["sbml_file_path"][-1] if len(state["sbml_file_path"]) > 0 else None
|
|
91
|
+
model_obj = load_biomodel(sys_bio_model, sbml_file_path=sbml_file_path)
|
|
92
|
+
dic_results = {}
|
|
93
|
+
# Extract species from the model
|
|
94
|
+
if requested_model_info.species:
|
|
95
|
+
df_species = basico.model_info.get_species(model=model_obj.copasi_model)
|
|
96
|
+
if df_species is None:
|
|
97
|
+
raise ValueError("Unable to extract species from the model.")
|
|
98
|
+
# Convert index into a column
|
|
99
|
+
df_species.reset_index(inplace=True)
|
|
100
|
+
dic_results["Species"] = df_species[
|
|
101
|
+
[
|
|
102
|
+
"name",
|
|
103
|
+
"compartment",
|
|
104
|
+
"type",
|
|
105
|
+
"unit",
|
|
106
|
+
"initial_concentration",
|
|
107
|
+
"display_name",
|
|
108
|
+
]
|
|
109
|
+
]
|
|
110
|
+
# Convert this into a dictionary
|
|
111
|
+
dic_results["Species"] = dic_results["Species"].to_dict(orient="records")
|
|
112
|
+
|
|
113
|
+
# Extract parameters from the model
|
|
114
|
+
if requested_model_info.parameters:
|
|
115
|
+
df_parameters = basico.model_info.get_parameters(model=model_obj.copasi_model)
|
|
116
|
+
if df_parameters is None:
|
|
117
|
+
raise ValueError("Unable to extract parameters from the model.")
|
|
118
|
+
# Convert index into a column
|
|
119
|
+
df_parameters.reset_index(inplace=True)
|
|
120
|
+
dic_results["Parameters"] = df_parameters[
|
|
121
|
+
["name", "type", "unit", "initial_value", "display_name"]
|
|
122
|
+
]
|
|
123
|
+
# Convert this into a dictionary
|
|
124
|
+
dic_results["Parameters"] = dic_results["Parameters"].to_dict(orient="records")
|
|
125
|
+
|
|
126
|
+
# Extract compartments from the model
|
|
127
|
+
if requested_model_info.compartments:
|
|
128
|
+
df_compartments = basico.model_info.get_compartments(model=model_obj.copasi_model)
|
|
129
|
+
dic_results["Compartments"] = df_compartments.index.tolist()
|
|
130
|
+
dic_results["Compartments"] = ",".join(dic_results["Compartments"])
|
|
131
|
+
|
|
132
|
+
# Extract description from the model
|
|
133
|
+
if requested_model_info.description:
|
|
134
|
+
dic_results["Description"] = model_obj.description
|
|
135
|
+
|
|
136
|
+
# Extract description from the model
|
|
137
|
+
if requested_model_info.name:
|
|
138
|
+
dic_results["Name"] = model_obj.name
|
|
139
|
+
|
|
140
|
+
# Extract time unit from the model
|
|
141
|
+
if requested_model_info.units:
|
|
142
|
+
dic_results["Units"] = basico.model_info.get_model_units(model=model_obj.copasi_model)
|
|
143
|
+
|
|
144
|
+
# Prepare the dictionary of updated state for the model
|
|
145
|
+
dic_updated_state_for_model = {}
|
|
146
|
+
for key, value in {
|
|
147
|
+
"model_id": [sys_bio_model.biomodel_id],
|
|
148
|
+
"sbml_file_path": [sbml_file_path],
|
|
149
|
+
}.items():
|
|
150
|
+
if value:
|
|
151
|
+
dic_updated_state_for_model[key] = value
|
|
152
|
+
|
|
153
|
+
return Command(
|
|
154
|
+
update=dic_updated_state_for_model
|
|
155
|
+
| {
|
|
156
|
+
# update the message history
|
|
157
|
+
"messages": [ToolMessage(content=dic_results, tool_call_id=tool_call_id)],
|
|
158
|
+
}
|
|
159
|
+
)
|