graphiti-core 0.30.0rc1__tar.gz → 0.30.0rc3__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 (192) hide show
  1. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/PKG-INFO +1 -1
  2. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/prompts/dedupe_nodes.py +42 -26
  3. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/utils/maintenance/node_operations.py +33 -6
  4. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/pyproject.toml +1 -1
  5. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/tests/utils/maintenance/test_node_operations.py +134 -0
  6. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/uv.lock +1 -1
  7. graphiti_core-0.30.0rc1/poetry.lock +0 -5627
  8. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/.env.example +0 -0
  9. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  10. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/.github/dependabot.yml +0 -0
  11. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/.github/pull_request_template.md +0 -0
  12. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/.github/secret_scanning.yml +0 -0
  13. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/.github/workflows/ai-moderator.yml +0 -0
  14. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/.github/workflows/cla.yml +0 -0
  15. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/.github/workflows/claude-code-review.yml +0 -0
  16. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/.github/workflows/claude.yml +0 -0
  17. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/.github/workflows/codeql.yml +0 -0
  18. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/.github/workflows/lint.yml +0 -0
  19. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/.github/workflows/mcp-server-docker.yml +0 -0
  20. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/.github/workflows/release-graphiti-core.yml +0 -0
  21. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/.github/workflows/typecheck.yml +0 -0
  22. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/.github/workflows/unit_tests.yml +0 -0
  23. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/.gitignore +0 -0
  24. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/AGENTS.md +0 -0
  25. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/CLAUDE.md +0 -0
  26. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/CODE_OF_CONDUCT.md +0 -0
  27. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/CONTRIBUTING.md +0 -0
  28. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/Dockerfile +0 -0
  29. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/LICENSE +0 -0
  30. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/Makefile +0 -0
  31. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/README.md +0 -0
  32. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/SECURITY.md +0 -0
  33. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/Zep-CLA.md +0 -0
  34. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/conftest.py +0 -0
  35. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/depot.json +0 -0
  36. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/docker-compose.test.yml +0 -0
  37. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/docker-compose.yml +0 -0
  38. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/ellipsis.yaml +0 -0
  39. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/examples/data/manybirds_products.json +0 -0
  40. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/examples/ecommerce/runner.ipynb +0 -0
  41. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/examples/ecommerce/runner.py +0 -0
  42. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/examples/langgraph-agent/agent.ipynb +0 -0
  43. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/examples/langgraph-agent/tinybirds-jess.png +0 -0
  44. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/examples/podcast/podcast_runner.py +0 -0
  45. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/examples/podcast/podcast_transcript.txt +0 -0
  46. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/examples/podcast/transcript_parser.py +0 -0
  47. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/examples/quickstart/README.md +0 -0
  48. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/examples/quickstart/quickstart_falkordb.py +0 -0
  49. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/examples/quickstart/quickstart_neo4j.py +0 -0
  50. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/examples/quickstart/quickstart_neptune.py +0 -0
  51. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/examples/quickstart/requirements.txt +0 -0
  52. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/examples/wizard_of_oz/parser.py +0 -0
  53. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/examples/wizard_of_oz/runner.py +0 -0
  54. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/examples/wizard_of_oz/woo.txt +0 -0
  55. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/__init__.py +0 -0
  56. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/cross_encoder/__init__.py +0 -0
  57. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/cross_encoder/bge_reranker_client.py +0 -0
  58. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/cross_encoder/client.py +0 -0
  59. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/cross_encoder/gemini_reranker_client.py +0 -0
  60. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/cross_encoder/openai_reranker_client.py +0 -0
  61. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/driver/__init__.py +0 -0
  62. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/driver/driver.py +0 -0
  63. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/driver/falkordb_driver.py +0 -0
  64. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/driver/kuzu_driver.py +0 -0
  65. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/driver/neo4j_driver.py +0 -0
  66. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/driver/neptune_driver.py +0 -0
  67. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/edges.py +0 -0
  68. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/embedder/__init__.py +0 -0
  69. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/embedder/azure_openai.py +0 -0
  70. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/embedder/client.py +0 -0
  71. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/embedder/gemini.py +0 -0
  72. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/embedder/openai.py +0 -0
  73. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/embedder/voyage.py +0 -0
  74. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/errors.py +0 -0
  75. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/graph_queries.py +0 -0
  76. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/graphiti.py +0 -0
  77. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/graphiti_types.py +0 -0
  78. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/helpers.py +0 -0
  79. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/llm_client/__init__.py +0 -0
  80. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/llm_client/anthropic_client.py +0 -0
  81. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/llm_client/azure_openai_client.py +0 -0
  82. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/llm_client/client.py +0 -0
  83. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/llm_client/config.py +0 -0
  84. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/llm_client/errors.py +0 -0
  85. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/llm_client/gemini_client.py +0 -0
  86. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/llm_client/groq_client.py +0 -0
  87. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/llm_client/openai_base_client.py +0 -0
  88. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/llm_client/openai_client.py +0 -0
  89. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/llm_client/openai_generic_client.py +0 -0
  90. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/llm_client/utils.py +0 -0
  91. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/migrations/__init__.py +0 -0
  92. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/models/__init__.py +0 -0
  93. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/models/edges/__init__.py +0 -0
  94. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/models/edges/edge_db_queries.py +0 -0
  95. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/models/nodes/__init__.py +0 -0
  96. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/models/nodes/node_db_queries.py +0 -0
  97. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/nodes.py +0 -0
  98. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/prompts/__init__.py +0 -0
  99. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/prompts/dedupe_edges.py +0 -0
  100. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/prompts/eval.py +0 -0
  101. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/prompts/extract_edge_dates.py +0 -0
  102. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/prompts/extract_edges.py +0 -0
  103. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/prompts/extract_nodes.py +0 -0
  104. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/prompts/invalidate_edges.py +0 -0
  105. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/prompts/lib.py +0 -0
  106. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/prompts/models.py +0 -0
  107. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/prompts/prompt_helpers.py +0 -0
  108. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/prompts/summarize_nodes.py +0 -0
  109. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/py.typed +0 -0
  110. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/search/__init__.py +0 -0
  111. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/search/search.py +0 -0
  112. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/search/search_config.py +0 -0
  113. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/search/search_config_recipes.py +0 -0
  114. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/search/search_filters.py +0 -0
  115. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/search/search_helpers.py +0 -0
  116. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/search/search_utils.py +0 -0
  117. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/telemetry/__init__.py +0 -0
  118. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/telemetry/telemetry.py +0 -0
  119. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/utils/__init__.py +0 -0
  120. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/utils/bulk_utils.py +0 -0
  121. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/utils/datetime_utils.py +0 -0
  122. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/utils/maintenance/__init__.py +0 -0
  123. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/utils/maintenance/community_operations.py +0 -0
  124. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/utils/maintenance/dedup_helpers.py +0 -0
  125. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/utils/maintenance/edge_operations.py +0 -0
  126. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/utils/maintenance/graph_data_operations.py +0 -0
  127. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/utils/maintenance/temporal_operations.py +0 -0
  128. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/utils/maintenance/utils.py +0 -0
  129. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/graphiti_core/utils/ontology_utils/entity_types_utils.py +0 -0
  130. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/images/arxiv-screenshot.png +0 -0
  131. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/images/graphiti-graph-intro.gif +0 -0
  132. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/images/graphiti-intro-slides-stock-2.gif +0 -0
  133. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/images/simple_graph.svg +0 -0
  134. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/mcp_server/.env.example +0 -0
  135. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/mcp_server/.python-version +0 -0
  136. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/mcp_server/Dockerfile +0 -0
  137. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/mcp_server/README.md +0 -0
  138. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/mcp_server/cursor_rules.md +0 -0
  139. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/mcp_server/docker-compose.yml +0 -0
  140. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/mcp_server/graphiti_mcp_server.py +0 -0
  141. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/mcp_server/mcp_config_sse_example.json +0 -0
  142. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/mcp_server/mcp_config_stdio_example.json +0 -0
  143. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/mcp_server/pyproject.toml +0 -0
  144. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/mcp_server/uv.lock +0 -0
  145. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/py.typed +0 -0
  146. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/pytest.ini +0 -0
  147. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/server/.env.example +0 -0
  148. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/server/Makefile +0 -0
  149. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/server/README.md +0 -0
  150. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/server/graph_service/__init__.py +0 -0
  151. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/server/graph_service/config.py +0 -0
  152. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/server/graph_service/dto/__init__.py +0 -0
  153. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/server/graph_service/dto/common.py +0 -0
  154. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/server/graph_service/dto/ingest.py +0 -0
  155. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/server/graph_service/dto/retrieve.py +0 -0
  156. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/server/graph_service/main.py +0 -0
  157. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/server/graph_service/routers/__init__.py +0 -0
  158. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/server/graph_service/routers/ingest.py +0 -0
  159. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/server/graph_service/routers/retrieve.py +0 -0
  160. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/server/graph_service/zep_graphiti.py +0 -0
  161. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/server/pyproject.toml +0 -0
  162. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/server/uv.lock +0 -0
  163. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/signatures/version1/cla.json +0 -0
  164. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/tests/cross_encoder/test_bge_reranker_client.py +0 -0
  165. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/tests/cross_encoder/test_gemini_reranker_client.py +0 -0
  166. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/tests/driver/__init__.py +0 -0
  167. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/tests/driver/test_falkordb_driver.py +0 -0
  168. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/tests/embedder/embedder_fixtures.py +0 -0
  169. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/tests/embedder/test_gemini.py +0 -0
  170. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/tests/embedder/test_openai.py +0 -0
  171. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/tests/embedder/test_voyage.py +0 -0
  172. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/tests/evals/data/longmemeval_data/README.md +0 -0
  173. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/tests/evals/data/longmemeval_data/longmemeval_oracle.json +0 -0
  174. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/tests/evals/eval_cli.py +0 -0
  175. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/tests/evals/eval_e2e_graph_building.py +0 -0
  176. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/tests/evals/pytest.ini +0 -0
  177. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/tests/evals/utils.py +0 -0
  178. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/tests/helpers_test.py +0 -0
  179. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/tests/llm_client/test_anthropic_client.py +0 -0
  180. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/tests/llm_client/test_anthropic_client_int.py +0 -0
  181. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/tests/llm_client/test_client.py +0 -0
  182. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/tests/llm_client/test_errors.py +0 -0
  183. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/tests/llm_client/test_gemini_client.py +0 -0
  184. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/tests/test_edge_int.py +0 -0
  185. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/tests/test_entity_exclusion_int.py +0 -0
  186. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/tests/test_graphiti_int.py +0 -0
  187. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/tests/test_graphiti_mock.py +0 -0
  188. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/tests/test_node_int.py +0 -0
  189. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/tests/utils/maintenance/test_bulk_utils.py +0 -0
  190. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/tests/utils/maintenance/test_edge_operations.py +0 -0
  191. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/tests/utils/maintenance/test_temporal_operations_int.py +0 -0
  192. {graphiti_core-0.30.0rc1 → graphiti_core-0.30.0rc3}/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.30.0rc1
