graphiti-core 0.13.1__py3-none-any.whl → 0.14.0__py3-none-any.whl

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/graphiti.py CHANGED
@@ -29,7 +29,12 @@ from graphiti_core.driver.neo4j_driver import Neo4jDriver
29
29
  from graphiti_core.edges import EntityEdge, EpisodicEdge
30
30
  from graphiti_core.embedder import EmbedderClient, OpenAIEmbedder
31
31
  from graphiti_core.graphiti_types import GraphitiClients
32
- from graphiti_core.helpers import DEFAULT_DATABASE, semaphore_gather, validate_group_id
32
+ from graphiti_core.helpers import (
33
+ DEFAULT_DATABASE,
34
+ semaphore_gather,
35
+ validate_excluded_entity_types,
36
+ validate_group_id,
37
+ )
33
38
  from graphiti_core.llm_client import LLMClient, OpenAIClient
34
39
  from graphiti_core.nodes import CommunityNode, EntityNode, EpisodeType, EpisodicNode
35
40
  from graphiti_core.search.search import SearchConfig, search
@@ -46,6 +51,7 @@ from graphiti_core.search.search_utils import (
46
51
  get_mentioned_nodes,
47
52
  get_relevant_edges,
48
53
  )
54
+ from graphiti_core.telemetry import capture_event
49
55
  from graphiti_core.utils.bulk_utils import (
50
56
  RawEpisode,
51
57
  add_nodes_and_edges_bulk,
@@ -181,6 +187,61 @@ class Graphiti:
181
187
  cross_encoder=self.cross_encoder,
182
188
  )
183
189
 
190
+ # Capture telemetry event
191
+ self._capture_initialization_telemetry()
192
+
193
+ def _capture_initialization_telemetry(self):
194
+ """Capture telemetry event for Graphiti initialization."""
195
+ try:
196
+ # Detect provider types from class names
197
+ llm_provider = self._get_provider_type(self.llm_client)
198
+ embedder_provider = self._get_provider_type(self.embedder)
199
+ reranker_provider = self._get_provider_type(self.cross_encoder)
200
+ database_provider = self._get_provider_type(self.driver)
201
+
202
+ properties = {
203
+ 'llm_provider': llm_provider,
204
+ 'embedder_provider': embedder_provider,
205
+ 'reranker_provider': reranker_provider,
206
+ 'database_provider': database_provider,
207
+ }
208
+
209
+ capture_event('graphiti_initialized', properties)
210
+ except Exception:
211
+ # Silently handle telemetry errors
212
+ pass
213
+
214
+ def _get_provider_type(self, client) -> str:
215
+ """Get provider type from client class name."""
216
+ if client is None:
217
+ return 'none'
218
+
219
+ class_name = client.__class__.__name__.lower()
220
+
221
+ # LLM providers
222
+ if 'openai' in class_name:
223
+ return 'openai'
224
+ elif 'azure' in class_name:
225
+ return 'azure'
226
+ elif 'anthropic' in class_name:
227
+ return 'anthropic'
228
+ elif 'crossencoder' in class_name:
229
+ return 'crossencoder'
230
+ elif 'gemini' in class_name:
231
+ return 'gemini'
232
+ elif 'groq' in class_name:
233
+ return 'groq'
234
+ # Database providers
235
+ elif 'neo4j' in class_name:
236
+ return 'neo4j'
237
+ elif 'falkor' in class_name:
238
+ return 'falkordb'
239
+ # Embedder providers
240
+ elif 'voyage' in class_name:
241
+ return 'voyage'
242
+ else:
243
+ return 'unknown'
244
+
184
245
  async def close(self):
