graphiti-core 0.15.1__py3-none-any.whl → 0.17.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/cross_encoder/gemini_reranker_client.py +4 -1
- graphiti_core/driver/driver.py +2 -4
- graphiti_core/driver/falkordb_driver.py +9 -7
- graphiti_core/driver/neo4j_driver.py +14 -13
- graphiti_core/edges.py +3 -20
- graphiti_core/embedder/gemini.py +17 -5
- graphiti_core/graphiti.py +107 -57
- graphiti_core/helpers.py +0 -1
- graphiti_core/llm_client/gemini_client.py +8 -5
- graphiti_core/nodes.py +3 -22
- graphiti_core/prompts/dedupe_edges.py +5 -4
- graphiti_core/prompts/dedupe_nodes.py +3 -3
- graphiti_core/search/search_utils.py +1 -20
- graphiti_core/utils/bulk_utils.py +212 -256
- graphiti_core/utils/maintenance/community_operations.py +1 -6
- graphiti_core/utils/maintenance/edge_operations.py +35 -122
- graphiti_core/utils/maintenance/graph_data_operations.py +2 -6
- graphiti_core/utils/maintenance/node_operations.py +11 -58
- {graphiti_core-0.15.1.dist-info → graphiti_core-0.17.0.dist-info}/METADATA +19 -1
- {graphiti_core-0.15.1.dist-info → graphiti_core-0.17.0.dist-info}/RECORD +22 -22
- {graphiti_core-0.15.1.dist-info → graphiti_core-0.17.0.dist-info}/WHEEL +0 -0
- {graphiti_core-0.15.1.dist-info → graphiti_core-0.17.0.dist-info}/licenses/LICENSE +0 -0
graphiti_core/nodes.py
CHANGED
|
@@ -28,7 +28,7 @@ from typing_extensions import LiteralString
|
|
|
28
28
|
from graphiti_core.driver.driver import GraphDriver
|
|
29
29
|
from graphiti_core.embedder import EmbedderClient
|
|
30
30
|
from graphiti_core.errors import NodeNotFoundError
|
|
31
|
-
from graphiti_core.helpers import
|
|
31
|
+
from graphiti_core.helpers import parse_db_date
|
|
32
32
|
from graphiti_core.models.nodes.node_db_queries import (
|
|
33
33
|
COMMUNITY_NODE_SAVE,
|
|
34
34
|
ENTITY_NODE_SAVE,
|
|
@@ -103,7 +103,6 @@ class Node(BaseModel, ABC):
|
|
|
103
103
|
DETACH DELETE n
|
|
104
104
|
""",
|
|
105
105
|
uuid=self.uuid,
|
|
106
|
-
database_=DEFAULT_DATABASE,
|
|
107
106
|
)
|
|
108
107
|
|
|
109
108
|
logger.debug(f'Deleted Node: {self.uuid}')
|
|
@@ -126,7 +125,6 @@ class Node(BaseModel, ABC):
|
|
|
126
125
|
DETACH DELETE n
|
|
127
126
|
""",
|
|
128
127
|
group_id=group_id,
|
|
129
|
-
database_=DEFAULT_DATABASE,
|
|
130
128
|
)
|
|
131
129
|
|
|
132
130
|
return 'SUCCESS'
|
|
@@ -162,7 +160,6 @@ class EpisodicNode(Node):
|
|
|
162
160
|
created_at=self.created_at,
|
|
163
161
|
valid_at=self.valid_at,
|
|
164
162
|
source=self.source.value,
|
|
165
|
-
database_=DEFAULT_DATABASE,
|
|
166
163
|
)
|
|
167
164
|
|
|
168
165
|
logger.debug(f'Saved Node to Graph: {self.uuid}')
|
|
@@ -185,7 +182,6 @@ class EpisodicNode(Node):
|
|
|
185
182
|
e.entity_edges AS entity_edges
|
|
186
183
|
""",
|
|
187
184
|
uuid=uuid,
|
|
188
|
-
database_=DEFAULT_DATABASE,
|
|
189
185
|
routing_='r',
|
|
190
186
|
)
|
|
191
187
|
|
|
@@ -213,7 +209,6 @@ class EpisodicNode(Node):
|
|
|
213
209
|
e.entity_edges AS entity_edges
|
|
214
210
|
""",
|
|
215
211
|
uuids=uuids,
|
|
216
|
-
database_=DEFAULT_DATABASE,
|
|
217
212
|
routing_='r',
|
|
218
213
|
)
|
|
219
214
|
|
|
@@ -254,7 +249,6 @@ class EpisodicNode(Node):
|
|
|
254
249
|
group_ids=group_ids,
|
|
255
250
|
uuid=uuid_cursor,
|
|
256
251
|
limit=limit,
|
|
257
|
-
database_=DEFAULT_DATABASE,
|
|
258
252
|
routing_='r',
|
|
259
253
|
)
|
|
260
254
|
|
|
@@ -279,7 +273,6 @@ class EpisodicNode(Node):
|
|
|
279
273
|
e.entity_edges AS entity_edges
|
|
280
274
|
""",
|
|
281
275
|
entity_node_uuid=entity_node_uuid,
|
|
282
|
-
database_=DEFAULT_DATABASE,
|
|
283
276
|
routing_='r',
|
|
284
277
|
)
|
|
285
278
|
|
|
@@ -309,9 +302,7 @@ class EntityNode(Node):
|
|
|
309
302
|
MATCH (n:Entity {uuid: $uuid})
|
|
310
303
|
RETURN n.name_embedding AS name_embedding
|
|
311
304
|
"""
|
|
312
|
-
records, _, _ = await driver.execute_query(
|
|
313
|
-
query, uuid=self.uuid, database_=DEFAULT_DATABASE, routing_='r'
|
|
314
|
-
)
|
|
305
|
+
records, _, _ = await driver.execute_query(query, uuid=self.uuid, routing_='r')
|
|
315
306
|
|
|
316
307
|
if len(records) == 0:
|
|
317
308
|
raise NodeNotFoundError(self.uuid)
|
|
@@ -334,7 +325,6 @@ class EntityNode(Node):
|
|
|
334
325
|
ENTITY_NODE_SAVE,
|
|
335
326
|
labels=self.labels + ['Entity'],
|
|
336
327
|
entity_data=entity_data,
|
|
337
|
-
database_=DEFAULT_DATABASE,
|
|
338
328
|
)
|
|
339
329
|
|
|
340
330
|
logger.debug(f'Saved Node to Graph: {self.uuid}')
|
|
@@ -352,7 +342,6 @@ class EntityNode(Node):
|
|
|
352
342
|
records, _, _ = await driver.execute_query(
|
|
353
343
|
query,
|
|
354
344
|
uuid=uuid,
|
|
355
|
-
database_=DEFAULT_DATABASE,
|
|
356
345
|
routing_='r',
|
|
357
346
|
)
|
|
358
347
|
|
|
@@ -371,7 +360,6 @@ class EntityNode(Node):
|
|
|
371
360
|
"""
|
|
372
361
|
+ ENTITY_NODE_RETURN,
|
|
373
362
|
uuids=uuids,
|
|
374
|
-
database_=DEFAULT_DATABASE,
|
|
375
363
|
routing_='r',
|
|
376
364
|
)
|
|
377
365
|
|
|
@@ -403,7 +391,6 @@ class EntityNode(Node):
|
|
|
403
391
|
group_ids=group_ids,
|
|
404
392
|
uuid=uuid_cursor,
|
|
405
393
|
limit=limit,
|
|
406
|
-
database_=DEFAULT_DATABASE,
|
|
407
394
|
routing_='r',
|
|
408
395
|
)
|
|
409
396
|
|
|
@@ -425,7 +412,6 @@ class CommunityNode(Node):
|
|
|
425
412
|
summary=self.summary,
|
|
426
413
|
name_embedding=self.name_embedding,
|
|
427
414
|
created_at=self.created_at,
|
|
428
|
-
database_=DEFAULT_DATABASE,
|
|
429
415
|
)
|
|
430
416
|
|
|
431
417
|
logger.debug(f'Saved Node to Graph: {self.uuid}')
|
|
@@ -446,9 +432,7 @@ class CommunityNode(Node):
|
|
|
446
432
|
MATCH (c:Community {uuid: $uuid})
|
|
447
433
|
RETURN c.name_embedding AS name_embedding
|
|
448
434
|
"""
|
|
449
|
-
records, _, _ = await driver.execute_query(
|
|
450
|
-
query, uuid=self.uuid, database_=DEFAULT_DATABASE, routing_='r'
|
|
451
|
-
)
|
|
435
|
+
records, _, _ = await driver.execute_query(query, uuid=self.uuid, routing_='r')
|
|
452
436
|
|
|
453
437
|
if len(records) == 0:
|
|
454
438
|
raise NodeNotFoundError(self.uuid)
|
|
@@ -468,7 +452,6 @@ class CommunityNode(Node):
|
|
|
468
452
|
n.summary AS summary
|
|
469
453
|
""",
|
|
470
454
|
uuid=uuid,
|
|
471
|
-
database_=DEFAULT_DATABASE,
|
|
472
455
|
routing_='r',
|
|
473
456
|
)
|
|
474
457
|
|
|
@@ -492,7 +475,6 @@ class CommunityNode(Node):
|
|
|
492
475
|
n.summary AS summary
|
|
493
476
|
""",
|
|
494
477
|
uuids=uuids,
|
|
495
|
-
database_=DEFAULT_DATABASE,
|
|
496
478
|
routing_='r',
|
|
497
479
|
)
|
|
498
480
|
|
|
@@ -529,7 +511,6 @@ class CommunityNode(Node):
|
|
|
529
511
|
group_ids=group_ids,
|
|
530
512
|
uuid=uuid_cursor,
|
|
531
513
|
limit=limit,
|
|
532
|
-
database_=DEFAULT_DATABASE,
|
|
533
514
|
routing_='r',
|
|
534
515
|
)
|
|
535
516
|
|
|
@@ -23,9 +23,9 @@ from .models import Message, PromptFunction, PromptVersion
|
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
class EdgeDuplicate(BaseModel):
|
|
26
|
-
|
|
26
|
+
duplicate_facts: list[int] = Field(
|
|
27
27
|
...,
|
|
28
|
-
description='
|
|
28
|
+
description='List of ids of any duplicate facts. If no duplicate facts are found, default to empty list.',
|
|
29
29
|
)
|
|
30
30
|
contradicted_facts: list[int] = Field(
|
|
31
31
|
...,
|
|
@@ -75,8 +75,9 @@ def edge(context: dict[str, Any]) -> list[Message]:
|
|
|
75
75
|
</NEW EDGE>
|
|
76
76
|
|
|
77
77
|
Task:
|
|
78
|
-
If the New Edges represents the same factual information as any edge in Existing Edges, return the id of the duplicate fact
|
|
79
|
-
|
|
78
|
+
If the New Edges represents the same factual information as any edge in Existing Edges, return the id of the duplicate fact
|
|
79
|
+
as part of the list of duplicate_facts.
|
|
80
|
+
If the NEW EDGE is not a duplicate of any of the EXISTING EDGES, return an empty list.
|
|
80
81
|
|
|
81
82
|
Guidelines:
|
|
82
83
|
1. The facts do not need to be completely identical to be duplicates, they just need to express the same information.
|
|
@@ -32,9 +32,9 @@ class NodeDuplicate(BaseModel):
|
|
|
32
32
|
...,
|
|
33
33
|
description='Name of the entity. Should be the most complete and descriptive name of the entity. Do not include any JSON formatting in the Entity name such as {}.',
|
|
34
34
|
)
|
|
35
|
-
|
|
35
|
+
duplicates: list[int] = Field(
|
|
36
36
|
...,
|
|
37
|
-
description='idx of
|
|
37
|
+
description='idx of all duplicate entities.',
|
|
38
38
|
)
|
|
39
39
|
|
|
40
40
|
|
|
@@ -94,7 +94,7 @@ def node(context: dict[str, Any]) -> list[Message]:
|
|
|
94
94
|
1. Compare `new_entity` against each item in `existing_entities`.
|
|
95
95
|
2. If it refers to the same real‐world object or concept, collect its index.
|
|
96
96
|
3. Let `duplicate_idx` = the *first* collected index, or –1 if none.
|
|
97
|
-
4. Let `
|
|
97
|
+
4. Let `duplicates` = the list of *all* collected indices (empty list if none).
|
|
98
98
|
|
|
99
99
|
Also return the full name of the NEW ENTITY (whether it is the name of the NEW ENTITY, a node it
|
|
100
100
|
is a duplicate of, or a combination of the two).
|
|
@@ -31,7 +31,6 @@ from graphiti_core.graph_queries import (
|
|
|
31
31
|
get_vector_cosine_func_query,
|
|
32
32
|
)
|
|
33
33
|
from graphiti_core.helpers import (
|
|
34
|
-
DEFAULT_DATABASE,
|
|
35
34
|
RUNTIME_QUERY,
|
|
36
35
|
lucene_sanitize,
|
|
37
36
|
normalize_l2,
|
|
@@ -116,7 +115,6 @@ async def get_mentioned_nodes(
|
|
|
116
115
|
records, _, _ = await driver.execute_query(
|
|
117
116
|
query,
|
|
118
117
|
uuids=episode_uuids,
|
|
119
|
-
database_=DEFAULT_DATABASE,
|
|
120
118
|
routing_='r',
|
|
121
119
|
)
|
|
122
120
|
|
|
@@ -143,7 +141,6 @@ async def get_communities_by_nodes(
|
|
|
143
141
|
records, _, _ = await driver.execute_query(
|
|
144
142
|
query,
|
|
145
143
|
uuids=node_uuids,
|
|
146
|
-
database_=DEFAULT_DATABASE,
|
|
147
144
|
routing_='r',
|
|
148
145
|
)
|
|
149
146
|
|
|
@@ -198,7 +195,6 @@ async def edge_fulltext_search(
|
|
|
198
195
|
query=fuzzy_query,
|
|
199
196
|
group_ids=group_ids,
|
|
200
197
|
limit=limit,
|
|
201
|
-
database_=DEFAULT_DATABASE,
|
|
202
198
|
routing_='r',
|
|
203
199
|
)
|
|
204
200
|
|
|
@@ -274,7 +270,6 @@ async def edge_similarity_search(
|
|
|
274
270
|
group_ids=group_ids,
|
|
275
271
|
limit=limit,
|
|
276
272
|
min_score=min_score,
|
|
277
|
-
database_=DEFAULT_DATABASE,
|
|
278
273
|
routing_='r',
|
|
279
274
|
)
|
|
280
275
|
|
|
@@ -329,7 +324,6 @@ async def edge_bfs_search(
|
|
|
329
324
|
bfs_origin_node_uuids=bfs_origin_node_uuids,
|
|
330
325
|
depth=bfs_max_depth,
|
|
331
326
|
limit=limit,
|
|
332
|
-
database_=DEFAULT_DATABASE,
|
|
333
327
|
routing_='r',
|
|
334
328
|
)
|
|
335
329
|
|
|
@@ -371,7 +365,6 @@ async def node_fulltext_search(
|
|
|
371
365
|
query=fuzzy_query,
|
|
372
366
|
group_ids=group_ids,
|
|
373
367
|
limit=limit,
|
|
374
|
-
database_=DEFAULT_DATABASE,
|
|
375
368
|
routing_='r',
|
|
376
369
|
)
|
|
377
370
|
|
|
@@ -425,7 +418,6 @@ async def node_similarity_search(
|
|
|
425
418
|
group_ids=group_ids,
|
|
426
419
|
limit=limit,
|
|
427
420
|
min_score=min_score,
|
|
428
|
-
database_=DEFAULT_DATABASE,
|
|
429
421
|
routing_='r',
|
|
430
422
|
)
|
|
431
423
|
|
|
@@ -465,7 +457,6 @@ async def node_bfs_search(
|
|
|
465
457
|
bfs_origin_node_uuids=bfs_origin_node_uuids,
|
|
466
458
|
depth=bfs_max_depth,
|
|
467
459
|
limit=limit,
|
|
468
|
-
database_=DEFAULT_DATABASE,
|
|
469
460
|
routing_='r',
|
|
470
461
|
)
|
|
471
462
|
nodes = [get_entity_node_from_record(record) for record in records]
|
|
@@ -511,7 +502,6 @@ async def episode_fulltext_search(
|
|
|
511
502
|
query=fuzzy_query,
|
|
512
503
|
group_ids=group_ids,
|
|
513
504
|
limit=limit,
|
|
514
|
-
database_=DEFAULT_DATABASE,
|
|
515
505
|
routing_='r',
|
|
516
506
|
)
|
|
517
507
|
episodes = [get_episodic_node_from_record(record) for record in records]
|
|
@@ -551,7 +541,6 @@ async def community_fulltext_search(
|
|
|
551
541
|
query=fuzzy_query,
|
|
552
542
|
group_ids=group_ids,
|
|
553
543
|
limit=limit,
|
|
554
|
-
database_=DEFAULT_DATABASE,
|
|
555
544
|
routing_='r',
|
|
556
545
|
)
|
|
557
546
|
communities = [get_community_node_from_record(record) for record in records]
|
|
@@ -603,7 +592,6 @@ async def community_similarity_search(
|
|
|
603
592
|
group_ids=group_ids,
|
|
604
593
|
limit=limit,
|
|
605
594
|
min_score=min_score,
|
|
606
|
-
database_=DEFAULT_DATABASE,
|
|
607
595
|
routing_='r',
|
|
608
596
|
)
|
|
609
597
|
communities = [get_community_node_from_record(record) for record in records]
|
|
@@ -764,7 +752,6 @@ async def get_relevant_nodes(
|
|
|
764
752
|
group_id=group_id,
|
|
765
753
|
limit=limit,
|
|
766
754
|
min_score=min_score,
|
|
767
|
-
database_=DEFAULT_DATABASE,
|
|
768
755
|
routing_='r',
|
|
769
756
|
)
|
|
770
757
|
|
|
@@ -834,7 +821,6 @@ async def get_relevant_edges(
|
|
|
834
821
|
edges=[edge.model_dump() for edge in edges],
|
|
835
822
|
limit=limit,
|
|
836
823
|
min_score=min_score,
|
|
837
|
-
database_=DEFAULT_DATABASE,
|
|
838
824
|
routing_='r',
|
|
839
825
|
)
|
|
840
826
|
|
|
@@ -905,7 +891,6 @@ async def get_edge_invalidation_candidates(
|
|
|
905
891
|
edges=[edge.model_dump() for edge in edges],
|
|
906
892
|
limit=limit,
|
|
907
893
|
min_score=min_score,
|
|
908
|
-
database_=DEFAULT_DATABASE,
|
|
909
894
|
routing_='r',
|
|
910
895
|
)
|
|
911
896
|
invalidation_edges_dict: dict[str, list[EntityEdge]] = {
|
|
@@ -955,7 +940,6 @@ async def node_distance_reranker(
|
|
|
955
940
|
query,
|
|
956
941
|
node_uuids=filtered_uuids,
|
|
957
942
|
center_uuid=center_node_uuid,
|
|
958
|
-
database_=DEFAULT_DATABASE,
|
|
959
943
|
routing_='r',
|
|
960
944
|
)
|
|
961
945
|
if driver.provider == 'falkordb':
|
|
@@ -997,7 +981,6 @@ async def episode_mentions_reranker(
|
|
|
997
981
|
results, _, _ = await driver.execute_query(
|
|
998
982
|
query,
|
|
999
983
|
node_uuids=sorted_uuids,
|
|
1000
|
-
database_=DEFAULT_DATABASE,
|
|
1001
984
|
routing_='r',
|
|
1002
985
|
)
|
|
1003
986
|
|
|
@@ -1060,7 +1043,7 @@ async def get_embeddings_for_nodes(
|
|
|
1060
1043
|
"""
|
|
1061
1044
|
|
|
1062
1045
|
results, _, _ = await driver.execute_query(
|
|
1063
|
-
query, node_uuids=[node.uuid for node in nodes],
|
|
1046
|
+
query, node_uuids=[node.uuid for node in nodes], routing_='r'
|
|
1064
1047
|
)
|
|
1065
1048
|
|
|
1066
1049
|
embeddings_dict: dict[str, list[float]] = {}
|
|
@@ -1086,7 +1069,6 @@ async def get_embeddings_for_communities(
|
|
|
1086
1069
|
results, _, _ = await driver.execute_query(
|
|
1087
1070
|
query,
|
|
1088
1071
|
community_uuids=[community.uuid for community in communities],
|
|
1089
|
-
database_=DEFAULT_DATABASE,
|
|
1090
1072
|
routing_='r',
|
|
1091
1073
|
)
|
|
1092
1074
|
|
|
@@ -1113,7 +1095,6 @@ async def get_embeddings_for_edges(
|
|
|
1113
1095
|
results, _, _ = await driver.execute_query(
|
|
1114
1096
|
query,
|
|
1115
1097
|
edge_uuids=[edge.uuid for edge in edges],
|
|
1116
|
-
database_=DEFAULT_DATABASE,
|
|
1117
1098
|
routing_='r',
|
|
1118
1099
|
)
|
|
1119
1100
|
|