graphiti-core 0.30.0rc3__py3-none-any.whl → 0.30.0rc5__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 +1 -0
- graphiti_core/utils/bulk_utils.py +1 -0
- graphiti_core/utils/maintenance/edge_operations.py +75 -6
- {graphiti_core-0.30.0rc3.dist-info → graphiti_core-0.30.0rc5.dist-info}/METADATA +4 -1
- {graphiti_core-0.30.0rc3.dist-info → graphiti_core-0.30.0rc5.dist-info}/RECORD +7 -7
- {graphiti_core-0.30.0rc3.dist-info → graphiti_core-0.30.0rc5.dist-info}/WHEEL +0 -0
- {graphiti_core-0.30.0rc3.dist-info → graphiti_core-0.30.0rc5.dist-info}/licenses/LICENSE +0 -0
graphiti_core/graphiti.py
CHANGED
|
@@ -43,6 +43,8 @@ from graphiti_core.search.search_filters import SearchFilters
|
|
|
43
43
|
from graphiti_core.utils.datetime_utils import ensure_utc, utc_now
|
|
44
44
|
from graphiti_core.utils.maintenance.dedup_helpers import _normalize_string_exact
|
|
45
45
|
|
|
46
|
+
DEFAULT_EDGE_NAME = 'RELATES_TO'
|
|
47
|
+
|
|
46
48
|
logger = logging.getLogger(__name__)
|
|
47
49
|
|
|
48
50
|
|
|
@@ -281,8 +283,12 @@ async def resolve_extracted_edges(
|
|
|
281
283
|
# Build entity hash table
|
|
282
284
|
uuid_entity_map: dict[str, EntityNode] = {entity.uuid: entity for entity in entities}
|
|
283
285
|
|
|
284
|
-
# Determine which edge types are relevant for each edge
|
|
286
|
+
# Determine which edge types are relevant for each edge.
|
|
287
|
+
# `edge_types_lst` stores the subset of custom edge definitions whose
|
|
288
|
+
# node signature matches each extracted edge. Anything outside this subset
|
|
289
|
+
# should only stay on the edge if it is a non-custom (LLM generated) label.
|
|
285
290
|
edge_types_lst: list[dict[str, type[BaseModel]]] = []
|
|
291
|
+
custom_type_names = set(edge_types or {})
|
|
286
292
|
for extracted_edge in extracted_edges:
|
|
287
293
|
source_node = uuid_entity_map.get(extracted_edge.source_node_uuid)
|
|
288
294
|
target_node = uuid_entity_map.get(extracted_edge.target_node_uuid)
|
|
@@ -310,6 +316,20 @@ async def resolve_extracted_edges(
|
|
|
310
316
|
|
|
311
317
|
edge_types_lst.append(extracted_edge_types)
|
|
312
318
|
|
|
319
|
+
for extracted_edge, extracted_edge_types in zip(extracted_edges, edge_types_lst, strict=True):
|
|
320
|
+
allowed_type_names = set(extracted_edge_types)
|
|
321
|
+
is_custom_name = extracted_edge.name in custom_type_names
|
|
322
|
+
if not allowed_type_names:
|
|
323
|
+
# No custom types are valid for this node pairing. Keep LLM generated
|
|
324
|
+
# labels, but flip disallowed custom names back to the default.
|
|
325
|
+
if is_custom_name and extracted_edge.name != DEFAULT_EDGE_NAME:
|
|
326
|
+
extracted_edge.name = DEFAULT_EDGE_NAME
|
|
327
|
+
continue
|
|
328
|
+
if is_custom_name and extracted_edge.name not in allowed_type_names:
|
|
329
|
+
# Custom name exists but it is not permitted for this source/target
|
|
330
|
+
# signature, so fall back to the default edge label.
|
|
331
|
+
extracted_edge.name = DEFAULT_EDGE_NAME
|
|
332
|
+
|
|
313
333
|
# resolve edges with related edges in the graph and find invalidation candidates
|
|
314
334
|
results: list[tuple[EntityEdge, list[EntityEdge], list[EntityEdge]]] = list(
|
|
315
335
|
await semaphore_gather(
|
|
@@ -321,6 +341,7 @@ async def resolve_extracted_edges(
|
|
|
321
341
|
existing_edges,
|
|
322
342
|
episode,
|
|
323
343
|
extracted_edge_types,
|
|
344
|
+
custom_type_names,
|
|
324
345
|
clients.ensure_ascii,
|
|
325
346
|
)
|
|
326
347
|
for extracted_edge, related_edges, existing_edges, extracted_edge_types in zip(
|
|
@@ -392,9 +413,38 @@ async def resolve_extracted_edge(
|
|
|
392
413
|
related_edges: list[EntityEdge],
|
|
393
414
|
existing_edges: list[EntityEdge],
|
|
394
415
|
episode: EpisodicNode,
|
|
395
|
-
|
|
416
|
+
edge_type_candidates: dict[str, type[BaseModel]] | None = None,
|
|
417
|
+
custom_edge_type_names: set[str] | None = None,
|
|
396
418
|
ensure_ascii: bool = True,
|
|
397
419
|
) -> tuple[EntityEdge, list[EntityEdge], list[EntityEdge]]:
|
|
420
|
+
"""Resolve an extracted edge against existing graph context.
|
|
421
|
+
|
|
422
|
+
Parameters
|
|
423
|
+
----------
|
|
424
|
+
llm_client : LLMClient
|
|
425
|
+
Client used to invoke the LLM for deduplication and attribute extraction.
|
|
426
|
+
extracted_edge : EntityEdge
|
|
427
|
+
Newly extracted edge whose canonical representation is being resolved.
|
|
428
|
+
related_edges : list[EntityEdge]
|
|
429
|
+
Candidate edges with identical endpoints used for duplicate detection.
|
|
430
|
+
existing_edges : list[EntityEdge]
|
|
431
|
+
Broader set of edges evaluated for contradiction / invalidation.
|
|
432
|
+
episode : EpisodicNode
|
|
433
|
+
Episode providing content context when extracting edge attributes.
|
|
434
|
+
edge_type_candidates : dict[str, type[BaseModel]] | None
|
|
435
|
+
Custom edge types permitted for the current source/target signature.
|
|
436
|
+
custom_edge_type_names : set[str] | None
|
|
437
|
+
Full catalog of registered custom edge names. Used to distinguish
|
|
438
|
+
between disallowed custom types (which fall back to the default label)
|
|
439
|
+
and ad-hoc labels emitted by the LLM.
|
|
440
|
+
ensure_ascii : bool
|
|
441
|
+
Whether prompt payloads should coerce ASCII output.
|
|
442
|
+
|
|
443
|
+
Returns
|
|
444
|
+
-------
|
|
445
|
+
tuple[EntityEdge, list[EntityEdge], list[EntityEdge]]
|
|
446
|
+
The resolved edge, any duplicates, and edges to invalidate.
|
|
447
|
+
"""
|
|
398
448
|
if len(related_edges) == 0 and len(existing_edges) == 0:
|
|
399
449
|
return extracted_edge, [], []
|
|
400
450
|
|
|
@@ -429,9 +479,9 @@ async def resolve_extracted_edge(
|
|
|
429
479
|
'fact_type_name': type_name,
|
|
430
480
|
'fact_type_description': type_model.__doc__,
|
|
431
481
|
}
|
|
432
|
-
for i, (type_name, type_model) in enumerate(
|
|
482
|
+
for i, (type_name, type_model) in enumerate(edge_type_candidates.items())
|
|
433
483
|
]
|
|
434
|
-
if
|
|
484
|
+
if edge_type_candidates is not None
|
|
435
485
|
else []
|
|
436
486
|
)
|
|
437
487
|
|
|
@@ -468,7 +518,16 @@ async def resolve_extracted_edge(
|
|
|
468
518
|
]
|
|
469
519
|
|
|
470
520
|
fact_type: str = response_object.fact_type
|
|
471
|
-
|
|
521
|
+
candidate_type_names = set(edge_type_candidates or {})
|
|
522
|
+
custom_type_names = custom_edge_type_names or set()
|
|
523
|
+
|
|
524
|
+
is_default_type = fact_type.upper() == 'DEFAULT'
|
|
525
|
+
is_custom_type = fact_type in custom_type_names
|
|
526
|
+
is_allowed_custom_type = fact_type in candidate_type_names
|
|
527
|
+
|
|
528
|
+
if is_allowed_custom_type:
|
|
529
|
+
# The LLM selected a custom type that is allowed for the node pair.
|
|
530
|
+
# Adopt the custom type and, if needed, extract its structured attributes.
|
|
472
531
|
resolved_edge.name = fact_type
|
|
473
532
|
|
|
474
533
|
edge_attributes_context = {
|
|
@@ -478,7 +537,7 @@ async def resolve_extracted_edge(
|
|
|
478
537
|
'ensure_ascii': ensure_ascii,
|
|
479
538
|
}
|
|
480
539
|
|
|
481
|
-
edge_model =
|
|
540
|
+
edge_model = edge_type_candidates.get(fact_type) if edge_type_candidates else None
|
|
482
541
|
if edge_model is not None and len(edge_model.model_fields) != 0:
|
|
483
542
|
edge_attributes_response = await llm_client.generate_response(
|
|
484
543
|
prompt_library.extract_edges.extract_attributes(edge_attributes_context),
|
|
@@ -487,6 +546,16 @@ async def resolve_extracted_edge(
|
|
|
487
546
|
)
|
|
488
547
|
|
|
489
548
|
resolved_edge.attributes = edge_attributes_response
|
|
549
|
+
elif not is_default_type and is_custom_type:
|
|
550
|
+
# The LLM picked a custom type that is not allowed for this signature.
|
|
551
|
+
# Reset to the default label and drop any structured attributes.
|
|
552
|
+
resolved_edge.name = DEFAULT_EDGE_NAME
|
|
553
|
+
resolved_edge.attributes = {}
|
|
554
|
+
elif not is_default_type:
|
|
555
|
+
# Non-custom labels are allowed to pass through so long as the LLM does
|
|
556
|
+
# not return the sentinel DEFAULT value.
|
|
557
|
+
resolved_edge.name = fact_type
|
|
558
|
+
resolved_edge.attributes = {}
|
|
490
559
|
|
|
491
560
|
end = time()
|
|
492
561
|
logger.debug(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: graphiti-core
|
|
3
|
-
Version: 0.30.
|
|
3
|
+
Version: 0.30.0rc5
|
|
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
|
|
@@ -20,6 +20,7 @@ Provides-Extra: anthropic
|
|
|
20
20
|
Requires-Dist: anthropic>=0.49.0; extra == 'anthropic'
|
|
21
21
|
Provides-Extra: dev
|
|
22
22
|
Requires-Dist: anthropic>=0.49.0; extra == 'dev'
|
|
23
|
+
Requires-Dist: boto3>=1.39.16; extra == 'dev'
|
|
23
24
|
Requires-Dist: diskcache-stubs>=5.6.3.6.20240818; extra == 'dev'
|
|
24
25
|
Requires-Dist: falkordb<2.0.0,>=1.1.2; extra == 'dev'
|
|
25
26
|
Requires-Dist: google-genai>=1.8.0; extra == 'dev'
|
|
@@ -28,9 +29,11 @@ Requires-Dist: ipykernel>=6.29.5; extra == 'dev'
|
|
|
28
29
|
Requires-Dist: jupyterlab>=4.2.4; extra == 'dev'
|
|
29
30
|
Requires-Dist: kuzu>=0.11.2; extra == 'dev'
|
|
30
31
|
Requires-Dist: langchain-anthropic>=0.2.4; extra == 'dev'
|
|
32
|
+
Requires-Dist: langchain-aws>=0.2.29; extra == 'dev'
|
|
31
33
|
Requires-Dist: langchain-openai>=0.2.6; extra == 'dev'
|
|
32
34
|
Requires-Dist: langgraph>=0.2.15; extra == 'dev'
|
|
33
35
|
Requires-Dist: langsmith>=0.1.108; extra == 'dev'
|
|
36
|
+
Requires-Dist: opensearch-py>=3.0.0; extra == 'dev'
|
|
34
37
|
Requires-Dist: pyright>=1.1.404; extra == 'dev'
|
|
35
38
|
Requires-Dist: pytest-asyncio>=0.24.0; extra == 'dev'
|
|
36
39
|
Requires-Dist: pytest-xdist>=3.6.1; extra == 'dev'
|
|
@@ -2,7 +2,7 @@ graphiti_core/__init__.py,sha256=e5SWFkRiaUwfprYIeIgVIh7JDedNiloZvd3roU-0aDY,55
|
|
|
2
2
|
graphiti_core/edges.py,sha256=PhJm_s28cHLEaIqcw66wP16hOq4P4bVQbC_sESHQkXU,20919
|
|
3
3
|
graphiti_core/errors.py,sha256=cH_v9TPgEPeQE6GFOHIg5TvejpUCBddGarMY2Whxbwc,2707
|
|
4
4
|
graphiti_core/graph_queries.py,sha256=ZWMqAo5pwb8PO5ddg4zZ0ArhHWuWV42g3R9ULIxsHOs,8058
|
|
5
|
-
graphiti_core/graphiti.py,sha256=
|
|
5
|
+
graphiti_core/graphiti.py,sha256=5Y3SdcC_Ebhp-oqbbIxb0KGshWU24EQx4YYKvK8Id8g,41935
|
|
6
6
|
graphiti_core/graphiti_types.py,sha256=C_p2XwScQlCzo7ets097TrSLs9ATxPZQ4WCsxDS7QHc,1066
|
|
7
7
|
graphiti_core/helpers.py,sha256=q8kbL9gz8igdlh-oMUS-ylUyeMlXZb-ccf-HQkrES_0,5184
|
|
8
8
|
graphiti_core/nodes.py,sha256=wYLQcVEXvQMxTpTc9LWSoPTzzaoUOm0rl07c9wS1XSY,30323
|
|
@@ -64,18 +64,18 @@ graphiti_core/search/search_utils.py,sha256=ak1aBeKNuxS7szydNHwva2ABWSRlQ0S_v8ZO
|
|
|
64
64
|
graphiti_core/telemetry/__init__.py,sha256=5kALLDlU9bb2v19CdN7qVANsJWyfnL9E60J6FFgzm3o,226
|
|
65
65
|
graphiti_core/telemetry/telemetry.py,sha256=47LrzOVBCcZxsYPsnSxWFiztHoxYKKxPwyRX0hnbDGc,3230
|
|
66
66
|
graphiti_core/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
67
|
-
graphiti_core/utils/bulk_utils.py,sha256=
|
|
67
|
+
graphiti_core/utils/bulk_utils.py,sha256=0rpBaPg1CBQu7djcSS9XWfv9T1unRRVW8_ge_Tf7lF0,20288
|
|
68
68
|
graphiti_core/utils/datetime_utils.py,sha256=J-zYSq7-H-2n9hYOXNIun12kM10vNX9mMATGR_egTmY,1806
|
|
69
69
|
graphiti_core/utils/maintenance/__init__.py,sha256=vW4H1KyapTl-OOz578uZABYcpND4wPx3Vt6aAPaXh78,301
|
|
70
70
|
graphiti_core/utils/maintenance/community_operations.py,sha256=XMiokEemn96GlvjkOvbo9hIX04Fea3eVj408NHG5P4o,11042
|
|
71
71
|
graphiti_core/utils/maintenance/dedup_helpers.py,sha256=B7k6KkB6Sii8PZCWNNTvsNiy4BNTNWpoLeGgrPLq6BE,9220
|
|
72
|
-
graphiti_core/utils/maintenance/edge_operations.py,sha256=
|
|
72
|
+
graphiti_core/utils/maintenance/edge_operations.py,sha256=9bRCI_3loKJX3EAMLpNULWLnhSDCHsCghiqbXPdicPM,24808
|
|
73
73
|
graphiti_core/utils/maintenance/graph_data_operations.py,sha256=42icj3S_ELAJ-NK3jVS_rg_243dmnaZOyUitJj_uJ-M,6085
|
|
74
74
|
graphiti_core/utils/maintenance/node_operations.py,sha256=TKpXPtnTVxxan8I1xQyVkGn3zyRdb_Q00cgUpLcloig,16860
|
|
75
75
|
graphiti_core/utils/maintenance/temporal_operations.py,sha256=IIaVtShpVkOYe6haxz3a1x3v54-MzaEXG8VsxFUNeoY,3582
|
|
76
76
|
graphiti_core/utils/maintenance/utils.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
77
77
|
graphiti_core/utils/ontology_utils/entity_types_utils.py,sha256=4eVgxLWY6Q8k9cRJ5pW59IYF--U4nXZsZIGOVb_yHfQ,1285
|
|
78
|
-
graphiti_core-0.30.
|
|
79
|
-
graphiti_core-0.30.
|
|
80
|
-
graphiti_core-0.30.
|
|
81
|
-
graphiti_core-0.30.
|
|
78
|
+
graphiti_core-0.30.0rc5.dist-info/METADATA,sha256=mHYpDhzM0wWbKChp3NqY8WbiLRfFroA718M6SOtKUy8,27084
|
|
79
|
+
graphiti_core-0.30.0rc5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
80
|
+
graphiti_core-0.30.0rc5.dist-info/licenses/LICENSE,sha256=KCUwCyDXuVEgmDWkozHyniRyWjnWUWjkuDHfU6o3JlA,11325
|
|
81
|
+
graphiti_core-0.30.0rc5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|