185
246
  """
186
247
  Close the connection to the Neo4j database.
@@ -293,6 +354,7 @@ class Graphiti:
293
354
  uuid: str | None = None,
294
355
  update_communities: bool = False,
295
356
  entity_types: dict[str, BaseModel] | None = None,
357
+ excluded_entity_types: list[str] | None = None,
296
358
  previous_episode_uuids: list[str] | None = None,
297
359
  edge_types: dict[str, BaseModel] | None = None,
298
360
  edge_type_map: dict[tuple[str, str], list[str]] | None = None,
@@ -321,6 +383,12 @@ class Graphiti:
321
383
  Optional uuid of the episode.
322
384
  update_communities : bool
323
385
  Optional. Whether to update communities with new node information
386
+ entity_types : dict[str, BaseModel] | None
387
+ Optional. Dictionary mapping entity type names to their Pydantic model definitions.
388
+ excluded_entity_types : list[str] | None
389
+ Optional. List of entity type names to exclude from the graph. Entities classified
390
+ into these types will not be added to the graph. Can include 'Entity' to exclude
391
+ the default entity type.
324
392
  previous_episode_uuids : list[str] | None
325
393
  Optional. list of episode uuids to use as the previous episodes. If this is not provided,
326
394
  the most recent episodes by created_at date will be used.
@@ -351,6 +419,7 @@ class Graphiti:
351
419
  now = utc_now()
352
420
 
353
421
  validate_entity_types(entity_types)
422
+ validate_excluded_entity_types(excluded_entity_types, entity_types)
354
423
  validate_group_id(group_id)
355
424
 
356
425
  previous_episodes = (
@@ -389,7 +458,7 @@ class Graphiti:
389
458
  # Extract entities as nodes
390
459
 
391
460
  extracted_nodes = await extract_nodes(
392
- self.clients, episode, previous_episodes, entity_types
461
+ self.clients, episode, previous_episodes, entity_types, excluded_entity_types
393
462
  )
394
463
 
395
464
  # Extract edges and resolve nodes
@@ -534,7 +603,7 @@ class Graphiti:
534
603
  extracted_nodes,
535
604
  extracted_edges,
536
605
  episodic_edges,
537
- ) = await extract_nodes_and_edges_bulk(self.clients, episode_pairs)
606
+ ) = await extract_nodes_and_edges_bulk(self.clients, episode_pairs, None, None)
538
607
 
539
608
  # Generate embeddings
540
609
  await semaphore_gather(
graphiti_core/helpers.py CHANGED
@@ -24,6 +24,7 @@ import numpy as np
24
24
  from dotenv import load_dotenv
25
25
  from neo4j import time as neo4j_time
26
26
  from numpy._typing import NDArray
27
+ from pydantic import BaseModel
27
28
  from typing_extensions import LiteralString
28
29
 
29
30
  from graphiti_core.errors import GroupIdValidationError
@@ -132,3 +133,37 @@ def validate_group_id(group_id: str) -> bool:
132
133
  raise GroupIdValidationError(group_id)
133
134
 
134
135
  return True
136
+
137
+
138
+ def validate_excluded_entity_types(
139
+ excluded_entity_types: list[str] | None, entity_types: dict[str, BaseModel] | None = None
140
+ ) -> bool:
141
+ """
142
+ Validate that excluded entity types are valid type names.
143
+
144
+ Args:
145
+ excluded_entity_types: List of entity type names to exclude
146
+ entity_types: Dictionary of available custom entity types
147
+
148
+ Returns:
149
+ True if valid
150
+
151
+ Raises:
152
+ ValueError: If any excluded type names are invalid
153
+ """
154
+ if not excluded_entity_types:
155
+ return True
156
+
157
+ # Build set of available type names
158
+ available_types = {'Entity'} # Default type is always available
159
+ if entity_types:
160
+ available_types.update(entity_types.keys())
161
+
162
+ # Check for invalid type names
163
+ invalid_types = set(excluded_entity_types) - available_types
164
+ if invalid_types:
165
+ raise ValueError(
166
+ f'Invalid excluded entity types: {sorted(invalid_types)}. Available types: {sorted(available_types)}'
167
+ )
168
+
169
+ return True
graphiti_core/nodes.py CHANGED
@@ -586,6 +586,8 @@ def get_community_node_from_record(record: Any) -> CommunityNode:
586
586
 
587
587
 
588
588
  async def create_entity_node_embeddings(embedder: EmbedderClient, nodes: list[EntityNode]):
589
+ if not nodes: # Handle empty list case
590
+ return
589
591
  name_embeddings = await embedder.create_batch([node.name for node in nodes])
590
592
  for node, name_embedding in zip(nodes, name_embeddings, strict=True):
591
593
  node.name_embedding = name_embedding
@@ -141,6 +141,7 @@ def resolve_edge(context: dict[str, Any]) -> list[Message]:
141
141
 
142
142
  Task:
143
143
  If the NEW FACT represents the same factual information as any fact in EXISTING FACTS, return the idx of the duplicate fact.
144
+ Facts with similar information that contain key differences should not be marked as duplicates.
144
145
  If the NEW FACT is not a duplicate of any of the EXISTING FACTS, return -1.
145
146
 
146
147
  Given the predefined FACT TYPES, determine if the NEW FACT should be classified as one of these types.
@@ -152,6 +153,7 @@ def resolve_edge(context: dict[str, Any]) -> list[Message]:
152
153
 
153
154
  Guidelines:
154
155
  1. The facts do not need to be completely identical to be duplicates, they just need to express the same information.
156
+ 2. Some facts may be very similar but will have key differences, particularly around numeric values in the facts.
155
157
  """,
156
158
  ),
157
159
  ]
@@ -67,7 +67,7 @@ def fulltext_query(query: str, group_ids: list[str] | None = None):
67
67
  )
68
68
  group_ids_filter = ''
69
69
  for f in group_ids_filter_list:
70
- group_ids_filter += f if not group_ids_filter else f'OR {f}'
70
+ group_ids_filter += f if not group_ids_filter else f' OR {f}'
71
71
 
72
72
  group_ids_filter += ' AND ' if group_ids_filter else ''
73
73
 
