graphiti-core 0.20.4__tar.gz → 0.21.0rc2__tar.gz

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.

Potentially problematic release.


This version of graphiti-core might be problematic. Click here for more details.

Files changed (189) hide show
  1. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/PKG-INFO +4 -1
  2. graphiti_core-0.21.0rc2/graphiti_core/driver/driver.py +313 -0
  3. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/driver/falkordb_driver.py +1 -0
  4. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/driver/kuzu_driver.py +1 -0
  5. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/driver/neo4j_driver.py +59 -2
  6. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/driver/neptune_driver.py +26 -45
  7. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/edges.py +61 -4
  8. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/embedder/client.py +2 -1
  9. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/graphiti.py +21 -5
  10. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/models/edges/edge_db_queries.py +36 -16
  11. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/models/nodes/node_db_queries.py +30 -10
  12. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/nodes.py +120 -22
  13. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/search/search_filters.py +53 -0
  14. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/search/search_utils.py +225 -57
  15. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/utils/bulk_utils.py +23 -3
  16. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/utils/maintenance/edge_operations.py +39 -5
  17. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/utils/maintenance/graph_data_operations.py +9 -5
  18. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/pyproject.toml +2 -1
  19. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/signatures/version1/cla.json +24 -0
  20. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/uv.lock +8 -2
  21. graphiti_core-0.20.4/graphiti_core/driver/driver.py +0 -89
  22. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/.env.example +0 -0
  23. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  24. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/.github/dependabot.yml +0 -0
  25. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/.github/pull_request_template.md +0 -0
  26. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/.github/secret_scanning.yml +0 -0
  27. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/.github/workflows/ai-moderator.yml +0 -0
  28. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/.github/workflows/cla.yml +0 -0
  29. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/.github/workflows/claude-code-review.yml +0 -0
  30. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/.github/workflows/claude.yml +0 -0
  31. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/.github/workflows/codeql.yml +0 -0
  32. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/.github/workflows/lint.yml +0 -0
  33. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/.github/workflows/mcp-server-docker.yml +0 -0
  34. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/.github/workflows/release-graphiti-core.yml +0 -0
  35. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/.github/workflows/typecheck.yml +0 -0
  36. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/.github/workflows/unit_tests.yml +0 -0
  37. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/.gitignore +0 -0
  38. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/CLAUDE.md +0 -0
  39. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/CODE_OF_CONDUCT.md +0 -0
  40. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/CONTRIBUTING.md +0 -0
  41. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/Dockerfile +0 -0
  42. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/LICENSE +0 -0
  43. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/Makefile +0 -0
  44. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/README.md +0 -0
  45. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/SECURITY.md +0 -0
  46. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/Zep-CLA.md +0 -0
  47. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/conftest.py +0 -0
  48. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/depot.json +0 -0
  49. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/docker-compose.test.yml +0 -0
  50. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/docker-compose.yml +0 -0
  51. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/ellipsis.yaml +0 -0
  52. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/examples/data/manybirds_products.json +0 -0
  53. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/examples/ecommerce/runner.ipynb +0 -0
  54. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/examples/ecommerce/runner.py +0 -0
  55. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/examples/langgraph-agent/agent.ipynb +0 -0
  56. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/examples/langgraph-agent/tinybirds-jess.png +0 -0
  57. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/examples/podcast/podcast_runner.py +0 -0
  58. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/examples/podcast/podcast_transcript.txt +0 -0
  59. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/examples/podcast/transcript_parser.py +0 -0
  60. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/examples/quickstart/README.md +0 -0
  61. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/examples/quickstart/quickstart_falkordb.py +0 -0
  62. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/examples/quickstart/quickstart_neo4j.py +0 -0
  63. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/examples/quickstart/quickstart_neptune.py +0 -0
  64. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/examples/quickstart/requirements.txt +0 -0
  65. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/examples/wizard_of_oz/parser.py +0 -0
  66. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/examples/wizard_of_oz/runner.py +0 -0
  67. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/examples/wizard_of_oz/woo.txt +0 -0
  68. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/__init__.py +0 -0
  69. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/cross_encoder/__init__.py +0 -0
  70. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/cross_encoder/bge_reranker_client.py +0 -0
  71. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/cross_encoder/client.py +0 -0
  72. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/cross_encoder/gemini_reranker_client.py +0 -0
  73. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/cross_encoder/openai_reranker_client.py +0 -0
  74. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/driver/__init__.py +0 -0
  75. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/embedder/__init__.py +0 -0
  76. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/embedder/azure_openai.py +0 -0
  77. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/embedder/gemini.py +0 -0
  78. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/embedder/openai.py +0 -0
  79. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/embedder/voyage.py +0 -0
  80. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/errors.py +0 -0
  81. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/graph_queries.py +0 -0
  82. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/graphiti_types.py +0 -0
  83. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/helpers.py +0 -0
  84. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/llm_client/__init__.py +0 -0
  85. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/llm_client/anthropic_client.py +0 -0
  86. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/llm_client/azure_openai_client.py +0 -0
  87. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/llm_client/client.py +0 -0
  88. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/llm_client/config.py +0 -0
  89. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/llm_client/errors.py +0 -0
  90. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/llm_client/gemini_client.py +0 -0
  91. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/llm_client/groq_client.py +0 -0
  92. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/llm_client/openai_base_client.py +0 -0
  93. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/llm_client/openai_client.py +0 -0
  94. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/llm_client/openai_generic_client.py +0 -0
  95. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/llm_client/utils.py +0 -0
  96. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/migrations/__init__.py +0 -0
  97. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/models/__init__.py +0 -0
  98. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/models/edges/__init__.py +0 -0
  99. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/models/nodes/__init__.py +0 -0
  100. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/prompts/__init__.py +0 -0
  101. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/prompts/dedupe_edges.py +0 -0
  102. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/prompts/dedupe_nodes.py +0 -0
  103. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/prompts/eval.py +0 -0
  104. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/prompts/extract_edge_dates.py +0 -0
  105. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/prompts/extract_edges.py +0 -0
  106. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/prompts/extract_nodes.py +0 -0
  107. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/prompts/invalidate_edges.py +0 -0
  108. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/prompts/lib.py +0 -0
  109. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/prompts/models.py +0 -0
  110. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/prompts/prompt_helpers.py +0 -0
  111. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/prompts/summarize_nodes.py +0 -0
  112. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/py.typed +0 -0
  113. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/search/__init__.py +0 -0
  114. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/search/search.py +0 -0
  115. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/search/search_config.py +0 -0
  116. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/search/search_config_recipes.py +0 -0
  117. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/search/search_helpers.py +0 -0
  118. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/telemetry/__init__.py +0 -0
  119. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/telemetry/telemetry.py +0 -0
  120. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/utils/__init__.py +0 -0
  121. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/utils/datetime_utils.py +0 -0
  122. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/utils/maintenance/__init__.py +0 -0
  123. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/utils/maintenance/community_operations.py +0 -0
  124. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/utils/maintenance/node_operations.py +0 -0
  125. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/utils/maintenance/temporal_operations.py +0 -0
  126. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/utils/maintenance/utils.py +0 -0
  127. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/graphiti_core/utils/ontology_utils/entity_types_utils.py +0 -0
  128. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/images/arxiv-screenshot.png +0 -0
  129. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/images/graphiti-graph-intro.gif +0 -0
  130. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/images/graphiti-intro-slides-stock-2.gif +0 -0
  131. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/images/simple_graph.svg +0 -0
  132. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/mcp_server/.env.example +0 -0
  133. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/mcp_server/.python-version +0 -0
  134. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/mcp_server/Dockerfile +0 -0
  135. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/mcp_server/README.md +0 -0
  136. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/mcp_server/cursor_rules.md +0 -0
  137. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/mcp_server/docker-compose.yml +0 -0
  138. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/mcp_server/graphiti_mcp_server.py +0 -0
  139. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/mcp_server/mcp_config_sse_example.json +0 -0
  140. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/mcp_server/mcp_config_stdio_example.json +0 -0
  141. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/mcp_server/pyproject.toml +0 -0
  142. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/mcp_server/uv.lock +0 -0
  143. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/poetry.lock +0 -0
  144. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/py.typed +0 -0
  145. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/pytest.ini +0 -0
  146. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/server/.env.example +0 -0
  147. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/server/Makefile +0 -0
  148. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/server/README.md +0 -0
  149. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/server/graph_service/__init__.py +0 -0
  150. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/server/graph_service/config.py +0 -0
  151. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/server/graph_service/dto/__init__.py +0 -0
  152. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/server/graph_service/dto/common.py +0 -0
  153. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/server/graph_service/dto/ingest.py +0 -0
  154. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/server/graph_service/dto/retrieve.py +0 -0
  155. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/server/graph_service/main.py +0 -0
  156. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/server/graph_service/routers/__init__.py +0 -0
  157. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/server/graph_service/routers/ingest.py +0 -0
  158. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/server/graph_service/routers/retrieve.py +0 -0
  159. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/server/graph_service/zep_graphiti.py +0 -0
  160. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/server/pyproject.toml +0 -0
  161. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/server/uv.lock +0 -0
  162. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/tests/cross_encoder/test_bge_reranker_client.py +0 -0
  163. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/tests/cross_encoder/test_gemini_reranker_client.py +0 -0
  164. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/tests/driver/__init__.py +0 -0
  165. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/tests/driver/test_falkordb_driver.py +0 -0
  166. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/tests/embedder/embedder_fixtures.py +0 -0
  167. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/tests/embedder/test_gemini.py +0 -0
  168. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/tests/embedder/test_openai.py +0 -0
  169. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/tests/embedder/test_voyage.py +0 -0
  170. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/tests/evals/data/longmemeval_data/README.md +0 -0
  171. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/tests/evals/data/longmemeval_data/longmemeval_oracle.json +0 -0
  172. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/tests/evals/eval_cli.py +0 -0
  173. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/tests/evals/eval_e2e_graph_building.py +0 -0
  174. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/tests/evals/pytest.ini +0 -0
  175. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/tests/evals/utils.py +0 -0
  176. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/tests/helpers_test.py +0 -0
  177. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/tests/llm_client/test_anthropic_client.py +0 -0
  178. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/tests/llm_client/test_anthropic_client_int.py +0 -0
  179. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/tests/llm_client/test_client.py +0 -0
  180. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/tests/llm_client/test_errors.py +0 -0
  181. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/tests/llm_client/test_gemini_client.py +0 -0
  182. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/tests/test_edge_int.py +0 -0
  183. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/tests/test_entity_exclusion_int.py +0 -0
  184. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/tests/test_graphiti_int.py +0 -0
  185. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/tests/test_graphiti_mock.py +0 -0
  186. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/tests/test_node_int.py +0 -0
  187. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/tests/utils/maintenance/test_edge_operations.py +0 -0
  188. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/tests/utils/maintenance/test_temporal_operations_int.py +0 -0
  189. {graphiti_core-0.20.4 → graphiti_core-0.21.0rc2}/tests/utils/search/search_utils_test.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: graphiti-core
