graphiti-core 0.17.10__tar.gz → 0.18.0__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 (183) hide show
  1. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/PKG-INFO +1 -1
  2. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/graphiti.py +1 -1
  3. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/search/search.py +68 -36
  4. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/search/search_config.py +8 -4
  5. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/search/search_utils.py +40 -22
  6. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/pyproject.toml +1 -1
  7. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/tests/test_graphiti_int.py +1 -1
  8. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/uv.lock +1 -1
  9. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/.env.example +0 -0
  10. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  11. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/.github/dependabot.yml +0 -0
  12. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/.github/pull_request_template.md +0 -0
  13. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/.github/secret_scanning.yml +0 -0
  14. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/.github/workflows/cla.yml +0 -0
  15. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/.github/workflows/claude-code-review.yml +0 -0
  16. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/.github/workflows/claude.yml +0 -0
  17. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/.github/workflows/codeql.yml +0 -0
  18. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/.github/workflows/lint.yml +0 -0
  19. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/.github/workflows/mcp-server-docker.yml +0 -0
  20. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/.github/workflows/release-graphiti-core.yml +0 -0
  21. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/.github/workflows/typecheck.yml +0 -0
  22. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/.github/workflows/unit_tests.yml +0 -0
  23. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/.gitignore +0 -0
  24. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/CLAUDE.md +0 -0
  25. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/CODE_OF_CONDUCT.md +0 -0
  26. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/CONTRIBUTING.md +0 -0
  27. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/Dockerfile +0 -0
  28. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/LICENSE +0 -0
  29. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/Makefile +0 -0
  30. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/README.md +0 -0
  31. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/SECURITY.md +0 -0
  32. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/Zep-CLA.md +0 -0
  33. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/conftest.py +0 -0
  34. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/depot.json +0 -0
  35. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/docker-compose.test.yml +0 -0
  36. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/docker-compose.yml +0 -0
  37. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/ellipsis.yaml +0 -0
  38. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/examples/data/manybirds_products.json +0 -0
  39. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/examples/ecommerce/runner.ipynb +0 -0
  40. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/examples/ecommerce/runner.py +0 -0
  41. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/examples/langgraph-agent/agent.ipynb +0 -0
  42. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/examples/langgraph-agent/tinybirds-jess.png +0 -0
  43. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/examples/podcast/podcast_runner.py +0 -0
  44. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/examples/podcast/podcast_transcript.txt +0 -0
  45. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/examples/podcast/transcript_parser.py +0 -0
  46. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/examples/quickstart/README.md +0 -0
  47. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/examples/quickstart/quickstart_falkordb.py +0 -0
  48. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/examples/quickstart/quickstart_neo4j.py +0 -0
  49. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/examples/quickstart/requirements.txt +0 -0
  50. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/examples/wizard_of_oz/parser.py +0 -0
  51. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/examples/wizard_of_oz/runner.py +0 -0
  52. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/examples/wizard_of_oz/woo.txt +0 -0
  53. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/__init__.py +0 -0
  54. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/cross_encoder/__init__.py +0 -0
  55. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/cross_encoder/bge_reranker_client.py +0 -0
  56. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/cross_encoder/client.py +0 -0
  57. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/cross_encoder/gemini_reranker_client.py +0 -0
  58. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/cross_encoder/openai_reranker_client.py +0 -0
  59. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/driver/__init__.py +0 -0
  60. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/driver/driver.py +0 -0
  61. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/driver/falkordb_driver.py +0 -0
  62. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/driver/neo4j_driver.py +0 -0
  63. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/edges.py +0 -0
  64. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/embedder/__init__.py +0 -0
  65. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/embedder/azure_openai.py +0 -0
  66. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/embedder/client.py +0 -0
  67. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/embedder/gemini.py +0 -0
  68. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/embedder/openai.py +0 -0
  69. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/embedder/voyage.py +0 -0
  70. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/errors.py +0 -0
  71. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/graph_queries.py +0 -0
  72. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/graphiti_types.py +0 -0
  73. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/helpers.py +0 -0
  74. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/llm_client/__init__.py +0 -0
  75. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/llm_client/anthropic_client.py +0 -0
  76. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/llm_client/azure_openai_client.py +0 -0
  77. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/llm_client/client.py +0 -0
  78. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/llm_client/config.py +0 -0
  79. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/llm_client/errors.py +0 -0
  80. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/llm_client/gemini_client.py +0 -0
  81. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/llm_client/groq_client.py +0 -0
  82. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/llm_client/openai_base_client.py +0 -0
  83. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/llm_client/openai_client.py +0 -0
  84. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/llm_client/openai_generic_client.py +0 -0
  85. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/llm_client/utils.py +0 -0
  86. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/models/__init__.py +0 -0
  87. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/models/edges/__init__.py +0 -0
  88. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/models/edges/edge_db_queries.py +0 -0
  89. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/models/nodes/__init__.py +0 -0
  90. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/models/nodes/node_db_queries.py +0 -0
  91. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/nodes.py +0 -0
  92. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/prompts/__init__.py +0 -0
  93. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/prompts/dedupe_edges.py +0 -0
  94. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/prompts/dedupe_nodes.py +0 -0
  95. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/prompts/eval.py +0 -0
  96. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/prompts/extract_edge_dates.py +0 -0
  97. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/prompts/extract_edges.py +0 -0
  98. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/prompts/extract_nodes.py +0 -0
  99. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/prompts/invalidate_edges.py +0 -0
  100. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/prompts/lib.py +0 -0
  101. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/prompts/models.py +0 -0
  102. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/prompts/prompt_helpers.py +0 -0
  103. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/prompts/summarize_nodes.py +0 -0
  104. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/py.typed +0 -0
  105. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/search/__init__.py +0 -0
  106. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/search/search_config_recipes.py +0 -0
  107. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/search/search_filters.py +0 -0
  108. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/search/search_helpers.py +0 -0
  109. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/telemetry/__init__.py +0 -0
  110. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/telemetry/telemetry.py +0 -0
  111. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/utils/__init__.py +0 -0
  112. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/utils/bulk_utils.py +0 -0
  113. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/utils/datetime_utils.py +0 -0
  114. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/utils/maintenance/__init__.py +0 -0
  115. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/utils/maintenance/community_operations.py +0 -0
  116. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/utils/maintenance/edge_operations.py +0 -0
  117. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/utils/maintenance/graph_data_operations.py +0 -0
  118. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/utils/maintenance/node_operations.py +0 -0
  119. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/utils/maintenance/temporal_operations.py +0 -0
  120. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/utils/maintenance/utils.py +0 -0
  121. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/graphiti_core/utils/ontology_utils/entity_types_utils.py +0 -0
  122. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/images/arxiv-screenshot.png +0 -0
  123. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/images/graphiti-graph-intro.gif +0 -0
  124. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/images/graphiti-intro-slides-stock-2.gif +0 -0
  125. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/images/simple_graph.svg +0 -0
  126. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/mcp_server/.env.example +0 -0
  127. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/mcp_server/.python-version +0 -0
  128. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/mcp_server/Dockerfile +0 -0
  129. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/mcp_server/README.md +0 -0
  130. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/mcp_server/cursor_rules.md +0 -0
  131. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/mcp_server/docker-compose.yml +0 -0
  132. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/mcp_server/graphiti_mcp_server.py +0 -0
  133. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/mcp_server/mcp_config_sse_example.json +0 -0
  134. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/mcp_server/mcp_config_stdio_example.json +0 -0
  135. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/mcp_server/pyproject.toml +0 -0
  136. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/mcp_server/uv.lock +0 -0
  137. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/poetry.lock +0 -0
  138. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/py.typed +0 -0
  139. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/pytest.ini +0 -0
  140. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/server/.env.example +0 -0
  141. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/server/Makefile +0 -0
  142. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/server/README.md +0 -0
  143. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/server/graph_service/__init__.py +0 -0
  144. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/server/graph_service/config.py +0 -0
  145. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/server/graph_service/dto/__init__.py +0 -0
  146. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/server/graph_service/dto/common.py +0 -0
  147. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/server/graph_service/dto/ingest.py +0 -0
  148. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/server/graph_service/dto/retrieve.py +0 -0
  149. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/server/graph_service/main.py +0 -0
  150. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/server/graph_service/routers/__init__.py +0 -0
  151. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/server/graph_service/routers/ingest.py +0 -0
  152. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/server/graph_service/routers/retrieve.py +0 -0
  153. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/server/graph_service/zep_graphiti.py +0 -0
  154. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/server/pyproject.toml +0 -0
  155. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/server/uv.lock +0 -0
  156. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/signatures/version1/cla.json +0 -0
  157. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/tests/cross_encoder/test_bge_reranker_client.py +0 -0
  158. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/tests/cross_encoder/test_gemini_reranker_client.py +0 -0
  159. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/tests/driver/__init__.py +0 -0
  160. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/tests/driver/test_falkordb_driver.py +0 -0
  161. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/tests/embedder/embedder_fixtures.py +0 -0
  162. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/tests/embedder/test_gemini.py +0 -0
  163. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/tests/embedder/test_openai.py +0 -0
  164. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/tests/embedder/test_voyage.py +0 -0
  165. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/tests/evals/data/longmemeval_data/README.md +0 -0
  166. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/tests/evals/data/longmemeval_data/longmemeval_oracle.json +0 -0
  167. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/tests/evals/eval_cli.py +0 -0
  168. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/tests/evals/eval_e2e_graph_building.py +0 -0
  169. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/tests/evals/pytest.ini +0 -0
  170. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/tests/evals/utils.py +0 -0
  171. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/tests/helpers_test.py +0 -0
  172. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/tests/llm_client/test_anthropic_client.py +0 -0
  173. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/tests/llm_client/test_anthropic_client_int.py +0 -0
  174. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/tests/llm_client/test_client.py +0 -0
  175. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/tests/llm_client/test_errors.py +0 -0
  176. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/tests/llm_client/test_gemini_client.py +0 -0
  177. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/tests/test_entity_exclusion_int.py +0 -0
  178. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/tests/test_graphiti_falkordb_int.py +0 -0
  179. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/tests/test_node_falkordb_int.py +0 -0
  180. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/tests/test_node_int.py +0 -0
  181. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/tests/utils/maintenance/test_edge_operations.py +0 -0
  182. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/tests/utils/maintenance/test_temporal_operations_int.py +0 -0
  183. {graphiti_core-0.17.10 → graphiti_core-0.18.0}/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.17.10
