graphiti-core 0.18.0__py3-none-any.whl → 0.18.1__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/driver/driver.py +20 -2
- graphiti_core/driver/falkordb_driver.py +16 -9
- graphiti_core/driver/neo4j_driver.py +8 -6
- graphiti_core/edges.py +73 -99
- graphiti_core/graph_queries.py +51 -97
- graphiti_core/graphiti.py +23 -8
- graphiti_core/helpers.py +3 -2
- graphiti_core/models/edges/edge_db_queries.py +106 -32
- graphiti_core/models/nodes/node_db_queries.py +101 -20
- graphiti_core/nodes.py +113 -128
- graphiti_core/prompts/dedupe_nodes.py +1 -1
- graphiti_core/prompts/extract_edges.py +4 -4
- graphiti_core/prompts/extract_nodes.py +12 -10
- graphiti_core/search/search_filters.py +5 -5
- graphiti_core/search/search_utils.py +139 -184
- graphiti_core/utils/bulk_utils.py +3 -5
- graphiti_core/utils/maintenance/community_operations.py +11 -7
- graphiti_core/utils/maintenance/edge_operations.py +19 -50
- graphiti_core/utils/maintenance/graph_data_operations.py +14 -29
- graphiti_core/utils/maintenance/node_operations.py +11 -55
- {graphiti_core-0.18.0.dist-info → graphiti_core-0.18.1.dist-info}/METADATA +11 -3
- {graphiti_core-0.18.0.dist-info → graphiti_core-0.18.1.dist-info}/RECORD +24 -24
- {graphiti_core-0.18.0.dist-info → graphiti_core-0.18.1.dist-info}/WHEEL +0 -0
- {graphiti_core-0.18.0.dist-info → graphiti_core-0.18.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -34,7 +34,7 @@ async def get_community_clusters(
|
|
|
34
34
|
group_id_values, _, _ = await driver.execute_query(
|
|
35
35
|
"""
|
|
36
36
|
MATCH (n:Entity WHERE n.group_id IS NOT NULL)
|
|
37
|
-
RETURN
|
|
37
|
+
RETURN
|
|
38
38
|
collect(DISTINCT n.group_id) AS group_ids
|
|
39
39
|
""",
|
|
40
40
|
)
|
|
@@ -233,10 +233,10 @@ async def determine_entity_community(
|
|
|
233
233
|
"""
|
|
234
234
|
MATCH (c:Community)-[:HAS_MEMBER]->(n:Entity {uuid: $entity_uuid})
|
|
235
235
|
RETURN
|
|
236
|
-
c.uuid
|
|
236
|
+
c.uuid AS uuid,
|
|
237
237
|
c.name AS name,
|
|
238
238
|
c.group_id AS group_id,
|
|
239
|
-
c.created_at AS created_at,
|
|
239
|
+
c.created_at AS created_at,
|
|
240
240
|
c.summary AS summary
|
|
241
241
|
""",
|
|
242
242
|
entity_uuid=entity.uuid,
|
|
@@ -250,10 +250,10 @@ async def determine_entity_community(
|
|
|
250
250
|
"""
|
|
251
251
|
MATCH (c:Community)-[:HAS_MEMBER]->(m:Entity)-[:RELATES_TO]-(n:Entity {uuid: $entity_uuid})
|
|
252
252
|
RETURN
|
|
253
|
-
c.uuid
|
|
253
|
+
c.uuid AS uuid,
|
|
254
254
|
c.name AS name,
|
|
255
255
|
c.group_id AS group_id,
|
|
256
|
-
c.created_at AS created_at,
|
|
256
|
+
c.created_at AS created_at,
|
|
257
257
|
c.summary AS summary
|
|
258
258
|
""",
|
|
259
259
|
entity_uuid=entity.uuid,
|
|
@@ -286,11 +286,11 @@ async def determine_entity_community(
|
|
|
286
286
|
|
|
287
287
|
async def update_community(
|
|
288
288
|
driver: GraphDriver, llm_client: LLMClient, embedder: EmbedderClient, entity: EntityNode
|
|
289
|
-
):
|
|
289
|
+
) -> tuple[list[CommunityNode], list[CommunityEdge]]:
|
|
290
290
|
community, is_new = await determine_entity_community(driver, entity)
|
|
291
291
|
|
|
292
292
|
if community is None:
|
|
293
|
-
return
|
|
293
|
+
return [], []
|
|
294
294
|
|
|
295
295
|
new_summary = await summarize_pair(llm_client, (entity.summary, community.summary))
|
|
296
296
|
new_name = await generate_summary_description(llm_client, new_summary)
|
|
@@ -298,10 +298,14 @@ async def update_community(
|
|
|
298
298
|
community.summary = new_summary
|
|
299
299
|
community.name = new_name
|
|
300
300
|
|
|
301
|
+
community_edges = []
|
|
301
302
|
if is_new:
|
|
302
303
|
community_edge = (build_community_edges([entity], community, utc_now()))[0]
|
|
303
304
|
await community_edge.save(driver)
|
|
305
|
+
community_edges.append(community_edge)
|
|
304
306
|
|
|
305
307
|
await community.generate_name_embedding(embedder)
|
|
306
308
|
|
|
307
309
|
await community.save(driver)
|
|
310
|
+
|
|
311
|
+
return [community], community_edges
|
|
@@ -34,7 +34,7 @@ from graphiti_core.llm_client import LLMClient
|
|
|
34
34
|
from graphiti_core.llm_client.config import ModelSize
|
|
35
35
|
from graphiti_core.nodes import CommunityNode, EntityNode, EpisodicNode
|
|
36
36
|
from graphiti_core.prompts import prompt_library
|
|
37
|
-
from graphiti_core.prompts.dedupe_edges import EdgeDuplicate
|
|
37
|
+
from graphiti_core.prompts.dedupe_edges import EdgeDuplicate
|
|
38
38
|
from graphiti_core.prompts.extract_edges import ExtractedEdges, MissingFacts
|
|
39
39
|
from graphiti_core.search.search_filters import SearchFilters
|
|
40
40
|
from graphiti_core.search.search_utils import get_edge_invalidation_candidates, get_relevant_edges
|
|
@@ -161,9 +161,9 @@ async def extract_edges(
|
|
|
161
161
|
response_model=ExtractedEdges,
|
|
162
162
|
max_tokens=extract_edges_max_tokens,
|
|
163
163
|
)
|
|
164
|
-
edges_data = llm_response.
|
|
164
|
+
edges_data = ExtractedEdges(**llm_response).edges
|
|
165
165
|
|
|
166
|
-
context['extracted_facts'] = [edge_data.
|
|
166
|
+
context['extracted_facts'] = [edge_data.fact for edge_data in edges_data]
|
|
167
167
|
|
|
168
168
|
reflexion_iterations += 1
|
|
169
169
|
if reflexion_iterations < MAX_REFLEXION_ITERATIONS:
|
|
@@ -193,20 +193,20 @@ async def extract_edges(
|
|
|
193
193
|
edges = []
|
|
194
194
|
for edge_data in edges_data:
|
|
195
195
|
# Validate Edge Date information
|
|
196
|
-
valid_at = edge_data.
|
|
197
|
-
invalid_at = edge_data.
|
|
196
|
+
valid_at = edge_data.valid_at
|
|
197
|
+
invalid_at = edge_data.invalid_at
|
|
198
198
|
valid_at_datetime = None
|
|
199
199
|
invalid_at_datetime = None
|
|
200
200
|
|
|
201
|
-
source_node_idx = edge_data.
|
|
202
|
-
target_node_idx = edge_data.
|
|
201
|
+
source_node_idx = edge_data.source_entity_id
|
|
202
|
+
target_node_idx = edge_data.target_entity_id
|
|
203
203
|
if not (-1 < source_node_idx < len(nodes) and -1 < target_node_idx < len(nodes)):
|
|
204
204
|
logger.warning(
|
|
205
|
-
f'WARNING: source or target node not filled {edge_data.
|
|
205
|
+
f'WARNING: source or target node not filled {edge_data.relation_type}. source_node_uuid: {source_node_idx} and target_node_uuid: {target_node_idx} '
|
|
206
206
|
)
|
|
207
207
|
continue
|
|
208
208
|
source_node_uuid = nodes[source_node_idx].uuid
|
|
209
|
-
target_node_uuid = nodes[edge_data.
|
|
209
|
+
target_node_uuid = nodes[edge_data.target_entity_id].uuid
|
|
210
210
|
|
|
211
211
|
if valid_at:
|
|
212
212
|
try:
|
|
@@ -226,9 +226,9 @@ async def extract_edges(
|
|
|
226
226
|
edge = EntityEdge(
|
|
227
227
|
source_node_uuid=source_node_uuid,
|
|
228
228
|
target_node_uuid=target_node_uuid,
|
|
229
|
-
name=edge_data.
|
|
229
|
+
name=edge_data.relation_type,
|
|
230
230
|
group_id=group_id,
|
|
231
|
-
fact=edge_data.
|
|
231
|
+
fact=edge_data.fact,
|
|
232
232
|
episodes=[episode.uuid],
|
|
233
233
|
created_at=utc_now(),
|
|
234
234
|
valid_at=valid_at_datetime,
|
|
@@ -422,10 +422,10 @@ async def resolve_extracted_edge(
|
|
|
422
422
|
response_model=EdgeDuplicate,
|
|
423
423
|
model_size=ModelSize.small,
|
|
424
424
|
)
|
|
425
|
+
response_object = EdgeDuplicate(**llm_response)
|
|
426
|
+
duplicate_facts = response_object.duplicate_facts
|
|
425
427
|
|
|
426
|
-
duplicate_fact_ids: list[int] =
|
|
427
|
-
filter(lambda i: 0 <= i < len(related_edges), llm_response.get('duplicate_facts', []))
|
|
428
|
-
)
|
|
428
|
+
duplicate_fact_ids: list[int] = [i for i in duplicate_facts if 0 <= i < len(related_edges)]
|
|
429
429
|
|
|
430
430
|
resolved_edge = extracted_edge
|
|
431
431
|
for duplicate_fact_id in duplicate_fact_ids:
|
|
@@ -435,11 +435,13 @@ async def resolve_extracted_edge(
|
|
|
435
435
|
if duplicate_fact_ids and episode is not None:
|
|
436
436
|
resolved_edge.episodes.append(episode.uuid)
|
|
437
437
|
|
|
438
|
-
contradicted_facts: list[int] =
|
|
438
|
+
contradicted_facts: list[int] = response_object.contradicted_facts
|
|
439
439
|
|
|
440
|
-
invalidation_candidates: list[EntityEdge] = [
|
|
440
|
+
invalidation_candidates: list[EntityEdge] = [
|
|
441
|
+
existing_edges[i] for i in contradicted_facts if 0 <= i < len(existing_edges)
|
|
442
|
+
]
|
|
441
443
|
|
|
442
|
-
fact_type: str =
|
|
444
|
+
fact_type: str = response_object.fact_type
|
|
443
445
|
if fact_type.upper() != 'DEFAULT' and edge_types is not None:
|
|
444
446
|
resolved_edge.name = fact_type
|
|
445
447
|
|
|
@@ -494,39 +496,6 @@ async def resolve_extracted_edge(
|
|
|
494
496
|
return resolved_edge, invalidated_edges, duplicate_edges
|
|
495
497
|
|
|
496
498
|
|
|
497
|
-
async def dedupe_edge_list(
|
|
498
|
-
llm_client: LLMClient,
|
|
499
|
-
edges: list[EntityEdge],
|
|
500
|
-
) -> list[EntityEdge]:
|
|
501
|
-
start = time()
|
|
502
|
-
|
|
503
|
-
# Create edge map
|
|
504
|
-
edge_map = {}
|
|
505
|
-
for edge in edges:
|
|
506
|
-
edge_map[edge.uuid] = edge
|
|
507
|
-
|
|
508
|
-
# Prepare context for LLM
|
|
509
|
-
context = {'edges': [{'uuid': edge.uuid, 'fact': edge.fact} for edge in edges]}
|
|
510
|
-
|
|
511
|
-
llm_response = await llm_client.generate_response(
|
|
512
|
-
prompt_library.dedupe_edges.edge_list(context), response_model=UniqueFacts
|
|
513
|
-
)
|
|
514
|
-
unique_edges_data = llm_response.get('unique_facts', [])
|
|
515
|
-
|
|
516
|
-
end = time()
|
|
517
|
-
logger.debug(f'Extracted edge duplicates: {unique_edges_data} in {(end - start) * 1000} ms ')
|
|
518
|
-
|
|
519
|
-
# Get full edge data
|
|
520
|
-
unique_edges = []
|
|
521
|
-
for edge_data in unique_edges_data:
|
|
522
|
-
uuid = edge_data['uuid']
|
|
523
|
-
edge = edge_map[uuid]
|
|
524
|
-
edge.fact = edge_data['fact']
|
|
525
|
-
unique_edges.append(edge)
|
|
526
|
-
|
|
527
|
-
return unique_edges
|
|
528
|
-
|
|
529
|
-
|
|
530
499
|
async def filter_existing_duplicate_of_edges(
|
|
531
500
|
driver: GraphDriver, duplicates_node_tuples: list[tuple[EntityNode, EntityNode]]
|
|
532
501
|
) -> list[tuple[EntityNode, EntityNode]]:
|
|
@@ -15,14 +15,15 @@ limitations under the License.
|
|
|
15
15
|
"""
|
|
16
16
|
|
|
17
17
|
import logging
|
|
18
|
-
from datetime import datetime
|
|
18
|
+
from datetime import datetime
|
|
19
19
|
|
|
20
20
|
from typing_extensions import LiteralString
|
|
21
21
|
|
|
22
22
|
from graphiti_core.driver.driver import GraphDriver
|
|
23
23
|
from graphiti_core.graph_queries import get_fulltext_indices, get_range_indices
|
|
24
|
-
from graphiti_core.helpers import
|
|
25
|
-
from graphiti_core.nodes import
|
|
24
|
+
from graphiti_core.helpers import semaphore_gather
|
|
25
|
+
from graphiti_core.models.nodes.node_db_queries import EPISODIC_NODE_RETURN
|
|
26
|
+
from graphiti_core.nodes import EpisodeType, EpisodicNode, get_episodic_node_from_record
|
|
26
27
|
|
|
27
28
|
EPISODE_WINDOW_LEN = 3
|
|
28
29
|
|
|
@@ -33,8 +34,8 @@ async def build_indices_and_constraints(driver: GraphDriver, delete_existing: bo
|
|
|
33
34
|
if delete_existing:
|
|
34
35
|
records, _, _ = await driver.execute_query(
|
|
35
36
|
"""
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
SHOW INDEXES YIELD name
|
|
38
|
+
""",
|
|
38
39
|
)
|
|
39
40
|
index_names = [record['name'] for record in records]
|
|
40
41
|
await semaphore_gather(
|
|
@@ -108,19 +109,16 @@ async def retrieve_episodes(
|
|
|
108
109
|
|
|
109
110
|
query: LiteralString = (
|
|
110
111
|
"""
|
|
111
|
-
|
|
112
|
-
|
|
112
|
+
MATCH (e:Episodic)
|
|
113
|
+
WHERE e.valid_at <= $reference_time
|
|
114
|
+
"""
|
|
113
115
|
+ group_id_filter
|
|
114
116
|
+ source_filter
|
|
115
117
|
+ """
|
|
116
|
-
RETURN
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
e.group_id AS group_id,
|
|
121
|
-
e.name AS name,
|
|
122
|
-
e.source_description AS source_description,
|
|
123
|
-
e.source AS source
|
|
118
|
+
RETURN
|
|
119
|
+
"""
|
|
120
|
+
+ EPISODIC_NODE_RETURN
|
|
121
|
+
+ """
|
|
124
122
|
ORDER BY e.valid_at DESC
|
|
125
123
|
LIMIT $num_episodes
|
|
126
124
|
"""
|
|
@@ -133,18 +131,5 @@ async def retrieve_episodes(
|
|
|
133
131
|
group_ids=group_ids,
|
|
134
132
|
)
|
|
135
133
|
|
|
136
|
-
episodes = [
|
|
137
|
-
EpisodicNode(
|
|
138
|
-
content=record['content'],
|
|
139
|
-
created_at=parse_db_date(record['created_at'])
|
|
140
|
-
or datetime.min.replace(tzinfo=timezone.utc),
|
|
141
|
-
valid_at=parse_db_date(record['valid_at']) or datetime.min.replace(tzinfo=timezone.utc),
|
|
142
|
-
uuid=record['uuid'],
|
|
143
|
-
group_id=record['group_id'],
|
|
144
|
-
source=EpisodeType.from_str(record['source']),
|
|
145
|
-
name=record['name'],
|
|
146
|
-
source_description=record['source_description'],
|
|
147
|
-
)
|
|
148
|
-
for record in result
|
|
149
|
-
]
|
|
134
|
+
episodes = [get_episodic_node_from_record(record) for record in result]
|
|
150
135
|
return list(reversed(episodes)) # Return in chronological order
|
|
@@ -29,7 +29,7 @@ from graphiti_core.llm_client import LLMClient
|
|
|
29
29
|
from graphiti_core.llm_client.config import ModelSize
|
|
30
30
|
from graphiti_core.nodes import EntityNode, EpisodeType, EpisodicNode, create_entity_node_embeddings
|
|
31
31
|
from graphiti_core.prompts import prompt_library
|
|
32
|
-
from graphiti_core.prompts.dedupe_nodes import NodeResolutions
|
|
32
|
+
from graphiti_core.prompts.dedupe_nodes import NodeDuplicate, NodeResolutions
|
|
33
33
|
from graphiti_core.prompts.extract_nodes import (
|
|
34
34
|
ExtractedEntities,
|
|
35
35
|
ExtractedEntity,
|
|
@@ -125,10 +125,9 @@ async def extract_nodes(
|
|
|
125
125
|
prompt_library.extract_nodes.extract_json(context), response_model=ExtractedEntities
|
|
126
126
|
)
|
|
127
127
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
]
|
|
128
|
+
response_object = ExtractedEntities(**llm_response)
|
|
129
|
+
|
|
130
|
+
extracted_entities: list[ExtractedEntity] = response_object.extracted_entities
|
|
132
131
|
|
|
133
132
|
reflexion_iterations += 1
|
|
134
133
|
if reflexion_iterations < MAX_REFLEXION_ITERATIONS:
|
|
@@ -254,14 +253,14 @@ async def resolve_extracted_nodes(
|
|
|
254
253
|
response_model=NodeResolutions,
|
|
255
254
|
)
|
|
256
255
|
|
|
257
|
-
node_resolutions: list = llm_response.
|
|
256
|
+
node_resolutions: list[NodeDuplicate] = NodeResolutions(**llm_response).entity_resolutions
|
|
258
257
|
|
|
259
258
|
resolved_nodes: list[EntityNode] = []
|
|
260
259
|
uuid_map: dict[str, str] = {}
|
|
261
260
|
node_duplicates: list[tuple[EntityNode, EntityNode]] = []
|
|
262
261
|
for resolution in node_resolutions:
|
|
263
|
-
resolution_id: int = resolution.
|
|
264
|
-
duplicate_idx: int = resolution.
|
|
262
|
+
resolution_id: int = resolution.id
|
|
263
|
+
duplicate_idx: int = resolution.duplicate_idx
|
|
265
264
|
|
|
266
265
|
extracted_node = extracted_nodes[resolution_id]
|
|
267
266
|
|
|
@@ -276,7 +275,7 @@ async def resolve_extracted_nodes(
|
|
|
276
275
|
resolved_nodes.append(resolved_node)
|
|
277
276
|
uuid_map[extracted_node.uuid] = resolved_node.uuid
|
|
278
277
|
|
|
279
|
-
duplicates: list[int] = resolution.
|
|
278
|
+
duplicates: list[int] = resolution.duplicates
|
|
280
279
|
if duplicate_idx not in duplicates and duplicate_idx > -1:
|
|
281
280
|
duplicates.append(duplicate_idx)
|
|
282
281
|
for idx in duplicates:
|
|
@@ -369,7 +368,9 @@ async def extract_attributes_from_node(
|
|
|
369
368
|
model_size=ModelSize.small,
|
|
370
369
|
)
|
|
371
370
|
|
|
372
|
-
|
|
371
|
+
entity_attributes_model(**llm_response)
|
|
372
|
+
|
|
373
|
+
node.summary = llm_response.get('summary', '')
|
|
373
374
|
node_attributes = {key: value for key, value in llm_response.items()}
|
|
374
375
|
|
|
375
376
|
with suppress(KeyError):
|
|
@@ -378,48 +379,3 @@ async def extract_attributes_from_node(
|
|
|
378
379
|
node.attributes.update(node_attributes)
|
|
379
380
|
|
|
380
381
|
return node
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
async def dedupe_node_list(
|
|
384
|
-
llm_client: LLMClient,
|
|
385
|
-
nodes: list[EntityNode],
|
|
386
|
-
) -> tuple[list[EntityNode], dict[str, str]]:
|
|
387
|
-
start = time()
|
|
388
|
-
|
|
389
|
-
# build node map
|
|
390
|
-
node_map = {}
|
|
391
|
-
for node in nodes:
|
|
392
|
-
node_map[node.uuid] = node
|
|
393
|
-
|
|
394
|
-
# Prepare context for LLM
|
|
395
|
-
nodes_context = [{'uuid': node.uuid, 'name': node.name, **node.attributes} for node in nodes]
|
|
396
|
-
|
|
397
|
-
context = {
|
|
398
|
-
'nodes': nodes_context,
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
llm_response = await llm_client.generate_response(
|
|
402
|
-
prompt_library.dedupe_nodes.node_list(context)
|
|
403
|
-
)
|
|
404
|
-
|
|
405
|
-
nodes_data = llm_response.get('nodes', [])
|
|
406
|
-
|
|
407
|
-
end = time()
|
|
408
|
-
logger.debug(f'Deduplicated nodes: {nodes_data} in {(end - start) * 1000} ms')
|
|
409
|
-
|
|
410
|
-
# Get full node data
|
|
411
|
-
unique_nodes = []
|
|
412
|
-
uuid_map: dict[str, str] = {}
|
|
413
|
-
for node_data in nodes_data:
|
|
414
|
-
node_instance: EntityNode | None = node_map.get(node_data['uuids'][0])
|
|
415
|
-
if node_instance is None:
|
|
416
|
-
logger.warning(f'Node {node_data["uuids"][0]} not found in node map')
|
|
417
|
-
continue
|
|
418
|
-
node_instance.summary = node_data['summary']
|
|
419
|
-
unique_nodes.append(node_instance)
|
|
420
|
-
|
|
421
|
-
for uuid in node_data['uuids'][1:]:
|
|
422
|
-
uuid_value = node_map[node_data['uuids'][0]].uuid
|
|
423
|
-
uuid_map[uuid] = uuid_value
|
|
424
|
-
|
|
425
|
-
return unique_nodes, uuid_map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: graphiti-core
|
|
3
|
-
Version: 0.18.
|
|
3
|
+
Version: 0.18.1
|
|
4
4
|
Summary: A temporal graph building library
|
|
5
5
|
Project-URL: Homepage, https://help.getzep.com/graphiti/graphiti/overview
|
|
6
6
|
Project-URL: Repository, https://github.com/getzep/graphiti
|
|
@@ -106,9 +106,9 @@ nodes ("Kendra", "Adidas shoes"), and their relationship, or edge ("loves"). Kno
|
|
|
106
106
|
extensively for information retrieval. What makes Graphiti unique is its ability to autonomously build a knowledge graph
|
|
107
107
|
while handling changing relationships and maintaining historical context.
|
|
108
108
|
|
|
109
|
-
## Graphiti and Zep
|
|
109
|
+
## Graphiti and Zep's Context Engineering Platform.
|
|
110
110
|
|
|
111
|
-
Graphiti powers the core of [Zep
|
|
111
|
+
Graphiti powers the core of [Zep](https://www.getzep.com), a turn-key context engineering platform for AI Agents. Zep offers agent memory, Graph RAG for dynamic data, and context retrieval and assembly.
|
|
112
112
|
|
|
113
113
|
Using Graphiti, we've demonstrated Zep is
|
|
114
114
|
the [State of the Art in Agent Memory](https://blog.getzep.com/state-of-the-art-agent-memory/).
|
|
@@ -219,6 +219,14 @@ pip install graphiti-core[anthropic,groq,google-genai]
|
|
|
219
219
|
pip install graphiti-core[falkordb,anthropic,google-genai]
|
|
220
220
|
```
|
|
221
221
|
|
|
222
|
+
## Default to Low Concurrency; LLM Provider 429 Rate Limit Errors
|
|
223
|
+
|
|
224
|
+
Graphiti's ingestion pipelines are designed for high concurrency. By default, concurrency is set low to avoid LLM Provider 429 Rate Limit Errors. If you find Graphiti slow, please increase concurrency as described below.
|
|
225
|
+
|
|
226
|
+
Concurrency controlled by the `SEMAPHORE_LIMIT` environment variable. By default, `SEMAPHORE_LIMIT` is set to `10` concurrent operations to help prevent `429` rate limit errors from your LLM provider. If you encounter such errors, try lowering this value.
|
|
227
|
+
|
|
228
|
+
If your LLM provider allows higher throughput, you can increase `SEMAPHORE_LIMIT` to boost episode ingestion performance.
|
|
229
|
+
|
|
222
230
|
## Quick Start
|
|
223
231
|
|
|
224
232
|
> [!IMPORTANT]
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
graphiti_core/__init__.py,sha256=e5SWFkRiaUwfprYIeIgVIh7JDedNiloZvd3roU-0aDY,55
|
|
2
|
-
graphiti_core/edges.py,sha256
|
|
2
|
+
graphiti_core/edges.py,sha256=KpgCzHlNgEcTTbUE62RAXKKi2YbG_fIwilE_W1TARYI,14864
|
|
3
3
|
graphiti_core/errors.py,sha256=cH_v9TPgEPeQE6GFOHIg5TvejpUCBddGarMY2Whxbwc,2707
|
|
4
|
-
graphiti_core/graph_queries.py,sha256=
|
|
5
|
-
graphiti_core/graphiti.py,sha256=
|
|
4
|
+
graphiti_core/graph_queries.py,sha256=mkSE8JbH4dTysT1quxR_QqCU-P_MUogbj48-BVxAcY4,5316
|
|
5
|
+
graphiti_core/graphiti.py,sha256=5A91hadPTFKxDnPhN2QmFr1Mm2Se77WaDb8Nz4p5EOs,40105
|
|
6
6
|
graphiti_core/graphiti_types.py,sha256=rL-9bvnLobunJfXU4hkD6mAj14pofKp_wq8QsFDZwDU,1035
|
|
7
|
-
graphiti_core/helpers.py,sha256=
|
|
8
|
-
graphiti_core/nodes.py,sha256
|
|
7
|
+
graphiti_core/helpers.py,sha256=fSLlipk03QbL0g_J4Gy_nMwTKnPNWQIputrXJsQReIg,5325
|
|
8
|
+
graphiti_core/nodes.py,sha256=-RnBtqLx1ukbQQqjZval9fDAWIJUTWaKwSMPLJ9AzM4,17866
|
|
9
9
|
graphiti_core/py.typed,sha256=vlmmzQOt7bmeQl9L3XJP4W6Ry0iiELepnOrinKz5KQg,79
|
|
10
10
|
graphiti_core/cross_encoder/__init__.py,sha256=hry59vz21x-AtGZ0MJ7ugw0HTwJkXiddpp_Yqnwsen0,723
|
|
11
11
|
graphiti_core/cross_encoder/bge_reranker_client.py,sha256=y3TfFxZh0Yvj6HUShmfUm6MC7OPXwWUlv1Qe5HF3S3I,1797
|
|
@@ -13,9 +13,9 @@ graphiti_core/cross_encoder/client.py,sha256=KLsbfWKOEaAV3adFe3XZlAeb-gje9_sVKCV
|
|
|
13
13
|
graphiti_core/cross_encoder/gemini_reranker_client.py,sha256=hmITG5YIib52nrKvINwRi4xTfAO1U4jCCaEVIwImHw0,6208
|
|
14
14
|
graphiti_core/cross_encoder/openai_reranker_client.py,sha256=hoaGyu9nCNMJyP8si0Bha5Q9CFszfiHQmLgE9IsX7sY,4653
|
|
15
15
|
graphiti_core/driver/__init__.py,sha256=kCWimqQU19airu5gKwCmZtZuXkDfaQfKSUhMDoL-rTA,626
|
|
16
|
-
graphiti_core/driver/driver.py,sha256=
|
|
17
|
-
graphiti_core/driver/falkordb_driver.py,sha256=
|
|
18
|
-
graphiti_core/driver/neo4j_driver.py,sha256=
|
|
16
|
+
graphiti_core/driver/driver.py,sha256=XFJzkyZKiqhwwW6G9enB2ouWxNB53PU58nhSCW_LOIc,2331
|
|
17
|
+
graphiti_core/driver/falkordb_driver.py,sha256=YLNuPvPBM7Pgr3Pv9gDuTVDGeDgHvEg8xD58uDYNweM,6766
|
|
18
|
+
graphiti_core/driver/neo4j_driver.py,sha256=LxYPJc8vUUBplVKLW9n2mofNzndFV4S2yHdAiT5gUJI,2323
|
|
19
19
|
graphiti_core/embedder/__init__.py,sha256=EL564ZuE-DZjcuKNUK_exMn_XHXm2LdO9fzdXePVKL4,179
|
|
20
20
|
graphiti_core/embedder/azure_openai.py,sha256=OyomPwC1fIsddI-3n6g00kQFdQznZorBhHwkQKCLUok,2384
|
|
21
21
|
graphiti_core/embedder/client.py,sha256=qEpSHceL_Gc4QQPJWIOnuNLemNuR_TYA4r28t2Vldbg,1115
|
|
@@ -36,16 +36,16 @@ graphiti_core/llm_client/openai_generic_client.py,sha256=WElMnPqdb1CxzYH4p2-m_9r
|
|
|
36
36
|
graphiti_core/llm_client/utils.py,sha256=zKpxXEbKa369m4W7RDEf-m56kH46V1Mx3RowcWZEWWs,1000
|
|
37
37
|
graphiti_core/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
38
38
|
graphiti_core/models/edges/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
39
|
-
graphiti_core/models/edges/edge_db_queries.py,sha256=
|
|
39
|
+
graphiti_core/models/edges/edge_db_queries.py,sha256=OBFqT9m6JDmGwpqe5TkcaCT2KxUGdW8h4yIsoacB5Mw,4661
|
|
40
40
|
graphiti_core/models/nodes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
41
|
-
graphiti_core/models/nodes/node_db_queries.py,sha256=
|
|
41
|
+
graphiti_core/models/nodes/node_db_queries.py,sha256=ADPkZzS4tq5i-8zvkocoiuOiDi64d5F2ChEY_JwLOwQ,4378
|
|
42
42
|
graphiti_core/prompts/__init__.py,sha256=EA-x9xUki9l8wnu2l8ek_oNf75-do5tq5hVq7Zbv8Kw,101
|
|
43
43
|
graphiti_core/prompts/dedupe_edges.py,sha256=WlW18HjhuKOXjxSbvrmwk0yH0tqA4t89ntG7LOTq_k4,5724
|
|
44
|
-
graphiti_core/prompts/dedupe_nodes.py,sha256=
|
|
44
|
+
graphiti_core/prompts/dedupe_nodes.py,sha256=T0LVocO5nfP4mOYpIcNMztLHjnRcE6zpYgT6OUCoujw,7783
|
|
45
45
|
graphiti_core/prompts/eval.py,sha256=gnBQTmwsCl3Qvwpcm7aieVszzo6y1sMCUT8jQiKTvvE,5317
|
|
46
46
|
graphiti_core/prompts/extract_edge_dates.py,sha256=3Drs3CmvP0gJN5BidWSxrNvLet3HPoTybU3BUIAoc0Y,4218
|
|
47
|
-
graphiti_core/prompts/extract_edges.py,sha256=
|
|
48
|
-
graphiti_core/prompts/extract_nodes.py,sha256=
|
|
47
|
+
graphiti_core/prompts/extract_edges.py,sha256=MY-GhBNxPhO07v6TZPE_dby-VevDHHmVXpyYm-khg04,6622
|
|
48
|
+
graphiti_core/prompts/extract_nodes.py,sha256=nOlcG4z1vNzsxgHaSPzmPZSdu6ERJofVhf1HukGJrkM,9749
|
|
49
49
|
graphiti_core/prompts/invalidate_edges.py,sha256=yfpcs_pyctnoM77ULPZXEtKW0oHr1MeLsJzC5yrE-o4,3547
|
|
50
50
|
graphiti_core/prompts/lib.py,sha256=DCyHePM4_q-CptTpEXGO_dBv9k7xDtclEaB1dGu7EcI,4092
|
|
51
51
|
graphiti_core/prompts/models.py,sha256=NgxdbPHJpBEcpbXovKyScgpBc73Q-GIW-CBDlBtDjto,894
|
|
@@ -55,23 +55,23 @@ graphiti_core/search/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hS
|
|
|
55
55
|
graphiti_core/search/search.py,sha256=u-kTmSu3VlRHYlQhuYsbwDQ-AKKCp3BZ9JZNRv3ttVY,16720
|
|
56
56
|
graphiti_core/search/search_config.py,sha256=v_rUHsu1yo5OuPfEm21lSuXexQs-o8qYwSSemW2QWhU,4165
|
|
57
57
|
graphiti_core/search/search_config_recipes.py,sha256=4GquRphHhJlpXQhAZOySYnCzBWYoTwxlJj44eTOavZQ,7443
|
|
58
|
-
graphiti_core/search/search_filters.py,sha256=
|
|
58
|
+
graphiti_core/search/search_filters.py,sha256=Xc8hNVqbPrCd8-Zql0rtf1ztjzC_0FgAqGj9vxgNwLM,6383
|
|
59
59
|
graphiti_core/search/search_helpers.py,sha256=G5Ceaq5Pfgx0Weelqgeylp_pUHwiBnINaUYsDbURJbE,2636
|
|
60
|
-
graphiti_core/search/search_utils.py,sha256=
|
|
60
|
+
graphiti_core/search/search_utils.py,sha256=kKVALClDk8UMnEkO3djc4RMYr8Q0biyI6dmFFplqmQ8,32130
|
|
61
61
|
graphiti_core/telemetry/__init__.py,sha256=5kALLDlU9bb2v19CdN7qVANsJWyfnL9E60J6FFgzm3o,226
|
|
62
62
|
graphiti_core/telemetry/telemetry.py,sha256=47LrzOVBCcZxsYPsnSxWFiztHoxYKKxPwyRX0hnbDGc,3230
|
|
63
63
|
graphiti_core/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
64
|
-
graphiti_core/utils/bulk_utils.py,sha256=
|
|
64
|
+
graphiti_core/utils/bulk_utils.py,sha256=xs7IPg2eT17c_6dZT-PK5MwQXzcI6ijEeZuCPMlHkoI,15025
|
|
65
65
|
graphiti_core/utils/datetime_utils.py,sha256=Ti-2tnrDFRzBsbfblzsHybsM3jaDLP4-VT2t0VhpIzU,1357
|
|
66
66
|
graphiti_core/utils/maintenance/__init__.py,sha256=vW4H1KyapTl-OOz578uZABYcpND4wPx3Vt6aAPaXh78,301
|
|
67
|
-
graphiti_core/utils/maintenance/community_operations.py,sha256=
|
|
68
|
-
graphiti_core/utils/maintenance/edge_operations.py,sha256=
|
|
69
|
-
graphiti_core/utils/maintenance/graph_data_operations.py,sha256=
|
|
70
|
-
graphiti_core/utils/maintenance/node_operations.py,sha256=
|
|
67
|
+
graphiti_core/utils/maintenance/community_operations.py,sha256=jAY_WdmvjxJG4MxAsXzTaETTjvX6G8YuKVq9FzvQQuc,10071
|
|
68
|
+
graphiti_core/utils/maintenance/edge_operations.py,sha256=84wKDG99e-xIWhloSIOWOVYJIxRX9LFB1vn8IXb3YYQ,18550
|
|
69
|
+
graphiti_core/utils/maintenance/graph_data_operations.py,sha256=joNZxL_OIFdXHBGkwtB57ar7nGmbq4Z8ItgqFWL45kw,4530
|
|
70
|
+
graphiti_core/utils/maintenance/node_operations.py,sha256=aSEXqgBuGfcJBvKjnGlI-4fbtrW4PGnfP5sd-tkFyKQ,13261
|
|
71
71
|
graphiti_core/utils/maintenance/temporal_operations.py,sha256=mJkw9xLB4W2BsLfC5POr0r-PHWL9SIfNj_l_xu0B5ug,3410
|
|
72
72
|
graphiti_core/utils/maintenance/utils.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
73
73
|
graphiti_core/utils/ontology_utils/entity_types_utils.py,sha256=QJX5cG0GSSNF_Mm_yrldr69wjVAbN_MxLhOSznz85Hk,1279
|
|
74
|
-
graphiti_core-0.18.
|
|
75
|
-
graphiti_core-0.18.
|
|
76
|
-
graphiti_core-0.18.
|
|
77
|
-
graphiti_core-0.18.
|
|
74
|
+
graphiti_core-0.18.1.dist-info/METADATA,sha256=sCiB_n-JnaYhcUnRj-RMmIB_tv4E5iyHIthB6d6BwB0,24621
|
|
75
|
+
graphiti_core-0.18.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
76
|
+
graphiti_core-0.18.1.dist-info/licenses/LICENSE,sha256=KCUwCyDXuVEgmDWkozHyniRyWjnWUWjkuDHfU6o3JlA,11325
|
|
77
|
+
graphiti_core-0.18.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|