graphiti-core 0.12.4__tar.gz → 0.13.0__tar.gz
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-0.12.4 → graphiti_core-0.13.0}/PKG-INFO +1 -1
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/errors.py +8 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/graphiti.py +60 -12
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/helpers.py +31 -2
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/models/edges/edge_db_queries.py +1 -1
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/prompts/dedupe_nodes.py +8 -8
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/prompts/extract_edges.py +1 -2
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/utils/maintenance/node_operations.py +1 -1
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/pyproject.toml +1 -1
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/LICENSE +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/README.md +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/__init__.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/cross_encoder/__init__.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/cross_encoder/bge_reranker_client.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/cross_encoder/client.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/cross_encoder/openai_reranker_client.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/driver/__init__.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/driver/driver.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/driver/falkordb_driver.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/driver/neo4j_driver.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/edges.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/embedder/__init__.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/embedder/azure_openai.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/embedder/client.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/embedder/gemini.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/embedder/openai.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/embedder/voyage.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/graph_queries.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/graphiti_types.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/llm_client/__init__.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/llm_client/anthropic_client.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/llm_client/azure_openai_client.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/llm_client/client.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/llm_client/config.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/llm_client/errors.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/llm_client/gemini_client.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/llm_client/groq_client.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/llm_client/openai_client.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/llm_client/openai_generic_client.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/llm_client/utils.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/models/__init__.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/models/edges/__init__.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/models/nodes/__init__.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/models/nodes/node_db_queries.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/nodes.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/prompts/__init__.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/prompts/dedupe_edges.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/prompts/eval.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/prompts/extract_edge_dates.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/prompts/extract_nodes.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/prompts/invalidate_edges.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/prompts/lib.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/prompts/models.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/prompts/prompt_helpers.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/prompts/summarize_nodes.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/py.typed +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/search/__init__.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/search/search.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/search/search_config.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/search/search_config_recipes.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/search/search_filters.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/search/search_helpers.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/search/search_utils.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/utils/__init__.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/utils/bulk_utils.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/utils/datetime_utils.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/utils/maintenance/__init__.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/utils/maintenance/community_operations.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/utils/maintenance/edge_operations.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/utils/maintenance/graph_data_operations.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/utils/maintenance/temporal_operations.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/utils/maintenance/utils.py +0 -0
- {graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/utils/ontology_utils/entity_types_utils.py +0 -0
|
@@ -73,3 +73,11 @@ class EntityTypeValidationError(GraphitiError):
|
|
|
73
73
|
def __init__(self, entity_type: str, entity_type_attribute: str):
|
|
74
74
|
self.message = f'{entity_type_attribute} cannot be used as an attribute for {entity_type} as it is a protected attribute name.'
|
|
75
75
|
super().__init__(self.message)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class GroupIdValidationError(GraphitiError):
|
|
79
|
+
"""Raised when a group_id contains invalid characters."""
|
|
80
|
+
|
|
81
|
+
def __init__(self, group_id: str):
|
|
82
|
+
self.message = f'group_id "{group_id}" must contain only alphanumeric characters, dashes, or underscores'
|
|
83
|
+
super().__init__(self.message)
|
|
@@ -29,7 +29,7 @@ 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
|
|
32
|
+
from graphiti_core.helpers import DEFAULT_DATABASE, semaphore_gather, validate_group_id
|
|
33
33
|
from graphiti_core.llm_client import LLMClient, OpenAIClient
|
|
34
34
|
from graphiti_core.nodes import CommunityNode, EntityNode, EpisodeType, EpisodicNode
|
|
35
35
|
from graphiti_core.search.search import SearchConfig, search
|
|
@@ -103,6 +103,7 @@ class Graphiti:
|
|
|
103
103
|
cross_encoder: CrossEncoderClient | None = None,
|
|
104
104
|
store_raw_episode_content: bool = True,
|
|
105
105
|
graph_driver: GraphDriver | None = None,
|
|
106
|
+
max_coroutines: int | None = None,
|
|
106
107
|
):
|
|
107
108
|
"""
|
|
108
109
|
Initialize a Graphiti instance.
|
|
@@ -121,6 +122,20 @@ class Graphiti:
|
|
|
121
122
|
llm_client : LLMClient | None, optional
|
|
122
123
|
An instance of LLMClient for natural language processing tasks.
|
|
123
124
|
If not provided, a default OpenAIClient will be initialized.
|
|
125
|
+
embedder : EmbedderClient | None, optional
|
|
126
|
+
An instance of EmbedderClient for embedding tasks.
|
|
127
|
+
If not provided, a default OpenAIEmbedder will be initialized.
|
|
128
|
+
cross_encoder : CrossEncoderClient | None, optional
|
|
129
|
+
An instance of CrossEncoderClient for reranking tasks.
|
|
130
|
+
If not provided, a default OpenAIRerankerClient will be initialized.
|
|
131
|
+
store_raw_episode_content : bool, optional
|
|
132
|
+
Whether to store the raw content of episodes. Defaults to True.
|
|
133
|
+
graph_driver : GraphDriver | None, optional
|
|
134
|
+
An instance of GraphDriver for database operations.
|
|
135
|
+
If not provided, a default Neo4jDriver will be initialized.
|
|
136
|
+
max_coroutines : int | None, optional
|
|
137
|
+
The maximum number of concurrent operations allowed. Overrides SEMAPHORE_LIMIT set in the environment.
|
|
138
|
+
If not set, the Graphiti default is used.
|
|
124
139
|
|
|
125
140
|
Returns
|
|
126
141
|
-------
|
|
@@ -145,6 +160,7 @@ class Graphiti:
|
|
|
145
160
|
|
|
146
161
|
self.database = DEFAULT_DATABASE
|
|
147
162
|
self.store_raw_episode_content = store_raw_episode_content
|
|
163
|
+
self.max_coroutines = max_coroutines
|
|
148
164
|
if llm_client:
|
|
149
165
|
self.llm_client = llm_client
|
|
150
166
|
else:
|
|
@@ -335,6 +351,7 @@ class Graphiti:
|
|
|
335
351
|
now = utc_now()
|
|
336
352
|
|
|
337
353
|
validate_entity_types(entity_types)
|
|
354
|
+
validate_group_id(group_id)
|
|
338
355
|
|
|
339
356
|
previous_episodes = (
|
|
340
357
|
await self.retrieve_episodes(
|
|
@@ -393,6 +410,7 @@ class Graphiti:
|
|
|
393
410
|
group_id,
|
|
394
411
|
edge_types,
|
|
395
412
|
),
|
|
413
|
+
max_coroutines=self.max_coroutines,
|
|
396
414
|
)
|
|
397
415
|
|
|
398
416
|
edges = resolve_edge_pointers(extracted_edges, uuid_map)
|
|
@@ -409,6 +427,7 @@ class Graphiti:
|
|
|
409
427
|
extract_attributes_from_nodes(
|
|
410
428
|
self.clients, nodes, episode, previous_episodes, entity_types
|
|
411
429
|
),
|
|
430
|
+
max_coroutines=self.max_coroutines,
|
|
412
431
|
)
|
|
413
432
|
|
|
414
433
|
duplicate_of_edges = build_duplicate_of_edges(episode, now, node_duplicates)
|
|
@@ -432,7 +451,8 @@ class Graphiti:
|
|
|
432
451
|
*[
|
|
433
452
|
update_community(self.driver, self.llm_client, self.embedder, node)
|
|
434
453
|
for node in nodes
|
|
435
|
-
]
|
|
454
|
+
],
|
|
455
|
+
max_coroutines=self.max_coroutines,
|
|
436
456
|
)
|
|
437
457
|
end = time()
|
|
438
458
|
logger.info(f'Completed add_episode in {(end - start) * 1000} ms')
|
|
@@ -484,6 +504,8 @@ class Graphiti:
|
|
|
484
504
|
start = time()
|
|
485
505
|
now = utc_now()
|
|
486
506
|
|
|
507
|
+
validate_group_id(group_id)
|
|
508
|
+
|
|
487
509
|
episodes = [
|
|
488
510
|
EpisodicNode(
|
|
489
511
|
name=episode.name,
|
|
@@ -499,7 +521,10 @@ class Graphiti:
|
|
|
499
521
|
]
|
|
500
522
|
|
|
501
523
|
# Save all the episodes
|
|
502
|
-
await semaphore_gather(
|
|
524
|
+
await semaphore_gather(
|
|
525
|
+
*[episode.save(self.driver) for episode in episodes],
|
|
526
|
+
max_coroutines=self.max_coroutines,
|
|
527
|
+
)
|
|
503
528
|
|
|
504
529
|
# Get previous episode context for each episode
|
|
505
530
|
episode_pairs = await retrieve_previous_episodes_bulk(self.driver, episodes)
|
|
@@ -515,16 +540,21 @@ class Graphiti:
|
|
|
515
540
|
await semaphore_gather(
|
|
516
541
|
*[node.generate_name_embedding(self.embedder) for node in extracted_nodes],
|
|
517
542
|
*[edge.generate_embedding(self.embedder) for edge in extracted_edges],
|
|
543
|
+
max_coroutines=self.max_coroutines,
|
|
518
544
|
)
|
|
519
545
|
|
|
520
546
|
# Dedupe extracted nodes, compress extracted edges
|
|
521
547
|
(nodes, uuid_map), extracted_edges_timestamped = await semaphore_gather(
|
|
522
548
|
dedupe_nodes_bulk(self.driver, self.llm_client, extracted_nodes),
|
|
523
549
|
extract_edge_dates_bulk(self.llm_client, extracted_edges, episode_pairs),
|
|
550
|
+
max_coroutines=self.max_coroutines,
|
|
524
551
|
)
|
|
525
552
|
|
|
526
553
|
# save nodes to KG
|
|
527
|
-
await semaphore_gather(
|
|
554
|
+
await semaphore_gather(
|
|
555
|
+
*[node.save(self.driver) for node in nodes],
|
|
556
|
+
max_coroutines=self.max_coroutines,
|
|
557
|
+
)
|
|
528
558
|
|
|
529
559
|
# re-map edge pointers so that they don't point to discard dupe nodes
|
|
530
560
|
extracted_edges_with_resolved_pointers: list[EntityEdge] = resolve_edge_pointers(
|
|
@@ -536,7 +566,8 @@ class Graphiti:
|
|
|
536
566
|
|
|
537
567
|
# save episodic edges to KG
|
|
538
568
|
await semaphore_gather(
|
|
539
|
-
*[edge.save(self.driver) for edge in episodic_edges_with_resolved_pointers]
|
|
569
|
+
*[edge.save(self.driver) for edge in episodic_edges_with_resolved_pointers],
|
|
570
|
+
max_coroutines=self.max_coroutines,
|
|
540
571
|
)
|
|
541
572
|
|
|
542
573
|
# Dedupe extracted edges
|
|
@@ -548,7 +579,10 @@ class Graphiti:
|
|
|
548
579
|
# invalidate edges
|
|
549
580
|
|
|
550
581
|
# save edges to KG
|
|
551
|
-
await semaphore_gather(
|
|
582
|
+
await semaphore_gather(
|
|
583
|
+
*[edge.save(self.driver) for edge in edges],
|
|
584
|
+
max_coroutines=self.max_coroutines,
|
|
585
|
+
)
|
|
552
586
|
|
|
553
587
|
end = time()
|
|
554
588
|
logger.info(f'Completed add_episode_bulk in {(end - start) * 1000} ms')
|
|
@@ -572,11 +606,18 @@ class Graphiti:
|
|
|
572
606
|
)
|
|
573
607
|
|
|
574
608
|
await semaphore_gather(
|
|
575
|
-
*[node.generate_name_embedding(self.embedder) for node in community_nodes]
|
|
609
|
+
*[node.generate_name_embedding(self.embedder) for node in community_nodes],
|
|
610
|
+
max_coroutines=self.max_coroutines,
|
|
576
611
|
)
|
|
577
612
|
|
|
578
|
-
await semaphore_gather(
|
|
579
|
-
|
|
613
|
+
await semaphore_gather(
|
|
614
|
+
*[node.save(self.driver) for node in community_nodes],
|
|
615
|
+
max_coroutines=self.max_coroutines,
|
|
616
|
+
)
|
|
617
|
+
await semaphore_gather(
|
|
618
|
+
*[edge.save(self.driver) for edge in community_edges],
|
|
619
|
+
max_coroutines=self.max_coroutines,
|
|
620
|
+
)
|
|
580
621
|
|
|
581
622
|
return community_nodes
|
|
582
623
|
|
|
@@ -683,7 +724,8 @@ class Graphiti:
|
|
|
683
724
|
episodes = await EpisodicNode.get_by_uuids(self.driver, episode_uuids)
|
|
684
725
|
|
|
685
726
|
edges_list = await semaphore_gather(
|
|
686
|
-
*[EntityEdge.get_by_uuids(self.driver, episode.entity_edges) for episode in episodes]
|
|
727
|
+
*[EntityEdge.get_by_uuids(self.driver, episode.entity_edges) for episode in episodes],
|
|
728
|
+
max_coroutines=self.max_coroutines,
|
|
687
729
|
)
|
|
688
730
|
|
|
689
731
|
edges: list[EntityEdge] = [edge for lst in edges_list for edge in lst]
|
|
@@ -759,6 +801,12 @@ class Graphiti:
|
|
|
759
801
|
if record['episode_count'] == 1:
|
|
760
802
|
nodes_to_delete.append(node)
|
|
761
803
|
|
|
762
|
-
await semaphore_gather(
|
|
763
|
-
|
|
804
|
+
await semaphore_gather(
|
|
805
|
+
*[node.delete(self.driver) for node in nodes_to_delete],
|
|
806
|
+
max_coroutines=self.max_coroutines,
|
|
807
|
+
)
|
|
808
|
+
await semaphore_gather(
|
|
809
|
+
*[edge.delete(self.driver) for edge in edges_to_delete],
|
|
810
|
+
max_coroutines=self.max_coroutines,
|
|
811
|
+
)
|
|
764
812
|
await episode.delete(self.driver)
|
|
@@ -16,6 +16,7 @@ limitations under the License.
|
|
|
16
16
|
|
|
17
17
|
import asyncio
|
|
18
18
|
import os
|
|
19
|
+
import re
|
|
19
20
|
from collections.abc import Coroutine
|
|
20
21
|
from datetime import datetime
|
|
21
22
|
|
|
@@ -25,6 +26,8 @@ from neo4j import time as neo4j_time
|
|
|
25
26
|
from numpy._typing import NDArray
|
|
26
27
|
from typing_extensions import LiteralString
|
|
27
28
|
|
|
29
|
+
from graphiti_core.errors import GroupIdValidationError
|
|
30
|
+
|
|
28
31
|
load_dotenv()
|
|
29
32
|
|
|
30
33
|
DEFAULT_DATABASE = os.getenv('DEFAULT_DATABASE', 'neo4j')
|
|
@@ -94,12 +97,38 @@ def normalize_l2(embedding: list[float]) -> NDArray:
|
|
|
94
97
|
# Use this instead of asyncio.gather() to bound coroutines
|
|
95
98
|
async def semaphore_gather(
|
|
96
99
|
*coroutines: Coroutine,
|
|
97
|
-
max_coroutines: int =
|
|
100
|
+
max_coroutines: int | None = None,
|
|
98
101
|
):
|
|
99
|
-
semaphore = asyncio.Semaphore(max_coroutines)
|
|
102
|
+
semaphore = asyncio.Semaphore(max_coroutines or SEMAPHORE_LIMIT)
|
|
100
103
|
|
|
101
104
|
async def _wrap_coroutine(coroutine):
|
|
102
105
|
async with semaphore:
|
|
103
106
|
return await coroutine
|
|
104
107
|
|
|
105
108
|
return await asyncio.gather(*(_wrap_coroutine(coroutine) for coroutine in coroutines))
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def validate_group_id(group_id: str) -> bool:
|
|
112
|
+
"""
|
|
113
|
+
Validate that a group_id contains only ASCII alphanumeric characters, dashes, and underscores.
|
|
114
|
+
|
|
115
|
+
Args:
|
|
116
|
+
group_id: The group_id to validate
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
True if valid, False otherwise
|
|
120
|
+
|
|
121
|
+
Raises:
|
|
122
|
+
GroupIdValidationError: If group_id contains invalid characters
|
|
123
|
+
"""
|
|
124
|
+
|
|
125
|
+
# Allow empty string (default case)
|
|
126
|
+
if not group_id:
|
|
127
|
+
return True
|
|
128
|
+
|
|
129
|
+
# Check if string contains only ASCII alphanumeric characters, dashes, or underscores
|
|
130
|
+
# Pattern matches: letters (a-z, A-Z), digits (0-9), hyphens (-), and underscores (_)
|
|
131
|
+
if not re.match(r'^[a-zA-Z0-9_-]+$', group_id):
|
|
132
|
+
raise GroupIdValidationError(group_id)
|
|
133
|
+
|
|
134
|
+
return True
|
|
@@ -35,7 +35,7 @@ ENTITY_EDGE_SAVE = """
|
|
|
35
35
|
MATCH (target:Entity {uuid: $target_uuid})
|
|
36
36
|
MERGE (source)-[r:RELATES_TO {uuid: $uuid}]->(target)
|
|
37
37
|
SET r = $edge_data
|
|
38
|
-
WITH r CALL db.create.setRelationshipVectorProperty(r, "fact_embedding", $fact_embedding)
|
|
38
|
+
WITH r CALL db.create.setRelationshipVectorProperty(r, "fact_embedding", $edge_data.fact_embedding)
|
|
39
39
|
RETURN r.uuid AS uuid"""
|
|
40
40
|
|
|
41
41
|
ENTITY_EDGE_SAVE_BULK = """
|
|
@@ -30,7 +30,7 @@ class NodeDuplicate(BaseModel):
|
|
|
30
30
|
)
|
|
31
31
|
name: str = Field(
|
|
32
32
|
...,
|
|
33
|
-
description='Name of the entity. Should be the most complete and descriptive name
|
|
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
|
additional_duplicates: list[int] = Field(
|
|
36
36
|
...,
|
|
@@ -84,19 +84,19 @@ def node(context: dict[str, Any]) -> list[Message]:
|
|
|
84
84
|
is a duplicate entity of one of the EXISTING ENTITIES.
|
|
85
85
|
|
|
86
86
|
Entities should only be considered duplicates if they refer to the *same real-world object or concept*.
|
|
87
|
+
Semantic Equivalence: if a descriptive label in existing_entities clearly refers to a named entity in context, treat them as duplicates.
|
|
87
88
|
|
|
88
89
|
Do NOT mark entities as duplicates if:
|
|
89
90
|
- They are related but distinct.
|
|
90
91
|
- They have similar names or purposes but refer to separate instances or concepts.
|
|
91
92
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
duplicate_entity_id should be set to -1.
|
|
93
|
+
TASK:
|
|
94
|
+
1. Compare `new_entity` against each item in `existing_entities`.
|
|
95
|
+
2. If it refers to the same real‐world object or concept, collect its index.
|
|
96
|
+
3. Let `duplicate_idx` = the *first* collected index, or –1 if none.
|
|
97
|
+
4. Let `additional_duplicates` = the list of *any other* collected indices (empty list if none).
|
|
98
98
|
|
|
99
|
-
Also return the name
|
|
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).
|
|
101
101
|
""",
|
|
102
102
|
),
|
|
@@ -97,8 +97,7 @@ Only extract facts that:
|
|
|
97
97
|
- The FACT TYPES provide a list of the most important types of facts, make sure to extract facts of these types
|
|
98
98
|
- The FACT TYPES are not an exhaustive list, extract all facts from the message even if they do not fit into one
|
|
99
99
|
of the FACT TYPES
|
|
100
|
-
- The FACT TYPES each contain their fact_type_signature which represents the
|
|
101
|
-
A Type of Entity in the signature represents any extracted entity (it is a generic universal type for all entities).
|
|
100
|
+
- The FACT TYPES each contain their fact_type_signature which represents the source and target entity types.
|
|
102
101
|
|
|
103
102
|
You may use information from the PREVIOUS MESSAGES only to disambiguate references or support continuity.
|
|
104
103
|
|
{graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/utils/maintenance/node_operations.py
RENAMED
|
@@ -310,7 +310,7 @@ async def resolve_extracted_nodes(
|
|
|
310
310
|
else extracted_node
|
|
311
311
|
)
|
|
312
312
|
|
|
313
|
-
resolved_node.name = resolution.get('name')
|
|
313
|
+
# resolved_node.name = resolution.get('name')
|
|
314
314
|
|
|
315
315
|
resolved_nodes.append(resolved_node)
|
|
316
316
|
uuid_map[extracted_node.uuid] = resolved_node.uuid
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "graphiti-core"
|
|
3
3
|
description = "A temporal graph building library"
|
|
4
|
-
version = "0.
|
|
4
|
+
version = "0.13.0"
|
|
5
5
|
authors = [
|
|
6
6
|
{ "name" = "Paul Paliychuk", "email" = "paul@getzep.com" },
|
|
7
7
|
{ "name" = "Preston Rasmussen", "email" = "preston@getzep.com" },
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/cross_encoder/bge_reranker_client.py
RENAMED
|
File without changes
|
|
File without changes
|
{graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/cross_encoder/openai_reranker_client.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/llm_client/azure_openai_client.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/llm_client/openai_generic_client.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/utils/maintenance/edge_operations.py
RENAMED
|
File without changes
|
|
File without changes
|
{graphiti_core-0.12.4 → graphiti_core-0.13.0}/graphiti_core/utils/maintenance/temporal_operations.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|