You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

test_graphrag_tools.py 8.2 kB

Graphrag integration (#4612) * add initial global search draft * add graphrag dep * fix local search embedding * linting * add from config constructor * remove draft notebook * update config factory and add docstrings * add graphrag sample * add sample prompts * update readme * update deps * Add API docs * Update python/samples/agentchat_graphrag/requirements.txt * Update python/samples/agentchat_graphrag/requirements.txt * update docstrings with snippet and doc ref * lint * improve set up instructions in docstring * lint * update lock * Update python/packages/autogen-ext/src/autogen_ext/tools/graphrag/_global_search.py Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com> * Update python/packages/autogen-ext/src/autogen_ext/tools/graphrag/_local_search.py Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com> * add unit tests * update lock * update uv lock * add docstring newlines * stubs and typing on graphrag tests * fix docstrings * fix mypy error * + linting and type fixes * type fix graphrag sample * Update python/packages/autogen-ext/src/autogen_ext/tools/graphrag/_global_search.py Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com> * Update python/packages/autogen-ext/src/autogen_ext/tools/graphrag/_local_search.py Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com> * Update python/samples/agentchat_graphrag/requirements.txt Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com> * update overrides * fix docstring client imports * additional docstring fix * add docstring missing import * use openai and fix db path * use console for displaying messages * add model config and gitignore * update readme * lint * Update python/samples/agentchat_graphrag/README.md * Update python/samples/agentchat_graphrag/README.md * Comment remaining azure config --------- Co-authored-by: Leonardo Pinheiro <lpinheiro@microsoft.com> Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com>
1 year ago
Graphrag integration (#4612) * add initial global search draft * add graphrag dep * fix local search embedding * linting * add from config constructor * remove draft notebook * update config factory and add docstrings * add graphrag sample * add sample prompts * update readme * update deps * Add API docs * Update python/samples/agentchat_graphrag/requirements.txt * Update python/samples/agentchat_graphrag/requirements.txt * update docstrings with snippet and doc ref * lint * improve set up instructions in docstring * lint * update lock * Update python/packages/autogen-ext/src/autogen_ext/tools/graphrag/_global_search.py Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com> * Update python/packages/autogen-ext/src/autogen_ext/tools/graphrag/_local_search.py Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com> * add unit tests * update lock * update uv lock * add docstring newlines * stubs and typing on graphrag tests * fix docstrings * fix mypy error * + linting and type fixes * type fix graphrag sample * Update python/packages/autogen-ext/src/autogen_ext/tools/graphrag/_global_search.py Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com> * Update python/packages/autogen-ext/src/autogen_ext/tools/graphrag/_local_search.py Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com> * Update python/samples/agentchat_graphrag/requirements.txt Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com> * update overrides * fix docstring client imports * additional docstring fix * add docstring missing import * use openai and fix db path * use console for displaying messages * add model config and gitignore * update readme * lint * Update python/samples/agentchat_graphrag/README.md * Update python/samples/agentchat_graphrag/README.md * Comment remaining azure config --------- Co-authored-by: Leonardo Pinheiro <lpinheiro@microsoft.com> Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com>
1 year ago
Graphrag integration (#4612) * add initial global search draft * add graphrag dep * fix local search embedding * linting * add from config constructor * remove draft notebook * update config factory and add docstrings * add graphrag sample * add sample prompts * update readme * update deps * Add API docs * Update python/samples/agentchat_graphrag/requirements.txt * Update python/samples/agentchat_graphrag/requirements.txt * update docstrings with snippet and doc ref * lint * improve set up instructions in docstring * lint * update lock * Update python/packages/autogen-ext/src/autogen_ext/tools/graphrag/_global_search.py Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com> * Update python/packages/autogen-ext/src/autogen_ext/tools/graphrag/_local_search.py Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com> * add unit tests * update lock * update uv lock * add docstring newlines * stubs and typing on graphrag tests * fix docstrings * fix mypy error * + linting and type fixes * type fix graphrag sample * Update python/packages/autogen-ext/src/autogen_ext/tools/graphrag/_global_search.py Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com> * Update python/packages/autogen-ext/src/autogen_ext/tools/graphrag/_local_search.py Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com> * Update python/samples/agentchat_graphrag/requirements.txt Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com> * update overrides * fix docstring client imports * additional docstring fix * add docstring missing import * use openai and fix db path * use console for displaying messages * add model config and gitignore * update readme * lint * Update python/samples/agentchat_graphrag/README.md * Update python/samples/agentchat_graphrag/README.md * Comment remaining azure config --------- Co-authored-by: Leonardo Pinheiro <lpinheiro@microsoft.com> Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com>
1 year ago
Graphrag integration (#4612) * add initial global search draft * add graphrag dep * fix local search embedding * linting * add from config constructor * remove draft notebook * update config factory and add docstrings * add graphrag sample * add sample prompts * update readme * update deps * Add API docs * Update python/samples/agentchat_graphrag/requirements.txt * Update python/samples/agentchat_graphrag/requirements.txt * update docstrings with snippet and doc ref * lint * improve set up instructions in docstring * lint * update lock * Update python/packages/autogen-ext/src/autogen_ext/tools/graphrag/_global_search.py Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com> * Update python/packages/autogen-ext/src/autogen_ext/tools/graphrag/_local_search.py Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com> * add unit tests * update lock * update uv lock * add docstring newlines * stubs and typing on graphrag tests * fix docstrings * fix mypy error * + linting and type fixes * type fix graphrag sample * Update python/packages/autogen-ext/src/autogen_ext/tools/graphrag/_global_search.py Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com> * Update python/packages/autogen-ext/src/autogen_ext/tools/graphrag/_local_search.py Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com> * Update python/samples/agentchat_graphrag/requirements.txt Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com> * update overrides * fix docstring client imports * additional docstring fix * add docstring missing import * use openai and fix db path * use console for displaying messages * add model config and gitignore * update readme * lint * Update python/samples/agentchat_graphrag/README.md * Update python/samples/agentchat_graphrag/README.md * Comment remaining azure config --------- Co-authored-by: Leonardo Pinheiro <lpinheiro@microsoft.com> Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com>
1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. # mypy: disable-error-code="no-any-unimported"
  2. import os
  3. import tempfile
  4. from typing import Any, AsyncGenerator, Generator
  5. import pandas as pd
  6. import pytest
  7. import tiktoken
  8. from autogen_core import CancellationToken
  9. from autogen_ext.tools.graphrag import GlobalSearchTool, GlobalSearchToolReturn, LocalSearchTool, LocalSearchToolReturn
  10. from autogen_ext.tools.graphrag._config import GlobalDataConfig, LocalDataConfig
  11. from graphrag.callbacks.llm_callbacks import BaseLLMCallback
  12. from graphrag.model.types import TextEmbedder
  13. from graphrag.query.llm.base import BaseLLM, BaseTextEmbedding
  14. from graphrag.vector_stores.base import BaseVectorStore, VectorStoreDocument, VectorStoreSearchResult
  15. class MockLLM(BaseLLM): # type: ignore
  16. def generate(
  17. self,
  18. messages: str | list[Any],
  19. streaming: bool = True,
  20. callbacks: list[BaseLLMCallback] | None = None,
  21. **kwargs: Any,
  22. ) -> str:
  23. return "Mock response"
  24. def stream_generate(
  25. self, messages: str | list[Any], callbacks: list[BaseLLMCallback] | None = None, **kwargs: Any
  26. ) -> Generator[str, None, None]:
  27. yield "Mock response"
  28. async def agenerate(
  29. self,
  30. messages: str | list[Any],
  31. streaming: bool = True,
  32. callbacks: list[BaseLLMCallback] | None = None,
  33. **kwargs: Any,
  34. ) -> str:
  35. return "Mock response"
  36. async def astream_generate( # type: ignore
  37. self, messages: str | list[Any], callbacks: list[BaseLLMCallback] | None = None, **kwargs: Any
  38. ) -> AsyncGenerator[str, None]:
  39. yield "Mock response"
  40. class MockTextEmbedding(BaseTextEmbedding): # type: ignore
  41. def embed(self, text: str, **kwargs: Any) -> list[float]:
  42. return [0.1] * 10
  43. async def aembed(self, text: str, **kwargs: Any) -> list[float]:
  44. return [0.1] * 10
  45. class MockVectorStore(BaseVectorStore): # type: ignore
  46. def __init__(self, **kwargs: Any) -> None:
  47. super().__init__(collection_name="mock", **kwargs)
  48. self.documents: dict[str | int, VectorStoreDocument] = {}
  49. def connect(self, **kwargs: Any) -> None:
  50. pass
  51. def load_documents(self, documents: list[VectorStoreDocument], overwrite: bool = True) -> None:
  52. if overwrite:
  53. self.documents = {}
  54. for doc in documents:
  55. self.documents[doc.id] = doc
  56. def filter_by_id(self, include_ids: list[str] | list[int]) -> None:
  57. return None
  58. def similarity_search_by_vector(
  59. self, query_embedding: list[float], k: int = 10, **kwargs: Any
  60. ) -> list[VectorStoreSearchResult]:
  61. docs = list(self.documents.values())[:k]
  62. return [VectorStoreSearchResult(document=doc, score=0.9) for doc in docs]
  63. def similarity_search_by_text(
  64. self, text: str, text_embedder: TextEmbedder, k: int = 10, **kwargs: Any
  65. ) -> list[VectorStoreSearchResult]:
  66. return self.similarity_search_by_vector([0.1] * 10, k)
  67. def search_by_id(self, id: str) -> VectorStoreDocument:
  68. return self.documents.get(id, VectorStoreDocument(id=id, text=None, vector=None))
  69. @pytest.mark.asyncio
  70. async def test_global_search_tool(
  71. community_df_fixture: pd.DataFrame,
  72. entity_df_fixture: pd.DataFrame,
  73. report_df_fixture: pd.DataFrame,
  74. entity_embedding_fixture: pd.DataFrame,
  75. caplog: pytest.LogCaptureFixture,
  76. ) -> None:
  77. # Create a temporary directory to simulate the data config
  78. with tempfile.TemporaryDirectory() as tempdir:
  79. # Save fixtures to parquet files
  80. community_table = os.path.join(tempdir, "create_final_communities.parquet")
  81. entity_table = os.path.join(tempdir, "create_final_nodes.parquet")
  82. community_report_table = os.path.join(tempdir, "create_final_community_reports.parquet")
  83. entity_embedding_table = os.path.join(tempdir, "create_final_entities.parquet")
  84. community_df_fixture.to_parquet(community_table) # type: ignore
  85. entity_df_fixture.to_parquet(entity_table) # type: ignore
  86. report_df_fixture.to_parquet(community_report_table) # type: ignore
  87. entity_embedding_fixture.to_parquet(entity_embedding_table) # type: ignore
  88. # Initialize the data config with the temporary directory
  89. data_config = GlobalDataConfig(
  90. input_dir=tempdir,
  91. community_table="create_final_communities",
  92. entity_table="create_final_nodes",
  93. community_report_table="create_final_community_reports",
  94. entity_embedding_table="create_final_entities",
  95. )
  96. # Initialize the GlobalSearchTool with mock data
  97. token_encoder = tiktoken.encoding_for_model("gpt-4o")
  98. llm = MockLLM()
  99. global_search_tool = GlobalSearchTool(token_encoder=token_encoder, llm=llm, data_config=data_config)
  100. with caplog.at_level("INFO"):
  101. # Example of running the tool and checking the result
  102. query = "What is the overall sentiment of the community reports?"
  103. cancellation_token = CancellationToken()
  104. result = await global_search_tool.run_json(args={"query": query}, cancellation_token=cancellation_token)
  105. assert isinstance(result, GlobalSearchToolReturn)
  106. assert isinstance(result.answer, str)
  107. # Check if the log contains the expected message
  108. assert result.answer in caplog.text
  109. @pytest.mark.asyncio
  110. async def test_local_search_tool(
  111. entity_df_fixture: pd.DataFrame,
  112. relationship_df_fixture: pd.DataFrame,
  113. text_unit_df_fixture: pd.DataFrame,
  114. entity_embedding_fixture: pd.DataFrame,
  115. monkeypatch: pytest.MonkeyPatch,
  116. caplog: pytest.LogCaptureFixture,
  117. ) -> None:
  118. # Create a temporary directory to simulate the data config
  119. with tempfile.TemporaryDirectory() as tempdir:
  120. # Save fixtures to parquet files
  121. entity_table = os.path.join(tempdir, "create_final_nodes.parquet")
  122. relationship_table = os.path.join(tempdir, "create_final_relationships.parquet")
  123. text_unit_table = os.path.join(tempdir, "create_final_text_units.parquet")
  124. entity_embedding_table = os.path.join(tempdir, "create_final_entities.parquet")
  125. entity_df_fixture.to_parquet(entity_table) # type: ignore
  126. relationship_df_fixture.to_parquet(relationship_table) # type: ignore
  127. text_unit_df_fixture.to_parquet(text_unit_table) # type: ignore
  128. entity_embedding_fixture.to_parquet(entity_embedding_table) # type: ignore
  129. # Initialize the data config with the temporary directory
  130. data_config = LocalDataConfig(
  131. input_dir=tempdir,
  132. entity_table="create_final_nodes",
  133. relationship_table="create_final_relationships",
  134. text_unit_table="create_final_text_units",
  135. entity_embedding_table="create_final_entities",
  136. )
  137. # Initialize the LocalSearchTool with mock data
  138. token_encoder = tiktoken.encoding_for_model("gpt-4o")
  139. llm = MockLLM()
  140. embedder = MockTextEmbedding()
  141. # Mock the vector store
  142. def mock_vector_store_factory(*args: Any, **kwargs: dict[str, Any]) -> MockVectorStore:
  143. store = MockVectorStore()
  144. store.document_collection = store # Make the store act as its own collection
  145. return store
  146. # Patch the LanceDBVectorStore class
  147. monkeypatch.setattr("autogen_ext.tools.graphrag._local_search.LanceDBVectorStore", mock_vector_store_factory) # type: ignore
  148. local_search_tool = LocalSearchTool(
  149. token_encoder=token_encoder, llm=llm, embedder=embedder, data_config=data_config
  150. )
  151. with caplog.at_level("INFO"):
  152. # Example of running the tool and checking the result
  153. query = "What are the relationships between Dr. Becher and the station-master?"
  154. cancellation_token = CancellationToken()
  155. result = await local_search_tool.run_json(args={"query": query}, cancellation_token=cancellation_token)
  156. assert isinstance(result, LocalSearchToolReturn)
  157. assert isinstance(result.answer, str)
  158. # Check if the log contains the expected message
  159. assert result.answer in caplog.text