@@ -0,0 +1,9 @@
1
+ """
2
+ Telemetry module for Graphiti.
3
+
4
+ This module provides anonymous usage analytics to help improve Graphiti.
5
+ """
6
+
7
+ from .telemetry import capture_event, is_telemetry_enabled
8
+
9
+ __all__ = ['capture_event', 'is_telemetry_enabled']
@@ -0,0 +1,117 @@
1
+ """
2
+ Telemetry client for Graphiti.
3
+
4
+ Collects anonymous usage statistics to help improve the product.
5
+ """
6
+
7
+ import contextlib
8
+ import os
9
+ import platform
10
+ import sys
11
+ import uuid
12
+ from pathlib import Path
13
+ from typing import Any
14
+
15
+ # PostHog configuration
16
+ # Note: This is a public API key intended for client-side use and safe to commit
17
+ # PostHog public keys are designed to be exposed in client applications
18
+ POSTHOG_API_KEY = 'phc_UG6EcfDbuXz92neb3rMlQFDY0csxgMqRcIPWESqnSmo'
19
+ POSTHOG_HOST = 'https://us.i.posthog.com'
20
+
21
+ # Environment variable to control telemetry
22
+ TELEMETRY_ENV_VAR = 'GRAPHITI_TELEMETRY_ENABLED'
23
+
24
+ # Cache directory for anonymous ID
25
+ CACHE_DIR = Path.home() / '.cache' / 'graphiti'
26
+ ANON_ID_FILE = CACHE_DIR / 'telemetry_anon_id'
27
+
28
+
29
+ def is_telemetry_enabled() -> bool:
30
+ """Check if telemetry is enabled."""
31
+ # Disable during pytest runs
32
+ if 'pytest' in sys.modules:
33
+ return False
34
+
35
+ # Check environment variable (default: enabled)
36
+ env_value = os.environ.get(TELEMETRY_ENV_VAR, 'true').lower()
37
+ return env_value in ('true', '1', 'yes', 'on')
38
+
39
+
40
+ def get_anonymous_id() -> str:
41
+ """Get or create anonymous user ID."""
42
+ try:
43
+ # Create cache directory if it doesn't exist
44
+ CACHE_DIR.mkdir(parents=True, exist_ok=True)
45
+
46
+ # Try to read existing ID
47
+ if ANON_ID_FILE.exists():
48
+ try:
49
+ return ANON_ID_FILE.read_text().strip()
50
+ except Exception:
51
+ pass
52
+
53
+ # Generate new ID
54
+ anon_id = str(uuid.uuid4())
55
+
56
+ # Save to file
57
+ with contextlib.suppress(Exception):
58
+ ANON_ID_FILE.write_text(anon_id)
59
+
60
+ return anon_id
61
+ except Exception:
62
+ return 'UNKNOWN'
63
+
64
+
65
+ def get_graphiti_version() -> str:
66
+ """Get Graphiti version."""
67
+ try:
68
+ # Try to get version from package metadata
69
+ import importlib.metadata
70
+
71
+ return importlib.metadata.version('graphiti-core')
72
+ except Exception:
73
+ return 'unknown'
74
+
75
+
76
+ def initialize_posthog():
77
+ """Initialize PostHog client."""
78
+ try:
79
+ import posthog
80
+
81
+ posthog.api_key = POSTHOG_API_KEY
82
+ posthog.host = POSTHOG_HOST
83
+ return posthog
84
+ except ImportError:
85
+ # PostHog not installed, silently disable telemetry
86
+ return None
87
+ except Exception:
88
+ # Any other error, silently disable telemetry
89
+ return None
90
+
91
+
92
+ def capture_event(event_name: str, properties: dict[str, Any] | None = None) -> None:
93
+ """Capture a telemetry event."""
94
+ if not is_telemetry_enabled():
95
+ return
96
+
97
+ try:
98
+ posthog_client = initialize_posthog()
99
+ if posthog_client is None:
100
+ return
101
+
102
+ # Get anonymous ID
103
+ user_id = get_anonymous_id()
104
+
105
+ # Prepare event properties
106
+ event_properties = {
107
+ '$process_person_profile': False,
108
+ 'graphiti_version': get_graphiti_version(),
109
+ 'architecture': platform.machine(),
110
+ **(properties or {}),
111
+ }
112
+
113
+ # Capture the event
114
+ posthog_client.capture(distinct_id=user_id, event=event_name, properties=event_properties)
115
+ except Exception:
116
+ # Silently handle all telemetry errors to avoid disrupting the main application
117
+ pass
@@ -177,11 +177,14 @@ async def add_nodes_and_edges_bulk_tx(
177
177
 
178
178
 
179
179
  async def extract_nodes_and_edges_bulk(
180
- clients: GraphitiClients, episode_tuples: list[tuple[EpisodicNode, list[EpisodicNode]]]
180
+ clients: GraphitiClients,
181
+ episode_tuples: list[tuple[EpisodicNode, list[EpisodicNode]]],
182
+ entity_types: dict[str, BaseModel] | None = None,
183
+ excluded_entity_types: list[str] | None = None,
181
184
  ) -> tuple[list[EntityNode], list[EntityEdge], list[EpisodicEdge]]:
182
185
  extracted_nodes_bulk = await semaphore_gather(
183
186
  *[
184
- extract_nodes(clients, episode, previous_episodes)
187
+ extract_nodes(clients, episode, previous_episodes, entity_types, excluded_entity_types)
185
188
  for episode, previous_episodes in episode_tuples
186
189
  ]
187
190
  )
@@ -71,6 +71,7 @@ async def extract_nodes(
71
71
  episode: EpisodicNode,
72
72
  previous_episodes: list[EpisodicNode],
73
73
  entity_types: dict[str, BaseModel] | None = None,
74
+ excluded_entity_types: list[str] | None = None,
74
75
  ) -> list[EntityNode]:
75
76
  start = time()
76
77
  llm_client = clients.llm_client
@@ -154,6 +155,11 @@ async def extract_nodes(
154
155
  'entity_type_name'
155
156
  )
156
157
 
158
+ # Check if this entity type should be excluded
159
+ if excluded_entity_types and entity_type_name in excluded_entity_types:
160
+ logger.debug(f'Excluding entity "{extracted_entity.name}" of type "{entity_type_name}"')
161
+ continue
162
+
157
163
  labels: list[str] = list({'Entity', str(entity_type_name)})
158
164
 
159
165
  new_node = EntityNode(
@@ -1,34 +1,48 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: graphiti-core
3
- Version: 0.13.1
3
+ Version: 0.14.0
4
4
  Summary: A temporal graph building library
5
- License: Apache-2.0
6
- Author: Paul Paliychuk
7
- Author-email: paul@getzep.com
8
- Requires-Python: >=3.10,<4
9
- Classifier: License :: OSI Approved :: Apache Software License
10
- Classifier: Programming Language :: Python :: 3
11
- Classifier: Programming Language :: Python :: 3.10
12
- Classifier: Programming Language :: Python :: 3.11
13
- Classifier: Programming Language :: Python :: 3.12
14
- Classifier: Programming Language :: Python :: 3.13
5
+ Project-URL: Homepage, https://help.getzep.com/graphiti/graphiti/overview
6
+ Project-URL: Repository, https://github.com/getzep/graphiti
7
+ Author-email: Paul Paliychuk <paul@getzep.com>, Preston Rasmussen <preston@getzep.com>, Daniel Chalef <daniel@getzep.com>
8
+ License-Expression: Apache-2.0
9
+ License-File: LICENSE
10
+ Requires-Python: <4,>=3.10
11
+ Requires-Dist: diskcache>=5.6.3
12
+ Requires-Dist: neo4j>=5.26.0
13
+ Requires-Dist: numpy>=1.0.0
14
+ Requires-Dist: openai>=1.91.0
15
+ Requires-Dist: posthog>=3.0.0
16
+ Requires-Dist: pydantic>=2.11.5
17
+ Requires-Dist: python-dotenv>=1.0.1
18
+ Requires-Dist: tenacity>=9.0.0
15
19
  Provides-Extra: anthropic
20
+ Requires-Dist: anthropic>=0.49.0; extra == 'anthropic'
21
+ Provides-Extra: dev
22
+ Requires-Dist: anthropic>=0.49.0; extra == 'dev'
23
+ Requires-Dist: diskcache-stubs>=5.6.3.6.20240818; extra == 'dev'
24
+ Requires-Dist: google-genai>=1.8.0; extra == 'dev'
25
+ Requires-Dist: groq>=0.2.0; extra == 'dev'
26
+ Requires-Dist: ipykernel>=6.29.5; extra == 'dev'
27
+ Requires-Dist: jupyterlab>=4.2.4; extra == 'dev'
28
+ Requires-Dist: langchain-anthropic>=0.2.4; extra == 'dev'
29
+ Requires-Dist: langchain-openai>=0.2.6; extra == 'dev'
30
+ Requires-Dist: langgraph>=0.2.15; extra == 'dev'
31
+ Requires-Dist: langsmith>=0.1.108; extra == 'dev'
32
+ Requires-Dist: mypy>=1.11.1; extra == 'dev'
33
+ Requires-Dist: pytest-asyncio>=0.24.0; extra == 'dev'
34
+ Requires-Dist: pytest-xdist>=3.6.1; extra == 'dev'
35
+ Requires-Dist: pytest>=8.3.3; extra == 'dev'
36
+ Requires-Dist: ruff>=0.7.1; extra == 'dev'
37
+ Requires-Dist: sentence-transformers>=3.2.1; extra == 'dev'
38
+ Requires-Dist: transformers>=4.45.2; extra == 'dev'
39
+ Requires-Dist: voyageai>=0.2.3; extra == 'dev'
16
40
  Provides-Extra: falkord-db
41
+ Requires-Dist: falkordb<2.0.0,>=1.1.2; extra == 'falkord-db'
17
42
  Provides-Extra: google-genai
43
+ Requires-Dist: google-genai>=1.8.0; extra == 'google-genai'
18
44
  Provides-Extra: groq
19
- Requires-Dist: anthropic (>=0.49.0) ; extra == "anthropic"
20
- Requires-Dist: diskcache (>=5.6.3)
21
- Requires-Dist: falkordb (>=1.1.2,<2.0.0) ; extra == "falkord-db"
22
- Requires-Dist: google-genai (>=1.8.0) ; extra == "google-genai"
23
- Requires-Dist: groq (>=0.2.0) ; extra == "groq"
24
- Requires-Dist: neo4j (>=5.26.0)
25
- Requires-Dist: numpy (>=1.0.0)
26
- Requires-Dist: openai (>=1.91.0)
27
- Requires-Dist: pydantic (>=2.11.5)
28
- Requires-Dist: python-dotenv (>=1.0.1)
29
- Requires-Dist: tenacity (>=9.0.0)
30
- Project-URL: Homepage, https://help.getzep.com/graphiti/graphiti/overview
31
- Project-URL: Repository, https://github.com/getzep/graphiti
45
+ Requires-Dist: groq>=0.2.0; extra == 'groq'
32
46
  Description-Content-Type: text/markdown
33
47
 
34
48
  <p align="center">
@@ -161,7 +175,7 @@ pip install graphiti-core
161
175
  or
162
176
 
163
177
  ```bash
164
- poetry add graphiti-core
178
+ uv add graphiti-core
165
179
  ```
166
180
 
167
181
  You can also install optional LLM providers as extras:
@@ -294,11 +308,11 @@ Graphiti supports Google's Gemini models for both LLM inference and embeddings.
294
308
  Install Graphiti:
295
309
 
296
310
  ```bash
297
- poetry add "graphiti-core[google-genai]"
311
+ uv add "graphiti-core[google-genai]"
298
312
 
299
313
  # or
300
314
 
301
- uv add "graphiti-core[google-genai]"
315
+ pip install "graphiti-core[google-genai]"
302
316
  ```
303
317
 
304
318
  ```python
@@ -335,10 +349,9 @@ graphiti = Graphiti(
335
349
 
336
350
  Graphiti supports Ollama for running local LLMs and embedding models via Ollama's OpenAI-compatible API. This is ideal for privacy-focused applications or when you want to avoid API costs.
337
351
 
338
-
339
352
  Install the models:
340
- ollama pull deepseek-r1:7b # LLM
341
- ollama pull nomic-embed-text # embeddings
353
+ ollama pull deepseek-r1:7b # LLM
354
+ ollama pull nomic-embed-text # embeddings
342
355
 
343
356
  ```python
344
357
  from graphiti_core import Graphiti
@@ -379,13 +392,93 @@ graphiti = Graphiti(
379
392
 
380
393
  Ensure Ollama is running (`ollama serve`) and that you have pulled the models you want to use.
381
394
 
382
-
383
395
  ## Documentation
384
396
 
385
397
  - [Guides and API documentation](https://help.getzep.com/graphiti).
386
398
  - [Quick Start](https://help.getzep.com/graphiti/graphiti/quick-start)
387
399
  - [Building an agent with LangChain's LangGraph and Graphiti](https://help.getzep.com/graphiti/graphiti/lang-graph-agent)
388
400
 
401
+ ## Telemetry
402
+
403
+ Graphiti collects anonymous usage statistics to help us understand how the framework is being used and improve it for everyone. We believe transparency is important, so here's exactly what we collect and why.
404
+
405
+ ### What We Collect
406
+
407
+ When you initialize a Graphiti instance, we collect:
408
+
409
+ - **Anonymous identifier**: A randomly generated UUID stored locally in `~/.cache/graphiti/telemetry_anon_id`
410
+ - **System information**: Operating system, Python version, and system architecture
411
+ - **Graphiti version**: The version you're using
412
+ - **Configuration choices**:
413
+ - LLM provider type (OpenAI, Azure, Anthropic, etc.)
414
+ - Database backend (Neo4j, FalkorDB)
415
+ - Embedder provider (OpenAI, Azure, Voyage, etc.)
416
+
417
+ ### What We Don't Collect
418
+
419
+ We are committed to protecting your privacy. We **never** collect:
420
+
421
+ - Personal information or identifiers
422
+ - API keys or credentials
423
+ - Your actual data, queries, or graph content
424
+ - IP addresses or hostnames
425
+ - File paths or system-specific information
426
+ - Any content from your episodes, nodes, or edges
427
+
428
+ ### Why We Collect This Data
429
+
430
+ This information helps us:
431
+
432
+ - Understand which configurations are most popular to prioritize support and testing
433
+ - Identify which LLM and database providers to focus development efforts on
434
+ - Track adoption patterns to guide our roadmap
435
+ - Ensure compatibility across different Python versions and operating systems
436
+
437
+ By sharing this anonymous information, you help us make Graphiti better for everyone in the community.
438
+
439
+ ### View the Telemetry Code
440
+
441
+ The Telemetry code [may be found here](graphiti_core/telemetry/telemetry.py).
442
+
443
+ ### How to Disable Telemetry
444
+
445
+ Telemetry is **opt-out** and can be disabled at any time. To disable telemetry collection:
446
+
447
+ **Option 1: Environment Variable**
448
+
449
+ ```bash
450
+ export GRAPHITI_TELEMETRY_ENABLED=false
451
+ ```
452
+
453
+ **Option 2: Set in your shell profile**
454
+
455
+ ```bash
456
+ # For bash users (~/.bashrc or ~/.bash_profile)
457
+ echo 'export GRAPHITI_TELEMETRY_ENABLED=false' >> ~/.bashrc
458
+
459
+ # For zsh users (~/.zshrc)
460
+ echo 'export GRAPHITI_TELEMETRY_ENABLED=false' >> ~/.zshrc
461
+ ```
462
+
463
+ **Option 3: Set for a specific Python session**
464
+
465
+ ```python
466
+ import os
467
+ os.environ['GRAPHITI_TELEMETRY_ENABLED'] = 'false'
468
+
469
+ # Then initialize Graphiti as usual
470
+ from graphiti_core import Graphiti
471
+ graphiti = Graphiti(...)
472
+ ```
473
+
474
+ Telemetry is automatically disabled during test runs (when `pytest` is detected).
475
+
476
+ ### Technical Details
477
+
478
+ - Telemetry uses PostHog for anonymous analytics collection
479
+ - All telemetry operations are designed to fail silently - they will never interrupt your application or affect Graphiti functionality
480
+ - The anonymous ID is stored locally and is not tied to any personal information
481
+
389
482
  ## Status and Roadmap
390
483
 
391
484
  Graphiti is under active development. We aim to maintain API stability while working on:
@@ -406,4 +499,3 @@ to [CONTRIBUTING](CONTRIBUTING.md).
406
499
  ## Support
407
500
 
408
501
  Join the [Zep Discord server](https://discord.com/invite/W8Kw6bsgXQ) and make your way to the **#Graphiti** channel!
409
-
@@ -1,4 +1,12 @@
1
1
  graphiti_core/__init__.py,sha256=e5SWFkRiaUwfprYIeIgVIh7JDedNiloZvd3roU-0aDY,55
2
+ graphiti_core/edges.py,sha256=h67vyXYhZYqlwaOmaqjHiGns6nEjuBVSIAFBMveNVo8,16257
3
+ graphiti_core/errors.py,sha256=cH_v9TPgEPeQE6GFOHIg5TvejpUCBddGarMY2Whxbwc,2707
4
+ graphiti_core/graph_queries.py,sha256=KfWDp8xDnPa9bcHskw8NeMpeeHBtZWBCosVdu1Iwv34,7076
5
+ graphiti_core/graphiti.py,sha256=FzSTwU5zK6aFOETXLzdEvGn8yuf5cEjrBfnwabYY-xw,32990
6
+ graphiti_core/graphiti_types.py,sha256=rL-9bvnLobunJfXU4hkD6mAj14pofKp_wq8QsFDZwDU,1035
7
+ graphiti_core/helpers.py,sha256=xHSlDlu5cCLOw40EeJSzshUqdsbqsNqv9AGGIiI-7qI,4907
8
+ graphiti_core/nodes.py,sha256=WG7czM-neIeUDjLc5JCS1k0xRDANMY1lT9rDBc7Ms8U,18724
9
+ graphiti_core/py.typed,sha256=vlmmzQOt7bmeQl9L3XJP4W6Ry0iiELepnOrinKz5KQg,79
2
10
  graphiti_core/cross_encoder/__init__.py,sha256=hry59vz21x-AtGZ0MJ7ugw0HTwJkXiddpp_Yqnwsen0,723
3
11
  graphiti_core/cross_encoder/bge_reranker_client.py,sha256=sY7RKsCp90vTjYxv6vmIHT4p3oCsFCRYWH-H0Ia0vN0,1449
4
12
  graphiti_core/cross_encoder/client.py,sha256=KLsbfWKOEaAV3adFe3XZlAeb-gje9_sVKCVZTaJP3ac,1441
@@ -7,18 +15,12 @@ graphiti_core/driver/__init__.py,sha256=DumfxIEY3z_nkz5YGaYH1GM50HgeAdEowNK189jc
7
15
  graphiti_core/driver/driver.py,sha256=-FHAA2gM8FA0re-q6udmjQ6pNFdFGRQrMRuAiqX_1A4,1829
8
16
  graphiti_core/driver/falkordb_driver.py,sha256=Iz3wnfoJIO7EslqZvG6mduyZ5C-DWxFDPM5Q4QJRCuo,4686
9
17
  graphiti_core/driver/neo4j_driver.py,sha256=D8CV5GbhKoHIQ78BA9ozlwdvXPLUbBmFSfT2lww8PJk,1910
10
- graphiti_core/edges.py,sha256=h67vyXYhZYqlwaOmaqjHiGns6nEjuBVSIAFBMveNVo8,16257
11
18
  graphiti_core/embedder/__init__.py,sha256=EL564ZuE-DZjcuKNUK_exMn_XHXm2LdO9fzdXePVKL4,179
12
19
  graphiti_core/embedder/azure_openai.py,sha256=OyomPwC1fIsddI-3n6g00kQFdQznZorBhHwkQKCLUok,2384
13
20
  graphiti_core/embedder/client.py,sha256=qEpSHceL_Gc4QQPJWIOnuNLemNuR_TYA4r28t2Vldbg,1115
14
21
  graphiti_core/embedder/gemini.py,sha256=7En-W46YxqC5qL3vYB5Ed-Xm0hqLxi7-LgZ95c4M7ME,3263
15
22
  graphiti_core/embedder/openai.py,sha256=bIThUoLMeGlHG2-3VikzK6JZfOHKn4PKvUMx5sHxJy8,2192
16
23
  graphiti_core/embedder/voyage.py,sha256=gQhdcz2IYPSyOcDn3w8aHToVS3KQhyZrUBm4vqr3WcE,2224
17
- graphiti_core/errors.py,sha256=cH_v9TPgEPeQE6GFOHIg5TvejpUCBddGarMY2Whxbwc,2707
18
- graphiti_core/graph_queries.py,sha256=KfWDp8xDnPa9bcHskw8NeMpeeHBtZWBCosVdu1Iwv34,7076
19
- graphiti_core/graphiti.py,sha256=6TcOq65HEtJ5gQ29YHJ6HVhBkjsoWtv_mVhlcZok2MY,30399
20
- graphiti_core/graphiti_types.py,sha256=rL-9bvnLobunJfXU4hkD6mAj14pofKp_wq8QsFDZwDU,1035
21
- graphiti_core/helpers.py,sha256=0qmGnKxxYk27JGQbx6PlM7E6nRghUrEKBym0d3WSJY4,3875
22
24
  graphiti_core/llm_client/__init__.py,sha256=QgBWUiCeBp6YiA_xqyrDvJ9jIyy1hngH8g7FWahN3nw,776
23
25
  graphiti_core/llm_client/anthropic_client.py,sha256=392rtkH_I7yOJUlQvjoOnS8Lz14WBP8egQ3OfRH0nFs,12481
24
26
  graphiti_core/llm_client/azure_openai_client.py,sha256=ekERggAekbb7enes1RJqdRChf_mjaZTFXsnMbxO7azQ,2497
@@ -36,9 +38,8 @@ graphiti_core/models/edges/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
36
38
  graphiti_core/models/edges/edge_db_queries.py,sha256=4vSWdmE5MKoDrlHJmmr2xNhVSQ-buE1O7mCX_H0Wtfk,2294
37
39
  graphiti_core/models/nodes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
40
  graphiti_core/models/nodes/node_db_queries.py,sha256=AQgRGVO-GgFWfLq1G6k8s86WItwpXruy3Mj4DBli-vM,2145
39
- graphiti_core/nodes.py,sha256=kdJY-Ugyk6J2x70w4EF_EoFNgy7D3TMOMVSUfEth6rE,18665
40
41
  graphiti_core/prompts/__init__.py,sha256=EA-x9xUki9l8wnu2l8ek_oNf75-do5tq5hVq7Zbv8Kw,101
41
- graphiti_core/prompts/dedupe_edges.py,sha256=AFVC1EQ0TvNkSp0G7QZmIh3YpGg9FVXo1_sT3TlRqA8,5473
42
+ graphiti_core/prompts/dedupe_edges.py,sha256=-Fq8YlCPHOEnjJceSOy68dya3VIbmvMtcS8V9u9Tv6g,5699
42
43
  graphiti_core/prompts/dedupe_nodes.py,sha256=WdSnqu6O4TkEE_z1u2CEnNH0sWgBNDl4dUx20gSp464,7852
43
44
  graphiti_core/prompts/eval.py,sha256=gnBQTmwsCl3Qvwpcm7aieVszzo6y1sMCUT8jQiKTvvE,5317
44
45
  graphiti_core/prompts/extract_edge_dates.py,sha256=3Drs3CmvP0gJN5BidWSxrNvLet3HPoTybU3BUIAoc0Y,4218
@@ -49,26 +50,27 @@ graphiti_core/prompts/lib.py,sha256=DCyHePM4_q-CptTpEXGO_dBv9k7xDtclEaB1dGu7EcI,
49
50
  graphiti_core/prompts/models.py,sha256=NgxdbPHJpBEcpbXovKyScgpBc73Q-GIW-CBDlBtDjto,894
50
51
  graphiti_core/prompts/prompt_helpers.py,sha256=-9TABwIcIQUVHcNANx6wIZd-FT2DgYKyGTfx4IGYq2I,64
51
52
  graphiti_core/prompts/summarize_nodes.py,sha256=tbg-AgWlzgFBeImKkZ28h2SpmqfPPqvN2Ol1Q71VF9Y,4146
52
- graphiti_core/py.typed,sha256=vlmmzQOt7bmeQl9L3XJP4W6Ry0iiELepnOrinKz5KQg,79
53
53
  graphiti_core/search/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
54
54
  graphiti_core/search/search.py,sha256=bJCFaNApu5396pXTa-xciu8ORDdRFJqfE3j2ieRVd7Y,15162
55
55
  graphiti_core/search/search_config.py,sha256=VvKg6AB_RPhoe56DBBXHRBXHThAVJ_OLFCyq_yKof-A,3765
56
56
  graphiti_core/search/search_config_recipes.py,sha256=4GquRphHhJlpXQhAZOySYnCzBWYoTwxlJj44eTOavZQ,7443
57
57
  graphiti_core/search/search_filters.py,sha256=jG30nMWX03xoT9ohgyHNu_Xes8GwjIF2eTv6QaiWMqw,6466
58
58
  graphiti_core/search/search_helpers.py,sha256=G5Ceaq5Pfgx0Weelqgeylp_pUHwiBnINaUYsDbURJbE,2636
59
- graphiti_core/search/search_utils.py,sha256=q-FMbSFf7mPXWdgnKQDKQIACrHI8NwqknGDnMy4dJzs,34957
59
+ graphiti_core/search/search_utils.py,sha256=74d3RDbx9MWkDei1U5g0K5l1EenzB1NPNYdSP9l8aEg,34958
60
+ graphiti_core/telemetry/__init__.py,sha256=5kALLDlU9bb2v19CdN7qVANsJWyfnL9E60J6FFgzm3o,226
61
+ graphiti_core/telemetry/telemetry.py,sha256=47LrzOVBCcZxsYPsnSxWFiztHoxYKKxPwyRX0hnbDGc,3230
60
62
  graphiti_core/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
61
- graphiti_core/utils/bulk_utils.py,sha256=RPPTAqBRg6iR1T6g6TDpfUGvkYmTEyVNrVPz_y91f-s,16196
63
+ graphiti_core/utils/bulk_utils.py,sha256=YnyXzmOFgqbLdIAIu9Y6aJjUZHhXj8nBnlegkXBTKi8,16344
62
64
  graphiti_core/utils/datetime_utils.py,sha256=Ti-2tnrDFRzBsbfblzsHybsM3jaDLP4-VT2t0VhpIzU,1357
63
65
  graphiti_core/utils/maintenance/__init__.py,sha256=vW4H1KyapTl-OOz578uZABYcpND4wPx3Vt6aAPaXh78,301
64
66
  graphiti_core/utils/maintenance/community_operations.py,sha256=2rhRqtL9gDbjXKO4-S0nGpaWvS4ck5rFiazZiogIJao,10088
65
67
  graphiti_core/utils/maintenance/edge_operations.py,sha256=Fwu2TLmQF_9EVcA-uUlt1ZiGC6RILIfKDr9W7R4gAno,21633
66
68
  graphiti_core/utils/maintenance/graph_data_operations.py,sha256=OHuiAyP1Z7dfR90dWVQ87TJQO83P0sQihJyr4WIhOhk,5362
67
- graphiti_core/utils/maintenance/node_operations.py,sha256=-PC1N-Hf2GElhLcTTSjTaCVvQdJdNpouJPB7joGACZo,15566
69
+ graphiti_core/utils/maintenance/node_operations.py,sha256=0WdH_VrkVXLV9YX3xPErXOFygOo2N9g3es9yIB2Yl8Q,15876
68
70
  graphiti_core/utils/maintenance/temporal_operations.py,sha256=mJkw9xLB4W2BsLfC5POr0r-PHWL9SIfNj_l_xu0B5ug,3410
69
71
  graphiti_core/utils/maintenance/utils.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
70
72
  graphiti_core/utils/ontology_utils/entity_types_utils.py,sha256=QJX5cG0GSSNF_Mm_yrldr69wjVAbN_MxLhOSznz85Hk,1279
71
- graphiti_core-0.13.1.dist-info/LICENSE,sha256=KCUwCyDXuVEgmDWkozHyniRyWjnWUWjkuDHfU6o3JlA,11325
72
- graphiti_core-0.13.1.dist-info/METADATA,sha256=BDBOGDqgXsLJu_FWwPHaVfOVSeTYJCIw5tfdcmnl884,17229
73
- graphiti_core-0.13.1.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
74
- graphiti_core-0.13.1.dist-info/RECORD,,
73
+ graphiti_core-0.14.0.dist-info/METADATA,sha256=ePJs8ax8EBgFysrMfz-D_uJ9RKo6O5T5DjvETb7ijqU,20591
74
+ graphiti_core-0.14.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
75
+ graphiti_core-0.14.0.dist-info/licenses/LICENSE,sha256=KCUwCyDXuVEgmDWkozHyniRyWjnWUWjkuDHfU6o3JlA,11325
76
+ graphiti_core-0.14.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.1.2
2
+ Generator: hatchling 1.27.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any