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,327 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Vectorstore class for managing PDF embeddings with Milvus.
|
|
3
|
+
Manages GPU normalization and similarity search and MMR operations.
|
|
4
|
+
With automatic handling of COSINE to IP conversion for GPU compatibility.
|
|
5
|
+
Supports both GPU and CPU configurations.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import logging
|
|
9
|
+
import os
|
|
10
|
+
import time
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
from langchain_core.documents import Document
|
|
14
|
+
from langchain_core.embeddings import Embeddings
|
|
15
|
+
from langchain_milvus import Milvus
|
|
16
|
+
|
|
17
|
+
from .collection_manager import ensure_collection_exists
|
|
18
|
+
from .gpu_detection import (
|
|
19
|
+
detect_nvidia_gpu,
|
|
20
|
+
get_optimal_index_config,
|
|
21
|
+
log_index_configuration,
|
|
22
|
+
)
|
|
23
|
+
from .singleton_manager import VectorstoreSingleton
|
|
24
|
+
from .vector_normalization import wrap_embedding_model_if_needed
|
|
25
|
+
|
|
26
|
+
# Set up logging with configurable level
|
|
27
|
+
log_level = os.environ.get("LOG_LEVEL", "INFO")
|
|
28
|
+
logging.basicConfig(level=getattr(logging, log_level))
|
|
29
|
+
logger = logging.getLogger(__name__)
|
|
30
|
+
logger.setLevel(getattr(logging, log_level))
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class Vectorstore:
|
|
34
|
+
"""
|
|
35
|
+
Enhanced Vectorstore class with GPU normalization support.
|
|
36
|
+
Automatically handles COSINE -> IP conversion for GPU compatibility.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
def __init__(
|
|
40
|
+
self,
|
|
41
|
+
embedding_model: Embeddings,
|
|
42
|
+
metadata_fields: list[str] | None = None,
|
|
43
|
+
config: Any = None,
|
|
44
|
+
):
|
|
45
|
+
"""
|
|
46
|
+
Initialize the document store with Milvus and GPU optimization.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
embedding_model: The embedding model to use
|
|
50
|
+
metadata_fields: Fields to include in document metadata
|
|
51
|
+
config: Configuration object containing Milvus connection details
|
|
52
|
+
"""
|
|
53
|
+
self.config = config
|
|
54
|
+
self.metadata_fields = metadata_fields or [
|
|
55
|
+
"title",
|
|
56
|
+
"paper_id",
|
|
57
|
+
"page",
|
|
58
|
+
"chunk_id",
|
|
59
|
+
]
|
|
60
|
+
self.initialization_time = time.time()
|
|
61
|
+
|
|
62
|
+
# GPU detection with config override (SINGLE CALL)
|
|
63
|
+
self.has_gpu = detect_nvidia_gpu(config)
|
|
64
|
+
|
|
65
|
+
# Additional check for force CPU mode
|
|
66
|
+
if (
|
|
67
|
+
config
|
|
68
|
+
and hasattr(config, "gpu_detection")
|
|
69
|
+
and getattr(config.gpu_detection, "force_cpu_mode", False)
|
|
70
|
+
):
|
|
71
|
+
logger.info("Running in forced CPU mode (config override)")
|
|
72
|
+
self.has_gpu = False
|
|
73
|
+
|
|
74
|
+
# Determine if we want to use COSINE similarity
|
|
75
|
+
self.use_cosine = True # Default preference
|
|
76
|
+
if config and hasattr(config, "similarity_metric"):
|
|
77
|
+
self.use_cosine = getattr(config.similarity_metric, "use_cosine", True)
|
|
78
|
+
|
|
79
|
+
# Wrap embedding model with normalization if needed for GPU
|
|
80
|
+
self.original_embedding_model = embedding_model
|
|
81
|
+
self.embedding_model = wrap_embedding_model_if_needed(
|
|
82
|
+
embedding_model, self.has_gpu, self.use_cosine
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
# Configure index parameters AFTER determining GPU usage and normalization
|
|
86
|
+
embedding_dim = config.milvus.embedding_dim if config else 768
|
|
87
|
+
self.index_params, self.search_params = get_optimal_index_config(
|
|
88
|
+
self.has_gpu, embedding_dim, self.use_cosine
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
# Log the configuration
|
|
92
|
+
log_index_configuration(self.index_params, self.search_params, self.use_cosine)
|
|
93
|
+
|
|
94
|
+
# Track loaded papers to prevent duplicate loading
|
|
95
|
+
self.loaded_papers = set()
|
|
96
|
+
|
|
97
|
+
# Initialize Milvus connection parameters with environment variable fallback
|
|
98
|
+
self.connection_args = {
|
|
99
|
+
"host": (config.milvus.host if config else os.getenv("MILVUS_HOST", "127.0.0.1")),
|
|
100
|
+
"port": (config.milvus.port if config else int(os.getenv("MILVUS_PORT", "19530"))),
|
|
101
|
+
}
|
|
102
|
+
# Log the connection parameters being used
|
|
103
|
+
logger.info(
|
|
104
|
+
"Using Milvus connection: %s:%s",
|
|
105
|
+
self.connection_args["host"],
|
|
106
|
+
self.connection_args["port"],
|
|
107
|
+
)
|
|
108
|
+
self.collection_name = config.milvus.collection_name if config else "pdf_rag_documents"
|
|
109
|
+
self.db_name = config.milvus.db_name if config else "pdf_rag_db"
|
|
110
|
+
|
|
111
|
+
# Get singleton instance
|
|
112
|
+
self._singleton = VectorstoreSingleton()
|
|
113
|
+
|
|
114
|
+
# Connect to Milvus (reuses existing connection if available)
|
|
115
|
+
self._connect_milvus()
|
|
116
|
+
|
|
117
|
+
# Create collection with proper metric type
|
|
118
|
+
self.collection = ensure_collection_exists(
|
|
119
|
+
self.collection_name, self.config, self.index_params, self.has_gpu
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
# Initialize the LangChain Milvus vector store
|
|
123
|
+
self.vector_store = self._initialize_vector_store()
|
|
124
|
+
|
|
125
|
+
# Load existing papers AFTER vector store is ready
|
|
126
|
+
self._load_existing_paper_ids()
|
|
127
|
+
|
|
128
|
+
# CRITICAL: Load collection into memory/GPU after any existing data is identified
|
|
129
|
+
logger.info(
|
|
130
|
+
"Calling _ensure_collection_loaded() for %s processing...",
|
|
131
|
+
"GPU" if self.has_gpu else "CPU",
|
|
132
|
+
)
|
|
133
|
+
self._ensure_collection_loaded()
|
|
134
|
+
|
|
135
|
+
# Store for document metadata (keeping for compatibility)
|
|
136
|
+
self.documents: dict[str, Document] = {}
|
|
137
|
+
self.paper_metadata: dict[str, dict[str, Any]] = {}
|
|
138
|
+
|
|
139
|
+
# Log final configuration
|
|
140
|
+
metric_info = (
|
|
141
|
+
"IP (normalized for COSINE)"
|
|
142
|
+
if self.has_gpu and self.use_cosine
|
|
143
|
+
else self.index_params["metric_type"]
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
logger.info(
|
|
147
|
+
"Milvus vector store initialized with collection: %s (GPU: %s, Metric: %s)",
|
|
148
|
+
self.collection_name,
|
|
149
|
+
"enabled" if self.has_gpu else "disabled",
|
|
150
|
+
metric_info,
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
def _connect_milvus(self) -> None:
|
|
154
|
+
"""Establish connection to Milvus server using singleton."""
|
|
155
|
+
self._singleton.get_connection(
|
|
156
|
+
self.connection_args["host"], self.connection_args["port"], self.db_name
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
def _initialize_vector_store(self) -> Milvus:
|
|
160
|
+
"""Initialize or load the Milvus vector store with proper embedding model."""
|
|
161
|
+
# Use the wrapped embedding model (with normalization if needed)
|
|
162
|
+
vector_store = self._singleton.get_vector_store(
|
|
163
|
+
self.collection_name, self.embedding_model, self.connection_args
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
return vector_store
|
|
167
|
+
|
|
168
|
+
def _load_existing_paper_ids(self):
|
|
169
|
+
"""Load already embedded paper IDs using LangChain's collection access."""
|
|
170
|
+
logger.info("Checking for existing papers via LangChain collection...")
|
|
171
|
+
|
|
172
|
+
# Access the collection through LangChain's wrapper
|
|
173
|
+
langchain_collection = getattr(self.vector_store, "col", None)
|
|
174
|
+
|
|
175
|
+
if langchain_collection is None:
|
|
176
|
+
langchain_collection = getattr(self.vector_store, "collection", None)
|
|
177
|
+
|
|
178
|
+
if langchain_collection is None:
|
|
179
|
+
logger.warning("No LangChain collection found, proceeding with empty loaded_papers")
|
|
180
|
+
return
|
|
181
|
+
|
|
182
|
+
# Force flush and check entity count
|
|
183
|
+
langchain_collection.flush()
|
|
184
|
+
num_entities = langchain_collection.num_entities
|
|
185
|
+
|
|
186
|
+
logger.info("LangChain collection entity count: %d", num_entities)
|
|
187
|
+
|
|
188
|
+
if num_entities > 0:
|
|
189
|
+
logger.info("Loading existing paper IDs from LangChain collection...")
|
|
190
|
+
|
|
191
|
+
results = langchain_collection.query(
|
|
192
|
+
expr="", # No filter - get all
|
|
193
|
+
output_fields=["paper_id"],
|
|
194
|
+
limit=16384, # Max limit
|
|
195
|
+
consistency_level="Strong",
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
# Extract unique paper IDs
|
|
199
|
+
existing_paper_ids = {result["paper_id"] for result in results}
|
|
200
|
+
self.loaded_papers.update(existing_paper_ids)
|
|
201
|
+
|
|
202
|
+
logger.info("Found %d unique papers in collection", len(existing_paper_ids))
|
|
203
|
+
else:
|
|
204
|
+
logger.info("Collection is empty - no existing papers")
|
|
205
|
+
|
|
206
|
+
def similarity_search(self, query: str, **kwargs: Any) -> list[Document]:
|
|
207
|
+
"""
|
|
208
|
+
Perform similarity search on the vector store.
|
|
209
|
+
Query embedding will be automatically normalized if using GPU with COSINE.
|
|
210
|
+
Keyword args:
|
|
211
|
+
k: int = 4
|
|
212
|
+
filter: Optional[Dict[str, Any]] = None
|
|
213
|
+
plus any other kwargs to pass through to the underlying vector_store.
|
|
214
|
+
"""
|
|
215
|
+
# Extract our parameters
|
|
216
|
+
k: int = kwargs.pop("k", 4)
|
|
217
|
+
filter_: dict[str, Any] | None = kwargs.pop("filter", None)
|
|
218
|
+
|
|
219
|
+
# Build Milvus expr from filter_, if present
|
|
220
|
+
expr = None
|
|
221
|
+
if filter_:
|
|
222
|
+
conditions = []
|
|
223
|
+
for key, value in filter_.items():
|
|
224
|
+
if isinstance(value, str):
|
|
225
|
+
conditions.append(f'{key} == "{value}"')
|
|
226
|
+
elif isinstance(value, list):
|
|
227
|
+
vals = ", ".join(f'"{v}"' if isinstance(v, str) else str(v) for v in value)
|
|
228
|
+
conditions.append(f"{key} in [{vals}]")
|
|
229
|
+
else:
|
|
230
|
+
conditions.append(f"{key} == {value}")
|
|
231
|
+
expr = " and ".join(conditions)
|
|
232
|
+
|
|
233
|
+
# Delegate to the wrapped store
|
|
234
|
+
return self.vector_store.similarity_search(query=query, k=k, expr=expr, **kwargs)
|
|
235
|
+
|
|
236
|
+
def max_marginal_relevance_search(self, query: str, **kwargs: Any) -> list[Document]:
|
|
237
|
+
"""
|
|
238
|
+
Perform MMR search on the vector store.
|
|
239
|
+
Query embedding will be automatically normalized if using GPU with COSINE.
|
|
240
|
+
Keyword args:
|
|
241
|
+
k: int = 4
|
|
242
|
+
fetch_k: int = 20
|
|
243
|
+
lambda_mult: float = 0.5
|
|
244
|
+
filter: Optional[Dict[str, Any]] = None
|
|
245
|
+
plus any other kwargs to pass through.
|
|
246
|
+
"""
|
|
247
|
+
# Extract our parameters
|
|
248
|
+
k: int = kwargs.pop("k", 4)
|
|
249
|
+
fetch_k: int = kwargs.pop("fetch_k", 20)
|
|
250
|
+
lambda_mult: float = kwargs.pop("lambda_mult", 0.5)
|
|
251
|
+
filter_: dict[str, Any] | None = kwargs.pop("filter", None)
|
|
252
|
+
|
|
253
|
+
# Build Milvus expr from filter_, if present
|
|
254
|
+
expr = None
|
|
255
|
+
if filter_:
|
|
256
|
+
conditions = []
|
|
257
|
+
for key, value in filter_.items():
|
|
258
|
+
if isinstance(value, str):
|
|
259
|
+
conditions.append(f'{key} == "{value}"')
|
|
260
|
+
elif isinstance(value, list):
|
|
261
|
+
vals = ", ".join(f'"{v}"' if isinstance(v, str) else str(v) for v in value)
|
|
262
|
+
conditions.append(f"{key} in [{vals}]")
|
|
263
|
+
else:
|
|
264
|
+
conditions.append(f"{key} == {value}")
|
|
265
|
+
expr = " and ".join(conditions)
|
|
266
|
+
|
|
267
|
+
# Delegate to the wrapped store
|
|
268
|
+
return self.vector_store.max_marginal_relevance_search(
|
|
269
|
+
query=query,
|
|
270
|
+
k=k,
|
|
271
|
+
fetch_k=fetch_k,
|
|
272
|
+
lambda_mult=lambda_mult,
|
|
273
|
+
expr=expr,
|
|
274
|
+
**kwargs,
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
def _ensure_collection_loaded(self):
|
|
278
|
+
"""Ensure collection is loaded into memory/GPU after data insertion."""
|
|
279
|
+
# Get the collection
|
|
280
|
+
collection = getattr(self.vector_store, "col", None)
|
|
281
|
+
if collection is None:
|
|
282
|
+
collection = getattr(self.vector_store, "collection", None)
|
|
283
|
+
|
|
284
|
+
if collection is None:
|
|
285
|
+
logger.warning("Cannot access collection for loading")
|
|
286
|
+
return
|
|
287
|
+
|
|
288
|
+
# Force flush to ensure we see all data
|
|
289
|
+
logger.info("Flushing collection to ensure data visibility...")
|
|
290
|
+
collection.flush()
|
|
291
|
+
|
|
292
|
+
# Check entity count after flush
|
|
293
|
+
num_entities = collection.num_entities
|
|
294
|
+
logger.info("Collection entity count after flush: %d", num_entities)
|
|
295
|
+
|
|
296
|
+
if num_entities > 0:
|
|
297
|
+
hardware_type = "GPU" if self.has_gpu else "CPU"
|
|
298
|
+
logger.info(
|
|
299
|
+
"Loading collection with %d entities into %s memory...",
|
|
300
|
+
num_entities,
|
|
301
|
+
hardware_type,
|
|
302
|
+
)
|
|
303
|
+
|
|
304
|
+
# Load collection into memory (CPU or GPU)
|
|
305
|
+
collection.load()
|
|
306
|
+
|
|
307
|
+
# Verify loading was successful
|
|
308
|
+
final_count = collection.num_entities
|
|
309
|
+
logger.info(
|
|
310
|
+
"Collection successfully loaded into %s memory with %d entities",
|
|
311
|
+
hardware_type,
|
|
312
|
+
final_count,
|
|
313
|
+
)
|
|
314
|
+
else:
|
|
315
|
+
logger.info("Collection is empty, skipping load operation")
|
|
316
|
+
|
|
317
|
+
def get_embedding_info(self) -> dict[str, Any]:
|
|
318
|
+
"""Get information about the embedding configuration."""
|
|
319
|
+
return {
|
|
320
|
+
"has_gpu": self.has_gpu,
|
|
321
|
+
"use_cosine": self.use_cosine,
|
|
322
|
+
"metric_type": self.index_params["metric_type"],
|
|
323
|
+
"index_type": self.index_params["index_type"],
|
|
324
|
+
"normalization_enabled": hasattr(self.embedding_model, "normalize_for_gpu"),
|
|
325
|
+
"original_model_type": type(self.original_embedding_model).__name__,
|
|
326
|
+
"wrapped_model_type": type(self.embedding_model).__name__,
|
|
327
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This file is used to import all the modules in the package.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from . import (
|
|
6
|
+
display_dataframe,
|
|
7
|
+
multi_paper_rec,
|
|
8
|
+
query_dataframe,
|
|
9
|
+
retrieve_semantic_scholar_paper_id,
|
|
10
|
+
search,
|
|
11
|
+
single_paper_rec,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
__all__ = [
|
|
15
|
+
"display_dataframe",
|
|
16
|
+
"multi_paper_rec",
|
|
17
|
+
"search",
|
|
18
|
+
"single_paper_rec",
|
|
19
|
+
"query_dataframe",
|
|
20
|
+
"retrieve_semantic_scholar_paper_id",
|
|
21
|
+
]
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
Tool for rendering the most recently displayed papers as a DataFrame artifact for the front-end.
|
|
6
|
+
|
|
7
|
+
Call this tool when you need to present the current set of retrieved papers to the user
|
|
8
|
+
(e.g., "show me the papers", "display results"). It reads the 'last_displayed_papers'
|
|
9
|
+
dictionary from the agent state and returns it as an artifact that the UI will render
|
|
10
|
+
as a pandas DataFrame. This tool does not perform any new searches or filtering; it
|
|
11
|
+
only displays the existing list. If no papers are available, it raises NoPapersFoundError
|
|
12
|
+
to signal that a search or recommendation must be executed first.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
import logging
|
|
16
|
+
from typing import Annotated
|
|
17
|
+
|
|
18
|
+
from langchain_core.messages import ToolMessage
|
|
19
|
+
from langchain_core.tools import tool
|
|
20
|
+
from langchain_core.tools.base import InjectedToolCallId
|
|
21
|
+
from langgraph.prebuilt import InjectedState
|
|
22
|
+
from langgraph.types import Command
|
|
23
|
+
from pydantic import BaseModel, Field
|
|
24
|
+
|
|
25
|
+
# Configure logging
|
|
26
|
+
logging.basicConfig(level=logging.INFO)
|
|
27
|
+
logger = logging.getLogger(__name__)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class NoPapersFoundError(Exception):
|
|
31
|
+
"""
|
|
32
|
+
Exception raised when no research papers are found in the agent's state.
|
|
33
|
+
|
|
34
|
+
This exception helps the language model determine whether a new search
|
|
35
|
+
or recommendation should be initiated.
|
|
36
|
+
|
|
37
|
+
Example:
|
|
38
|
+
>>> if not papers:
|
|
39
|
+
>>> raise NoPapersFoundError("No papers found. A search is needed.")
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class DisplayDataFrameInput(BaseModel):
|
|
44
|
+
"""
|
|
45
|
+
Pydantic schema for displaying the last set of papers as a DataFrame artifact.
|
|
46
|
+
|
|
47
|
+
Fields:
|
|
48
|
+
state: Agent state dict containing the 'last_displayed_papers' key.
|
|
49
|
+
tool_call_id: LangGraph-injected identifier for this tool invocation.
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
state: Annotated[dict, InjectedState] = Field(
|
|
53
|
+
..., description="Agent state containing the 'last_displayed_papers' reference."
|
|
54
|
+
)
|
|
55
|
+
tool_call_id: Annotated[str, InjectedToolCallId] = Field(
|
|
56
|
+
..., description="LangGraph-injected identifier for this tool call."
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@tool(
|
|
61
|
+
"display_dataframe",
|
|
62
|
+
args_schema=DisplayDataFrameInput,
|
|
63
|
+
parse_docstring=True,
|
|
64
|
+
)
|
|
65
|
+
def display_dataframe(
|
|
66
|
+
tool_call_id: str,
|
|
67
|
+
state: dict,
|
|
68
|
+
) -> Command:
|
|
69
|
+
"""
|
|
70
|
+
Render the last set of retrieved papers as a DataFrame in the front-end.
|
|
71
|
+
|
|
72
|
+
This function reads the 'last_displayed_papers' key from state, fetches the
|
|
73
|
+
corresponding metadata dictionary, and returns a Command with a ToolMessage
|
|
74
|
+
containing the artifact (dictionary) for the front-end to render as a DataFrame.
|
|
75
|
+
If no papers are found in state, it raises a NoPapersFoundError to indicate
|
|
76
|
+
that a search or recommendation must be performed first.
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
tool_call_id (str): LangGraph-injected unique ID for this tool call.
|
|
80
|
+
state (dict): The agent's state containing the 'last_displayed_papers' reference.
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
Command: A command whose update contains a ToolMessage with the artifact
|
|
84
|
+
(papers dict) for DataFrame rendering in the UI.
|
|
85
|
+
|
|
86
|
+
Raises:
|
|
87
|
+
NoPapersFoundError: If no entries exist under 'last_displayed_papers' in state.
|
|
88
|
+
"""
|
|
89
|
+
logger.info("Displaying papers from 'last_displayed_papers'")
|
|
90
|
+
context_val = state.get("last_displayed_papers")
|
|
91
|
+
# Support both key reference (str) and direct mapping
|
|
92
|
+
if isinstance(context_val, dict):
|
|
93
|
+
artifact = context_val
|
|
94
|
+
else:
|
|
95
|
+
artifact = state.get(context_val)
|
|
96
|
+
if not artifact:
|
|
97
|
+
logger.info("No papers found in state, raising NoPapersFoundError")
|
|
98
|
+
raise NoPapersFoundError("No papers found. A search/rec needs to be performed first.")
|
|
99
|
+
content = f"{len(artifact)} papers found. Papers are attached as an artifact."
|
|
100
|
+
return Command(
|
|
101
|
+
update={
|
|
102
|
+
"messages": [
|
|
103
|
+
ToolMessage(
|
|
104
|
+
content=content,
|
|
105
|
+
tool_call_id=tool_call_id,
|
|
106
|
+
artifact=artifact,
|
|
107
|
+
)
|
|
108
|
+
],
|
|
109
|
+
}
|
|
110
|
+
)
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Recommend research papers related to a set of input papers using Semantic Scholar.
|
|
5
|
+
|
|
6
|
+
Given a list of Semantic Scholar paper IDs, this tool aggregates related works
|
|
7
|
+
(citations and references) from each input paper and returns a consolidated list
|
|
8
|
+
of recommended papers.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import logging
|
|
12
|
+
from typing import Annotated, Any
|
|
13
|
+
|
|
14
|
+
from langchain_core.messages import ToolMessage
|
|
15
|
+
from langchain_core.tools import tool
|
|
16
|
+
from langchain_core.tools.base import InjectedToolCallId
|
|
17
|
+
from langgraph.types import Command
|
|
18
|
+
from pydantic import BaseModel, Field
|
|
19
|
+
|
|
20
|
+
from .utils.multi_helper import MultiPaperRecData
|
|
21
|
+
|
|
22
|
+
# Configure logging
|
|
23
|
+
logging.basicConfig(level=logging.INFO)
|
|
24
|
+
logger = logging.getLogger(__name__)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class MultiPaperRecInput(BaseModel):
|
|
28
|
+
"""Defines the input schema for the multi-paper recommendation tool.
|
|
29
|
+
|
|
30
|
+
Attributes:
|
|
31
|
+
paper_ids: List of 40-character Semantic Scholar Paper IDs (provide at least two).
|
|
32
|
+
limit: Maximum total number of recommendations to return (1-500).
|
|
33
|
+
year: Optional publication year filter; supports formats:
|
|
34
|
+
'YYYY', 'YYYY-', '-YYYY', 'YYYY:YYYY'.
|
|
35
|
+
tool_call_id: Internal tool call identifier injected by the system.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
paper_ids: list[str] = Field(
|
|
39
|
+
description="List of 40-character Semantic Scholar Paper IDs"
|
|
40
|
+
"(at least two) to base recommendations on"
|
|
41
|
+
)
|
|
42
|
+
limit: int = Field(
|
|
43
|
+
default=10,
|
|
44
|
+
description="Maximum total number of recommendations to return (1-500)",
|
|
45
|
+
ge=1,
|
|
46
|
+
le=500,
|
|
47
|
+
)
|
|
48
|
+
year: str | None = Field(
|
|
49
|
+
default=None,
|
|
50
|
+
description="Publication year filter; supports formats:"
|
|
51
|
+
"'YYYY', 'YYYY-', '-YYYY', 'YYYY:YYYY'",
|
|
52
|
+
)
|
|
53
|
+
tool_call_id: Annotated[str, InjectedToolCallId]
|
|
54
|
+
|
|
55
|
+
model_config = {"arbitrary_types_allowed": True}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@tool(
|
|
59
|
+
args_schema=MultiPaperRecInput,
|
|
60
|
+
parse_docstring=True,
|
|
61
|
+
)
|
|
62
|
+
def get_multi_paper_recommendations(
|
|
63
|
+
paper_ids: list[str],
|
|
64
|
+
tool_call_id: Annotated[str, InjectedToolCallId],
|
|
65
|
+
limit: int = 10,
|
|
66
|
+
year: str | None = None,
|
|
67
|
+
) -> Command[Any]:
|
|
68
|
+
"""
|
|
69
|
+
Recommend related research papers using the Semantic Scholar API.
|
|
70
|
+
|
|
71
|
+
This tool is designed to suggest relevant papers based on a list of
|
|
72
|
+
input Semantic Scholar paper IDs.
|
|
73
|
+
|
|
74
|
+
It fetches citations and references for each input paper and aggregates
|
|
75
|
+
them to generate a set of
|
|
76
|
+
recommended papers.
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
paper_ids (List[str]): List of 40-character Semantic Scholar paper IDs.
|
|
80
|
+
Provide at least two IDs to improve the relevance of recommendations.
|
|
81
|
+
tool_call_id (str): Internal tool call identifier injected by the system.
|
|
82
|
+
limit (int, optional): Maximum number of recommendations to return. Defaults to 10.
|
|
83
|
+
year (str, optional): Filter recommendations by publication year.
|
|
84
|
+
Supports formats: 'YYYY', 'YYYY-', '-YYYY', or 'YYYY:YYYY'. Defaults to None.
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
Command: A Command object containing:
|
|
88
|
+
- multi_papers: List of recommended papers.
|
|
89
|
+
- last_displayed_papers: Same list for display purposes.
|
|
90
|
+
- messages: List containing a ToolMessage with recommendation details.
|
|
91
|
+
"""
|
|
92
|
+
# Create recommendation data object to organize variables
|
|
93
|
+
rec_data = MultiPaperRecData(paper_ids, limit, year, tool_call_id)
|
|
94
|
+
|
|
95
|
+
# Process the recommendations
|
|
96
|
+
results = rec_data.process_recommendations()
|
|
97
|
+
|
|
98
|
+
return Command(
|
|
99
|
+
update={
|
|
100
|
+
"multi_papers": results["papers"],
|
|
101
|
+
# Store the latest multi-paper results mapping directly for display
|
|
102
|
+
"last_displayed_papers": results["papers"],
|
|
103
|
+
"messages": [
|
|
104
|
+
ToolMessage(
|
|
105
|
+
content=results["content"],
|
|
106
|
+
tool_call_id=tool_call_id,
|
|
107
|
+
artifact=results["papers"],
|
|
108
|
+
)
|
|
109
|
+
],
|
|
110
|
+
}
|
|
111
|
+
)
|