Commit graph

312 commits

Author SHA1 Message Date
Matthew Mo
50bcb74502
Add dynamic max_tokens configuration for Anthropic models (#1043)
* Add dynamic max_tokens configuration for Anthropic models

Implements model-specific max output token limits for AnthropicClient,
following the same pattern as GeminiClient. This replaces the previous
hardcoded min() cap that was preventing models from using their full
output capacity.

Changes:
- Added ANTHROPIC_MODEL_MAX_TOKENS mapping with limits for all supported
  Claude models (ranging from 4K to 65K tokens)
- Implemented _get_max_tokens_for_model() to lookup model-specific limits
- Implemented _resolve_max_tokens() with clear precedence rules:
  1. Explicit max_tokens parameter
  2. Instance max_tokens from initialization
  3. Model-specific limit from mapping
  4. Default fallback (8192 tokens)

This allows edge_operations.py to request 16384 tokens for edge extraction
without being artificially capped, while ensuring cheaper models with lower
limits are still properly handled.

Resolves TODO in anthropic_client.py:207-208.

* Clarify that max_tokens mapping represents standard limits

Updated comments to explicitly state that ANTHROPIC_MODEL_MAX_TOKENS
represents standard limits without beta headers. This prevents confusion
about extended limits (e.g., Claude 3.7's 128K with beta header) which
are not currently implemented in this mapping.
2025-11-14 08:34:56 -08:00
Daniel Chalef
55ef6acb16
Add Azure OpenAI example with Neo4j (#1064)
* Add Azure OpenAI example with Neo4j

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Convert Azure OpenAI example to use uv

- Remove requirements.txt (uv uses pyproject.toml)
- Update README to use 'uv sync' and 'uv run'

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Update Azure OpenAI example to use gpt-4.1

- Change default deployment from gpt-4 to gpt-4.1
- Update README recommendations to prioritize gpt-4.1 models

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Remove model recommendations from Azure OpenAI example

Model recommendations quickly become outdated.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Add default Neo4j credentials to docker-compose

Set sensible defaults (neo4j/password) to prevent NEO4J_AUTH error
when .env file is not present.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Update Azure OpenAI documentation to use v1 API

- Simplified Azure OpenAI setup using AsyncOpenAI with v1 endpoint
- Updated main README with clearer Quick Start example
- Removed outdated API version configuration
- Updated example deployment to gpt-5-mini
- Added note about v1 API endpoint format

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Update LLMConfig to include both model and small_model

Both parameters are needed for proper LLM configuration.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Address PR review feedback

- Remove flawed validation check in azure_openai_neo4j.py
- Remove unused azure-identity dependency
- Update docstrings to reflect dual client support (AsyncAzureOpenAI and AsyncOpenAI)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-14 08:34:35 -08:00
Daniel Chalef
90d7757c17
Use OpenAI structured output API for response validation (#1061)
* Use OpenAI structured output API for response validation

Replace prompt-based schema injection with native json_schema response format. This improves token efficiency and reliability by having OpenAI enforce the schema directly instead of embedding it in the prompt message.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Add type ignore for response_format to fix pyright error

* Increase OpenAIGenericClient max_tokens to 16K and update docs

- Set default max_tokens to 16384 (16K) for OpenAIGenericClient to better support local models
- Add documentation note clarifying OpenAIGenericClient should be used for Ollama and LM Studio
- Previous default was 8192 (8K)

* Refactor max_tokens override to use constructor parameter pattern

- Add max_tokens parameter to __init__ with 16K default
- Override self.max_tokens after super().__init__() instead of mutating config
- Consistent with OpenAIBaseClient and AnthropicClient patterns
- Avoids unintended config mutation side effects

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-11 06:53:37 -08:00
Gal Shubeli
9d023eb400
Fix entity edge save (#1013)
save-edge-properties
2025-11-08 18:32:51 -08:00
Daniel Chalef
f7816c29b3
Implement build_indices_and_constraints for Kuzu and Neptune drivers (#1048)
* Implement build_indices_and_constraints for Kuzu and Neptune drivers

Both Kuzu and Neptune drivers were missing the build_indices_and_constraints
method required by the abstract GraphDriver base class. Kuzu uses a no-op
implementation since indices are created during schema setup. Neptune delegates
to its existing OpenSearch (AOSS) index creation logic.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Skip fulltext search tests for Kuzu driver

Kuzu requires explicit schema definition and doesn't support dynamic fulltext
index creation like Neo4j or FalkorDB. These tests were already being skipped
for FalkorDB for similar reasons. Updated all four fulltext search tests to
skip for both FalkorDB and Kuzu providers.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-05 11:51:59 -05:00
Gal Shubeli
c144ff5995
[Improvement] Add GraphID isolation support for FalkorDB multi-tenant architecture (#835)
* Update node_db_queries.py

* Update node_db_queries.py

* graph-per-graphid

* fix-groupid-usage

* ruff-fix

* rev-driver-changes

* rm-un-changes

* fix lint

---------

Co-authored-by: Naseem Ali <34807727+Naseem77@users.noreply.github.com>
2025-11-03 10:56:53 -05:00
Daniel Chalef
8d99984204
Fix Azure structured completions (#1039)
update azure azure structured parsing
2025-11-01 18:40:43 -07:00
Daniel Chalef
375023b9e8
feat: MCP Server v1.0.0 - Modular architecture with multi-provider support (#1024)
* feat: MCP Server v1.0.0rc0 - Complete refactoring with modular architecture

This is a major refactoring of the MCP Server to support multiple providers
through a YAML-based configuration system with factory pattern implementation.

## Key Changes

### Architecture Improvements
- Modular configuration system with YAML-based settings
- Factory pattern for LLM, Embedder, and Database providers
- Support for multiple database backends (Neo4j, FalkorDB, KuzuDB)
- Clean separation of concerns with dedicated service modules

### Provider Support
- **LLM**: OpenAI, Anthropic, Gemini, Groq
- **Embedders**: OpenAI, Voyage, Gemini, Anthropic, Sentence Transformers
- **Databases**: Neo4j, FalkorDB, KuzuDB (new default)
- Azure OpenAI support with AD authentication

### Configuration
- YAML configuration with environment variable expansion
- CLI argument overrides for runtime configuration
- Multiple pre-configured Docker Compose setups
- Proper boolean handling in environment variables

### Testing & CI
- Comprehensive test suite with unit and integration tests
- GitHub Actions workflows for linting and testing
- Multi-database testing support

### Docker Support
- Updated Docker images with multi-stage builds
- Database-specific docker-compose configurations
- Persistent volume support for all databases

### Bug Fixes
- Fixed KuzuDB connectivity checks
- Corrected Docker command paths
- Improved error handling and logging
- Fixed boolean environment variable expansion

Co-authored-by: Claude <noreply@anthropic.com>

* conductor-checkpoint-msg_01PmXwij9S976CQk798DJ4PH

* fix: Improve MCP server configuration and initialization

- Fix API key detection: Remove hardcoded OpenAI checks, let factories handle provider-specific validation
- Fix .env file loading: Search for .env in mcp_server directory first
- Change default transport to SSE for broader compatibility (was stdio)
- Add proper error handling with warnings for failed client initialization
- Model already defaults to gpt-4o as requested

These changes ensure the MCP server properly loads API keys from .env files
and creates the appropriate LLM/embedder clients based on configuration.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* conductor-checkpoint-msg_01PCGAWzQUbmh7hAKBvadbYN

* chore: Update default transport from SSE to HTTP

- Changed default transport to 'http' as SSE is deprecated
- Updated all configuration files to use HTTP transport
- Updated Docker compose commands to use HTTP transport
- Updated comments to reflect HTTP transport usage

This change ensures the MCP server uses the recommended HTTP transport
instead of the deprecated SSE transport.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* conductor-checkpoint-msg_01FErZjFG5iWrvbdUD2acQwQ

* chore: Update default OpenAI model to gpt-4o-mini

Changed the default LLM model from gpt-4o to gpt-4o-mini across all
configuration files for better cost efficiency while maintaining quality.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* conductor-checkpoint-msg_01FETp6u9mWAMjJAeT6WFgAf

* conductor-checkpoint-msg_01AJJ48RbkPaZ99G2GmE6HUi

* fix: Correct default OpenAI model to gpt-4.1

Changed the default LLM model from gpt-4o-mini to gpt-4.1 as requested.
This is the latest GPT-4 series model.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* conductor-checkpoint-msg_013HP1MYHKZ5wdTHHxrpBaT9

* fix: Update hardcoded default model to gpt-4.1 and fix config path

- Changed hardcoded default in schema.py from gpt-4o to gpt-4.1
- Fixed default config path to look in config/config.yaml relative to mcp_server directory
- This ensures the server uses gpt-4.1 as the default model everywhere

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* conductor-checkpoint-msg_01EaN8GZtehm8LV3a7CdWJ8u

* feat: Add detailed server URL logging and improve access information

- Added comprehensive logging showing exact URLs to access the MCP server
- Display localhost instead of 0.0.0.0 for better usability
- Show MCP endpoint, transport type, and status endpoint information
- Added visual separators to make server info stand out in logs

This helps users understand exactly how to connect to the MCP server
and troubleshoot connection issues.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* conductor-checkpoint-msg_01SNpbaZMdxWbefo2zsLprcW

* fix: Correct MCP HTTP endpoint path from / to /mcp/

- Remove incorrect /status endpoint reference
- Update logging to show correct MCP endpoint at /mcp/
- Align with FastMCP documentation standards

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* conductor-checkpoint-msg_01417YVh3s6afJadN5AM5Ahk

* fix: Configure consistent logging format between uvicorn and MCP server

- Use simplified format matching uvicorn's default (LEVEL message)
- Remove timestamps from custom logger format
- Suppress verbose MCP and uvicorn access logs
- Improve readability of server startup output

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* conductor-checkpoint-msg_014BF6Kzdy7qXc5AgC7eeVa5

* conductor-checkpoint-msg_01TscHXmijzkqcTJX5sGTYP8

* conductor-checkpoint-msg_01Q7VLFTJrtmpkaB7hfUzZLP

* fix: Improve test runner to load API keys from .env file

- Add dotenv loading support in test runner
- Fix duplicate os import issue
- Improve prerequisite checking with helpful hints
- Update error messages to guide users

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* conductor-checkpoint-msg_01NfviLNeAhFDA1G5841YKCS

* conductor-checkpoint-msg_015EewQhKbqAGSQkasWtRQjp

* fix: Fix all linting errors in test suite

- Replace bare except with except Exception
- Remove unused imports and variables
- Fix type hints to use modern syntax
- Apply ruff formatting for line length
- Ensure all tests pass linting checks

* conductor-checkpoint-msg_01RedNheKT4yWyXcM83o3Nmv

* fix: Use contextlib.suppress instead of try-except-pass (SIM105)

- Replace try-except-pass with contextlib.suppress in test_async_operations.py
- Replace try-except-pass with contextlib.suppress in test_fixtures.py
- Fixes ruff SIM105 linting errors

* conductor-checkpoint-msg_01GuBj69k2CsqgojBsGJ2zFT

* fix: Move README back to mcp_server root folder

The main README for the MCP server should be in the root of the mcp_server folder for better discoverability

* conductor-checkpoint-msg_01VsJQ3MgDxPwyb4ynvswZfb

* docs: Update README with comprehensive features and database options

- Add comprehensive features list including all supported databases, LLM providers, and transports
- Document Kuzu as the default database with explanation of its benefits and archived status
- Add detailed instructions for running with different databases (Kuzu, Neo4j, FalkorDB)
- Update transport references from SSE to HTTP (default transport)
- Add database-specific Docker Compose instructions
- Update MCP client configurations to use /mcp/ endpoint
- Clarify prerequisites to reflect optional nature of external databases
- Add detailed database configuration examples for all supported backends

* conductor-checkpoint-msg_018Z7AjbTkuDfhqdjB9iGbbD

* docs: Address README review comments

- Shorten Kuzu database description to be more concise
- Update Ollama model example to use 'gpt-oss:120b'
- Restore Azure OpenAI environment variables documentation
- Remove implementation details from Docker section (irrelevant to container users)
- Clarify mcp-remote supports both HTTP and SSE transports

Addresses review comments #1-7 on the PR

* conductor-checkpoint-msg_01QMeMEMe9rTVDgd8Ce5hmXp

* docs: Remove SSE transport reference from Claude Desktop section

Since the MCP server no longer supports SSE transport, removed the
mention of SSE from the mcp-remote description. The server only
uses HTTP transport.

Addresses review comment on line 514

* conductor-checkpoint-msg_01DNn76rvpx7rmTBwsUQd1De

* docs: Remove telemetry from features list

Telemetry is not a feature but a notice about data collection,
so it shouldn't be listed as a feature.

Addresses review comment on line 29

* conductor-checkpoint-msg_01Jcb8sm9bpqB9Ksz1W6YrSz

* feat: Update default embedding model to text-embedding-3-small

Replace outdated text-embedding-ada-002 with the newer, more efficient
text-embedding-3-small model as the default embedder. The new model
offers better performance and is more cost-effective.

Updated:
- config/config.yaml: Changed default model
- README.md: Updated documentation to reflect new default

* conductor-checkpoint-msg_016AXAH98nYKTj5WCueBubmA

* fix: Resolve database connection and episode processing errors

Fixed two critical runtime errors:

1. Database connection check for KuzuDB
   - KuzuDB session.run() returns None, causing async iteration error
   - Added special handling for KuzuDB (in-memory, no query needed)
   - Other databases (Neo4j, FalkorDB) still perform connection test

2. Episode processing parameter error
   - Changed 'episode_type' parameter to 'source' to match Graphiti API
   - Added required 'reference_time' parameter with current timestamp
   - Added datetime imports (UTC, datetime)

Errors fixed:
- 'async for' requires an object with __aiter__ method, got NoneType
- Graphiti.add_episode() got an unexpected keyword argument 'episode_type'

* conductor-checkpoint-msg_01JvcW97a4s3icDWFkhF3kEJ

* fix: Use timezone.utc instead of UTC for Python 3.10 compatibility

The UTC constant was added in Python 3.11. Changed to use
timezone.utc which is available in Python 3.10+.

Fixed ImportError: cannot import name 'UTC' from 'datetime'

* conductor-checkpoint-msg_01Br69UnYf8QXvtAhJVTuDGD

* fix: Convert entity_types from list to dict for Graphiti API

The Graphiti add_episode() API expects entity_types as a
dict[str, type[BaseModel]], not a list. Changed entity type
building to create a dictionary mapping entity names to their
Pydantic model classes.

Fixed error: 'list' object has no attribute 'items'

Changes:
- Build entity_types as dict instead of list in config processing
- Add fallback to convert ENTITY_TYPES list to dict if needed
- Map entity type names to their model classes

* conductor-checkpoint-msg_0173SR9CxbBH9jVWp8tLooRp

* conductor-checkpoint-msg_0169v3hqZG1Sqb13Kp1Vijms

* fix: Remove protected 'name' attribute from entity type models

Pydantic BaseModel reserves 'name' as a protected attribute. Removed
the 'name' attribute from dynamically created entity type models as
it's not needed - the entity type name is already stored as the class
name and dict key.

Fixed error: name cannot be used as an attribute for Requirement as
it is a protected attribute name.

* conductor-checkpoint-msg_0118QJWvZLyoZfwb1UWZqrRa

* conductor-checkpoint-msg_01B78jtT59YDt1Xm5hJpoqQw

* conductor-checkpoint-msg_01MsqeFGoCEXpoNMiDRM3Gjh

* conductor-checkpoint-msg_01SwJkCDAScffk8116KPVpTd

* conductor-checkpoint-msg_01EBWwDRC8bZ7oLYxsrmVnLH

* conductor-checkpoint-msg_01SAcxuF3eqtP4exA47CBqAi

* conductor-checkpoint-msg_011dRKwJM31K3ob9Gy4JCmae

* conductor-checkpoint-msg_018d52yUXdPF48UBWPQdiB4W

* conductor-checkpoint-msg_01MGFAenMDnTX3H9HSZEbj2T

* conductor-checkpoint-msg_01MHw4g8TicrXegSK9phncfw

* conductor-checkpoint-msg_018YrqWa3c2ZpkxemiiaE9tA

* conductor-checkpoint-msg_01SNsax9AwiCBFrC7Fpo7BNe

* conductor-checkpoint-msg_01K7QC1X8iPiYaMdvbi7WtR5

* conductor-checkpoint-msg_01KgGgzpbiuM31KWKxQhNBfY

* conductor-checkpoint-msg_01KL3wzQUn3gekDmznXVgXne

* conductor-checkpoint-msg_016GKc3DYwYUjngGw8pArRJK

* conductor-checkpoint-msg_01QLbhPMGDeB5EHbMq5KT86U

* conductor-checkpoint-msg_01Qdskq96hJ6Q9DPg1h5Jjgg

* conductor-checkpoint-msg_01JhPXYdc6HGsoEW2f1USSyd

* conductor-checkpoint-msg_018NLrtFxs5zfcNwQnNCfvNg

* conductor-checkpoint-msg_01G1G9J7cbupmLkyiQufj335

* conductor-checkpoint-msg_01BHEPsv2EML14gFa6vkn1NP

* conductor-checkpoint-msg_0127MeSvxWk8BLXjB5k3wDJY

* conductor-checkpoint-msg_018dRGHW6fPNqJDN6eV6SpoH

* conductor-checkpoint-msg_01CPPZ9JKakjsmHpzzoFVhaM

* conductor-checkpoint-msg_014jJQ4FkGU4485gF41K2suG

* conductor-checkpoint-msg_01MS72hQDCrr1rB6GSd3zy4h

* conductor-checkpoint-msg_01P7ur6mQEusfHTYpBrBnpk3

* conductor-checkpoint-msg_01JiEiEuJN3sQXheqMzCa6hX

* conductor-checkpoint-msg_01D7XfEJqzTeKGyuE5EFmjND

* conductor-checkpoint-msg_01Gn6qZrD3DZd8c6a6fmMap7

* conductor-checkpoint-msg_01Ji7gxCG4jR145rBAupwU49

* conductor-checkpoint-msg_01CYzyiAtLo95iVLeqWSuYiR

* conductor-checkpoint-msg_017fAeUG21Ym1EeofanFzFGa

* conductor-checkpoint-msg_013rt24pyzMHbrmEQein2dJJ

* conductor-checkpoint-msg_016bN3uyAxN28Rh8uvDpExit

* conductor-checkpoint-msg_017QV6m73ShaMBdQi7L3kmhP

* conductor-checkpoint-msg_01LUZ9XS7C1LCG6A1VFNcRL2

* conductor-checkpoint-msg_0136b9tNU5ko18T3PmRkW3LJ

* conductor-checkpoint-msg_018FX6Mibr66cKLnpL84f2Js

* conductor-checkpoint-msg_01WRZxPMQYjNEjcFNTMzWYeL

* conductor-checkpoint-msg_015Tbxjxrj6dynf7TbZscFD3

* conductor-checkpoint-msg_01ELC9AyZZGry9tN4XKrwEM6

* conductor-checkpoint-msg_01Jk4ugkAqMs4iRYWwnaNAHR

* conductor-checkpoint-msg_01NLStrCDq7HZJy3pKyGSqxM

* conductor-checkpoint-msg_01BFZEVpXbdxuXJguFH3caek

* Remove User and Assistant exception from Preference prioritization

* conductor-checkpoint-msg_01JP4eGXZfEjoSXWUwTHNYoJ

* Add combined FalkorDB + MCP server Docker image

- Created Dockerfile.falkordb-combined extending official FalkorDB image
- Added startup script to run both FalkorDB daemon and MCP server
- Created docker-compose-falkordb-combined.yml for simplified deployment
- Added comprehensive README-falkordb-combined.md documentation
- Updated main README with Option 4 for combined image
- Single container solution for development and single-node deployments

* conductor-checkpoint-msg_01PRJ1fre9d6J4qgBmCBQhCu

* Fix Dockerfile syntax version and Python compatibility

- Set Dockerfile syntax to version 1 as requested
- Use Python 3.11 from Debian Bookworm instead of 3.12
- Add comment explaining Bookworm ships with Python 3.11
- Python 3.11 meets project requirement of >=3.10
- Build tested successfully

* conductor-checkpoint-msg_011Thrsv6CjZKRCXvordMWeb

* Fix combined FalkorDB image to run both services successfully

- Override FalkorDB ENTRYPOINT to use custom startup script
- Use correct FalkorDB module path: /var/lib/falkordb/bin/falkordb.so
- Create config-docker-falkordb-combined.yaml with localhost URI
- Create /var/lib/falkordb/data directory for persistence
- Both FalkorDB and MCP server now start successfully
- Tested: FalkorDB ready, MCP server running on port 8000

* conductor-checkpoint-msg_01FT3bsTuv7466EvCeRtgDsD

* Fix health check to eliminate 404 errors

- Changed health check to only verify FalkorDB (redis-cli ping)
- Removed non-existent /health endpoint check
- MCP server startup is visible in logs
- Container now runs without health check errors

* conductor-checkpoint-msg_01KWBc5S8vWzyovUTWLvPYNw

* Replace Kuzu with FalkorDB as default database

BREAKING CHANGE: Kuzu is no longer supported. FalkorDB is now the default.

- Renamed Dockerfile.falkordb-combined to Dockerfile (default)
- Renamed docker-compose-falkordb-combined.yml to docker-compose.yml (default)
- Updated config.yaml to use FalkorDB with localhost:6379 as default
- Removed Kuzu from pyproject.toml dependencies (now only falkordb extra)
- Updated Dockerfile to use graphiti-core[falkordb] instead of [kuzu,falkordb]
- Completely removed all Kuzu references from README
- Updated README to document FalkorDB combined container as default
- Docker Compose now starts single container with FalkorDB + MCP server
- Prerequisites now require Docker instead of Python for default setup
- Removed old Kuzu docker-compose files

Running from command line now requires external FalkorDB instance at localhost:6379

* conductor-checkpoint-msg_014wBY9WG9GRXP7cUZ2JiqGz

* Complete Kuzu removal from MCP server

Removed all remaining Kuzu references from:
- Test fixtures (test_fixtures.py): Changed default database to falkordb, removed kuzu configuration
- Test runner (run_tests.py): Removed kuzu from database choices, checks, and markers
- Integration tests (test_comprehensive_integration.py): Removed kuzu from parameterized tests and environment setup
- Test README: Updated all examples and documentation to reflect falkordb as default
- Docker README: Completely rewrote to remove KuzuDB section, updated with FalkorDB combined image as default

All Kuzu support has been completely removed from the MCP server codebase. FalkorDB (via combined container) is now the default database backend.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* conductor-checkpoint-msg_01FAgmoDFBPETezbBr18Bpir

* Fix Anthropic client temperature type error

Fixed pyright type error where temperature parameter (float | None) was being passed directly to Anthropic's messages.create() method which expects (float | Omit).

Changes:
- Build message creation parameters as a dictionary
- Conditionally include temperature only when not None
- Use dictionary unpacking to pass parameters

This allows temperature to be properly omitted when None, rather than passing None as a value.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* conductor-checkpoint-msg_01KEuAQucnvsH94BwFgCAQXg

* Fix critical PR review issues

Fixed high-impact issues from PR #1024 code review:

1. **Boolean conversion bug (schema.py)**
   - Fixed _expand_env_vars returning strings 'true'/'false' instead of booleans
   - Now properly converts boolean-like strings (true/false/1/0/yes/no/on/off) to actual booleans
   - Simplified logic by removing redundant string-to-string conversions
   - Added support for common boolean string variations

2. **Dependency management (pyproject.toml)**
   - Removed pytest from main dependencies (now only in dev dependencies)
   - Moved azure-identity to optional dependencies under new [azure] group
   - Prevents forcing Azure and testing dependencies on all users

3. **Conditional Azure imports (utils.py)**
   - Made azure-identity import conditional in create_azure_credential_token_provider()
   - Raises helpful ImportError with installation instructions if not available
   - Follows lazy-import pattern for optional dependencies

4. **Documentation fix (graphiti_mcp_server.py)**
   - Fixed confusing JSON escaping in add_memory docstring example
   - Changed from triple-backslash escaping to standard JSON string
   - Updated comment to clarify standard JSON escaping is used

Issues verified as already fixed:
- Docker build context (all docker-compose files use context: ..)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* conductor-checkpoint-msg_013aEa7tUV8rEmfw38BzJatc

* Add comprehensive SEMAPHORE_LIMIT documentation

Added detailed documentation for SEMAPHORE_LIMIT configuration to help users optimize episode processing concurrency based on their LLM provider's rate limits.

Changes:

1. **graphiti_mcp_server.py**
   - Expanded inline comments from 3 lines to 26 lines
   - Added provider-specific tuning guidelines (OpenAI, Anthropic, Azure, Ollama)
   - Documented symptoms of too-high/too-low settings
   - Added monitoring recommendations

2. **README.md**
   - Expanded "Concurrency and LLM Provider 429 Rate Limit Errors" section
   - Added tier-specific recommendations for each provider
   - Explained relationship between episode concurrency and LLM request rates
   - Added troubleshooting symptoms and monitoring guidance
   - Included example .env configuration

3. **config.yaml**
   - Added header comment referencing detailed documentation
   - Noted default value and suitable use case

4. **.env.example**
   - Added SEMAPHORE_LIMIT with inline tuning guidelines
   - Quick reference for all major LLM provider tiers
   - Cross-reference to README for full details

Benefits:
- Users can now make informed decisions about concurrency settings
- Reduces likelihood of 429 rate limit errors from misconfiguration
- Helps users maximize throughput within their rate limits
- Provides clear troubleshooting guidance

Addresses PR #1024 review comment about magic number documentation.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* conductor-checkpoint-msg_017netxNYzmam5Cu8PM2uQXW

* conductor-checkpoint-msg_012B8ESfBFcMeG3tFimpjbce

* conductor-checkpoint-msg_01Xe46bzgCGV4c8g4piPtSMQ

* conductor-checkpoint-start

* conductor-checkpoint-msg_01QPZK2pa2vUMpURRFmX93Jt

* conductor-checkpoint-msg_01UU5jQcfrW5btRJB3zy5KQZ

* conductor-checkpoint-msg_01884eN3wprtCkrEgEaRDzko

* conductor-checkpoint-msg_01GC2fQiu9gLGPGf8SvG5VW8

* conductor-checkpoint-msg_018ZD567wd4skoiAz7oML7WX

* conductor-checkpoint-msg_01C3AxzcQQSNZxJcuVxAMYpG

* conductor-checkpoint-msg_014w5iHAnv7mVkKfTroeNkuM

* docs: Add current LLM model reference to CLAUDE.md

Added comprehensive model reference section documenting valid model names for OpenAI, Anthropic, and Google Gemini as of January 2025.

OpenAI Models:
- GPT-5 family (reasoning models): gpt-5-mini, gpt-5-nano
- GPT-4.1 family (standard models): gpt-4.1, gpt-4.1-mini, gpt-4.1-nano
- Legacy models: gpt-4o, gpt-4o-mini

Anthropic Models:
- Claude 3.7 family (latest)
- Claude 3.5 family
- Legacy Claude 3 models

Google Gemini Models:
- Gemini 2.5 family (latest)
- Gemini 2.0 family (experimental)
- Gemini 1.5 family (stable)

This documents that model names like gpt-5-mini, gpt-4.1, and gpt-4.1-mini used throughout the codebase are valid OpenAI model identifiers, not errors.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* conductor-checkpoint-msg_014JsovjGyTM1mGwR1nVWLvX

* conductor-checkpoint-msg_013ooHLBEhPccaSY4cFse8vK

* conductor-checkpoint-msg_01WfmUCwXhWxEFtV7R3zJLwT

* conductor-checkpoint-msg_01SbjZ9mm9YwqeJHTDUDoKU8

* conductor-checkpoint-msg_01T2cR1aXUjNSegqzXQcW2jC

* conductor-checkpoint-msg_01EnQy5A9dMFD8F11hWKvzGo

* conductor-checkpoint-msg_01R1zsLmxvwjZ9SwKNhSnQAv

* refactor: Remove duplicate is_reasoning_model calculation in factories.py

* conductor-checkpoint-msg_015oLk8qck3TbfaCryY9gngJ

* conductor-checkpoint-msg_018YAxG5GsLq1dBMuGE6kwEJ

* conductor-checkpoint-msg_014fda5sUsvofb537BvqkuBY

* fix: Change default transport to http, mark SSE as deprecated

* conductor-checkpoint-msg_01S3x8oHkFTM2x4ZiT81QetV

* conductor-checkpoint-msg_01AVxUgejEA9piS6narw4omz

* conductor-checkpoint-msg_019W9KoNBmkobBguViYUj18s

* conductor-checkpoint-msg_01S2mYUmqLohxEmoZaNqsm2f

* conductor-checkpoint-msg_013ZGKfZjdDsqiCkAjAiuEk7

* fix: Handle default config path and empty env vars correctly

- Change default config path from 'config.yaml' to 'config/config.yaml'
- Fix env var expansion to return None for empty strings instead of False
- Prevents validation errors when optional string fields have unset env vars

* conductor-checkpoint-msg_01Bx1BqH3BaBxHMrnsbUQXww

* fix: Allow None for episode_id_prefix and convert to empty string

- Change episode_id_prefix type to str | None to accept None from YAML
- Add model_post_init to convert None to empty string for backward compatibility

* conductor-checkpoint-msg_01CXVkHJC8gp5i395MQMhp6D

* feat: Add helpful error message for database connection failures

- Catch Redis/database connection errors during initialization
- Provide clear, formatted error messages with startup instructions
- Include provider-specific guidance (FalkorDB vs Neo4j)
- Improves developer experience when database is not running

* conductor-checkpoint-msg_01Cd9u1z7pqmX1EG7vXXo4GA

* feat: Add specific Neo4j connection error message with startup instructions

* conductor-checkpoint-msg_01XgbmgFaUMPopni4Q8EhG23

* fix: Remove obsolete KuzuDB check from status endpoint

- Remove dead code checking for 'kuzu' provider (was removed)
- Simplify status check to use configured database provider directly
- Status now correctly reports neo4j or falkordb based on config

* conductor-checkpoint-msg_01WLjwygBwfvbJcVoUMDV3h6

* fix: Use service config instead of global config in status endpoint

- Changed status check to use graphiti_service.config.database.provider
- Ensures status reports the actual running database, not potentially stale global
- Fixes issue where status always reported falkordb regardless of config

* conductor-checkpoint-msg_01DoLD51xqrrdFvq3AgkYuQi

* conductor-checkpoint-msg_01EUW7ArnNM6kHCgFDrQZrro

* conductor-checkpoint-msg_01LqYK6nj1ZFfRNBRP15FMLo

* feat: Add standalone Dockerfile for external database deployments

- Create Dockerfile.standalone for MCP server without embedded FalkorDB
- Supports both Neo4j and FalkorDB via DATABASE_PROVIDER build arg
- Update docker-compose-neo4j.yml to use standalone Dockerfile
- Update docker-compose-falkordb.yml to use standalone Dockerfile
- Fixes issue where Neo4j compose was starting embedded FalkorDB
- Separate images: standalone-neo4j and standalone-falkordb

* conductor-checkpoint-msg_01QSHNgVZvF1id5UtLhpzuUa

* refactor: Unified standalone image with both Neo4j and FalkorDB drivers

- Modified Dockerfile.standalone to install both neo4j and falkordb extras
- Both compose files now use the same standalone image
- Config file determines which database to connect to at runtime
- Added build-standalone.sh script for building and pushing to DockerHub
- Image tags: standalone, {version}-standalone, {version}-graphiti-{core}-standalone

* conductor-checkpoint-msg_01H4isP3oHK25sGpVWzXq9kX

* fix: Correct config file paths in compose files

- Fix CONFIG_PATH env var: /app/config/config.yaml -> /app/mcp/config/config.yaml
- Fix volume mount path: /app/config/config.yaml -> /app/mcp/config/config.yaml
- Matches WORKDIR /app/mcp in Dockerfile.standalone
- Fixes issue where wrong config was being loaded

* conductor-checkpoint-msg_01Pv3Qj9UJJat288xZTsfCm3

* conductor-checkpoint-msg_01DkBq4kQA5Fdmxfikm8aBYG

* conductor-checkpoint-msg_01EBqphY68KNzRWei4QNpcYg

* feat: Add /health endpoint for Docker healthchecks

- Add @mcp.custom_route for /health endpoint using FastMCP
- Returns {status: 'healthy', service: 'graphiti-mcp'}
- Update Dockerfile.standalone healthcheck to use /health instead of /
- Eliminates 404 errors in logs from healthcheck pings
- Follows FastMCP best practices for operational monitoring

* conductor-checkpoint-msg_01UpNeurS45bREPEeGkV3uCx

* feat: Add logging to verify entity types are loaded from config

Added INFO level logging during GraphitiService initialization to confirm
that custom entity types from the configuration file are properly loaded.
This helps debug issues where the entity ontology may not be applied.

Logs the entity type names when custom types are present:
  INFO - Using custom entity types: Preference, Requirement, Procedure, ...

* fix: Correct logging message for entity types and add embedder logging

Fixed copy-paste error where entity types else clause was logging about
embedder client. Also added missing else clause for embedder client logging
for consistency.

- Fixed: "No Embedder client configured" -> "Using default entity types"
- Added: Missing embedder client else clause logging

* conductor-checkpoint-msg_01WMuxAzUnkpsa5WSXKMyLLP

* fix: Return JSONResponse from health check endpoint

Fixed TypeError in health check endpoint by returning a proper Starlette
JSONResponse object instead of a plain dict. Starlette custom routes require
ASGI-compatible response objects.

Error was: TypeError: 'dict' object is not callable

* conductor-checkpoint-msg_01CSgKFQaLsKVrBJAYCFoSGa

* conductor-checkpoint-msg_01SFY9xCnHxeCFGf53FESncs

* feat: Return complete node properties and exclude all embeddings

Enhanced node search results to include all relevant properties:
- Added `attributes` dict for custom entity properties
- Changed from single `type` to full `labels` array
- Added `group_id` for partition information
- Added safety filter to strip any keys containing "embedding" from attributes

Added format_node_result() helper function for consistent node formatting
that excludes name_embedding vectors, matching the pattern used for edges.

Embeddings are now explicitly excluded in all data returns:
- EntityNode: name_embedding excluded + attributes filtered
- EntityEdge: fact_embedding excluded (existing)
- EpisodicNode: No embeddings to exclude

This ensures clients receive complete metadata while keeping payload
sizes manageable and avoiding exposure of internal vector representations.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-30 22:59:01 -07:00
Preston Rasmussen
c29f4da21e
update mmr to use bulk load overrides (#1029)
* update mmr to use bulk load overrides

* update returns

* update
2025-10-29 09:51:58 -04:00
Preston Rasmussen
71f1f66d11
Search client update (#1026)
* update bulk interfae handling

* bump version

* format
2025-10-26 22:07:36 -04:00
Naseem Ali
d0a3cd97ae
Integrate MCP for FalkorDB (#910)
* Integrate MCP for FalkorDB

* fix lint errors
2025-10-21 12:06:57 -04:00
Daniel Chalef
37a9ea65a2
Remove integration markers from database tests (#1000)
* Remove integration markers from database tests

Removed @pytest.mark.integration from database tests to allow them to run
while excluding API integration tests that call external services.

Database tests (now run):
- tests/test_edge_int.py
- tests/test_graphiti_int.py
- tests/test_node_int.py
- tests/test_entity_exclusion_int.py
- tests/cross_encoder/test_bge_reranker_client_int.py
- tests/driver/test_falkordb_driver.py

API integration tests (excluded):
- tests/llm_client/test_anthropic_client_int.py
- tests/utils/maintenance/test_temporal_operations_int.py

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Apply ruff formatting to falkordb driver and node queries

- Quote style fixes in falkordb_driver.py
- Trailing whitespace cleanup in node_db_queries.py
- Update uv.lock

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Remove api-integration-tests job from CI workflow

The api-integration-tests job has been removed since API integration tests
are now excluded via @pytest.mark.integration marker.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix database-integration-tests to run all database tests

Previously only ran test_graphiti_mock.py, now runs all database tests:
- tests/test_graphiti_mock.py
- tests/test_graphiti_int.py
- tests/test_node_int.py
- tests/test_edge_int.py
- tests/test_entity_exclusion_int.py
- tests/cross_encoder/test_bge_reranker_client_int.py
- tests/driver/test_falkordb_driver.py

The -m "not integration" filter excludes API integration tests that call
external services (Anthropic, OpenAI, etc).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Restore integration markers for tests that call LLM APIs

test_graphiti_int.py and test_entity_exclusion_int.py call graphiti.add_episode()
and graphiti.search_() which require LLM API calls, so they are API integration
tests, not pure database tests.

Final categorization:

Pure unit tests (no external dependencies):
- tests/llm_client/test_*.py (except test_anthropic_client_int.py)
- tests/embedder/test_*.py
- tests/utils/maintenance/test_*.py (except test_temporal_operations_int.py)
- tests/utils/search/search_utils_test.py
- tests/test_text_utils.py

Database tests (require Neo4j/FalkorDB, no API calls):
- tests/test_graphiti_mock.py
- tests/test_node_int.py
- tests/test_edge_int.py
- tests/cross_encoder/test_bge_reranker_client_int.py
- tests/driver/test_falkordb_driver.py

API integration tests (excluded via @pytest.mark.integration):
- tests/test_graphiti_int.py
- tests/test_entity_exclusion_int.py
- tests/llm_client/test_anthropic_client_int.py
- tests/utils/maintenance/test_temporal_operations_int.py

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-12 10:16:34 -07:00
Naseem Ali
a8ec45b1bd
fix: wrap embeddings with vecf32() in FalkorDB single save paths (#991)
Fixes #972. Entity and edge single save operations now properly convert
embeddings to vecf32 type, matching bulk save behavior and preventing
type mismatch errors during vector similarity searches.
2025-10-12 09:42:52 -07:00
Daniel Chalef
a5f26b6764
Fix FalkorDB index deletion implementation (#998)
* Update node_db_queries.py

* Update node_db_queries.py

* fix-delete-idx

* improve-delete

* fix uint tests

---------

Co-authored-by: Naseem Ali <34807727+Naseem77@users.noreply.github.com>
Co-authored-by: Gal Shubeli <galshubeli93@gmail.com>
2025-10-12 09:36:22 -07:00
Preston Rasmussen
1e35306126
fix deprecated cypher pattern (#993) 2025-10-09 16:12:55 -04:00
Preston Rasmussen
604e3199a3
add search and graph operations interfaces (#984)
* add search and graph operations interfaces

* update

* update

* update

* update

* update

* update
2025-10-07 13:34:37 -04:00
Daniel Chalef
73015e980e
Fix datetime comparison errors by normalizing to UTC (#988)
* Fix datetime comparison errors by normalizing to UTC

Applied ensure_utc() to all datetime comparisons in edge_operations.py to prevent TypeError when comparing timezone-naive and timezone-aware datetimes. Removed redundant tzinfo checks since ensure_utc() handles both None and naive datetimes.

Fixed comparisons at:
- Lines 419, 423: resolve_edge_contradictions function
- Line 430: resolve_edge_contradictions function
- Line 627: resolve_extracted_edge function (removed redundant tzinfo checks)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Update uv.lock

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix sorting with mixed timezone-aware/naive datetimes

Normalize datetime to UTC in sort key to prevent TypeError when comparing mixed timezone-aware and timezone-naive datetimes during sorting.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-07 08:28:56 -07:00
Daniel Chalef
196eb2f077
Remove JSON indentation from prompts to reduce token usage (#985)
Changes to `to_prompt_json()` helper to default to minified JSON (no indentation) instead of 2-space indentation. This reduces token consumption in LLM prompts while maintaining all necessary information.

- Changed default `indent` parameter from `2` to `None` in `prompt_helpers.py`
- Updated all prompt modules to remove explicit `indent=2` arguments
- Minor code formatting fixes in LLM clients

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-06 16:08:43 -07:00
Daniel Chalef
6ad695186a
Add OpenTelemetry distributed tracing support (#982)
* Add OpenTelemetry distributed tracing support

- Add tracer abstraction with no-op and OpenTelemetry implementations
- Instrument add_episode and add_episode_bulk with tracing spans
- Instrument LLM client with cache-aware tracing
- Add configurable span name prefix support
- Refactor add_episode methods to improve code quality
- Add OTEL_TRACING.md documentation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix linting errors in tracing implementation

- Remove unused episodes_by_uuid variable
- Fix tracer type annotations for context manager support
- Replace isinstance tuple with union syntax
- Use contextlib.suppress for exception handling
- Fix import ordering and use AbstractContextManager

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Address PR review feedback on tracing implementation

Critical fixes:
- Remove flawed error span creation in graphiti.py that created orphaned spans
- Restructure LLM client tracing to create span once at start, eliminating code duplication
- Initialize LLM client tracer to NoOpTracer by default to fix type checking

Enhancements:
- Add comprehensive span attributes to add_episode: reference_time, entity/edge type counts, previous episodes count, invalidated edge count, community count
- Optimize isinstance check for better performance

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Add prompt name tracking to OpenTelemetry tracing spans

Add prompt_name parameter to all LLM client generate_response() methods
and set it as a span attribute in the llm.generate span. This enables
better observability by identifying which prompt template was used for
each LLM call.

Changes:
- Add prompt_name parameter to LLMClient.generate_response() base method
- Add prompt_name parameter and tracing to OpenAIBaseClient,
  AnthropicClient, GeminiClient, and OpenAIGenericClient
- Update all 14 LLM call sites across maintenance operations to include
  prompt_name:
  - edge_operations.py: 4 calls
  - node_operations.py: 6 calls (note: 7 listed but only 6 unique)
  - temporal_operations.py: 2 calls
  - community_operations.py: 2 calls

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix exception handling in add_episode to record errors in OpenTelemetry span

Moved try-except block inside the OpenTelemetry span context and added
proper error recording with span.set_status() and span.record_exception().
This ensures exceptions are captured in the distributed trace, matching
the pattern used in add_episode_bulk.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-05 12:26:14 -07:00
Daniel Chalef
8770012745
Refactor prompt structure: move MESSAGES after instructions (#980)
* Refactor prompt structure: move MESSAGES after instructions

Reordered prompt structure in extract_nodes.py to place MESSAGES section
after instructions/guidelines in both extract_attributes and extract_summary
functions for improved prompt clarity.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Add sentence-aware text truncator for entity summaries

- Created truncate_at_sentence() utility function that truncates text at
  sentence boundaries while respecting max character limits
- Added MAX_SUMMARY_CHARS constant (250 chars) for entity summaries
- Applied truncator to entity summaries in prompts (extract_nodes.py)
- Applied truncator to LLM-generated summaries (node_operations.py)
- Added comprehensive test suite for truncation logic

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Clean up formatting in extract_attributes prompt

- Remove extra blank lines
- Fix indentation of MESSAGES tag

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Bump version to 0.22.0pre3

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-04 19:06:32 -07:00
Daniel Chalef
896cb4e990
Refactor summary prompts to use character limit and prevent meta-commentary (#979)
* Refactor summary prompts to use character limit and prevent meta-commentary

- Changed summary length constraint from "8 sentences" to "250 characters" for more predictable output
- Created reusable summary_instructions snippet in snippets.py with clear BAD/GOOD examples
- Added explicit instruction to output only factual content without meta-commentary
- Applied consistent formatting across extract_nodes.py and summarize_nodes.py
- Bumped version to 0.22.0pre2

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Add copyright header to snippets.py

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-04 15:44:00 -07:00
Daniel Chalef
8a78633e2f
Enforce shorter summaries with 8 sentence limit (#978)
* Enforce shorter summaries with 8 sentence limit

Replace 250-word limit with 8 sentence limit for node summaries to improve conciseness. Also update prompt system message for summarize_context to better reflect its dual purpose of generating summaries and attributes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Update graphiti_core/prompts/summarize_nodes.py

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>

* Bump version to 0.22.0pre1

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Update graphiti_core/prompts/summarize_nodes.py

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2025-10-04 14:37:16 -07:00
Daniel Chalef
2864786dd9
Refactor node extraction; remove summary from attribute extraction (#977)
* Refactor node extraction for better maintainability

- Extract helper functions from extract_attributes_from_node to improve code organization
- Add _extract_entity_attributes, _extract_entity_summary, and _build_episode_context helpers
- Apply consistent formatting (double quotes per ruff configuration)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Apply consistent single quote style throughout node_operations

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* cleanup

* cleanup

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Bump version to 0.22.0pre0

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-04 13:37:39 -07:00
Preston Rasmussen
5a67e660dc
remove generic aoss_client interactions for release build (#975)
* remove generic aoss_client interactions for release build

* remove unused imports

* update

* revert changes to Neptune driver

* Update graphiti_core/driver/neptune_driver.py

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>

* default to sync OpenSearch client

* update

* aoss_client now Any type

* update stubs

---------

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2025-10-03 13:41:15 -04:00
Daniel Chalef
189e45617f
Add group_id parameter to language extraction function (#952)
* Add group_id parameter to get_extraction_language_instruction

Enable consumers to provide group-specific language extraction
instructions by passing group_id through the call chain.

Changes:
- Add optional group_id parameter to get_extraction_language_instruction()
- Add group_id parameter to all LLMClient.generate_response() methods
- Pass group_id through to language instruction function
- Maintain backward compatibility with default None value

Users can now customize extraction per group:
```python
def custom_instruction(group_id: str | None = None) -> str:
    if group_id == 'spanish-users':
        return '\n\nExtract in Spanish.'
    return '\n\nExtract in original language.'

client.get_extraction_language_instruction = custom_instruction
```

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Pass group_id to generate_response in extraction operations

Thread group_id parameter through all extraction-related generate_response()
calls where it's naturally available (via episode.group_id or node.group_id).
This enables consumers to override get_extraction_language_instruction() with
group-specific language preferences.

Changes:
- edge_operations.py: Pass group_id in extract_edges()
- node_operations.py: Pass episode.group_id in extract_nodes() and
  node.group_id in extract_attributes_from_node()
- node_operations.py: Add group_id parameter to extract_nodes_reflexion()

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix type inconsistency in extract_nodes_reflexion parameter

Change group_id parameter from str = '' to str | None = None to match
the pattern used throughout the codebase and align with the optional
nature of group_id in generate_response().

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Remove ensure_ascii parameter and uv.lock file

* Reset uv.lock to main branch version

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-03 09:05:45 -07:00
Preston Rasmussen
ff260f010e
validate nodes and edges aren't falsey (#973)
* validate nodes and edges aren't falsey

* update

* update
2025-10-03 11:10:07 -04:00
Daniel Chalef
590282524a
fix: Improve edge extraction entity ID validation (#968)
* fix: Improve edge extraction entity ID validation

Fixes invalid entity ID references in edge extraction that caused warnings like:
"WARNING: source or target node not filled WILL_FIND. source_node_uuid: 23 and target_node_uuid: 3"

Changes:
- Format ENTITIES list as proper JSON in prompt for better LLM parsing
- Clarify field descriptions to reference entity id from ENTITIES list
- Add explicit entity ID validation as #1 extraction rule with examples
- Improve error logging (removed PII, added entity count and valid range)

These changes follow patterns from extract_nodes.py and dedupe_nodes.py where
entity referencing works reliably.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* wip

* fix: Align fact field naming and add description

- Change extraction rule to reference 'fact' instead of 'fact_text'
- Add descriptive text for fact field in Edge model

* fix: Remove ensure_ascii parameter from to_prompt_json call

Align with other to_prompt_json calls that don't use ensure_ascii

* fix: Use validated target_node_idx variable consistently

Line 190 was using raw edge_data.target_entity_id instead of the
validated target_node_idx variable, creating inconsistency with line 189

* fix: Improve edge extraction validation checks

- Add explicit check for empty nodes list
- Use more explicit 0 <= idx comparison instead of -1 < idx
- Prevents nonsensical error message when no entities provided

* chore: Restore uv.lock from main branch

Previously deleted in commit 7e4464b, now restored to match main branch state

* Update uv.lock

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-02 22:45:11 -07:00
Daniel Chalef
4a307dbf10
Optimize edge deduplication prompt for caching and clarity (#970)
* Optimize edge deduplication prompt for caching and clarity

- Restructure prompt to place invariant instructions at top and dynamic context at bottom for better LLM caching
- Change 'id' to 'idx' in edge context lists to avoid confusion with other identifiers
- Remove 'fact_type_id' from edge types context as LLM only needs fact_type_name
- Remove dynamic range values from prompt instructions (e.g., "range 0-N")
- Add debug logging before LLM call to track input sizes
- Add validation logging after LLM response to catch invalid idx values
- Clarify that duplicate_facts uses EXISTING FACTS idx and contradicted_facts uses INVALIDATION CANDIDATES idx

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Address terminology consistency and edge case logging

- Update Pydantic field descriptions to use 'idx' instead of 'ids' for consistency
- Fix debug logging to handle empty list edge case (avoid 'idx 0--1' display)

Note on review feedback:
- Validation is intentionally non-redundant: warnings provide visibility, list comprehensions ensure robustness
- WARNING level is appropriate for LLM output issues (not system errors)
- Existing test coverage is sufficient for this defensive logging addition

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-02 17:07:43 -07:00
Daniel Chalef
b28bd92c16
Remove ensure_ascii configuration parameter (#969)
* Remove ensure_ascii configuration parameter

- Changed to_prompt_json default from ensure_ascii=True to False
- Removed ensure_ascii parameter from Graphiti.__init__ and GraphitiClients
- Removed ensure_ascii from all function signatures and context dictionaries
- Removed ensure_ascii from all test files
- All JSON serialization now preserves Unicode characters by default

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* format

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-02 15:10:57 -07:00
Preston Rasmussen
bec3f02036
filter out falsey values before creating embeddings (#966)
* filter out falsey values

* update

* early return
2025-10-02 15:26:51 -04:00
Daniel Chalef
5ca8b9565c
fix: Improve deduplication ID validation and logging (#965)
* fix: Improve deduplication ID validation and logging

- Add comprehensive logging to verify IDs sent to LLM (sent vs received)
- Enhance prompt with explicit ID bounds (0 through N-1)
- Add validation warnings for missing and extra IDs from LLM responses
- Improve error message clarity for invalid dedupe IDs
- Log actual IDs sent to LLM to confirm no index leakage

This helps diagnose cases where the LLM returns IDs outside the valid
range (e.g., ID 19 when only 0-18 were sent).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: Remove redundant logging parameter

Address reviewer comment about redundant third parameter in debug log statement.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: Address reviewer comments on list slicing and prompt clarity

- Fix list slicing bug: change <= to < to avoid gap when exactly 20 elements
  (previously would skip element 10 when showing 21 elements)
- Consolidate redundant prompt phrasing while maintaining clarity
  (reduced from 3 sentences to 2, keeping essential constraints)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: Remove redundant prompt text to reduce token usage

Consolidate 'using these exact IDs (0 through N-1)' with following sentence
to eliminate repetition. Changes:
- 'using these exact IDs (0 through {N-1}). Do not skip IDs or use IDs outside this range'
- 'with IDs 0 through {N-1}. Do not skip or add IDs'

Saves ~15 tokens per deduplication call.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-02 12:22:07 -07:00
Daniel Chalef
644aa2b967
feat: Add optional callback to control node summary generation (#959)
Add NodeSummaryFilter callback parameter to extract_attributes_from_nodes
and extract_attributes_from_node functions, allowing consumers to
selectively skip summary regeneration for specific nodes.

This enables downstream applications to implement custom logic for
throttling or filtering which nodes should have summaries regenerated,
reducing unnecessary LLM calls and token costs.

Key changes:
- Add NodeSummaryFilter type alias: Callable[[EntityNode], Awaitable[bool]]
- Update extract_attributes_from_nodes with optional should_summarize_node parameter
- Update extract_attributes_from_node with conditional summary generation logic
- Add 5 comprehensive test cases covering callback functionality
- Maintain full backwards compatibility (default None = all summaries generated)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-01 16:17:48 -07:00
Jack Ryan
59fcc9545f
fix: Fix typo in JSON entity extraction prompt (#953)
* fix: Fix typo in JSON entity extraction prompt

Change "an entities" to "any entities" in guideline 1 of the extract_json prompt.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Update graphiti_core/prompts/extract_nodes.py

Co-authored-by: Daniel Chalef <131175+danielchalef@users.noreply.github.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Daniel Chalef <131175+danielchalef@users.noreply.github.com>
2025-10-01 11:23:39 -05:00
Daniel Chalef
7bd8f8a2f2
chore: Update edge extraction prompt to paraphrase instead of quote (#957)
* chore: Update edge extraction prompt to paraphrase instead of quote

- Changed instruction 5 to request paraphrasing rather than verbatim quoting
- Updated string quotes to use double quotes for consistency

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* chore: Format edge_operations.py and update lock file

- Minor formatting fix in edge_operations.py list comprehension
- Update uv.lock with version bump to 0.21.0rc8

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-01 09:05:04 -07:00
Daniel Chalef
420676faf2
fix: Prevent duplicate edge facts within same episode (#955)
* fix: Prevent duplicate edge facts within same episode

This fixes three related bugs that allowed verbatim duplicate edge facts:

1. Fixed LLM deduplication: Changed related_edges_context to use integer
   indices instead of UUIDs, matching the EdgeDuplicate model expectations.

2. Fixed batch deduplication: Removed episode skip in dedupe_edges_bulk
   that prevented comparing edges from the same episode. Added self-comparison
   guard to prevent edge from comparing against itself.

3. Added fast-path deduplication: Added exact string matching before parallel
   processing in resolve_extracted_edges to catch within-episode duplicates
   early, preventing race conditions where concurrent edges can't see each other.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* test: Add tests for edge deduplication fixes

Added three tests to verify the edge deduplication fixes:

1. test_dedupe_edges_bulk_deduplicates_within_episode: Verifies that
   dedupe_edges_bulk now compares edges from the same episode after
   removing the `if i == j: continue` check.

2. test_resolve_extracted_edge_uses_integer_indices_for_duplicates:
   Validates that the LLM receives integer indices for duplicate
   detection and correctly processes returned duplicate_facts.

3. test_resolve_extracted_edges_fast_path_deduplication: Confirms that
   the fast-path exact string matching deduplicates identical edges
   before parallel processing, preventing race conditions.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: Remove unused variables flagged by ruff

- Remove unused loop variable 'j' in bulk_utils.py
- Remove unused return value 'edges_by_episode' in test
- Replace unused 'edge_uuid' with '_' in test loop

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-01 07:30:30 -07:00
Daniel Chalef
b2ff050e57
Make natural language extraction configurable (#943)
Replace MULTILINGUAL_EXTRACTION_RESPONSES constant with configurable
get_extraction_language_instruction() function to improve determinism
and allow customization.

Changes:
- Replace constant with function in client.py
- Update all LLM client implementations to use new function
- Maintain backward compatibility with same default behavior
- Enable users to override function for custom language requirements

Users can now customize extraction behavior by monkey-patching:
```python
import graphiti_core.llm_client.client as client
client.get_extraction_language_instruction = lambda: "Custom instruction"
```

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-authored-by: Claude <noreply@anthropic.com>
2025-09-30 11:09:03 -04:00
Jack Ryan
f632a8ae9e
Improve JSON entity extraction prompt (#949)
Add guideline to extract entities from all JSON properties, not just primary fields like name/user. This ensures comprehensive entity extraction while maintaining the existing exclusion of date properties.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-authored-by: Claude <noreply@anthropic.com>
2025-09-30 11:00:14 -04:00
Daniel Chalef
f2c4c97362
Allow Edge extraction to keep discovered edge labels (#950)
* chore: Update dependencies and enhance edge resolution logic

- Add new dependencies: boto3, opensearch-py, and langchain-aws to pyproject.toml.
- Modify Graphiti class to handle additional parameters in edge resolution.
- Improve edge type handling in deduplication logic by introducing custom edge type names.
- Enhance tests for edge resolution to cover new scenarios and ensure correct behavior.

This update improves the flexibility and functionality of edge operations while ensuring compatibility with new libraries.

* refactor: Clean up test_edge_operations.py and format response returns

- Remove unnecessary stubs for opensearchpy module.
- Format return values in llm_client.generate_response for consistency.
- Enhance readability by ensuring proper indentation and structure in test cases.

This refactor improves the clarity and maintainability of the test suite for edge operations.

* bump version to 0.30.0pre5 and enhance docstring for resolve_extracted_edge function

- Update version in pyproject.toml to 0.30.0pre5.
- Add detailed docstring to resolve_extracted_edge function in edge_operations.py, clarifying parameters and return values.

This update improves documentation clarity for the edge resolution process.
2025-09-29 21:32:47 -07:00
Daniel Chalef
3fcd587276
fix: Add edge type validation based on node labels (#948)
* fix: Add edge type validation based on node labels

- Add DEFAULT_EDGE_NAME constant for 'RELATES_TO'
- Implement pre-resolution validation to reset invalid edge names
- Add post-resolution validation for LLM-returned fact types
- Rename parameter from edge_types to edge_type_candidates for clarity
- Add comprehensive tests for validation scenarios

This ensures edges conform to edge_type_map constraints and prevents
misclassification when edge types don't match node label pairs.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* chore: Bump version to 0.30.0pre4

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-09-29 16:35:00 -07:00
Daniel Chalef
02efeea8e9
Improve node dedup prompts (#942)
* remove poetry.lock

* Improve dedup prompts

* normalize string formatting in dedupe_nodes.py to use single quotes
2025-09-28 12:18:06 -07:00
Daniel Chalef
d7828d48d8
Fix index out of range errors in LLM deduplication responses (#939)
* add tests for llm dedupe guardrails

* document llm dedupe guardrails
2025-09-26 14:57:48 -07:00
Daniel Chalef
9aee3174bd
Refactor batch deduplication logic to enhance node resolution and track duplicate pairs (#929) (#936)
* Refactor deduplication logic to enhance node resolution and track duplicate pairs (#929)

* Simplify deduplication process in bulk_utils by reusing canonical nodes.
* Update dedup_helpers to store duplicate pairs during resolution.
* Modify node_operations to append duplicate pairs when resolving nodes.
* Add tests to verify deduplication behavior and ensure correct state updates.

* reveret to concurrent dedup with fanout and then reconcilation

* add performance note for deduplication loop in bulk_utils

* enhance deduplication logic in bulk_utils to handle missing canonical nodes gracefully

* Update graphiti_core/utils/bulk_utils.py

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>

* refactor deduplication logic in bulk_utils to use directed union-find for canonical UUID resolution

* implement _build_directed_uuid_map for efficient UUID resolution in bulk_utils

* document directed union-find lookup in bulk_utils for clarity

---------

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2025-09-26 08:40:18 -07:00
Daniel Chalef
7c469e8e2b
Improve node deduplication w/ deterministic matching, LLM fallbacks (#929)
* add repository guidelines and project structure documentation

* update neo4j image version and modify test command to disable specific databases

* implement deduplication helpers and integrate with node operations

* refactor string formatting to use single quotes in node operations

* enhance deduplication helpers with UUID indexing and update resolution logic

* implement exact fact matching (#931)
2025-09-25 07:13:19 -07:00
Preston Rasmussen
d6d4bbdeb7
don't save duplicate edges (#927)
* don't save duplicate edges

* remove build duplicate edges
2025-09-24 17:24:57 -04:00
Daniel Chalef
7cf5ee6288
Skip entity attribute extraction when no fields defined (#924) 2025-09-24 13:23:37 -04:00
Preston Rasmussen
36056ad141
Graph quality updates (#922)
duplicate_of updates
2025-09-23 17:53:39 -04:00
Gal Shubeli
d725fcdf8e
fix-fulltext-syntax-error (#914)
* fix-fulltext-syntax-error

* update-abs-method
2025-09-23 10:52:44 -04:00
Preston Rasmussen
da71d118db
Embedding fix (#917)
* embedding fix

* pre3

* fixedmake format
2025-09-20 09:00:04 -04:00
Preston Rasmussen
3efe085a92
OpenSearch updates (#906)
* updates

* add uuid filter functionality

* update

* updates

* bump-version

* update

* fix typo

* use async function

* update unit tests

* update delete

* update deletion

* async update

* update

* update

* update

* update
2025-09-14 01:43:37 -04:00
Preston Rasmussen
0884cc00e5
OpenSearch Integration for Neo4j (#896)
* move aoss to driver

* add indexes

* don't save vectors to neo4j with aoss

* load embeddings from aoss

* add group_id routing

* add search filters and similarity search

* neptune regression update

* update neptune for regression purposes

* update index creation with aliasing

* regression tested

* update version

* edits

* claude suggestions

* cleanup

* updates

* add embedding dim env var

* use cosine sim

* updates

* updates

* remove unused imports

* update
2025-09-09 10:51:46 -04:00