3
+ Version: 0.18.0
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
@@ -959,7 +959,7 @@ class Graphiti:
959
959
 
960
960
  nodes = await get_mentioned_nodes(self.driver, episodes)
961
961
 
962
- return SearchResults(edges=edges, nodes=nodes, episodes=[], communities=[])
962
+ return SearchResults(edges=edges, nodes=nodes)
963
963
 
964
964
  async def add_triplet(self, source_node: EntityNode, edge: EntityEdge, target_node: EntityNode):
965
965
  if source_node.name_embedding is None:
@@ -80,12 +80,7 @@ async def search(
80
80
  cross_encoder = clients.cross_encoder
81
81
 
82
82
  if query.strip() == '':
83
- return SearchResults(
84
- edges=[],
85
- nodes=[],
86
- episodes=[],
87
- communities=[],
88
- )
83
+ return SearchResults()
89
84
  query_vector = (
90
85
  query_vector
91
86
  if query_vector is not None
@@ -94,7 +89,12 @@ async def search(
94
89
 
95
90
  # if group_ids is empty, set it to None
96
91
  group_ids = group_ids if group_ids and group_ids != [''] else None
97
- edges, nodes, episodes, communities = await semaphore_gather(
92
+ (
93
+ (edges, edge_reranker_scores),
94
+ (nodes, node_reranker_scores),
95
+ (episodes, episode_reranker_scores),
96
+ (communities, community_reranker_scores),
97
+ ) = await semaphore_gather(
98
98
  edge_search(
99
99
  driver,
100
100
  cross_encoder,
@@ -146,9 +146,13 @@ async def search(
146
146
 
147
147
  results = SearchResults(
148
148
  edges=edges,
149
+ edge_reranker_scores=edge_reranker_scores,
149
150
  nodes=nodes,
151
+ node_reranker_scores=node_reranker_scores,
150
152
  episodes=episodes,
153
+ episode_reranker_scores=episode_reranker_scores,
151
154
  communities=communities,
155
+ community_reranker_scores=community_reranker_scores,
152
156
  )
153
157
 
154
158
  latency = (time() - start) * 1000
@@ -170,9 +174,9 @@ async def edge_search(
170
174
  bfs_origin_node_uuids: list[str] | None = None,
171
175
  limit=DEFAULT_SEARCH_LIMIT,
172
176
  reranker_min_score: float = 0,
173
- ) -> list[EntityEdge]:
177
+ ) -> tuple[list[EntityEdge], list[float]]:
174
178
  if config is None:
175
- return []
179
+ return [], []
176
180
  search_results: list[list[EntityEdge]] = list(
177
181
  await semaphore_gather(
178
182
  *[
@@ -188,7 +192,12 @@ async def edge_search(
188
192
  config.sim_min_score,
189
193
  ),
190
194
  edge_bfs_search(
191
- driver, bfs_origin_node_uuids, config.bfs_max_depth, search_filter, 2 * limit
195
+ driver,
196
+ bfs_origin_node_uuids,
197
+ config.bfs_max_depth,
198
+ search_filter,
199
+ group_ids,
200
+ 2 * limit,
192
201
  ),
193
202
  ]
194
203
  )
@@ -198,22 +207,28 @@ async def edge_search(
198
207
  source_node_uuids = [edge.source_node_uuid for result in search_results for edge in result]
199
208
  search_results.append(
200
209
  await edge_bfs_search(
201
- driver, source_node_uuids, config.bfs_max_depth, search_filter, 2 * limit
210
+ driver,
211
+ source_node_uuids,
212
+ config.bfs_max_depth,
213
+ search_filter,
214
+ group_ids,
215
+ 2 * limit,
202
216
  )
203
217
  )
204
218
 
205
219
  edge_uuid_map = {edge.uuid: edge for result in search_results for edge in result}
206
220
 
207
221
  reranked_uuids: list[str] = []
222
+ edge_scores: list[float] = []
208
223
  if config.reranker == EdgeReranker.rrf or config.reranker == EdgeReranker.episode_mentions:
209
224
  search_result_uuids = [[edge.uuid for edge in result] for result in search_results]
210
225
 
211
- reranked_uuids = rrf(search_result_uuids, min_score=reranker_min_score)
226
+ reranked_uuids, edge_scores = rrf(search_result_uuids, min_score=reranker_min_score)
212
227
  elif config.reranker == EdgeReranker.mmr:
213
228
  search_result_uuids_and_vectors = await get_embeddings_for_edges(
214
229
  driver, list(edge_uuid_map.values())
215
230
  )
216
- reranked_uuids = maximal_marginal_relevance(
231
+ reranked_uuids, edge_scores = maximal_marginal_relevance(
217
232
  query_vector,
218
233
  search_result_uuids_and_vectors,
219
234
  config.mmr_lambda,
@@ -225,12 +240,13 @@ async def edge_search(
225
240
  reranked_uuids = [
226
241
  fact_to_uuid_map[fact] for fact, score in reranked_facts if score >= reranker_min_score
227
242
  ]
243
+ edge_scores = [score for _, score in reranked_facts if score >= reranker_min_score]
228
244
  elif config.reranker == EdgeReranker.node_distance:
229
245
  if center_node_uuid is None:
230
246
  raise SearchRerankerError('No center node provided for Node Distance reranker')
231
247
 
232
248
  # use rrf as a preliminary sort
233
- sorted_result_uuids = rrf(
249
+ sorted_result_uuids, node_scores = rrf(
234
250
  [[edge.uuid for edge in result] for result in search_results],
235
251
  min_score=reranker_min_score,
236
252
  )
@@ -243,7 +259,7 @@ async def edge_search(
243
259
 
244
260
  source_uuids = [source_node_uuid for source_node_uuid in source_to_edge_uuid_map]
245
261
 
246
- reranked_node_uuids = await node_distance_reranker(
262
+ reranked_node_uuids, edge_scores = await node_distance_reranker(
247
263
  driver, source_uuids, center_node_uuid, min_score=reranker_min_score
248
264
  )
249
265
 
@@ -255,7 +271,7 @@ async def edge_search(
255
271
  if config.reranker == EdgeReranker.episode_mentions:
256
272
  reranked_edges.sort(reverse=True, key=lambda edge: len(edge.episodes))
257
273
 
258
- return reranked_edges[:limit]
274
+ return reranked_edges[:limit], edge_scores[:limit]
259
275
 
260
276
 
261
277
  async def node_search(
@@ -270,9 +286,9 @@ async def node_search(
270
286
  bfs_origin_node_uuids: list[str] | None = None,
271
287
  limit=DEFAULT_SEARCH_LIMIT,
272
288
  reranker_min_score: float = 0,
273
- ) -> list[EntityNode]:
289
+ ) -> tuple[list[EntityNode], list[float]]:
274
290
  if config is None:
275
- return []
291
+ return [], []
276
292
  search_results: list[list[EntityNode]] = list(
277
293
  await semaphore_gather(
278
294
  *[
@@ -281,7 +297,12 @@ async def node_search(
281
297
  driver, query_vector, search_filter, group_ids, 2 * limit, config.sim_min_score
282
298
  ),
283
299
  node_bfs_search(
284
- driver, bfs_origin_node_uuids, search_filter, config.bfs_max_depth, 2 * limit
300
+ driver,
301
+ bfs_origin_node_uuids,
302
+ search_filter,
303
+ config.bfs_max_depth,
304
+ group_ids,
305
+ 2 * limit,
285
306
  ),
286
307
  ]
287
308
  )
@@ -291,7 +312,12 @@ async def node_search(
291
312
  origin_node_uuids = [node.uuid for result in search_results for node in result]
292
313
  search_results.append(
293
314
  await node_bfs_search(
294
- driver, origin_node_uuids, search_filter, config.bfs_max_depth, 2 * limit
315
+ driver,
316
+ origin_node_uuids,
317
+ search_filter,
318
+ config.bfs_max_depth,
319
+ group_ids,
320
+ 2 * limit,
295
321
  )
296
322
  )
297
323
 
@@ -299,14 +325,15 @@ async def node_search(
299
325
  node_uuid_map = {node.uuid: node for result in search_results for node in result}
300
326
 
301
327
  reranked_uuids: list[str] = []
328
+ node_scores: list[float] = []
302
329
  if config.reranker == NodeReranker.rrf:
303
- reranked_uuids = rrf(search_result_uuids, min_score=reranker_min_score)
330
+ reranked_uuids, node_scores = rrf(search_result_uuids, min_score=reranker_min_score)
304
331
  elif config.reranker == NodeReranker.mmr:
305
332
  search_result_uuids_and_vectors = await get_embeddings_for_nodes(
306
333
  driver, list(node_uuid_map.values())
307
334
  )
308
335
 
309
- reranked_uuids = maximal_marginal_relevance(
336
+ reranked_uuids, node_scores = maximal_marginal_relevance(
310
337
  query_vector,
311
338
  search_result_uuids_and_vectors,
312
339
  config.mmr_lambda,
@@ -321,23 +348,24 @@ async def node_search(
321
348
  for name, score in reranked_node_names
322
349
  if score >= reranker_min_score
323
350
  ]
351
+ node_scores = [score for _, score in reranked_node_names if score >= reranker_min_score]
324
352
  elif config.reranker == NodeReranker.episode_mentions:
325
- reranked_uuids = await episode_mentions_reranker(
353
+ reranked_uuids, node_scores = await episode_mentions_reranker(
326
354
  driver, search_result_uuids, min_score=reranker_min_score
327
355
  )
328
356
  elif config.reranker == NodeReranker.node_distance:
329
357
  if center_node_uuid is None:
330
358
  raise SearchRerankerError('No center node provided for Node Distance reranker')
331
- reranked_uuids = await node_distance_reranker(
359
+ reranked_uuids, node_scores = await node_distance_reranker(
332
360
  driver,
333
- rrf(search_result_uuids, min_score=reranker_min_score),
361
+ rrf(search_result_uuids, min_score=reranker_min_score)[0],
334
362
  center_node_uuid,
335
363
  min_score=reranker_min_score,
336
364
  )
337
365
 
338
366
  reranked_nodes = [node_uuid_map[uuid] for uuid in reranked_uuids]
339
367
 
340
- return reranked_nodes[:limit]
368
+ return reranked_nodes[:limit], node_scores[:limit]
341
369
 
342
370
 
343
371
  async def episode_search(
@@ -350,9 +378,9 @@ async def episode_search(
350
378
  search_filter: SearchFilters,
351
379
  limit=DEFAULT_SEARCH_LIMIT,
352
380
  reranker_min_score: float = 0,
353
- ) -> list[EpisodicNode]:
381
+ ) -> tuple[list[EpisodicNode], list[float]]:
354
382
  if config is None:
355
- return []
383
+ return [], []
356
384
  search_results: list[list[EpisodicNode]] = list(
357
385
  await semaphore_gather(
358
386
  *[
@@ -365,12 +393,13 @@ async def episode_search(
365
393
  episode_uuid_map = {episode.uuid: episode for result in search_results for episode in result}
366
394
 
367
395
  reranked_uuids: list[str] = []
396
+ episode_scores: list[float] = []
368
397
  if config.reranker == EpisodeReranker.rrf:
369
- reranked_uuids = rrf(search_result_uuids, min_score=reranker_min_score)
398
+ reranked_uuids, episode_scores = rrf(search_result_uuids, min_score=reranker_min_score)
370
399
 
371
400
  elif config.reranker == EpisodeReranker.cross_encoder:
372
401
  # use rrf as a preliminary reranker
373
- rrf_result_uuids = rrf(search_result_uuids, min_score=reranker_min_score)
402
+ rrf_result_uuids, episode_scores = rrf(search_result_uuids, min_score=reranker_min_score)
374
403
  rrf_results = [episode_uuid_map[uuid] for uuid in rrf_result_uuids][:limit]
375
404
 
376
405
  content_to_uuid_map = {episode.content: episode.uuid for episode in rrf_results}
@@ -381,10 +410,11 @@ async def episode_search(
381
410
  for content, score in reranked_contents
382
411
  if score >= reranker_min_score
383
412
  ]
413
+ episode_scores = [score for _, score in reranked_contents if score >= reranker_min_score]
384
414
 
385
415
  reranked_episodes = [episode_uuid_map[uuid] for uuid in reranked_uuids]
386
416
 
387
- return reranked_episodes[:limit]
417
+ return reranked_episodes[:limit], episode_scores[:limit]
388
418
 
389
419
 
390
420
  async def community_search(
@@ -396,9 +426,9 @@ async def community_search(
396
426
  config: CommunitySearchConfig | None,
397
427
  limit=DEFAULT_SEARCH_LIMIT,
398
428
  reranker_min_score: float = 0,
399
- ) -> list[CommunityNode]:
429
+ ) -> tuple[list[CommunityNode], list[float]]:
400
430
  if config is None:
401
- return []
431
+ return [], []
402
432
 
403
433
  search_results: list[list[CommunityNode]] = list(
404
434
  await semaphore_gather(
@@ -417,14 +447,15 @@ async def community_search(
417
447
  }
418
448
 
419
449
  reranked_uuids: list[str] = []
450
+ community_scores: list[float] = []
420
451
  if config.reranker == CommunityReranker.rrf:
421
- reranked_uuids = rrf(search_result_uuids, min_score=reranker_min_score)
452
+ reranked_uuids, community_scores = rrf(search_result_uuids, min_score=reranker_min_score)
422
453
  elif config.reranker == CommunityReranker.mmr:
423
454
  search_result_uuids_and_vectors = await get_embeddings_for_communities(
424
455
  driver, list(community_uuid_map.values())
425
456
  )
426
457
 
427
- reranked_uuids = maximal_marginal_relevance(
458
+ reranked_uuids, community_scores = maximal_marginal_relevance(
428
459
  query_vector, search_result_uuids_and_vectors, config.mmr_lambda, reranker_min_score
429
460
  )
430
461
  elif config.reranker == CommunityReranker.cross_encoder:
@@ -433,7 +464,8 @@ async def community_search(
433
464
  reranked_uuids = [
434
465
  name_to_uuid_map[name] for name, score in reranked_nodes if score >= reranker_min_score
435
466
  ]
467
+ community_scores = [score for _, score in reranked_nodes if score >= reranker_min_score]
436
468
 
437
469
  reranked_communities = [community_uuid_map[uuid] for uuid in reranked_uuids]
438
470
 
439
- return reranked_communities[:limit]
471
+ return reranked_communities[:limit], community_scores[:limit]
@@ -119,7 +119,11 @@ class SearchConfig(BaseModel):
119
119
 
120
120
 
121
121
  class SearchResults(BaseModel):
122
- edges: list[EntityEdge]
123
- nodes: list[EntityNode]
124
- episodes: list[EpisodicNode]
125
- communities: list[CommunityNode]
122
+ edges: list[EntityEdge] = Field(default_factory=list)
123
+ edge_reranker_scores: list[float] = Field(default_factory=list)
124
+ nodes: list[EntityNode] = Field(default_factory=list)
125
+ node_reranker_scores: list[float] = Field(default_factory=list)
126
+ episodes: list[EpisodicNode] = Field(default_factory=list)
127
+ episode_reranker_scores: list[float] = Field(default_factory=list)
128
+ communities: list[CommunityNode] = Field(default_factory=list)
129
+ community_reranker_scores: list[float] = Field(default_factory=list)
@@ -283,7 +283,8 @@ async def edge_bfs_search(
283
283
  bfs_origin_node_uuids: list[str] | None,
284
284
  bfs_max_depth: int,
285
285
  search_filter: SearchFilters,
286
- limit: int,
286
+ group_ids: list[str] | None = None,
287
+ limit: int = RELEVANT_SCHEMA_LIMIT,
287
288
  ) -> list[EntityEdge]:
288
289
  # vector similarity search over embedded facts
289
290
  if bfs_origin_node_uuids is None:
@@ -293,12 +294,13 @@ async def edge_bfs_search(
293
294
 
294
295
  query = (
295
296
  """
296
- UNWIND $bfs_origin_node_uuids AS origin_uuid
297
- MATCH path = (origin:Entity|Episodic {uuid: origin_uuid})-[:RELATES_TO|MENTIONS]->{1,3}(n:Entity)
298
- UNWIND relationships(path) AS rel
299
- MATCH (n:Entity)-[r:RELATES_TO]-(m:Entity)
300
- WHERE r.uuid = rel.uuid
301
- """
297
+ UNWIND $bfs_origin_node_uuids AS origin_uuid
298
+ MATCH path = (origin:Entity|Episodic {uuid: origin_uuid})-[:RELATES_TO|MENTIONS]->{1,3}(n:Entity)
299
+ UNWIND relationships(path) AS rel
300
+ MATCH (n:Entity)-[r:RELATES_TO]-(m:Entity)
301
+ WHERE r.uuid = rel.uuid
302
+ AND r.group_id IN $group_ids
303
+ """
302
304
  + filter_query
303
305
  + """
304
306
  RETURN DISTINCT
@@ -323,6 +325,7 @@ async def edge_bfs_search(
323
325
  params=filter_params,
324
326
  bfs_origin_node_uuids=bfs_origin_node_uuids,
325
327
  depth=bfs_max_depth,
328
+ group_ids=group_ids,
326
329
  limit=limit,
327
330
  routing_='r',
328
331
  )
@@ -431,7 +434,8 @@ async def node_bfs_search(
431
434
  bfs_origin_node_uuids: list[str] | None,
432
435
  search_filter: SearchFilters,
433
436
  bfs_max_depth: int,
434
- limit: int,
437
+ group_ids: list[str] | None = None,
438
+ limit: int = RELEVANT_SCHEMA_LIMIT,
435
439
  ) -> list[EntityNode]:
436
440
  # vector similarity search over entity names
437
441
  if bfs_origin_node_uuids is None:
@@ -441,10 +445,11 @@ async def node_bfs_search(
441
445
 
442
446
  query = (
443
447
  """
444
- UNWIND $bfs_origin_node_uuids AS origin_uuid
445
- MATCH (origin:Entity|Episodic {uuid: origin_uuid})-[:RELATES_TO|MENTIONS]->{1,3}(n:Entity)
446
- WHERE n.group_id = origin.group_id
447
- """
448
+ UNWIND $bfs_origin_node_uuids AS origin_uuid
449
+ MATCH (origin:Entity|Episodic {uuid: origin_uuid})-[:RELATES_TO|MENTIONS]->{1,3}(n:Entity)
450
+ WHERE n.group_id = origin.group_id
451
+ AND origin.group_id IN $group_ids
452
+ """
448
453
  + filter_query
449
454
  + ENTITY_NODE_RETURN
450
455
  + """
@@ -456,6 +461,7 @@ async def node_bfs_search(
456
461
  params=filter_params,
457
462
  bfs_origin_node_uuids=bfs_origin_node_uuids,
458
463
  depth=bfs_max_depth,
464
+ group_ids=group_ids,
459
465
  limit=limit,
460
466
  routing_='r',
461
467
  )
@@ -482,6 +488,7 @@ async def episode_fulltext_search(
482
488
  YIELD node AS episode, score
483
489
  MATCH (e:Episodic)
484
490
  WHERE e.uuid = episode.uuid
491
+ AND e.group_id IN $group_ids
485
492
  RETURN
486
493
  e.content AS content,
487
494
  e.created_at AS created_at,
@@ -524,6 +531,7 @@ async def community_fulltext_search(
524
531
  get_nodes_query(driver.provider, 'community_name', '$query')
525
532
  + """
526
533
  YIELD node AS comm, score
534
+ WHERE comm.group_id IN $group_ids
527
535
  RETURN
528
536
  comm.uuid AS uuid,
529
537
  comm.group_id AS group_id,
@@ -664,7 +672,7 @@ async def hybrid_node_search(
664
672
  }
665
673
  result_uuids = [[node.uuid for node in result] for result in results]
666
674
 
667
- ranked_uuids = rrf(result_uuids)
675
+ ranked_uuids, _ = rrf(result_uuids)
668
676
 
669
677
  relevant_nodes: list[EntityNode] = [node_uuid_map[uuid] for uuid in ranked_uuids]
670
678
 
@@ -906,7 +914,9 @@ async def get_edge_invalidation_candidates(
906
914
 
907
915
 
908
916
  # takes in a list of rankings of uuids
909
- def rrf(results: list[list[str]], rank_const=1, min_score: float = 0) -> list[str]:
917
+ def rrf(
918
+ results: list[list[str]], rank_const=1, min_score: float = 0
919
+ ) -> tuple[list[str], list[float]]:
910
920
  scores: dict[str, float] = defaultdict(float)
911
921
  for result in results:
912
922
  for i, uuid in enumerate(result):
@@ -917,7 +927,9 @@ def rrf(results: list[list[str]], rank_const=1, min_score: float = 0) -> list[st
917
927
 
918
928
  sorted_uuids = [term[0] for term in scored_uuids]
919
929
 
920
- return [uuid for uuid in sorted_uuids if scores[uuid] >= min_score]
930
+ return [uuid for uuid in sorted_uuids if scores[uuid] >= min_score], [
931
+ scores[uuid] for uuid in sorted_uuids if scores[uuid] >= min_score
932
+ ]
921
933
 
922
934
 
923
935
  async def node_distance_reranker(
@@ -925,7 +937,7 @@ async def node_distance_reranker(
925
937
  node_uuids: list[str],
926
938
  center_node_uuid: str,
927
939
  min_score: float = 0,
928
- ) -> list[str]:
940
+ ) -> tuple[list[str], list[float]]:
929
941
  # filter out node_uuid center node node uuid
930
942
  filtered_uuids = list(filter(lambda node_uuid: node_uuid != center_node_uuid, node_uuids))
931
943
  scores: dict[str, float] = {center_node_uuid: 0.0}
@@ -962,14 +974,16 @@ async def node_distance_reranker(
962
974
  scores[center_node_uuid] = 0.1
963
975
  filtered_uuids = [center_node_uuid] + filtered_uuids
964
976
 
965
- return [uuid for uuid in filtered_uuids if (1 / scores[uuid]) >= min_score]
977
+ return [uuid for uuid in filtered_uuids if (1 / scores[uuid]) >= min_score], [
978
+ 1 / scores[uuid] for uuid in filtered_uuids if (1 / scores[uuid]) >= min_score
979
+ ]
966
980
 
967
981
 
968
982
  async def episode_mentions_reranker(
969
983
  driver: GraphDriver, node_uuids: list[list[str]], min_score: float = 0
970
- ) -> list[str]:
984
+ ) -> tuple[list[str], list[float]]:
971
985
  # use rrf as a preliminary ranker
972
- sorted_uuids = rrf(node_uuids)
986
+ sorted_uuids, _ = rrf(node_uuids)
973
987
  scores: dict[str, float] = {}
974
988
 
975
989
  # Find the shortest path to center node
@@ -990,7 +1004,9 @@ async def episode_mentions_reranker(
990
1004
  # rerank on shortest distance
991
1005
  sorted_uuids.sort(key=lambda cur_uuid: scores[cur_uuid])
992
1006
 
993
- return [uuid for uuid in sorted_uuids if scores[uuid] >= min_score]
1007
+ return [uuid for uuid in sorted_uuids if scores[uuid] >= min_score], [
1008
+ scores[uuid] for uuid in sorted_uuids if scores[uuid] >= min_score
1009
+ ]
994
1010
 
995
1011
 
996
1012
  def maximal_marginal_relevance(
@@ -998,7 +1014,7 @@ def maximal_marginal_relevance(
998
1014
  candidates: dict[str, list[float]],
999
1015
  mmr_lambda: float = DEFAULT_MMR_LAMBDA,
1000
1016
  min_score: float = -2.0,
1001
- ) -> list[str]:
1017
+ ) -> tuple[list[str], list[float]]:
1002
1018
  start = time()
1003
1019
  query_array = np.array(query_vector)
1004
1020
  candidate_arrays: dict[str, NDArray] = {}
@@ -1029,7 +1045,9 @@ def maximal_marginal_relevance(
1029
1045
  end = time()
1030
1046
  logger.debug(f'Completed MMR reranking in {(end - start) * 1000} ms')
1031
1047
 
1032
- return [uuid for uuid in uuids if mmr_scores[uuid] >= min_score]
1048
+ return [uuid for uuid in uuids if mmr_scores[uuid] >= min_score], [
1049
+ mmr_scores[uuid] for uuid in uuids if mmr_scores[uuid] >= min_score
1050
+ ]
1033
1051
 
1034
1052
 
1035
1053
  async def get_embeddings_for_nodes(
@@ -1,7 +1,7 @@
1
1
  [project]
2
2
  name = "graphiti-core"
3
3
  description = "A temporal graph building library"
4
- version = "0.17.10"
4
+ version = "0.18.0"
5
5
  authors = [
6
6
  { "name" = "Paul Paliychuk", "email" = "paul@getzep.com" },
7
7
  { "name" = "Preston Rasmussen", "email" = "preston@getzep.com" },
@@ -71,7 +71,7 @@ async def test_graphiti_init():
71
71
  )
72
72
 
73
73
  results = await graphiti.search_(
74
- query='What is the hall of portrait?',
74
+ query='Who is Tania',
75
75
  search_filter=search_filter,
76
76
  )
77
77
 
@@ -746,7 +746,7 @@ wheels = [
746
746
 
747
747
  [[package]]
748
748
  name = "graphiti-core"
749
- version = "0.17.10"
749
+ version = "0.18.0"
750
750
  source = { editable = "." }
751
751
  dependencies = [
752
752
  { name = "diskcache" },
File without changes
File without changes