3
+ Version: 0.30.0rc3
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
@@ -92,12 +92,23 @@ def node(context: dict[str, Any]) -> list[Message]:
92
92
 
93
93
  TASK:
94
94
  1. Compare `new_entity` against each item in `existing_entities`.
95
- 2. If it refers to the same realworld object or concept, collect its index.
96
- 3. Let `duplicate_idx` = the *first* collected index, or 1 if none.
97
- 4. Let `duplicates` = the list of *all* collected indices (empty list if none).
98
-
99
- Also return the full name of the NEW ENTITY (whether it is the name of the NEW ENTITY, a node it
100
- is a duplicate of, or a combination of the two).
95
+ 2. If it refers to the same real-world object or concept, collect its index.
96
+ 3. Let `duplicate_idx` = the smallest collected index, or -1 if none.
97
+ 4. Let `duplicates` = the sorted list of all collected indices (empty list if none).
98
+
99
+ Respond with a JSON object containing an "entity_resolutions" array with a single entry:
100
+ {{
101
+ "entity_resolutions": [
102
+ {{
103
+ "id": integer id from NEW ENTITY,
104
+ "name": the best full name for the entity,
105
+ "duplicate_idx": integer index of the best duplicate in EXISTING ENTITIES, or -1 if none,
106
+ "duplicates": sorted list of all duplicate indices you collected (deduplicate the list, use [] when none)
107
+ }}
108
+ ]
109
+ }}
110
+
111
+ Only reference indices that appear in EXISTING ENTITIES, and return [] / -1 when unsure.
101
112
  """,
102
113
  ),
103
114
  ]
@@ -126,26 +137,26 @@ def nodes(context: dict[str, Any]) -> list[Message]:
126
137
  {{
127
138
  id: integer id of the entity,
128
139
  name: "name of the entity",
129
- entity_type: "ontological classification of the entity",
130
- entity_type_description: "Description of what the entity type represents",
131
- duplication_candidates: [
132
- {{
133
- idx: integer index of the candidate entity,
134
- name: "name of the candidate entity",
135
- entity_type: "ontological classification of the candidate entity",
136
- ...<additional attributes>
137
- }}
138
- ]
140
+ entity_type: ["Entity", "<optional additional label>", ...],
141
+ entity_type_description: "Description of what the entity type represents"
139
142
  }}
140
-
143
+
141
144
  <ENTITIES>
142
145
  {to_prompt_json(context['extracted_nodes'], ensure_ascii=context.get('ensure_ascii', True), indent=2)}
143
146
  </ENTITIES>
144
-
147
+
145
148
  <EXISTING ENTITIES>
146
149
  {to_prompt_json(context['existing_nodes'], ensure_ascii=context.get('ensure_ascii', True), indent=2)}
147
150
  </EXISTING ENTITIES>
148
151
 
152
+ Each entry in EXISTING ENTITIES is an object with the following structure:
153
+ {{
154
+ idx: integer index of the candidate entity (use this when referencing a duplicate),
155
+ name: "name of the candidate entity",
156
+ entity_types: ["Entity", "<optional additional label>", ...],
157
+ ...<additional attributes such as summaries or metadata>
158
+ }}
159
+
149
160
  For each of the above ENTITIES, determine if the entity is a duplicate of any of the EXISTING ENTITIES.
150
161
 
151
162
  Entities should only be considered duplicates if they refer to the *same real-world object or concept*.
@@ -155,14 +166,19 @@ def nodes(context: dict[str, Any]) -> list[Message]:
155
166
  - They have similar names or purposes but refer to separate instances or concepts.
156
167
 
157
168
  Task:
158
- Your response will be a list called entity_resolutions which contains one entry for each entity.
159
-
160
- For each entity, return the id of the entity as id, the name of the entity as name, and the duplicate_idx
161
- as an integer.
162
-
163
- - If an entity is a duplicate of one of the EXISTING ENTITIES, return the idx of the candidate it is a
164
- duplicate of.
165
- - If an entity is not a duplicate of one of the EXISTING ENTITIES, return the -1 as the duplication_idx
169
+ Respond with a JSON object that contains an "entity_resolutions" array with one entry for each entity in ENTITIES, ordered by the entity id.
170
+
171
+ For every entity, return an object with the following keys:
172
+ {{
173
+ "id": integer id from ENTITIES,
174
+ "name": the best full name for the entity (preserve the original name unless a duplicate has a more complete name),
175
+ "duplicate_idx": the idx of the EXISTING ENTITY that is the best duplicate match, or -1 if there is no duplicate,
176
+ "duplicates": a sorted list of all idx values from EXISTING ENTITIES that refer to duplicates (deduplicate the list, use [] when none or unsure)
177
+ }}
178
+
179
+ - Only use idx values that appear in EXISTING ENTITIES.
180
+ - Set duplicate_idx to the smallest idx you collected for that entity, or -1 if duplicates is empty.
181
+ - Never fabricate entities or indices.
166
182
  """,
