aiagents4pharma 1.39.0__py3-none-any.whl → 1.39.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. aiagents4pharma/talk2scholars/agents/main_agent.py +7 -7
  2. aiagents4pharma/talk2scholars/configs/agents/talk2scholars/main_agent/default.yaml +88 -12
  3. aiagents4pharma/talk2scholars/configs/agents/talk2scholars/s2_agent/default.yaml +1 -20
  4. aiagents4pharma/talk2scholars/configs/agents/talk2scholars/zotero_agent/default.yaml +1 -26
  5. aiagents4pharma/talk2scholars/tests/test_main_agent.py +20 -2
  6. aiagents4pharma/talk2scholars/tests/test_nvidia_nim_reranker_utils.py +28 -0
  7. aiagents4pharma/talk2scholars/tests/test_paper_download_tools.py +107 -29
  8. aiagents4pharma/talk2scholars/tests/test_pdf_agent.py +2 -3
  9. aiagents4pharma/talk2scholars/tests/test_question_and_answer_tool.py +194 -543
  10. aiagents4pharma/talk2scholars/tests/test_s2_agent.py +2 -2
  11. aiagents4pharma/talk2scholars/tests/{test_s2_display.py → test_s2_display_dataframe.py} +2 -3
  12. aiagents4pharma/talk2scholars/tests/test_s2_query_dataframe.py +201 -0
  13. aiagents4pharma/talk2scholars/tests/test_s2_retrieve.py +7 -6
  14. aiagents4pharma/talk2scholars/tests/test_s2_utils_ext_ids.py +413 -0
  15. aiagents4pharma/talk2scholars/tests/test_tool_helper_utils.py +140 -0
  16. aiagents4pharma/talk2scholars/tests/test_zotero_agent.py +0 -1
  17. aiagents4pharma/talk2scholars/tests/test_zotero_read.py +16 -18
  18. aiagents4pharma/talk2scholars/tools/paper_download/download_arxiv_input.py +92 -37
  19. aiagents4pharma/talk2scholars/tools/pdf/question_and_answer.py +73 -575
  20. aiagents4pharma/talk2scholars/tools/pdf/utils/__init__.py +10 -0
  21. aiagents4pharma/talk2scholars/tools/pdf/utils/generate_answer.py +97 -0
  22. aiagents4pharma/talk2scholars/tools/pdf/utils/nvidia_nim_reranker.py +77 -0
  23. aiagents4pharma/talk2scholars/tools/pdf/utils/retrieve_chunks.py +83 -0
  24. aiagents4pharma/talk2scholars/tools/pdf/utils/tool_helper.py +125 -0
  25. aiagents4pharma/talk2scholars/tools/pdf/utils/vector_store.py +162 -0
  26. aiagents4pharma/talk2scholars/tools/s2/display_dataframe.py +33 -10
  27. aiagents4pharma/talk2scholars/tools/s2/multi_paper_rec.py +39 -16
  28. aiagents4pharma/talk2scholars/tools/s2/query_dataframe.py +124 -10
  29. aiagents4pharma/talk2scholars/tools/s2/retrieve_semantic_scholar_paper_id.py +49 -17
  30. aiagents4pharma/talk2scholars/tools/s2/search.py +39 -16
  31. aiagents4pharma/talk2scholars/tools/s2/single_paper_rec.py +34 -16
  32. aiagents4pharma/talk2scholars/tools/s2/utils/multi_helper.py +49 -16
  33. aiagents4pharma/talk2scholars/tools/s2/utils/search_helper.py +51 -16
  34. aiagents4pharma/talk2scholars/tools/s2/utils/single_helper.py +50 -17
  35. {aiagents4pharma-1.39.0.dist-info → aiagents4pharma-1.39.1.dist-info}/METADATA +58 -105
  36. {aiagents4pharma-1.39.0.dist-info → aiagents4pharma-1.39.1.dist-info}/RECORD +39 -32
  37. aiagents4pharma/talk2scholars/tests/test_llm_main_integration.py +0 -89
  38. aiagents4pharma/talk2scholars/tests/test_routing_logic.py +0 -74
  39. aiagents4pharma/talk2scholars/tests/test_s2_query.py +0 -95
  40. {aiagents4pharma-1.39.0.dist-info → aiagents4pharma-1.39.1.dist-info}/WHEEL +0 -0
  41. {aiagents4pharma-1.39.0.dist-info → aiagents4pharma-1.39.1.dist-info}/licenses/LICENSE +0 -0
  42. {aiagents4pharma-1.39.0.dist-info → aiagents4pharma-1.39.1.dist-info}/top_level.txt +0 -0
