graphiti-core 0.5.3__py3-none-any.whl → 0.6.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/graphiti.py +37 -3
- graphiti_core/nodes.py +7 -3
- graphiti_core/prompts/summarize_nodes.py +5 -2
- graphiti_core/utils/maintenance/node_operations.py +1 -0
- {graphiti_core-0.5.3.dist-info → graphiti_core-0.6.1.dist-info}/METADATA +20 -16
- {graphiti_core-0.5.3.dist-info → graphiti_core-0.6.1.dist-info}/RECORD +8 -8
- {graphiti_core-0.5.3.dist-info → graphiti_core-0.6.1.dist-info}/LICENSE +0 -0
- {graphiti_core-0.5.3.dist-info → graphiti_core-0.6.1.dist-info}/WHEEL +0 -0
graphiti_core/graphiti.py
CHANGED
|
@@ -21,6 +21,7 @@ from time import time
|
|
|
21
21
|
from dotenv import load_dotenv
|
|
22
22
|
from neo4j import AsyncGraphDatabase
|
|
23
23
|
from pydantic import BaseModel
|
|
24
|
+
from typing_extensions import LiteralString
|
|
24
25
|
|
|
25
26
|
from graphiti_core.cross_encoder.client import CrossEncoderClient
|
|
26
27
|
from graphiti_core.cross_encoder.openai_reranker_client import OpenAIRerankerClient
|
|
@@ -723,7 +724,7 @@ class Graphiti:
|
|
|
723
724
|
if edge.fact_embedding is None:
|
|
724
725
|
await edge.generate_embedding(self.embedder)
|
|
725
726
|
|
|
726
|
-
resolved_nodes,
|
|
727
|
+
resolved_nodes, uuid_map = await resolve_extracted_nodes(
|
|
727
728
|
self.llm_client,
|
|
728
729
|
[source_node, target_node],
|
|
729
730
|
[
|
|
@@ -732,14 +733,16 @@ class Graphiti:
|
|
|
732
733
|
],
|
|
733
734
|
)
|
|
734
735
|
|
|
736
|
+
updated_edge = resolve_edge_pointers([edge], uuid_map)[0]
|
|
737
|
+
|
|
735
738
|
related_edges = await get_relevant_edges(
|
|
736
739
|
self.driver,
|
|
737
|
-
[
|
|
740
|
+
[updated_edge],
|
|
738
741
|
source_node_uuid=resolved_nodes[0].uuid,
|
|
739
742
|
target_node_uuid=resolved_nodes[1].uuid,
|
|
740
743
|
)
|
|
741
744
|
|
|
742
|
-
resolved_edge = await dedupe_extracted_edge(self.llm_client,
|
|
745
|
+
resolved_edge = await dedupe_extracted_edge(self.llm_client, updated_edge, related_edges)
|
|
743
746
|
|
|
744
747
|
contradicting_edges = await get_edge_contradictions(self.llm_client, edge, related_edges)
|
|
745
748
|
invalidated_edges = resolve_edge_contradictions(resolved_edge, contradicting_edges)
|
|
@@ -747,3 +750,34 @@ class Graphiti:
|
|
|
747
750
|
await add_nodes_and_edges_bulk(
|
|
748
751
|
self.driver, [], [], resolved_nodes, [resolved_edge] + invalidated_edges
|
|
749
752
|
)
|
|
753
|
+
|
|
754
|
+
async def remove_episode(self, episode_uuid: str):
|
|
755
|
+
# Find the episode to be deleted
|
|
756
|
+
episode = await EpisodicNode.get_by_uuid(self.driver, episode_uuid)
|
|
757
|
+
|
|
758
|
+
# Find edges mentioned by the episode
|
|
759
|
+
edges = await EntityEdge.get_by_uuids(self.driver, episode.entity_edges)
|
|
760
|
+
|
|
761
|
+
# We should only delete edges created by the episode
|
|
762
|
+
edges_to_delete: list[EntityEdge] = []
|
|
763
|
+
for edge in edges:
|
|
764
|
+
if edge.episodes[0] == episode.uuid:
|
|
765
|
+
edges_to_delete.append(edge)
|
|
766
|
+
|
|
767
|
+
# Find nodes mentioned by the episode
|
|
768
|
+
nodes = await get_mentioned_nodes(self.driver, [episode])
|
|
769
|
+
# We should delete all nodes that are only mentioned in the deleted episode
|
|
770
|
+
nodes_to_delete: list[EntityNode] = []
|
|
771
|
+
for node in nodes:
|
|
772
|
+
query: LiteralString = 'MATCH (e:Episodic)-[:MENTIONS]->(n:Entity {uuid: $uuid}) RETURN count(*) AS episode_count'
|
|
773
|
+
records, _, _ = await self.driver.execute_query(
|
|
774
|
+
query, uuid=node.uuid, database_=DEFAULT_DATABASE, routing_='r'
|
|
775
|
+
)
|
|
776
|
+
|
|
777
|
+
for record in records:
|
|
778
|
+
if record['episode_count'] == 1:
|
|
779
|
+
nodes_to_delete.append(node)
|
|
780
|
+
|
|
781
|
+
await semaphore_gather(*[node.delete(self.driver) for node in nodes_to_delete])
|
|
782
|
+
await semaphore_gather(*[edge.delete(self.driver) for edge in edges_to_delete])
|
|
783
|
+
await episode.delete(self.driver)
|
graphiti_core/nodes.py
CHANGED
|
@@ -170,7 +170,8 @@ class EpisodicNode(Node):
|
|
|
170
170
|
e.name AS name,
|
|
171
171
|
e.group_id AS group_id,
|
|
172
172
|
e.source_description AS source_description,
|
|
173
|
-
e.source AS source
|
|
173
|
+
e.source AS source,
|
|
174
|
+
e.entity_edges AS entity_edges
|
|
174
175
|
""",
|
|
175
176
|
uuid=uuid,
|
|
176
177
|
database_=DEFAULT_DATABASE,
|
|
@@ -197,7 +198,8 @@ class EpisodicNode(Node):
|
|
|
197
198
|
e.name AS name,
|
|
198
199
|
e.group_id AS group_id,
|
|
199
200
|
e.source_description AS source_description,
|
|
200
|
-
e.source AS source
|
|
201
|
+
e.source AS source,
|
|
202
|
+
e.entity_edges AS entity_edges
|
|
201
203
|
""",
|
|
202
204
|
uuids=uuids,
|
|
203
205
|
database_=DEFAULT_DATABASE,
|
|
@@ -233,7 +235,8 @@ class EpisodicNode(Node):
|
|
|
233
235
|
e.name AS name,
|
|
234
236
|
e.group_id AS group_id,
|
|
235
237
|
e.source_description AS source_description,
|
|
236
|
-
e.source AS source
|
|
238
|
+
e.source AS source,
|
|
239
|
+
e.entity_edges AS entity_edges
|
|
237
240
|
ORDER BY e.uuid DESC
|
|
238
241
|
"""
|
|
239
242
|
+ limit_query,
|
|
@@ -490,6 +493,7 @@ def get_episodic_node_from_record(record: Any) -> EpisodicNode:
|
|
|
490
493
|
source=EpisodeType.from_str(record['source']),
|
|
491
494
|
name=record['name'],
|
|
492
495
|
source_description=record['source_description'],
|
|
496
|
+
entity_edges=record['entity_edges'],
|
|
493
497
|
)
|
|
494
498
|
|
|
495
499
|
|
|
@@ -79,8 +79,8 @@ def summarize_context(context: dict[str, Any]) -> list[Message]:
|
|
|
79
79
|
{json.dumps(context['episode_content'], indent=2)}
|
|
80
80
|
</MESSAGES>
|
|
81
81
|
|
|
82
|
-
Given the above MESSAGES and the following ENTITY name, create a summary for the ENTITY. Your summary must only use
|
|
83
|
-
information from the provided MESSAGES. Your summary should also only contain information relevant to the
|
|
82
|
+
Given the above MESSAGES and the following ENTITY name and ENTITY CONTEXT, create a summary for the ENTITY. Your summary must only use
|
|
83
|
+
information from the provided MESSAGES and from the ENTITY CONTEXT. Your summary should also only contain information relevant to the
|
|
84
84
|
provided ENTITY.
|
|
85
85
|
|
|
86
86
|
Summaries must be under 500 words.
|
|
@@ -88,6 +88,9 @@ def summarize_context(context: dict[str, Any]) -> list[Message]:
|
|
|
88
88
|
<ENTITY>
|
|
89
89
|
{context['node_name']}
|
|
90
90
|
</ENTITY>
|
|
91
|
+
<ENTITY CONTEXT>
|
|
92
|
+
{context['node_summary']}
|
|
93
|
+
</ENTITY CONTEXT>
|
|
91
94
|
""",
|
|
92
95
|
),
|
|
93
96
|
]
|
|
@@ -268,6 +268,7 @@ async def resolve_extracted_node(
|
|
|
268
268
|
|
|
269
269
|
summary_context = {
|
|
270
270
|
'node_name': extracted_node.name,
|
|
271
|
+
'node_summary': extracted_node.summary,
|
|
271
272
|
'episode_content': episode.content if episode is not None else '',
|
|
272
273
|
'previous_episodes': [ep.content for ep in previous_episodes]
|
|
273
274
|
if previous_episodes is not None
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: graphiti-core
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.1
|
|
4
4
|
Summary: A temporal graph building library
|
|
5
5
|
License: Apache-2.0
|
|
6
6
|
Author: Paul Paliychuk
|
|
@@ -22,7 +22,7 @@ Description-Content-Type: text/markdown
|
|
|
22
22
|
|
|
23
23
|
<div align="center">
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
# Graphiti
|
|
26
26
|
|
|
27
27
|
## Temporal Knowledge Graphs for Agentic Applications
|
|
28
28
|
|
|
@@ -45,7 +45,7 @@ a fusion of time, full-text, semantic, and graph algorithm approaches.
|
|
|
45
45
|
<br />
|
|
46
46
|
|
|
47
47
|
<p align="center">
|
|
48
|
-
<img src="
|
|
48
|
+
<img src="images/graphiti-graph-intro.gif" alt="Graphiti temporal walkthrough" width="700px">
|
|
49
49
|
</p>
|
|
50
50
|
|
|
51
51
|
<br />
|
|
@@ -65,6 +65,20 @@ With Graphiti, you can build LLM applications such as:
|
|
|
65
65
|
Graphiti supports a wide range of applications in sales, customer service, health, finance, and more, enabling long-term
|
|
66
66
|
recall and state-based reasoning for both assistants and agents.
|
|
67
67
|
|
|
68
|
+
## Graphiti and Zep Memory
|
|
69
|
+
|
|
70
|
+
Graphiti powers the core of [Zep's memory layer](https://www.getzep.com) for LLM-powered Assistants and Agents.
|
|
71
|
+
|
|
72
|
+
Using Graphiti, we've demonstrated Zep is the [State of the Art in Agent Memory](https://blog.getzep.com/state-of-the-art-agent-memory/).
|
|
73
|
+
|
|
74
|
+
Read our paper: [Zep: A Temporal Knowledge Graph Architecture for Agent Memory](https://arxiv.org/abs/2501.13956).
|
|
75
|
+
|
|
76
|
+
We're excited to open-source Graphiti, believing its potential reaches far beyond memory applications.
|
|
77
|
+
|
|
78
|
+
<p align="center">
|
|
79
|
+
<a href="https://arxiv.org/abs/2501.13956"><img src="images/arxiv-screenshot.png" alt="Zep: A Temporal Knowledge Graph Architecture for Agent Memory" width="700px"></a>
|
|
80
|
+
</p>
|
|
81
|
+
|
|
68
82
|
## Why Graphiti?
|
|
69
83
|
|
|
70
84
|
We were intrigued by Microsoft’s GraphRAG, which expanded on RAG text chunking by using a graph to better model a
|
|
@@ -89,12 +103,6 @@ scale:
|
|
|
89
103
|
<img src="/images/graphiti-intro-slides-stock-2.gif" alt="Graphiti structured + unstructured demo" width="700px">
|
|
90
104
|
</p>
|
|
91
105
|
|
|
92
|
-
## Graphiti and Zep Memory
|
|
93
|
-
|
|
94
|
-
Graphiti powers the core of [Zep's memory layer](https://www.getzep.com) for LLM-powered Assistants and Agents.
|
|
95
|
-
|
|
96
|
-
We're excited to open-source Graphiti, believing its potential reaches far beyond memory applications.
|
|
97
|
-
|
|
98
106
|
## Installation
|
|
99
107
|
|
|
100
108
|
Requirements:
|
|
@@ -125,7 +133,7 @@ poetry add graphiti-core
|
|
|
125
133
|
|
|
126
134
|
> [!IMPORTANT]
|
|
127
135
|
> Graphiti uses OpenAI for LLM inference and embedding. Ensure that an `OPENAI_API_KEY` is set in your environment.
|
|
128
|
-
> Support for Anthropic and Groq LLM inferences is available, too.
|
|
136
|
+
> Support for Anthropic and Groq LLM inferences is available, too. Other LLM providers may be supported via OpenAI compatible APIs.
|
|
129
137
|
|
|
130
138
|
```python
|
|
131
139
|
from graphiti_core import Graphiti
|
|
@@ -216,13 +224,9 @@ as such this feature is off by default.
|
|
|
216
224
|
|
|
217
225
|
Graphiti is under active development. We aim to maintain API stability while working on:
|
|
218
226
|
|
|
219
|
-
- [x] Implementing node and edge CRUD operations
|
|
220
|
-
- [ ] Improving performance and scalability
|
|
221
|
-
- [ ] Achieving good performance with different LLM and embedding models
|
|
222
|
-
- [x] Creating a dedicated embedder interface
|
|
223
227
|
- [ ] Supporting custom graph schemas:
|
|
224
|
-
|
|
225
|
-
|
|
228
|
+
- Allow developers to provide their own defined node and edge classes when ingesting episodes
|
|
229
|
+
- Enable more flexible knowledge representation tailored to specific use cases
|
|
226
230
|
- [x] Enhancing retrieval capabilities with more robust and configurable options
|
|
227
231
|
- [ ] Expanding test coverage to ensure reliability and catch edge cases
|
|
228
232
|
|
|
@@ -9,7 +9,7 @@ graphiti_core/embedder/client.py,sha256=HKIlpPLnzFT81jurPkry6z8F8nxfZVfejdcfxHVU
|
|
|
9
9
|
graphiti_core/embedder/openai.py,sha256=FzEM9rtSDK1wTb4iYKjNjjdFf8BEBTDxG2vM_E-5W-8,1621
|
|
10
10
|
graphiti_core/embedder/voyage.py,sha256=7kqrLG75J3Q6cdA2Nlx1JSYtpk2141ckdl3OtDDw0vU,1882
|
|
11
11
|
graphiti_core/errors.py,sha256=ddHrHGQxhwkVAtSph4AV84UoOlgwZufMczXPwB7uqPo,1795
|
|
12
|
-
graphiti_core/graphiti.py,sha256=
|
|
12
|
+
graphiti_core/graphiti.py,sha256=IaQ2xUM3Z1BG7ByJpznRAdg3FWtcOuIOq9YkY_JfiLE,28974
|
|
13
13
|
graphiti_core/helpers.py,sha256=z7ApOgrm_J7hk5FN_XPAwkKyopEY943BgHjDJbSXr2s,2869
|
|
14
14
|
graphiti_core/llm_client/__init__.py,sha256=PA80TSMeX-sUXITXEAxMDEt3gtfZgcJrGJUcyds1mSo,207
|
|
15
15
|
graphiti_core/llm_client/anthropic_client.py,sha256=RlD6e49XvMJsTKU0krpq46gPSFm6-hfLkkq4Sfx27BE,2574
|
|
@@ -25,7 +25,7 @@ graphiti_core/models/edges/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
|
|
|
25
25
|
graphiti_core/models/edges/edge_db_queries.py,sha256=2UoLkmazO-FJYqjc3g0LuL-pyjekzQxxed_XHVv_HZE,2671
|
|
26
26
|
graphiti_core/models/nodes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
27
27
|
graphiti_core/models/nodes/node_db_queries.py,sha256=I0top_N23FN0U5ZbypaS5IXvtfx2zgJmKUCT_7mpUdo,2257
|
|
28
|
-
graphiti_core/nodes.py,sha256=
|
|
28
|
+
graphiti_core/nodes.py,sha256=_ExaTj2HU-xDczbls4aFcLdpc8zwPZUZ8JgVOrBiEdw,16098
|
|
29
29
|
graphiti_core/prompts/__init__.py,sha256=EA-x9xUki9l8wnu2l8ek_oNf75-do5tq5hVq7Zbv8Kw,101
|
|
30
30
|
graphiti_core/prompts/dedupe_edges.py,sha256=EuX8ngeItBzrlMBOgeHrpExzxIFHD2aoDyaX1ZniF6I,3556
|
|
31
31
|
graphiti_core/prompts/dedupe_nodes.py,sha256=mqvNATL-4Vo33vaxUEZfOq6hXXOiL-ftY0zcx2G-82I,4624
|
|
@@ -37,7 +37,7 @@ graphiti_core/prompts/invalidate_edges.py,sha256=DV2mEyIhhjc0hdKEMFLQMeG0FiUCkv_
|
|
|
37
37
|
graphiti_core/prompts/lib.py,sha256=oxhlpGEgV15VOLEZiwirxmIJBIdfzfiyL58iyzFDskE,4254
|
|
38
38
|
graphiti_core/prompts/models.py,sha256=cvx_Bv5RMFUD_5IUawYrbpOKLPHogai7_bm7YXrSz84,867
|
|
39
39
|
graphiti_core/prompts/prompt_helpers.py,sha256=-9TABwIcIQUVHcNANx6wIZd-FT2DgYKyGTfx4IGYq2I,64
|
|
40
|
-
graphiti_core/prompts/summarize_nodes.py,sha256=
|
|
40
|
+
graphiti_core/prompts/summarize_nodes.py,sha256=XOJykwT7LtzWk2bRquFgv4tRAU3JOkkNkWBg-mkYOKc,3593
|
|
41
41
|
graphiti_core/py.typed,sha256=vlmmzQOt7bmeQl9L3XJP4W6Ry0iiELepnOrinKz5KQg,79
|
|
42
42
|
graphiti_core/search/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
43
43
|
graphiti_core/search/search.py,sha256=4DaeP5aRT7ZOByDO3H5UK0edxfwQ4mzAOdFjnjwaDJs,12454
|
|
@@ -52,10 +52,10 @@ graphiti_core/utils/maintenance/__init__.py,sha256=TRY3wWWu5kn3Oahk_KKhltrWnh0NA
|
|
|
52
52
|
graphiti_core/utils/maintenance/community_operations.py,sha256=gIw1M5HGgc2c3TXag5ygPPpAv5WsG-yoC8Lhmfr6FMs,10011
|
|
53
53
|
graphiti_core/utils/maintenance/edge_operations.py,sha256=tNw56vN586JYZMgie6RLRTiHZ680-kWzDIxW8ucL6SU,12780
|
|
54
54
|
graphiti_core/utils/maintenance/graph_data_operations.py,sha256=qds9ALk9PhpQs1CNZTZGpi70mqJ93Y2KhIh9X2r8MUI,6533
|
|
55
|
-
graphiti_core/utils/maintenance/node_operations.py,sha256=
|
|
55
|
+
graphiti_core/utils/maintenance/node_operations.py,sha256=lrlp27clVhWrxy2BxofTjIISZpwqNG12evHO5wNwOY8,12084
|
|
56
56
|
graphiti_core/utils/maintenance/temporal_operations.py,sha256=RdNtubCyYhOVrvcOIq2WppHls1Q-BEjtsN8r38l-Rtc,3691
|
|
57
57
|
graphiti_core/utils/maintenance/utils.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
58
|
-
graphiti_core-0.
|
|
59
|
-
graphiti_core-0.
|
|
60
|
-
graphiti_core-0.
|
|
61
|
-
graphiti_core-0.
|
|
58
|
+
graphiti_core-0.6.1.dist-info/LICENSE,sha256=KCUwCyDXuVEgmDWkozHyniRyWjnWUWjkuDHfU6o3JlA,11325
|
|
59
|
+
graphiti_core-0.6.1.dist-info/METADATA,sha256=T7rqCclsf8c92WTRWiYXFzWpQR36gy3whh_w-uXWjvA,10242
|
|
60
|
+
graphiti_core-0.6.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
61
|
+
graphiti_core-0.6.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|