graphiti-core 0.18.8__tar.gz → 0.19.0rc1__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.
- graphiti_core-0.19.0rc1/.github/workflows/ai-moderator.yml +30 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/PKG-INFO +44 -6
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/README.md +38 -4
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/examples/podcast/podcast_runner.py +5 -1
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/examples/quickstart/README.md +16 -1
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/driver/driver.py +1 -0
- graphiti_core-0.19.0rc1/graphiti_core/driver/neptune_driver.py +299 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/edges.py +35 -7
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/graphiti.py +2 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/llm_client/config.py +1 -1
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/llm_client/openai_base_client.py +15 -5
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/llm_client/openai_client.py +16 -6
- graphiti_core-0.19.0rc1/graphiti_core/migrations/neo4j_node_group_labels.py +53 -0
- graphiti_core-0.19.0rc1/graphiti_core/models/edges/edge_db_queries.py +180 -0
- graphiti_core-0.19.0rc1/graphiti_core/models/nodes/node_db_queries.py +233 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/nodes.py +121 -51
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/prompts/extract_edges.py +1 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/prompts/extract_nodes.py +1 -1
- graphiti_core-0.19.0rc1/graphiti_core/search/search_utils.py +1690 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/utils/bulk_utils.py +6 -3
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/utils/maintenance/edge_operations.py +36 -13
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/utils/maintenance/graph_data_operations.py +59 -7
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/utils/maintenance/node_operations.py +7 -3
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/pyproject.toml +4 -3
- graphiti_core-0.19.0rc1/server/graph_service/routers/__init__.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/signatures/version1/cla.json +16 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/tests/helpers_test.py +22 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/uv.lock +160 -16
- graphiti_core-0.18.8/graphiti_core/models/edges/edge_db_queries.py +0 -130
- graphiti_core-0.18.8/graphiti_core/models/nodes/node_db_queries.py +0 -133
- graphiti_core-0.18.8/graphiti_core/search/search_utils.py +0 -1079
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/.env.example +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/.github/dependabot.yml +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/.github/pull_request_template.md +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/.github/secret_scanning.yml +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/.github/workflows/cla.yml +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/.github/workflows/claude-code-review.yml +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/.github/workflows/claude.yml +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/.github/workflows/codeql.yml +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/.github/workflows/lint.yml +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/.github/workflows/mcp-server-docker.yml +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/.github/workflows/release-graphiti-core.yml +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/.github/workflows/typecheck.yml +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/.github/workflows/unit_tests.yml +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/.gitignore +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/CLAUDE.md +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/CODE_OF_CONDUCT.md +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/CONTRIBUTING.md +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/Dockerfile +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/LICENSE +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/Makefile +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/SECURITY.md +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/Zep-CLA.md +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/conftest.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/depot.json +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/docker-compose.test.yml +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/docker-compose.yml +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/ellipsis.yaml +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/examples/data/manybirds_products.json +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/examples/ecommerce/runner.ipynb +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/examples/ecommerce/runner.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/examples/langgraph-agent/agent.ipynb +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/examples/langgraph-agent/tinybirds-jess.png +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/examples/podcast/podcast_transcript.txt +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/examples/podcast/transcript_parser.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/examples/quickstart/quickstart_falkordb.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/examples/quickstart/quickstart_neo4j.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/examples/quickstart/requirements.txt +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/examples/wizard_of_oz/parser.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/examples/wizard_of_oz/runner.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/examples/wizard_of_oz/woo.txt +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/__init__.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/cross_encoder/__init__.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/cross_encoder/bge_reranker_client.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/cross_encoder/client.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/cross_encoder/gemini_reranker_client.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/cross_encoder/openai_reranker_client.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/driver/__init__.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/driver/falkordb_driver.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/driver/neo4j_driver.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/embedder/__init__.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/embedder/azure_openai.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/embedder/client.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/embedder/gemini.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/embedder/openai.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/embedder/voyage.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/errors.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/graph_queries.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/graphiti_types.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/helpers.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/llm_client/__init__.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/llm_client/anthropic_client.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/llm_client/azure_openai_client.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/llm_client/client.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/llm_client/errors.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/llm_client/gemini_client.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/llm_client/groq_client.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/llm_client/openai_generic_client.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/llm_client/utils.py +0 -0
- {graphiti_core-0.18.8/graphiti_core/models → graphiti_core-0.19.0rc1/graphiti_core/migrations}/__init__.py +0 -0
- {graphiti_core-0.18.8/graphiti_core/models/edges → graphiti_core-0.19.0rc1/graphiti_core/models}/__init__.py +0 -0
- {graphiti_core-0.18.8/graphiti_core/models/nodes → graphiti_core-0.19.0rc1/graphiti_core/models/edges}/__init__.py +0 -0
- {graphiti_core-0.18.8/graphiti_core/search → graphiti_core-0.19.0rc1/graphiti_core/models/nodes}/__init__.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/prompts/__init__.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/prompts/dedupe_edges.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/prompts/dedupe_nodes.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/prompts/eval.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/prompts/extract_edge_dates.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/prompts/invalidate_edges.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/prompts/lib.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/prompts/models.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/prompts/prompt_helpers.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/prompts/summarize_nodes.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/py.typed +0 -0
- {graphiti_core-0.18.8/graphiti_core/utils → graphiti_core-0.19.0rc1/graphiti_core/search}/__init__.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/search/search.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/search/search_config.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/search/search_config_recipes.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/search/search_filters.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/search/search_helpers.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/telemetry/__init__.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/telemetry/telemetry.py +0 -0
- {graphiti_core-0.18.8/server/graph_service → graphiti_core-0.19.0rc1/graphiti_core/utils}/__init__.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/utils/datetime_utils.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/utils/maintenance/__init__.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/utils/maintenance/community_operations.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/utils/maintenance/temporal_operations.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/utils/maintenance/utils.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/graphiti_core/utils/ontology_utils/entity_types_utils.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/images/arxiv-screenshot.png +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/images/graphiti-graph-intro.gif +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/images/graphiti-intro-slides-stock-2.gif +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/images/simple_graph.svg +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/mcp_server/.env.example +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/mcp_server/.python-version +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/mcp_server/Dockerfile +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/mcp_server/README.md +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/mcp_server/cursor_rules.md +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/mcp_server/docker-compose.yml +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/mcp_server/graphiti_mcp_server.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/mcp_server/mcp_config_sse_example.json +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/mcp_server/mcp_config_stdio_example.json +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/mcp_server/pyproject.toml +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/mcp_server/uv.lock +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/poetry.lock +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/py.typed +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/pytest.ini +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/server/.env.example +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/server/Makefile +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/server/README.md +0 -0
- {graphiti_core-0.18.8/server/graph_service/routers → graphiti_core-0.19.0rc1/server/graph_service}/__init__.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/server/graph_service/config.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/server/graph_service/dto/__init__.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/server/graph_service/dto/common.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/server/graph_service/dto/ingest.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/server/graph_service/dto/retrieve.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/server/graph_service/main.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/server/graph_service/routers/ingest.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/server/graph_service/routers/retrieve.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/server/graph_service/zep_graphiti.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/server/pyproject.toml +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/server/uv.lock +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/tests/cross_encoder/test_bge_reranker_client.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/tests/cross_encoder/test_gemini_reranker_client.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/tests/driver/__init__.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/tests/driver/test_falkordb_driver.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/tests/embedder/embedder_fixtures.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/tests/embedder/test_gemini.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/tests/embedder/test_openai.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/tests/embedder/test_voyage.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/tests/evals/data/longmemeval_data/README.md +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/tests/evals/data/longmemeval_data/longmemeval_oracle.json +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/tests/evals/eval_cli.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/tests/evals/eval_e2e_graph_building.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/tests/evals/pytest.ini +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/tests/evals/utils.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/tests/llm_client/test_anthropic_client.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/tests/llm_client/test_anthropic_client_int.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/tests/llm_client/test_client.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/tests/llm_client/test_errors.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/tests/llm_client/test_gemini_client.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/tests/test_edge_int.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/tests/test_entity_exclusion_int.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/tests/test_graphiti_int.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/tests/test_node_int.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/tests/utils/maintenance/test_edge_operations.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/tests/utils/maintenance/test_temporal_operations_int.py +0 -0
- {graphiti_core-0.18.8 → graphiti_core-0.19.0rc1}/tests/utils/search/search_utils_test.py +0 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
name: AI Moderator
|
|
2
|
+
on:
|
|
3
|
+
issues:
|
|
4
|
+
types: [opened]
|
|
5
|
+
issue_comment:
|
|
6
|
+
types: [created]
|
|
7
|
+
pull_request_review_comment:
|
|
8
|
+
types: [created]
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
spam-detection:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
permissions:
|
|
14
|
+
issues: write
|
|
15
|
+
pull-requests: write
|
|
16
|
+
models: read
|
|
17
|
+
contents: read
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
- uses: github/ai-moderator@v1
|
|
21
|
+
with:
|
|
22
|
+
token: ${{ secrets.GITHUB_TOKEN }}
|
|
23
|
+
spam-label: 'spam'
|
|
24
|
+
ai-label: 'ai-generated'
|
|
25
|
+
minimize-detected-comments: true
|
|
26
|
+
# Built-in prompt configuration (all enabled by default)
|
|
27
|
+
enable-spam-detection: true
|
|
28
|
+
enable-link-spam-detection: true
|
|
29
|
+
enable-ai-detection: true
|
|
30
|
+
# custom-prompt-path: '.github/prompts/my-custom.prompt.yml' # Optional
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: graphiti-core
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.19.0rc1
|
|
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
|
|
@@ -30,7 +30,7 @@ Requires-Dist: langchain-anthropic>=0.2.4; extra == 'dev'
|
|
|
30
30
|
Requires-Dist: langchain-openai>=0.2.6; extra == 'dev'
|
|
31
31
|
Requires-Dist: langgraph>=0.2.15; extra == 'dev'
|
|
32
32
|
Requires-Dist: langsmith>=0.1.108; extra == 'dev'
|
|
33
|
-
Requires-Dist: pyright>=1.1.
|
|
33
|
+
Requires-Dist: pyright>=1.1.404; extra == 'dev'
|
|
34
34
|
Requires-Dist: pytest-asyncio>=0.24.0; extra == 'dev'
|
|
35
35
|
Requires-Dist: pytest-xdist>=3.6.1; extra == 'dev'
|
|
36
36
|
Requires-Dist: pytest>=8.3.3; extra == 'dev'
|
|
@@ -44,6 +44,10 @@ Provides-Extra: google-genai
|
|
|
44
44
|
Requires-Dist: google-genai>=1.8.0; extra == 'google-genai'
|
|
45
45
|
Provides-Extra: groq
|
|
46
46
|
Requires-Dist: groq>=0.2.0; extra == 'groq'
|
|
47
|
+
Provides-Extra: neptune
|
|
48
|
+
Requires-Dist: boto3>=1.39.16; extra == 'neptune'
|
|
49
|
+
Requires-Dist: langchain-aws>=0.2.29; extra == 'neptune'
|
|
50
|
+
Requires-Dist: opensearch-py>=3.0.0; extra == 'neptune'
|
|
47
51
|
Provides-Extra: sentence-transformers
|
|
48
52
|
Requires-Dist: sentence-transformers>=3.2.1; extra == 'sentence-transformers'
|
|
49
53
|
Provides-Extra: voyageai
|
|
@@ -157,7 +161,7 @@ Graphiti is specifically designed to address the challenges of dynamic and frequ
|
|
|
157
161
|
Requirements:
|
|
158
162
|
|
|
159
163
|
- Python 3.10 or higher
|
|
160
|
-
- Neo4j 5.26 / FalkorDB 1.1.2 or
|
|
164
|
+
- Neo4j 5.26 / FalkorDB 1.1.2 / Amazon Neptune Database Cluster or Neptune Analytics Graph + Amazon OpenSearch Serverless collection (serves as the full text search backend)
|
|
161
165
|
- OpenAI API key (Graphiti defaults to OpenAI for LLM inference and embedding)
|
|
162
166
|
|
|
163
167
|
> [!IMPORTANT]
|
|
@@ -200,6 +204,17 @@ pip install graphiti-core[falkordb]
|
|
|
200
204
|
uv add graphiti-core[falkordb]
|
|
201
205
|
```
|
|
202
206
|
|
|
207
|
+
### Installing with Amazon Neptune Support
|
|
208
|
+
|
|
209
|
+
If you plan to use Amazon Neptune as your graph database backend, install with the Amazon Neptune extra:
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
pip install graphiti-core[neptune]
|
|
213
|
+
|
|
214
|
+
# or with uv
|
|
215
|
+
uv add graphiti-core[neptune]
|
|
216
|
+
```
|
|
217
|
+
|
|
203
218
|
### You can also install optional LLM providers as extras:
|
|
204
219
|
|
|
205
220
|
```bash
|
|
@@ -217,6 +232,9 @@ pip install graphiti-core[anthropic,groq,google-genai]
|
|
|
217
232
|
|
|
218
233
|
# Install with FalkorDB and LLM providers
|
|
219
234
|
pip install graphiti-core[falkordb,anthropic,google-genai]
|
|
235
|
+
|
|
236
|
+
# Install with Amazon Neptune
|
|
237
|
+
pip install graphiti-core[neptune]
|
|
220
238
|
```
|
|
221
239
|
|
|
222
240
|
## Default to Low Concurrency; LLM Provider 429 Rate Limit Errors
|
|
@@ -236,7 +254,7 @@ If your LLM provider allows higher throughput, you can increase `SEMAPHORE_LIMIT
|
|
|
236
254
|
|
|
237
255
|
For a complete working example, see the [Quickstart Example](./examples/quickstart/README.md) in the examples directory. The quickstart demonstrates:
|
|
238
256
|
|
|
239
|
-
1. Connecting to a Neo4j or FalkorDB database
|
|
257
|
+
1. Connecting to a Neo4j, Amazon Neptune, or FalkorDB database
|
|
240
258
|
2. Initializing Graphiti indices and constraints
|
|
241
259
|
3. Adding episodes to the graph (both text and structured JSON)
|
|
242
260
|
4. Searching for relationships (edges) using hybrid search
|
|
@@ -319,6 +337,26 @@ driver = FalkorDriver(
|
|
|
319
337
|
graphiti = Graphiti(graph_driver=driver)
|
|
320
338
|
```
|
|
321
339
|
|
|
340
|
+
#### Amazon Neptune
|
|
341
|
+
|
|
342
|
+
```python
|
|
343
|
+
from graphiti_core import Graphiti
|
|
344
|
+
from graphiti_core.driver.neptune_driver import NeptuneDriver
|
|
345
|
+
|
|
346
|
+
# Create a FalkorDB driver with custom database name
|
|
347
|
+
driver = NeptuneDriver(
|
|
348
|
+
host=<NEPTUNE ENDPOINT>,
|
|
349
|
+
aoss_host=<Amazon OpenSearch Serverless Host>,
|
|
350
|
+
port=<PORT> # Optional, defaults to 8182,
|
|
351
|
+
aoss_port=<PORT> # Optional, defaults to 443
|
|
352
|
+
)
|
|
353
|
+
|
|
354
|
+
driver = NeptuneDriver(host=neptune_uri, aoss_host=aoss_host, port=neptune_port)
|
|
355
|
+
|
|
356
|
+
# Pass the driver to Graphiti
|
|
357
|
+
graphiti = Graphiti(graph_driver=driver)
|
|
358
|
+
```
|
|
359
|
+
|
|
322
360
|
|
|
323
361
|
### Performance Configuration
|
|
324
362
|
|
|
@@ -495,7 +533,7 @@ Ensure Ollama is running (`ollama serve`) and that you have pulled the models yo
|
|
|
495
533
|
|
|
496
534
|
- [Guides and API documentation](https://help.getzep.com/graphiti).
|
|
497
535
|
- [Quick Start](https://help.getzep.com/graphiti/graphiti/quick-start)
|
|
498
|
-
- [Building an agent with LangChain's LangGraph and Graphiti](https://help.getzep.com/graphiti/
|
|
536
|
+
- [Building an agent with LangChain's LangGraph and Graphiti](https://help.getzep.com/graphiti/integrations/lang-graph-agent)
|
|
499
537
|
|
|
500
538
|
## Telemetry
|
|
501
539
|
|
|
@@ -510,7 +548,7 @@ When you initialize a Graphiti instance, we collect:
|
|
|
510
548
|
- **Graphiti version**: The version you're using
|
|
511
549
|
- **Configuration choices**:
|
|
512
550
|
- LLM provider type (OpenAI, Azure, Anthropic, etc.)
|
|
513
|
-
- Database backend (Neo4j, FalkorDB)
|
|
551
|
+
- Database backend (Neo4j, FalkorDB, Amazon Neptune Database or Neptune Analytics)
|
|
514
552
|
- Embedder provider (OpenAI, Azure, Voyage, etc.)
|
|
515
553
|
|
|
516
554
|
### What We Don't Collect
|
|
@@ -105,7 +105,7 @@ Graphiti is specifically designed to address the challenges of dynamic and frequ
|
|
|
105
105
|
Requirements:
|
|
106
106
|
|
|
107
107
|
- Python 3.10 or higher
|
|
108
|
-
- Neo4j 5.26 / FalkorDB 1.1.2 or
|
|
108
|
+
- Neo4j 5.26 / FalkorDB 1.1.2 / Amazon Neptune Database Cluster or Neptune Analytics Graph + Amazon OpenSearch Serverless collection (serves as the full text search backend)
|
|
109
109
|
- OpenAI API key (Graphiti defaults to OpenAI for LLM inference and embedding)
|
|
110
110
|
|
|
111
111
|
> [!IMPORTANT]
|
|
@@ -148,6 +148,17 @@ pip install graphiti-core[falkordb]
|
|
|
148
148
|
uv add graphiti-core[falkordb]
|
|
149
149
|
```
|
|
150
150
|
|
|
151
|
+
### Installing with Amazon Neptune Support
|
|
152
|
+
|
|
153
|
+
If you plan to use Amazon Neptune as your graph database backend, install with the Amazon Neptune extra:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
pip install graphiti-core[neptune]
|
|
157
|
+
|
|
158
|
+
# or with uv
|
|
159
|
+
uv add graphiti-core[neptune]
|
|
160
|
+
```
|
|
161
|
+
|
|
151
162
|
### You can also install optional LLM providers as extras:
|
|
152
163
|
|
|
153
164
|
```bash
|
|
@@ -165,6 +176,9 @@ pip install graphiti-core[anthropic,groq,google-genai]
|
|
|
165
176
|
|
|
166
177
|
# Install with FalkorDB and LLM providers
|
|
167
178
|
pip install graphiti-core[falkordb,anthropic,google-genai]
|
|
179
|
+
|
|
180
|
+
# Install with Amazon Neptune
|
|
181
|
+
pip install graphiti-core[neptune]
|
|
168
182
|
```
|
|
169
183
|
|
|
170
184
|
## Default to Low Concurrency; LLM Provider 429 Rate Limit Errors
|
|
@@ -184,7 +198,7 @@ If your LLM provider allows higher throughput, you can increase `SEMAPHORE_LIMIT
|
|
|
184
198
|
|
|
185
199
|
For a complete working example, see the [Quickstart Example](./examples/quickstart/README.md) in the examples directory. The quickstart demonstrates:
|
|
186
200
|
|
|
187
|
-
1. Connecting to a Neo4j or FalkorDB database
|
|
201
|
+
1. Connecting to a Neo4j, Amazon Neptune, or FalkorDB database
|
|
188
202
|
2. Initializing Graphiti indices and constraints
|
|
189
203
|
3. Adding episodes to the graph (both text and structured JSON)
|
|
190
204
|
4. Searching for relationships (edges) using hybrid search
|
|
@@ -267,6 +281,26 @@ driver = FalkorDriver(
|
|
|
267
281
|
graphiti = Graphiti(graph_driver=driver)
|
|
268
282
|
```
|
|
269
283
|
|
|
284
|
+
#### Amazon Neptune
|
|
285
|
+
|
|
286
|
+
```python
|
|
287
|
+
from graphiti_core import Graphiti
|
|
288
|
+
from graphiti_core.driver.neptune_driver import NeptuneDriver
|
|
289
|
+
|
|
290
|
+
# Create a FalkorDB driver with custom database name
|
|
291
|
+
driver = NeptuneDriver(
|
|
292
|
+
host=<NEPTUNE ENDPOINT>,
|
|
293
|
+
aoss_host=<Amazon OpenSearch Serverless Host>,
|
|
294
|
+
port=<PORT> # Optional, defaults to 8182,
|
|
295
|
+
aoss_port=<PORT> # Optional, defaults to 443
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
driver = NeptuneDriver(host=neptune_uri, aoss_host=aoss_host, port=neptune_port)
|
|
299
|
+
|
|
300
|
+
# Pass the driver to Graphiti
|
|
301
|
+
graphiti = Graphiti(graph_driver=driver)
|
|
302
|
+
```
|
|
303
|
+
|
|
270
304
|
|
|
271
305
|
### Performance Configuration
|
|
272
306
|
|
|
@@ -443,7 +477,7 @@ Ensure Ollama is running (`ollama serve`) and that you have pulled the models yo
|
|
|
443
477
|
|
|
444
478
|
- [Guides and API documentation](https://help.getzep.com/graphiti).
|
|
445
479
|
- [Quick Start](https://help.getzep.com/graphiti/graphiti/quick-start)
|
|
446
|
-
- [Building an agent with LangChain's LangGraph and Graphiti](https://help.getzep.com/graphiti/
|
|
480
|
+
- [Building an agent with LangChain's LangGraph and Graphiti](https://help.getzep.com/graphiti/integrations/lang-graph-agent)
|
|
447
481
|
|
|
448
482
|
## Telemetry
|
|
449
483
|
|
|
@@ -458,7 +492,7 @@ When you initialize a Graphiti instance, we collect:
|
|
|
458
492
|
- **Graphiti version**: The version you're using
|
|
459
493
|
- **Configuration choices**:
|
|
460
494
|
- LLM provider type (OpenAI, Azure, Anthropic, etc.)
|
|
461
|
-
- Database backend (Neo4j, FalkorDB)
|
|
495
|
+
- Database backend (Neo4j, FalkorDB, Amazon Neptune Database or Neptune Analytics)
|
|
462
496
|
- Embedder provider (OpenAI, Azure, Voyage, etc.)
|
|
463
497
|
|
|
464
498
|
### What We Don't Collect
|
|
@@ -77,7 +77,11 @@ class IsPresidentOf(BaseModel):
|
|
|
77
77
|
|
|
78
78
|
async def main(use_bulk: bool = False):
|
|
79
79
|
setup_logging()
|
|
80
|
-
client = Graphiti(
|
|
80
|
+
client = Graphiti(
|
|
81
|
+
neo4j_uri,
|
|
82
|
+
neo4j_user,
|
|
83
|
+
neo4j_password,
|
|
84
|
+
)
|
|
81
85
|
await clear_data(client.driver)
|
|
82
86
|
await client.build_indices_and_constraints()
|
|
83
87
|
messages = parse_podcast_messages()
|
|
@@ -18,6 +18,8 @@ This example demonstrates the basic functionality of Graphiti, including:
|
|
|
18
18
|
- A local DBMS created and started in Neo4j Desktop
|
|
19
19
|
- **For FalkorDB**:
|
|
20
20
|
- FalkorDB server running (see [FalkorDB documentation](https://falkordb.com/docs/) for setup)
|
|
21
|
+
- **For Amazon Neptune**:
|
|
22
|
+
- Amazon server running (see [Amazon Neptune documentation](https://aws.amazon.com/neptune/developer-resources/) for setup)
|
|
21
23
|
|
|
22
24
|
|
|
23
25
|
## Setup Instructions
|
|
@@ -42,9 +44,19 @@ export NEO4J_PASSWORD=password
|
|
|
42
44
|
# Optional FalkorDB connection parameters (defaults shown)
|
|
43
45
|
export FALKORDB_URI=falkor://localhost:6379
|
|
44
46
|
|
|
47
|
+
# Optional Amazon Neptune connection parameters
|
|
48
|
+
NEPTUNE_HOST=your_neptune_host
|
|
49
|
+
NEPTUNE_PORT=your_port_or_8182
|
|
50
|
+
AOSS_HOST=your_aoss_host
|
|
51
|
+
AOSS_PORT=your_port_or_443
|
|
52
|
+
|
|
45
53
|
# To use a different database, modify the driver constructor in the script
|
|
46
54
|
```
|
|
47
55
|
|
|
56
|
+
TIP: For Amazon Neptune host string please use the following formats
|
|
57
|
+
* For Neptune Database: `neptune-db://<cluster endpoint>`
|
|
58
|
+
* For Neptune Analytics: `neptune-graph://<graph identifier>`
|
|
59
|
+
|
|
48
60
|
3. Run the example:
|
|
49
61
|
|
|
50
62
|
```bash
|
|
@@ -52,11 +64,14 @@ python quickstart_neo4j.py
|
|
|
52
64
|
|
|
53
65
|
# For FalkorDB
|
|
54
66
|
python quickstart_falkordb.py
|
|
67
|
+
|
|
68
|
+
# For Amazon Neptune
|
|
69
|
+
python quickstart_neptune.py
|
|
55
70
|
```
|
|
56
71
|
|
|
57
72
|
## What This Example Demonstrates
|
|
58
73
|
|
|
59
|
-
- **Graph Initialization**: Setting up the Graphiti indices and constraints in Neo4j or FalkorDB
|
|
74
|
+
- **Graph Initialization**: Setting up the Graphiti indices and constraints in Neo4j, Amazon Neptune, or FalkorDB
|
|
60
75
|
- **Adding Episodes**: Adding text content that will be analyzed and converted into knowledge graph nodes and edges
|
|
61
76
|
- **Edge Search Functionality**: Performing hybrid searches that combine semantic similarity and BM25 retrieval to find relationships (edges)
|
|
62
77
|
- **Graph-Aware Search**: Using the source node UUID from the top search result to rerank additional search results based on graph distance
|
|
@@ -0,0 +1,299 @@
|
|
|
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 datetime
|
|
19
|
+
import logging
|
|
20
|
+
from collections.abc import Coroutine
|
|
21
|
+
from typing import Any
|
|
22
|
+
|
|
23
|
+
import boto3
|
|
24
|
+
from langchain_aws.graphs import NeptuneAnalyticsGraph, NeptuneGraph
|
|
25
|
+
from opensearchpy import OpenSearch, Urllib3AWSV4SignerAuth, Urllib3HttpConnection, helpers
|
|
26
|
+
|
|
27
|
+
from graphiti_core.driver.driver import GraphDriver, GraphDriverSession, GraphProvider
|
|
28
|
+
|
|
29
|
+
logger = logging.getLogger(__name__)
|
|
30
|
+
DEFAULT_SIZE = 10
|
|
31
|
+
|
|
32
|
+
aoss_indices = [
|
|
33
|
+
{
|
|
34
|
+
'index_name': 'node_name_and_summary',
|
|
35
|
+
'body': {
|
|
36
|
+
'mappings': {
|
|
37
|
+
'properties': {
|
|
38
|
+
'uuid': {'type': 'keyword'},
|
|
39
|
+
'name': {'type': 'text'},
|
|
40
|
+
'summary': {'type': 'text'},
|
|
41
|
+
'group_id': {'type': 'text'},
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
'query': {
|
|
46
|
+
'query': {'multi_match': {'query': '', 'fields': ['name', 'summary', 'group_id']}},
|
|
47
|
+
'size': DEFAULT_SIZE,
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
'index_name': 'community_name',
|
|
52
|
+
'body': {
|
|
53
|
+
'mappings': {
|
|
54
|
+
'properties': {
|
|
55
|
+
'uuid': {'type': 'keyword'},
|
|
56
|
+
'name': {'type': 'text'},
|
|
57
|
+
'group_id': {'type': 'text'},
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
'query': {
|
|
62
|
+
'query': {'multi_match': {'query': '', 'fields': ['name', 'group_id']}},
|
|
63
|
+
'size': DEFAULT_SIZE,
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
'index_name': 'episode_content',
|
|
68
|
+
'body': {
|
|
69
|
+
'mappings': {
|
|
70
|
+
'properties': {
|
|
71
|
+
'uuid': {'type': 'keyword'},
|
|
72
|
+
'content': {'type': 'text'},
|
|
73
|
+
'source': {'type': 'text'},
|
|
74
|
+
'source_description': {'type': 'text'},
|
|
75
|
+
'group_id': {'type': 'text'},
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
'query': {
|
|
80
|
+
'query': {
|
|
81
|
+
'multi_match': {
|
|
82
|
+
'query': '',
|
|
83
|
+
'fields': ['content', 'source', 'source_description', 'group_id'],
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
'size': DEFAULT_SIZE,
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
'index_name': 'edge_name_and_fact',
|
|
91
|
+
'body': {
|
|
92
|
+
'mappings': {
|
|
93
|
+
'properties': {
|
|
94
|
+
'uuid': {'type': 'keyword'},
|
|
95
|
+
'name': {'type': 'text'},
|
|
96
|
+
'fact': {'type': 'text'},
|
|
97
|
+
'group_id': {'type': 'text'},
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
'query': {
|
|
102
|
+
'query': {'multi_match': {'query': '', 'fields': ['name', 'fact', 'group_id']}},
|
|
103
|
+
'size': DEFAULT_SIZE,
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
]
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
class NeptuneDriver(GraphDriver):
|
|
110
|
+
provider: GraphProvider = GraphProvider.NEPTUNE
|
|
111
|
+
|
|
112
|
+
def __init__(self, host: str, aoss_host: str, port: int = 8182, aoss_port: int = 443):
|
|
113
|
+
"""This initializes a NeptuneDriver for use with Neptune as a backend
|
|
114
|
+
|
|
115
|
+
Args:
|
|
116
|
+
host (str): The Neptune Database or Neptune Analytics host
|
|
117
|
+
aoss_host (str): The OpenSearch host value
|
|
118
|
+
port (int, optional): The Neptune Database port, ignored for Neptune Analytics. Defaults to 8182.
|
|
119
|
+
aoss_port (int, optional): The OpenSearch port. Defaults to 443.
|
|
120
|
+
"""
|
|
121
|
+
if not host:
|
|
122
|
+
raise ValueError('You must provide an endpoint to create a NeptuneDriver')
|
|
123
|
+
|
|
124
|
+
if host.startswith('neptune-db://'):
|
|
125
|
+
# This is a Neptune Database Cluster
|
|
126
|
+
endpoint = host.replace('neptune-db://', '')
|
|
127
|
+
self.client = NeptuneGraph(endpoint, port)
|
|
128
|
+
logger.debug('Creating Neptune Database session for %s', host)
|
|
129
|
+
elif host.startswith('neptune-graph://'):
|
|
130
|
+
# This is a Neptune Analytics Graph
|
|
131
|
+
graphId = host.replace('neptune-graph://', '')
|
|
132
|
+
self.client = NeptuneAnalyticsGraph(graphId)
|
|
133
|
+
logger.debug('Creating Neptune Graph session for %s', host)
|
|
134
|
+
else:
|
|
135
|
+
raise ValueError(
|
|
136
|
+
'You must provide an endpoint to create a NeptuneDriver as either neptune-db://<endpoint> or neptune-graph://<graphid>'
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
if not aoss_host:
|
|
140
|
+
raise ValueError('You must provide an AOSS endpoint to create an OpenSearch driver.')
|
|
141
|
+
|
|
142
|
+
session = boto3.Session()
|
|
143
|
+
self.aoss_client = OpenSearch(
|
|
144
|
+
hosts=[{'host': aoss_host, 'port': aoss_port}],
|
|
145
|
+
http_auth=Urllib3AWSV4SignerAuth(
|
|
146
|
+
session.get_credentials(), session.region_name, 'aoss'
|
|
147
|
+
),
|
|
148
|
+
use_ssl=True,
|
|
149
|
+
verify_certs=True,
|
|
150
|
+
connection_class=Urllib3HttpConnection,
|
|
151
|
+
pool_maxsize=20,
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
def _sanitize_parameters(self, query, params: dict):
|
|
155
|
+
if isinstance(query, list):
|
|
156
|
+
queries = []
|
|
157
|
+
for q in query:
|
|
158
|
+
queries.append(self._sanitize_parameters(q, params))
|
|
159
|
+
return queries
|
|
160
|
+
else:
|
|
161
|
+
for k, v in params.items():
|
|
162
|
+
if isinstance(v, datetime.datetime):
|
|
163
|
+
params[k] = v.isoformat()
|
|
164
|
+
elif isinstance(v, list):
|
|
165
|
+
# Handle lists that might contain datetime objects
|
|
166
|
+
for i, item in enumerate(v):
|
|
167
|
+
if isinstance(item, datetime.datetime):
|
|
168
|
+
v[i] = item.isoformat()
|
|
169
|
+
query = str(query).replace(f'${k}', f'datetime(${k})')
|
|
170
|
+
if isinstance(item, dict):
|
|
171
|
+
query = self._sanitize_parameters(query, v[i])
|
|
172
|
+
|
|
173
|
+
# If the list contains datetime objects, we need to wrap each element with datetime()
|
|
174
|
+
if any(isinstance(item, str) and 'T' in item for item in v):
|
|
175
|
+
# Create a new list expression with datetime() wrapped around each element
|
|
176
|
+
datetime_list = (
|
|
177
|
+
'['
|
|
178
|
+
+ ', '.join(
|
|
179
|
+
f'datetime("{item}")'
|
|
180
|
+
if isinstance(item, str) and 'T' in item
|
|
181
|
+
else repr(item)
|
|
182
|
+
for item in v
|
|
183
|
+
)
|
|
184
|
+
+ ']'
|
|
185
|
+
)
|
|
186
|
+
query = str(query).replace(f'${k}', datetime_list)
|
|
187
|
+
elif isinstance(v, dict):
|
|
188
|
+
query = self._sanitize_parameters(query, v)
|
|
189
|
+
return query
|
|
190
|
+
|
|
191
|
+
async def execute_query(
|
|
192
|
+
self, cypher_query_, **kwargs: Any
|
|
193
|
+
) -> tuple[dict[str, Any], None, None]:
|
|
194
|
+
params = dict(kwargs)
|
|
195
|
+
if isinstance(cypher_query_, list):
|
|
196
|
+
for q in cypher_query_:
|
|
197
|
+
result, _, _ = self._run_query(q[0], q[1])
|
|
198
|
+
return result, None, None
|
|
199
|
+
else:
|
|
200
|
+
return self._run_query(cypher_query_, params)
|
|
201
|
+
|
|
202
|
+
def _run_query(self, cypher_query_, params):
|
|
203
|
+
cypher_query_ = str(self._sanitize_parameters(cypher_query_, params))
|
|
204
|
+
try:
|
|
205
|
+
result = self.client.query(cypher_query_, params=params)
|
|
206
|
+
except Exception as e:
|
|
207
|
+
logger.error('Query: %s', cypher_query_)
|
|
208
|
+
logger.error('Parameters: %s', params)
|
|
209
|
+
logger.error('Error executing query: %s', e)
|
|
210
|
+
raise e
|
|
211
|
+
|
|
212
|
+
return result, None, None
|
|
213
|
+
|
|
214
|
+
def session(self, database: str | None = None) -> GraphDriverSession:
|
|
215
|
+
return NeptuneDriverSession(driver=self)
|
|
216
|
+
|
|
217
|
+
async def close(self) -> None:
|
|
218
|
+
return self.client.client.close()
|
|
219
|
+
|
|
220
|
+
async def _delete_all_data(self) -> Any:
|
|
221
|
+
return await self.execute_query('MATCH (n) DETACH DELETE n')
|
|
222
|
+
|
|
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
|
+
async def create_aoss_indices(self):
|
|
231
|
+
for index in aoss_indices:
|
|
232
|
+
index_name = index['index_name']
|
|
233
|
+
client = self.aoss_client
|
|
234
|
+
if not client.indices.exists(index=index_name):
|
|
235
|
+
client.indices.create(index=index_name, body=index['body'])
|
|
236
|
+
# Sleep for 1 minute to let the index creation complete
|
|
237
|
+
await asyncio.sleep(60)
|
|
238
|
+
|
|
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
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
class NeptuneDriverSession(GraphDriverSession):
|
|
274
|
+
def __init__(self, driver: NeptuneDriver): # type: ignore[reportUnknownArgumentType]
|
|
275
|
+
self.driver = driver
|
|
276
|
+
|
|
277
|
+
async def __aenter__(self):
|
|
278
|
+
return self
|
|
279
|
+
|
|
280
|
+
async def __aexit__(self, exc_type, exc, tb):
|
|
281
|
+
# No cleanup needed for Neptune, but method must exist
|
|
282
|
+
pass
|
|
283
|
+
|
|
284
|
+
async def close(self):
|
|
285
|
+
# No explicit close needed for Neptune, but method must exist
|
|
286
|
+
pass
|
|
287
|
+
|
|
288
|
+
async def execute_write(self, func, *args, **kwargs):
|
|
289
|
+
# Directly await the provided async function with `self` as the transaction/session
|
|
290
|
+
return await func(self, *args, **kwargs)
|
|
291
|
+
|
|
292
|
+
async def run(self, query: str | list, **kwargs: Any) -> Any:
|
|
293
|
+
if isinstance(query, list):
|
|
294
|
+
res = None
|
|
295
|
+
for q in query:
|
|
296
|
+
res = await self.driver.execute_query(q, **kwargs)
|
|
297
|
+
return res
|
|
298
|
+
else:
|
|
299
|
+
return await self.driver.execute_query(str(query), **kwargs)
|