@@ -1,74 +0,0 @@
1
- """
2
- Routing logic for zotero_agent through the main_agent
3
- """
4
-
5
- import pytest
6
- from langgraph.types import Command
7
- from langgraph.graph import END
8
- from langchain_core.messages import HumanMessage
9
- from aiagents4pharma.talk2scholars.state.state_talk2scholars import Talk2Scholars
10
-
11
- # pylint: disable=redefined-outer-name
12
-
13
-
14
- @pytest.fixture
15
- def mock_state():
16
- """Creates a mock state to simulate an ongoing conversation."""
17
- return Talk2Scholars(messages=[])
18
-
19
-
20
- @pytest.fixture
21
- def mock_router():
22
- """Creates a mock supervisor router that routes based on keyword matching."""
23
-
24
- def mock_supervisor_node(state):
25
- """Mock supervisor node that routes based on keyword matching."""
26
- query = state["messages"][-1].content.lower()
27
- # Define keywords for each sub-agent.
28
- s2_keywords = [
29
- "paper",
30
- "research",
31
- "citations",
32
- "journal",
33
- "articles",
34
- "references",
35
- ]
36
- zotero_keywords = ["zotero", "library", "saved papers", "academic library"]
37
- pdf_keywords = ["pdf", "document", "read pdf"]
38
- paper_download_keywords = ["download", "arxiv", "fetch paper", "paper download"]
39
-
40
- # Priority ordering: Zotero, then paper download, then PDF, then S2.
41
- if any(keyword in query for keyword in zotero_keywords):
42
- return Command(goto="zotero_agent")
43
- if any(keyword in query for keyword in paper_download_keywords):
44
- return Command(goto="paper_download_agent")
45
- if any(keyword in query for keyword in pdf_keywords):
46
- return Command(goto="pdf_agent")
47
- if any(keyword in query for keyword in s2_keywords):
48
- return Command(goto="s2_agent")
49
- # Default to end if no keyword matches.
50
- return Command(goto=END)
51
-
52
- return mock_supervisor_node
53
-
54
-
55
- @pytest.mark.parametrize(
56
- "user_query,expected_agent",
57
- [
58
- ("Find papers on deep learning.", "s2_agent"),
59
- ("Show me my saved references in Zotero.", "zotero_agent"),
60
- ("I need some research articles.", "s2_agent"),
61
- ("Fetch my academic library.", "zotero_agent"),
62
- ("Retrieve citations.", "s2_agent"),
63
- ("Can you get journal articles?", "s2_agent"),
64
- ("I want to read the PDF document.", "pdf_agent"),
65
- ("Download the paper from arxiv.", "paper_download_agent"),
66
- ("Completely unrelated query.", "__end__"),
67
- ],
68
- )
69
- def test_routing_logic(mock_state, mock_router, user_query, expected_agent):
70
- """Tests that the routing logic correctly assigns the right agent or ends conversation."""
71
- mock_state["messages"].append(HumanMessage(content=user_query))
72
- result = mock_router(mock_state)
73
-
74
- assert result.goto == expected_agent, f"Failed for query: {user_query}"
@@ -1,95 +0,0 @@
1
- """
2
- Unit tests for S2 tools functionality.
3
- """
4
-
5
- # pylint: disable=redefined-outer-name
6
- from unittest.mock import patch
7
- from unittest.mock import MagicMock
8
- import pytest
9
- from ..tools.s2.query_dataframe import query_dataframe, NoPapersFoundError
10
-
11
-
12
- @pytest.fixture
13
- def initial_state():
14
- """Provides an empty initial state for tests."""
15
- return {"papers": {}, "multi_papers": {}}
16
-
17
-
18
- # Fixed test data for deterministic results
19
- MOCK_SEARCH_RESPONSE = {
20
- "data": [
21
- {
22
- "paperId": "123",
23
- "title": "Machine Learning Basics",
24
- "abstract": "An introduction to ML",
25
- "year": 2023,
26
- "citationCount": 100,
27
- "url": "https://example.com/paper1",
28
- "authors": [{"name": "Test Author"}],
29
- }
30
- ]
31
- }
32
-
33
- MOCK_STATE_PAPER = {
34
- "123": {
35
- "Title": "Machine Learning Basics",
36
- "Abstract": "An introduction to ML",
37
- "Year": 2023,
38
- "Citation Count": 100,
39
- "URL": "https://example.com/paper1",
40
- }
41
- }
42
-
43
-
44
- class TestS2Tools:
45
- """Unit tests for individual S2 tools"""
46
-
47
- def test_query_dataframe_empty_state(self, initial_state):
48
- """Tests query_dataframe tool behavior when no papers are found."""
49
- with pytest.raises(
50
- NoPapersFoundError,
51
- match="No papers found. A search needs to be performed first.",
52
- ):
53
- query_dataframe.invoke(
54
- {"question": "List all papers", "state": initial_state}
55
- )
56
-
57
- @patch(
58
- "aiagents4pharma.talk2scholars.tools.s2.query_dataframe.create_pandas_dataframe_agent"
59
- )
60
- def test_query_dataframe_with_papers(self, mock_create_agent, initial_state):
61
- """Tests querying papers when data is available."""
62
- state = initial_state.copy()
63
- state["last_displayed_papers"] = "papers"
64
- state["papers"] = MOCK_STATE_PAPER
65
-
66
- # Mock the dataframe agent instead of the LLM
67
- mock_agent = MagicMock()
68
- mock_agent.invoke.return_value = {"output": "Mocked response"}
69
-
70
- mock_create_agent.return_value = (
71
- mock_agent # Mock the function returning the agent
72
- )
73
-
74
- # Ensure that the output of query_dataframe is correctly structured
75
- result = query_dataframe.invoke({"question": "List all papers", "state": state})
76
-
77
- assert isinstance(result, str) # Ensure output is a string
78
- assert result == "Mocked response" # Validate the expected response
79
-
80
- @patch(
81
- "aiagents4pharma.talk2scholars.tools.s2.query_dataframe.create_pandas_dataframe_agent"
82
- )
83
- def test_query_dataframe_direct_mapping(self, mock_create_agent, initial_state):
84
- """Tests query_dataframe when last_displayed_papers is a direct dict mapping."""
85
- # Prepare state with direct mapping
86
- state = initial_state.copy()
87
- state["last_displayed_papers"] = MOCK_STATE_PAPER
88
- # Mock the dataframe agent
89
- mock_agent = MagicMock()
90
- mock_agent.invoke.return_value = {"output": "Direct mapping response"}
91
- mock_create_agent.return_value = mock_agent
92
- # Invoke tool
93
- result = query_dataframe.invoke({"question": "Filter papers", "state": state})
94
- assert isinstance(result, str)
95
- assert result == "Direct mapping response"