167
183
  ),
168
184
  ]
@@ -241,7 +241,11 @@ async def _resolve_with_llm(
241
241
  previous_episodes: list[EpisodicNode] | None,
242
242
  entity_types: dict[str, type[BaseModel]] | None,
243
243
  ) -> None:
244
- """Escalate unresolved nodes to the dedupe prompt so the LLM can select or reject duplicates."""
244
+ """Escalate unresolved nodes to the dedupe prompt so the LLM can select or reject duplicates.
245
+
246
+ The guardrails below defensively ignore malformed or duplicate LLM responses so the
247
+ ingestion workflow remains deterministic even when the model misbehaves.
248
+ """
245
249
  if not state.unresolved_indices:
246
250
  return
247
251
 
@@ -291,18 +295,41 @@ async def _resolve_with_llm(
291
295
 
292
296
  node_resolutions: list[NodeDuplicate] = NodeResolutions(**llm_response).entity_resolutions
293
297
 
298
+ valid_relative_range = range(len(state.unresolved_indices))
299
+ processed_relative_ids: set[int] = set()
300
+
294
301
  for resolution in node_resolutions:
295
302
  relative_id: int = resolution.id
296
303
  duplicate_idx: int = resolution.duplicate_idx
297
304
 
305
+ if relative_id not in valid_relative_range:
306
+ logger.warning(
307
+ 'Skipping invalid LLM dedupe id %s (unresolved indices: %s)',
308
+ relative_id,
309
+ state.unresolved_indices,
310
+ )
311
+ continue
312
+
313
+ if relative_id in processed_relative_ids:
314
+ logger.warning('Duplicate LLM dedupe id %s received; ignoring.', relative_id)
315
+ continue
316
+ processed_relative_ids.add(relative_id)
317
+
298
318
  original_index = state.unresolved_indices[relative_id]
299
319
  extracted_node = extracted_nodes[original_index]
300
320
 
301
- resolved_node = (
302
- indexes.existing_nodes[duplicate_idx]
303
- if 0 <= duplicate_idx < len(indexes.existing_nodes)
304
- else extracted_node
305
- )
321
+ resolved_node: EntityNode
322
+ if duplicate_idx == -1:
323
+ resolved_node = extracted_node
324
+ elif 0 <= duplicate_idx < len(indexes.existing_nodes):
325
+ resolved_node = indexes.existing_nodes[duplicate_idx]
326
+ else:
327
+ logger.warning(
328
+ 'Invalid duplicate_idx %s for extracted node %s; treating as no duplicate.',
329
+ duplicate_idx,
330
+ extracted_node.uuid,
331
+ )
332
+ resolved_node = extracted_node
306
333
 
307
334
  state.resolved_nodes[original_index] = resolved_node
308
335
  state.uuid_map[extracted_node.uuid] = resolved_node.uuid
@@ -1,7 +1,7 @@
1
1
  [project]
2
2
  name = "graphiti-core"
3
3
  description = "A temporal graph building library"
4
- version = "0.30.0pre1"
4
+ version = "0.30.0pre3"
5
5
  authors = [
6
6
  { name = "Paul Paliychuk", email = "paul@getzep.com" },
7
7
  { name = "Preston Rasmussen", email = "preston@getzep.com" },
@@ -1,3 +1,4 @@
1
+ import logging
1
2
  from collections import defaultdict
2
3
  from unittest.mock import AsyncMock, MagicMock
3
4
 
@@ -343,3 +344,136 @@ async def test_resolve_with_llm_updates_unresolved(monkeypatch):
343
344
  assert captured_context['existing_nodes'][0]['idx'] == 0
344
345
  assert isinstance(captured_context['existing_nodes'], list)
345
346
  assert state.duplicate_pairs == [(extracted, candidate)]
347
+
348
+
349
+ @pytest.mark.asyncio
350
+ async def test_resolve_with_llm_ignores_out_of_range_relative_ids(monkeypatch, caplog):
351
+ extracted = EntityNode(name='Dexter', group_id='group', labels=['Entity'])
352
+
353
+ indexes = _build_candidate_indexes([])
354
+ state = DedupResolutionState(resolved_nodes=[None], uuid_map={}, unresolved_indices=[0])
355
+
356
+ monkeypatch.setattr(
357
+ 'graphiti_core.utils.maintenance.node_operations.prompt_library.dedupe_nodes.nodes',
358
+ lambda context: ['prompt'],
359
+ )
360
+
361
+ llm_client = MagicMock()
362
+ llm_client.generate_response = AsyncMock(
363
+ return_value={
364
+ 'entity_resolutions': [
365
+ {
366
+ 'id': 5,
367
+ 'duplicate_idx': -1,
368
+ 'name': 'Dexter',
369
+ 'duplicates': [],
370
+ }
371
+ ]
372
+ }
373
+ )
374
+
375
+ with caplog.at_level(logging.WARNING):
376
+ await _resolve_with_llm(
377
+ llm_client,
378
+ [extracted],
379
+ indexes,
380
+ state,
381
+ ensure_ascii=False,
382
+ episode=_make_episode(),
383
+ previous_episodes=[],
384
+ entity_types=None,
385
+ )
386
+
387
+ assert state.resolved_nodes[0] is None
388
+ assert 'Skipping invalid LLM dedupe id 5' in caplog.text
389
+
390
+
391
+ @pytest.mark.asyncio
392
+ async def test_resolve_with_llm_ignores_duplicate_relative_ids(monkeypatch):
393
+ extracted = EntityNode(name='Dizzy', group_id='group', labels=['Entity'])
394
+ candidate = EntityNode(name='Dizzy Gillespie', group_id='group', labels=['Entity'])
395
+
396
+ indexes = _build_candidate_indexes([candidate])
397
+ state = DedupResolutionState(resolved_nodes=[None], uuid_map={}, unresolved_indices=[0])
398
+
399
+ monkeypatch.setattr(
400
+ 'graphiti_core.utils.maintenance.node_operations.prompt_library.dedupe_nodes.nodes',
401
+ lambda context: ['prompt'],
402
+ )
403
+
404
+ llm_client = MagicMock()
405
+ llm_client.generate_response = AsyncMock(
406
+ return_value={
407
+ 'entity_resolutions': [
408
+ {
409
+ 'id': 0,
410
+ 'duplicate_idx': 0,
411
+ 'name': 'Dizzy Gillespie',
412
+ 'duplicates': [0],
413
+ },
414
+ {
415
+ 'id': 0,
416
+ 'duplicate_idx': -1,
417
+ 'name': 'Dizzy',
418
+ 'duplicates': [],
419
+ },
420
+ ]
421
+ }
422
+ )
423
+
424
+ await _resolve_with_llm(
425
+ llm_client,
426
+ [extracted],
427
+ indexes,
428
+ state,
429
+ ensure_ascii=False,
430
+ episode=_make_episode(),
431
+ previous_episodes=[],
432
+ entity_types=None,
433
+ )
434
+
435
+ assert state.resolved_nodes[0].uuid == candidate.uuid
436
+ assert state.uuid_map[extracted.uuid] == candidate.uuid
437
+ assert state.duplicate_pairs == [(extracted, candidate)]
438
+
439
+
440
+ @pytest.mark.asyncio
441
+ async def test_resolve_with_llm_invalid_duplicate_idx_defaults_to_extracted(monkeypatch):
442
+ extracted = EntityNode(name='Dexter', group_id='group', labels=['Entity'])
443
+
444
+ indexes = _build_candidate_indexes([])
445
+ state = DedupResolutionState(resolved_nodes=[None], uuid_map={}, unresolved_indices=[0])
446
+
447
+ monkeypatch.setattr(
448
+ 'graphiti_core.utils.maintenance.node_operations.prompt_library.dedupe_nodes.nodes',
449
+ lambda context: ['prompt'],
450
+ )
451
+
452
+ llm_client = MagicMock()
453
+ llm_client.generate_response = AsyncMock(
454
+ return_value={
455
+ 'entity_resolutions': [
456
+ {
457
+ 'id': 0,
458
+ 'duplicate_idx': 10,
459
+ 'name': 'Dexter',
460
+ 'duplicates': [],
461
+ }
462
+ ]
463
+ }
464
+ )
465
+
466
+ await _resolve_with_llm(
467
+ llm_client,
468
+ [extracted],
469
+ indexes,
470
+ state,
471
+ ensure_ascii=False,
472
+ episode=_make_episode(),
473
+ previous_episodes=[],
474
+ entity_types=None,
475
+ )
476
+
477
+ assert state.resolved_nodes[0] == extracted
478
+ assert state.uuid_map[extracted.uuid] == extracted.uuid
479
+ assert state.duplicate_pairs == []
@@ -783,7 +783,7 @@ wheels = [
783
783
 
784
784
  [[package]]
785
785
  name = "graphiti-core"
786
- version = "0.30.0rc1"
786
+ version = "0.30.0rc3"
787
787
  source = { editable = "." }
788
788
  dependencies = [
789
789
  { name = "diskcache" },