3
- Version: 0.20.4
3
+ Version: 0.21.0rc2
4
4
  Summary: A temporal graph building library
5
5
  Project-URL: Homepage, https://help.getzep.com/graphiti/graphiti/overview
6
6
  Project-URL: Repository, https://github.com/getzep/graphiti
@@ -47,6 +47,9 @@ Provides-Extra: groq
47
47
  Requires-Dist: groq>=0.2.0; extra == 'groq'
48
48
  Provides-Extra: kuzu
49
49
  Requires-Dist: kuzu>=0.11.2; extra == 'kuzu'
50
+ Provides-Extra: neo4j-opensearch
51
+ Requires-Dist: boto3>=1.39.16; extra == 'neo4j-opensearch'
52
+ Requires-Dist: opensearch-py>=3.0.0; extra == 'neo4j-opensearch'
50
53
  Provides-Extra: neptune
51
54
  Requires-Dist: boto3>=1.39.16; extra == 'neptune'
52
55
  Requires-Dist: langchain-aws>=0.2.29; extra == 'neptune'
@@ -0,0 +1,313 @@
1
+ """
2
+ Copyright 2024, Zep Software, Inc.
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ """
16
+
17
+ import asyncio
18
+ import copy
19
+ import logging
20
+ import os
21
+ from abc import ABC, abstractmethod
22
+ from collections.abc import Coroutine
23
+ from datetime import datetime
24
+ from enum import Enum
25
+ from typing import Any
26
+
27
+ from dotenv import load_dotenv
28
+
29
+ from graphiti_core.embedder.client import EMBEDDING_DIM
30
+
31
+ try:
32
+ from opensearchpy import AsyncOpenSearch, helpers
33
+
34
+ _HAS_OPENSEARCH = True
35
+ except ImportError:
36
+ OpenSearch = None
37
+ helpers = None
38
+ _HAS_OPENSEARCH = False
39
+
40
+ logger = logging.getLogger(__name__)
41
+
42
+ DEFAULT_SIZE = 10
43
+
44
+ load_dotenv()
45
+
46
+ ENTITY_INDEX_NAME = os.environ.get('ENTITY_INDEX_NAME', 'entities')
47
+ EPISODE_INDEX_NAME = os.environ.get('EPISODE_INDEX_NAME', 'episodes')
48
+ COMMUNITY_INDEX_NAME = os.environ.get('COMMUNITY_INDEX_NAME', 'communities')
49
+ ENTITY_EDGE_INDEX_NAME = os.environ.get('ENTITY_EDGE_INDEX_NAME', 'entity_edges')
50
+
51
+
52
+ class GraphProvider(Enum):
53
+ NEO4J = 'neo4j'
54
+ FALKORDB = 'falkordb'
55
+ KUZU = 'kuzu'
56
+ NEPTUNE = 'neptune'
57
+
58
+
59
+ aoss_indices = [
60
+ {
61
+ 'index_name': ENTITY_INDEX_NAME,
62
+ 'body': {
63
+ 'settings': {'index': {'knn': True}},
64
+ 'mappings': {
65
+ 'properties': {
66
+ 'uuid': {'type': 'keyword'},
67
+ 'name': {'type': 'text'},
68
+ 'summary': {'type': 'text'},
69
+ 'group_id': {'type': 'keyword'},
70
+ 'created_at': {'type': 'date', 'format': 'strict_date_optional_time_nanos'},
71
+ 'name_embedding': {
72
+ 'type': 'knn_vector',
73
+ 'dimension': EMBEDDING_DIM,
74
+ 'method': {
75
+ 'engine': 'faiss',
76
+ 'space_type': 'cosinesimil',
77
+ 'name': 'hnsw',
78
+ 'parameters': {'ef_construction': 128, 'm': 16},
79
+ },
80
+ },
81
+ }
82
+ },
83
+ },
84
+ },
85
+ {
86
+ 'index_name': COMMUNITY_INDEX_NAME,
87
+ 'body': {
88
+ 'mappings': {
89
+ 'properties': {
90
+ 'uuid': {'type': 'keyword'},
91
+ 'name': {'type': 'text'},
92
+ 'group_id': {'type': 'keyword'},
93
+ }
94
+ }
95
+ },
96
+ },
97
+ {
98
+ 'index_name': EPISODE_INDEX_NAME,
99
+ 'body': {
100
+ 'mappings': {
101
+ 'properties': {
102
+ 'uuid': {'type': 'keyword'},
103
+ 'content': {'type': 'text'},
104
+ 'source': {'type': 'text'},
105
+ 'source_description': {'type': 'text'},
106
+ 'group_id': {'type': 'keyword'},
107
+ 'created_at': {'type': 'date', 'format': 'strict_date_optional_time_nanos'},
108
+ 'valid_at': {'type': 'date', 'format': 'strict_date_optional_time_nanos'},
109
+ }
110
+ }
111
+ },
112
+ },
113
+ {
114
+ 'index_name': ENTITY_EDGE_INDEX_NAME,
115
+ 'body': {
116
+ 'settings': {'index': {'knn': True}},
117
+ 'mappings': {
118
+ 'properties': {
119
+ 'uuid': {'type': 'keyword'},
120
+ 'name': {'type': 'text'},
121
+ 'fact': {'type': 'text'},
122
+ 'group_id': {'type': 'keyword'},
123
+ 'created_at': {'type': 'date', 'format': 'strict_date_optional_time_nanos'},
124
+ 'valid_at': {'type': 'date', 'format': 'strict_date_optional_time_nanos'},
125
+ 'expired_at': {'type': 'date', 'format': 'strict_date_optional_time_nanos'},
126
+ 'invalid_at': {'type': 'date', 'format': 'strict_date_optional_time_nanos'},
127
+ 'fact_embedding': {
128
+ 'type': 'knn_vector',
129
+ 'dimension': EMBEDDING_DIM,
130
+ 'method': {
131
+ 'engine': 'faiss',
132
+ 'space_type': 'cosinesimil',
133
+ 'name': 'hnsw',
134
+ 'parameters': {'ef_construction': 128, 'm': 16},
135
+ },
136
+ },
137
+ }
138
+ },
139
+ },
140
+ },
141
+ ]
142
+
143
+
144
+ class GraphDriverSession(ABC):
145
+ provider: GraphProvider
146
+
147
+ async def __aenter__(self):
148
+ return self
149
+
150
+ @abstractmethod
151
+ async def __aexit__(self, exc_type, exc, tb):
152
+ # No cleanup needed for Falkor, but method must exist
153
+ pass
154
+
155
+ @abstractmethod
156
+ async def run(self, query: str, **kwargs: Any) -> Any:
157
+ raise NotImplementedError()
158
+
159
+ @abstractmethod
160
+ async def close(self):
161
+ raise NotImplementedError()
162
+
163
+ @abstractmethod
164
+ async def execute_write(self, func, *args, **kwargs):
165
+ raise NotImplementedError()
166
+
167
+
168
+ class GraphDriver(ABC):
169
+ provider: GraphProvider
170
+ fulltext_syntax: str = (
171
+ '' # Neo4j (default) syntax does not require a prefix for fulltext queries
172
+ )
173
+ _database: str
174
+ aoss_client: AsyncOpenSearch | None # type: ignore
175
+
176
+ @abstractmethod
177
+ def execute_query(self, cypher_query_: str, **kwargs: Any) -> Coroutine:
178
+ raise NotImplementedError()
179
+
180
+ @abstractmethod
181
+ def session(self, database: str | None = None) -> GraphDriverSession:
182
+ raise NotImplementedError()
183
+
184
+ @abstractmethod
185
+ def close(self):
186
+ raise NotImplementedError()
187
+
188
+ @abstractmethod
189
+ def delete_all_indexes(self) -> Coroutine:
190
+ raise NotImplementedError()
191
+
192
+ def with_database(self, database: str) -> 'GraphDriver':
193
+ """
194
+ Returns a shallow copy of this driver with a different default database.
195
+ Reuses the same connection (e.g. FalkorDB, Neo4j).
196
+ """
197
+ cloned = copy.copy(self)
198
+ cloned._database = database
199
+
200
+ return cloned
201
+
202
+ async def delete_all_indexes_impl(self) -> Coroutine[Any, Any, Any]:
203
+ # No matter what happens above, always return True
204
+ return self.delete_aoss_indices()
205
+
206
+ async def create_aoss_indices(self):
207
+ client = self.aoss_client
208
+ if not client:
209
+ logger.warning('No OpenSearch client found')
210
+ return
211
+
212
+ for index in aoss_indices:
213
+ alias_name = index['index_name']
214
+
215
+ # If alias already exists, skip (idempotent behavior)
216
+ if await client.indices.exists_alias(name=alias_name):
217
+ continue
218
+
219
+ # Build a physical index name with timestamp
220
+ ts_suffix = datetime.utcnow().strftime('%Y%m%d%H%M%S')
221
+ physical_index_name = f'{alias_name}_{ts_suffix}'
222
+
223
+ # Create the index
224
+ await client.indices.create(index=physical_index_name, body=index['body'])
225
+
226
+ # Point alias to it
227
+ await client.indices.put_alias(index=physical_index_name, name=alias_name)
228
+
229
+ # Allow some time for index creation
230
+ await asyncio.sleep(1)
231
+
232
+ async def delete_aoss_indices(self):
233
+ client = self.aoss_client
234
+
235
+ if not client:
236
+ logger.warning('No OpenSearch client found')
237
+ return
238
+
239
+ for entry in aoss_indices:
240
+ alias_name = entry['index_name']
241
+
242
+ try:
243
+ # Resolve alias → indices
244
+ alias_info = await client.indices.get_alias(name=alias_name)
245
+ indices = list(alias_info.keys())
246
+
247
+ if not indices:
248
+ logger.info(f"No indices found for alias '{alias_name}'")
249
+ continue
250
+
251
+ for index in indices:
252
+ if await client.indices.exists(index=index):
253
+ await client.indices.delete(index=index)
254
+ logger.info(f"Deleted index '{index}' (alias: {alias_name})")
255
+ else:
256
+ logger.warning(f"Index '{index}' not found for alias '{alias_name}'")
257
+
258
+ except Exception as e:
259
+ logger.error(f"Error deleting indices for alias '{alias_name}': {e}")
260
+
261
+ async def clear_aoss_indices(self):
262
+ client = self.aoss_client
263
+
264
+ if not client:
265
+ logger.warning('No OpenSearch client found')
266
+ return
267
+
268
+ for index in aoss_indices:
269
+ index_name = index['index_name']
270
+
271
+ if await client.indices.exists(index=index_name):
272
+ try:
273
+ # Delete all documents but keep the index
274
+ response = await client.delete_by_query(
275
+ index=index_name,
276
+ body={'query': {'match_all': {}}},
277
+ )
278
+ logger.info(f"Cleared index '{index_name}': {response}")
279
+ except Exception as e:
280
+ logger.error(f"Error clearing index '{index_name}': {e}")
281
+ else:
282
+ logger.warning(f"Index '{index_name}' does not exist")
283
+
284
+ async def save_to_aoss(self, name: str, data: list[dict]) -> int:
285
+ client = self.aoss_client
286
+ if not client or not helpers:
287
+ logger.warning('No OpenSearch client found')
288
+ return 0
289
+
290
+ for index in aoss_indices:
291
+ if name.lower() == index['index_name']:
292
+ to_index = []
293
+ for d in data:
294
+ doc = {}
295
+ for p in index['body']['mappings']['properties']:
296
+ if p in d: # protect against missing fields
297
+ doc[p] = d[p]
298
+
299
+ item = {
300
+ '_index': name,
301
+ '_id': d['uuid'],
302
+ '_routing': d.get('group_id'),
303
+ '_source': doc,
304
+ }
305
+ to_index.append(item)
306
+
307
+ success, failed = await helpers.async_bulk(
308
+ client, to_index, stats_only=True, request_timeout=60
309
+ )
310
+
311
+ return success if failed == 0 else success
312
+
313
+ return 0
@@ -74,6 +74,7 @@ class FalkorDriverSession(GraphDriverSession):
74
74
 
75
75
  class FalkorDriver(GraphDriver):
76
76
  provider = GraphProvider.FALKORDB
77
+ aoss_client: None = None
77
78
 
78
79
  def __init__(
79
80
  self,
@@ -92,6 +92,7 @@ SCHEMA_QUERIES = """
92
92
 
93
93
  class KuzuDriver(GraphDriver):
94
94
  provider: GraphProvider = GraphProvider.KUZU
95
+ aoss_client: None = None
95
96
 
96
97
  def __init__(
97
98
  self,
@@ -22,14 +22,44 @@ from neo4j import AsyncGraphDatabase, EagerResult
22
22
  from typing_extensions import LiteralString
23
23
 
24
24
  from graphiti_core.driver.driver import GraphDriver, GraphDriverSession, GraphProvider
25
+ from graphiti_core.helpers import semaphore_gather
25
26
 
26
27
  logger = logging.getLogger(__name__)
27
28
 
29
+ try:
30
+ import boto3
31
+ from opensearchpy import (
32
+ AIOHttpConnection,
33
+ AsyncOpenSearch,
34
+ AWSV4SignerAuth,
35
+ Urllib3AWSV4SignerAuth,
36
+ Urllib3HttpConnection,
37
+ )
38
+
39
+ _HAS_OPENSEARCH = True
40
+ except ImportError:
41
+ boto3 = None
42
+ OpenSearch = None
43
+ Urllib3AWSV4SignerAuth = None
44
+ Urllib3HttpConnection = None
45
+ _HAS_OPENSEARCH = False
46
+
28
47
 
29
48
  class Neo4jDriver(GraphDriver):
30
49
  provider = GraphProvider.NEO4J
31
50
 
32
- def __init__(self, uri: str, user: str | None, password: str | None, database: str = 'neo4j'):
51
+ def __init__(
52
+ self,
53
+ uri: str,
54
+ user: str | None,
55
+ password: str | None,
56
+ database: str = 'neo4j',
57
+ aoss_host: str | None = None,
58
+ aoss_port: int | None = None,
59
+ aws_profile_name: str | None = None,
60
+ aws_region: str | None = None,
61
+ aws_service: str | None = None,
62
+ ):
33
63
  super().__init__()
34
64
  self.client = AsyncGraphDatabase.driver(
35
65
  uri=uri,
@@ -37,6 +67,26 @@ class Neo4jDriver(GraphDriver):
37
67
  )
38
68
  self._database = database
39
69
 
70
+ self.aoss_client = None
71
+ if aoss_host and aoss_port and boto3 is not None:
72
+ try:
73
+ region = aws_region
74
+ service = aws_service
75
+ credentials = boto3.Session(profile_name=aws_profile_name).get_credentials()
76
+ auth = AWSV4SignerAuth(credentials, region or '', service or '')
77
+
78
+ self.aoss_client = AsyncOpenSearch(
79
+ hosts=[{'host': aoss_host, 'port': aoss_port}],
80
+ auth=auth,
81
+ use_ssl=True,
82
+ verify_certs=True,
83
+ connection_class=AIOHttpConnection,
84
+ pool_maxsize=20,
85
+ ) # type: ignore
86
+ except Exception as e:
87
+ logger.warning(f'Failed to initialize OpenSearch client: {e}')
88
+ self.aoss_client = None
89
+
40
90
  async def execute_query(self, cypher_query_: LiteralString, **kwargs: Any) -> EagerResult:
41
91
  # Check if database_ is provided in kwargs.
42
92
  # If not populated, set the value to retain backwards compatibility
@@ -60,7 +110,14 @@ class Neo4jDriver(GraphDriver):
60
110
  async def close(self) -> None:
61
111
  return await self.client.close()
62
112
 
63
- def delete_all_indexes(self) -> Coroutine[Any, Any, EagerResult]:
113
+ def delete_all_indexes(self) -> Coroutine:
114
+ if self.aoss_client:
115
+ return semaphore_gather(
116
+ self.client.execute_query(
117
+ 'CALL db.indexes() YIELD name DROP INDEX name',
118
+ ),
119
+ self.delete_aoss_indices(),
120
+ )
64
121
  return self.client.execute_query(
65
122
  'CALL db.indexes() YIELD name DROP INDEX name',
66
123
  )
@@ -22,16 +22,21 @@ from typing import Any
22
22
 
23
23
  import boto3
24
24
  from langchain_aws.graphs import NeptuneAnalyticsGraph, NeptuneGraph
25
- from opensearchpy import OpenSearch, Urllib3AWSV4SignerAuth, Urllib3HttpConnection, helpers
25
+ from opensearchpy import OpenSearch, Urllib3AWSV4SignerAuth, Urllib3HttpConnection
26
26
 
27
- from graphiti_core.driver.driver import GraphDriver, GraphDriverSession, GraphProvider
27
+ from graphiti_core.driver.driver import (
28
+ DEFAULT_SIZE,
29
+ GraphDriver,
30
+ GraphDriverSession,
31
+ GraphProvider,
32
+ )
28
33
 
29
34
  logger = logging.getLogger(__name__)
30
- DEFAULT_SIZE = 10
31
35
 
32
- aoss_indices = [
36
+ neptune_aoss_indices = [
33
37
  {
34
38
  'index_name': 'node_name_and_summary',
39
+ 'alias_name': 'entities',
35
40
  'body': {
36
41
  'mappings': {
37
42
  'properties': {
@@ -49,6 +54,7 @@ aoss_indices = [
49
54
  },
50
55
  {
51
56
  'index_name': 'community_name',
57
+ 'alias_name': 'communities',
52
58
  'body': {
53
59
  'mappings': {
54
60
  'properties': {
@@ -65,6 +71,7 @@ aoss_indices = [
65
71
  },
66
72
  {
67
73
  'index_name': 'episode_content',
74
+ 'alias_name': 'episodes',
68
75
  'body': {
69
76
  'mappings': {
70
77
  'properties': {
@@ -88,6 +95,7 @@ aoss_indices = [
88
95
  },
89
96
  {
90
97
  'index_name': 'edge_name_and_fact',
98
+ 'alias_name': 'facts',
91
99
  'body': {
92
100
  'mappings': {
93
101
  'properties': {
@@ -220,54 +228,27 @@ class NeptuneDriver(GraphDriver):
220
228
  async def _delete_all_data(self) -> Any:
221
229
  return await self.execute_query('MATCH (n) DETACH DELETE n')
222
230
 
223
- def delete_all_indexes(self) -> Coroutine[Any, Any, Any]:
224
- return self.delete_all_indexes_impl()
225
-
226
- async def delete_all_indexes_impl(self) -> Coroutine[Any, Any, Any]:
227
- # No matter what happens above, always return True
228
- return self.delete_aoss_indices()
229
-
230
231
  async def create_aoss_indices(self):
231
- for index in aoss_indices:
232
+ for index in neptune_aoss_indices:
232
233
  index_name = index['index_name']
233
234
  client = self.aoss_client
235
+ if not client:
236
+ raise ValueError(
237
+ 'You must provide an AOSS endpoint to create an OpenSearch driver.'
238
+ )
234
239
  if not client.indices.exists(index=index_name):
235
- client.indices.create(index=index_name, body=index['body'])
240
+ await client.indices.create(index=index_name, body=index['body'])
241
+
242
+ alias_name = index.get('alias_name', index_name)
243
+
244
+ if not client.indices.exists_alias(name=alias_name, index=index_name):
245
+ await client.indices.put_alias(index=index_name, name=alias_name)
246
+
236
247
  # Sleep for 1 minute to let the index creation complete
237
248
  await asyncio.sleep(60)
238
249
 
239
- async def delete_aoss_indices(self):
240
- for index in aoss_indices:
241
- index_name = index['index_name']
242
- client = self.aoss_client
243
- if client.indices.exists(index=index_name):
244
- client.indices.delete(index=index_name)
245
-
246
- def run_aoss_query(self, name: str, query_text: str, limit: int = 10) -> dict[str, Any]:
247
- for index in aoss_indices:
248
- if name.lower() == index['index_name']:
249
- index['query']['query']['multi_match']['query'] = query_text
250
- query = {'size': limit, 'query': index['query']}
251
- resp = self.aoss_client.search(body=query['query'], index=index['index_name'])
252
- return resp
253
- return {}
254
-
255
- def save_to_aoss(self, name: str, data: list[dict]) -> int:
256
- for index in aoss_indices:
257
- if name.lower() == index['index_name']:
258
- to_index = []
259
- for d in data:
260
- item = {'_index': name}
261
- for p in index['body']['mappings']['properties']:
262
- item[p] = d[p]
263
- to_index.append(item)
264
- success, failed = helpers.bulk(self.aoss_client, to_index, stats_only=True)
265
- if failed > 0:
266
- return success
267
- else:
268
- return 0
269
-
270
- return 0
250
+ def delete_all_indexes(self) -> Coroutine[Any, Any, Any]:
251
+ return self.delete_all_indexes_impl()
271
252
 
272
253
 
273
254
  class NeptuneDriverSession(GraphDriverSession):
@@ -25,7 +25,7 @@ from uuid import uuid4
25
25
  from pydantic import BaseModel, Field
26
26
  from typing_extensions import LiteralString
27
27
 
28
- from graphiti_core.driver.driver import GraphDriver, GraphProvider
28
+ from graphiti_core.driver.driver import ENTITY_EDGE_INDEX_NAME, GraphDriver, GraphProvider
29
29
  from graphiti_core.embedder import EmbedderClient
30
30
  from graphiti_core.errors import EdgeNotFoundError, GroupsEdgesNotFoundError
31
31
  from graphiti_core.helpers import parse_db_date
@@ -77,6 +77,13 @@ class Edge(BaseModel, ABC):
77
77
  uuid=self.uuid,
78
78
  )
79
79
 
80
+ if driver.aoss_client:
81
+ await driver.aoss_client.delete(
82
+ index=ENTITY_EDGE_INDEX_NAME,
83
+ id=self.uuid,
84
+ params={'routing': self.group_id},
85
+ )
86
+
80
87
  logger.debug(f'Deleted Edge: {self.uuid}')
81
88
 
82
89
  @classmethod
@@ -108,6 +115,12 @@ class Edge(BaseModel, ABC):
108
115
  uuids=uuids,
109
116
  )
110
117
 
118
+ if driver.aoss_client:
119
+ await driver.aoss_client.delete_by_query(
120
+ index=ENTITY_EDGE_INDEX_NAME,
121
+ body={'query': {'terms': {'uuid': uuids}}},
122
+ )
123
+
111
124
  logger.debug(f'Deleted Edges: {uuids}')
112
125
 
113
126
  def __hash__(self):
@@ -255,6 +268,21 @@ class EntityEdge(Edge):
255
268
  MATCH (n:Entity)-[e:RELATES_TO {uuid: $uuid}]->(m:Entity)
256
269
  RETURN [x IN split(e.fact_embedding, ",") | toFloat(x)] as fact_embedding
257
270
  """
271
+ elif driver.aoss_client:
272
+ resp = await driver.aoss_client.search(
273
+ body={
274
+ 'query': {'multi_match': {'query': self.uuid, 'fields': ['uuid']}},
275
+ 'size': 1,
276
+ },
277
+ index=ENTITY_EDGE_INDEX_NAME,
278
+ params={'routing': self.group_id},
279
+ )
280
+
281
+ if resp['hits']['hits']:
282
+ self.fact_embedding = resp['hits']['hits'][0]['_source']['fact_embedding']
283
+ return
284
+ else:
285
+ raise EdgeNotFoundError(self.uuid)
258
286
 
259
287
  if driver.provider == GraphProvider.KUZU:
260
288
  query = """
@@ -292,14 +320,14 @@ class EntityEdge(Edge):
292
320
  if driver.provider == GraphProvider.KUZU:
293
321
  edge_data['attributes'] = json.dumps(self.attributes)
294
322
  result = await driver.execute_query(
295
- get_entity_edge_save_query(driver.provider),
323
+ get_entity_edge_save_query(driver.provider, has_aoss=bool(driver.aoss_client)),
296
324
  **edge_data,
297
325
  )
298
326
  else:
299
327
  edge_data.update(self.attributes or {})
300
328
 
301
- if driver.provider == GraphProvider.NEPTUNE:
302
- driver.save_to_aoss('edge_name_and_fact', [edge_data]) # pyright: ignore reportAttributeAccessIssue
329
+ if driver.aoss_client:
330
+ await driver.save_to_aoss(ENTITY_EDGE_INDEX_NAME, [edge_data]) # pyright: ignore reportAttributeAccessIssue
303
331
 
304
332
  result = await driver.execute_query(
305
333
  get_entity_edge_save_query(driver.provider),
@@ -336,6 +364,35 @@ class EntityEdge(Edge):
336
364
  raise EdgeNotFoundError(uuid)
337
365
  return edges[0]
338
366
 
367
+ @classmethod
368
+ async def get_between_nodes(
369
+ cls, driver: GraphDriver, source_node_uuid: str, target_node_uuid: str
370
+ ):
371
+ match_query = """
372
+ MATCH (n:Entity {uuid: $source_node_uuid})-[e:RELATES_TO]->(m:Entity {uuid: $target_node_uuid})
373
+ """
374
+ if driver.provider == GraphProvider.KUZU:
375
+ match_query = """
376
+ MATCH (n:Entity {uuid: $source_node_uuid})
377
+ -[:RELATES_TO]->(e:RelatesToNode_)
378
+ -[:RELATES_TO]->(m:Entity {uuid: $target_node_uuid})
379
+ """
380
+
381
+ records, _, _ = await driver.execute_query(
382
+ match_query
383
+ + """
384
+ RETURN
385
+ """
386
+ + get_entity_edge_return_query(driver.provider),
387
+ source_node_uuid=source_node_uuid,
388
+ target_node_uuid=target_node_uuid,
389
+ routing_='r',
390
+ )
391
+
392
+ edges = [get_entity_edge_from_record(record, driver.provider) for record in records]
393
+
394
+ return edges
395
+
339
396
  @classmethod
340
397
  async def get_by_uuids(cls, driver: GraphDriver, uuids: list[str]):
341
398
  if len(uuids) == 0:
@@ -14,12 +14,13 @@ See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
15
  """
16
16
 
17
+ import os
17
18
  from abc import ABC, abstractmethod
18
19
  from collections.abc import Iterable
19
20
 
20
21
  from pydantic import BaseModel, Field
21
22
 
22
- EMBEDDING_DIM = 1024
23
+ EMBEDDING_DIM = int(os.getenv('EMBEDDING_DIM', 1024))
23
24
 
24
25
 
25
26
  class EmbedderConfig(BaseModel):