graphiti-core 0.12.0rc1__py3-none-any.whl → 0.24.3__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.
- graphiti_core/cross_encoder/bge_reranker_client.py +12 -2
- graphiti_core/cross_encoder/gemini_reranker_client.py +161 -0
- graphiti_core/cross_encoder/openai_reranker_client.py +7 -5
- graphiti_core/decorators.py +110 -0
- graphiti_core/driver/__init__.py +19 -0
- graphiti_core/driver/driver.py +124 -0
- graphiti_core/driver/falkordb_driver.py +362 -0
- graphiti_core/driver/graph_operations/graph_operations.py +191 -0
- graphiti_core/driver/kuzu_driver.py +182 -0
- graphiti_core/driver/neo4j_driver.py +117 -0
- graphiti_core/driver/neptune_driver.py +305 -0
- graphiti_core/driver/search_interface/search_interface.py +89 -0
- graphiti_core/edges.py +287 -172
- graphiti_core/embedder/azure_openai.py +71 -0
- graphiti_core/embedder/client.py +2 -1
- graphiti_core/embedder/gemini.py +116 -22
- graphiti_core/embedder/voyage.py +13 -2
- graphiti_core/errors.py +8 -0
- graphiti_core/graph_queries.py +162 -0
- graphiti_core/graphiti.py +705 -193
- graphiti_core/graphiti_types.py +4 -2
- graphiti_core/helpers.py +87 -10
- graphiti_core/llm_client/__init__.py +16 -0
- graphiti_core/llm_client/anthropic_client.py +159 -56
- graphiti_core/llm_client/azure_openai_client.py +115 -0
- graphiti_core/llm_client/client.py +98 -21
- graphiti_core/llm_client/config.py +1 -1
- graphiti_core/llm_client/gemini_client.py +290 -41
- graphiti_core/llm_client/groq_client.py +14 -3
- graphiti_core/llm_client/openai_base_client.py +261 -0
- graphiti_core/llm_client/openai_client.py +56 -132
- graphiti_core/llm_client/openai_generic_client.py +91 -56
- graphiti_core/models/edges/edge_db_queries.py +259 -35
- graphiti_core/models/nodes/node_db_queries.py +311 -32
- graphiti_core/nodes.py +420 -205
- graphiti_core/prompts/dedupe_edges.py +46 -32
- graphiti_core/prompts/dedupe_nodes.py +67 -42
- graphiti_core/prompts/eval.py +4 -4
- graphiti_core/prompts/extract_edges.py +27 -16
- graphiti_core/prompts/extract_nodes.py +74 -31
- graphiti_core/prompts/prompt_helpers.py +39 -0
- graphiti_core/prompts/snippets.py +29 -0
- graphiti_core/prompts/summarize_nodes.py +23 -25
- graphiti_core/search/search.py +158 -82
- graphiti_core/search/search_config.py +39 -4
- graphiti_core/search/search_filters.py +126 -35
- graphiti_core/search/search_helpers.py +5 -6
- graphiti_core/search/search_utils.py +1405 -485
- graphiti_core/telemetry/__init__.py +9 -0
- graphiti_core/telemetry/telemetry.py +117 -0
- graphiti_core/tracer.py +193 -0
- graphiti_core/utils/bulk_utils.py +364 -285
- graphiti_core/utils/datetime_utils.py +13 -0
- graphiti_core/utils/maintenance/community_operations.py +67 -49
- graphiti_core/utils/maintenance/dedup_helpers.py +262 -0
- graphiti_core/utils/maintenance/edge_operations.py +339 -197
- graphiti_core/utils/maintenance/graph_data_operations.py +50 -114
- graphiti_core/utils/maintenance/node_operations.py +319 -238
- graphiti_core/utils/maintenance/temporal_operations.py +11 -3
- graphiti_core/utils/ontology_utils/entity_types_utils.py +1 -1
- graphiti_core/utils/text_utils.py +53 -0
- graphiti_core-0.24.3.dist-info/METADATA +726 -0
- graphiti_core-0.24.3.dist-info/RECORD +86 -0
- {graphiti_core-0.12.0rc1.dist-info → graphiti_core-0.24.3.dist-info}/WHEEL +1 -1
- graphiti_core-0.12.0rc1.dist-info/METADATA +0 -350
- graphiti_core-0.12.0rc1.dist-info/RECORD +0 -66
- /graphiti_core/{utils/maintenance/utils.py → migrations/__init__.py} +0 -0
- {graphiti_core-0.12.0rc1.dist-info → graphiti_core-0.24.3.dist-info/licenses}/LICENSE +0 -0
|
@@ -19,7 +19,8 @@ from enum import Enum
|
|
|
19
19
|
from typing import Any
|
|
20
20
|
|
|
21
21
|
from pydantic import BaseModel, Field
|
|
22
|
-
|
|
22
|
+
|
|
23
|
+
from graphiti_core.driver.driver import GraphProvider
|
|
23
24
|
|
|
24
25
|
|
|
25
26
|
class ComparisonOperator(Enum):
|
|
@@ -29,143 +30,233 @@ class ComparisonOperator(Enum):
|
|
|
29
30
|
less_than = '<'
|
|
30
31
|
greater_than_equal = '>='
|
|
31
32
|
less_than_equal = '<='
|
|
33
|
+
is_null = 'IS NULL'
|
|
34
|
+
is_not_null = 'IS NOT NULL'
|
|
32
35
|
|
|
33
36
|
|
|
34
37
|
class DateFilter(BaseModel):
|
|
35
|
-
date: datetime = Field(description='A datetime to filter on')
|
|
38
|
+
date: datetime | None = Field(description='A datetime to filter on')
|
|
36
39
|
comparison_operator: ComparisonOperator = Field(
|
|
37
40
|
description='Comparison operator for date filter'
|
|
38
41
|
)
|
|
39
42
|
|
|
40
43
|
|
|
44
|
+
class PropertyFilter(BaseModel):
|
|
45
|
+
property_name: str = Field(description='Property name')
|
|
46
|
+
property_value: str | int | float | None = Field(
|
|
47
|
+
description='Value you want to match on for the property'
|
|
48
|
+
)
|
|
49
|
+
comparison_operator: ComparisonOperator = Field(
|
|
50
|
+
description='Comparison operator for the property'
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
|
|
41
54
|
class SearchFilters(BaseModel):
|
|
42
55
|
node_labels: list[str] | None = Field(
|
|
43
56
|
default=None, description='List of node labels to filter on'
|
|
44
57
|
)
|
|
58
|
+
edge_types: list[str] | None = Field(
|
|
59
|
+
default=None, description='List of edge types to filter on'
|
|
60
|
+
)
|
|
45
61
|
valid_at: list[list[DateFilter]] | None = Field(default=None)
|
|
46
62
|
invalid_at: list[list[DateFilter]] | None = Field(default=None)
|
|
47
63
|
created_at: list[list[DateFilter]] | None = Field(default=None)
|
|
48
64
|
expired_at: list[list[DateFilter]] | None = Field(default=None)
|
|
65
|
+
edge_uuids: list[str] | None = Field(default=None)
|
|
66
|
+
property_filters: list[PropertyFilter] | None = Field(default=None)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def cypher_to_opensearch_operator(op: ComparisonOperator) -> str:
|
|
70
|
+
mapping = {
|
|
71
|
+
ComparisonOperator.greater_than: 'gt',
|
|
72
|
+
ComparisonOperator.less_than: 'lt',
|
|
73
|
+
ComparisonOperator.greater_than_equal: 'gte',
|
|
74
|
+
ComparisonOperator.less_than_equal: 'lte',
|
|
75
|
+
}
|
|
76
|
+
return mapping.get(op, op.value)
|
|
49
77
|
|
|
50
78
|
|
|
51
79
|
def node_search_filter_query_constructor(
|
|
52
80
|
filters: SearchFilters,
|
|
53
|
-
|
|
54
|
-
|
|
81
|
+
provider: GraphProvider,
|
|
82
|
+
) -> tuple[list[str], dict[str, Any]]:
|
|
83
|
+
filter_queries: list[str] = []
|
|
55
84
|
filter_params: dict[str, Any] = {}
|
|
56
85
|
|
|
57
86
|
if filters.node_labels is not None:
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
87
|
+
if provider == GraphProvider.KUZU:
|
|
88
|
+
node_label_filter = 'list_has_all(n.labels, $labels)'
|
|
89
|
+
filter_params['labels'] = filters.node_labels
|
|
90
|
+
else:
|
|
91
|
+
node_labels = '|'.join(filters.node_labels)
|
|
92
|
+
node_label_filter = 'n:' + node_labels
|
|
93
|
+
filter_queries.append(node_label_filter)
|
|
61
94
|
|
|
62
|
-
return
|
|
95
|
+
return filter_queries, filter_params
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def date_filter_query_constructor(
|
|
99
|
+
value_name: str, param_name: str, operator: ComparisonOperator
|
|
100
|
+
) -> str:
|
|
101
|
+
query = '(' + value_name + ' '
|
|
102
|
+
|
|
103
|
+
if operator == ComparisonOperator.is_null or operator == ComparisonOperator.is_not_null:
|
|
104
|
+
query += operator.value + ')'
|
|
105
|
+
else:
|
|
106
|
+
query += operator.value + ' ' + param_name + ')'
|
|
107
|
+
|
|
108
|
+
return query
|
|
63
109
|
|
|
64
110
|
|
|
65
111
|
def edge_search_filter_query_constructor(
|
|
66
112
|
filters: SearchFilters,
|
|
67
|
-
|
|
68
|
-
|
|
113
|
+
provider: GraphProvider,
|
|
114
|
+
) -> tuple[list[str], dict[str, Any]]:
|
|
115
|
+
filter_queries: list[str] = []
|
|
69
116
|
filter_params: dict[str, Any] = {}
|
|
70
117
|
|
|
118
|
+
if filters.edge_types is not None:
|
|
119
|
+
edge_types = filters.edge_types
|
|
120
|
+
filter_queries.append('e.name in $edge_types')
|
|
121
|
+
filter_params['edge_types'] = edge_types
|
|
122
|
+
|
|
123
|
+
if filters.edge_uuids is not None:
|
|
124
|
+
filter_queries.append('e.uuid in $edge_uuids')
|
|
125
|
+
filter_params['edge_uuids'] = filters.edge_uuids
|
|
126
|
+
|
|
127
|
+
if filters.node_labels is not None:
|
|
128
|
+
if provider == GraphProvider.KUZU:
|
|
129
|
+
node_label_filter = (
|
|
130
|
+
'list_has_all(n.labels, $labels) AND list_has_all(m.labels, $labels)'
|
|
131
|
+
)
|
|
132
|
+
filter_params['labels'] = filters.node_labels
|
|
133
|
+
else:
|
|
134
|
+
node_labels = '|'.join(filters.node_labels)
|
|
135
|
+
node_label_filter = 'n:' + node_labels + ' AND m:' + node_labels
|
|
136
|
+
filter_queries.append(node_label_filter)
|
|
137
|
+
|
|
71
138
|
if filters.valid_at is not None:
|
|
72
|
-
valid_at_filter = '
|
|
139
|
+
valid_at_filter = '('
|
|
73
140
|
for i, or_list in enumerate(filters.valid_at):
|
|
74
141
|
for j, date_filter in enumerate(or_list):
|
|
75
|
-
|
|
142
|
+
if date_filter.comparison_operator not in [
|
|
143
|
+
ComparisonOperator.is_null,
|
|
144
|
+
ComparisonOperator.is_not_null,
|
|
145
|
+
]:
|
|
146
|
+
filter_params['valid_at_' + str(j)] = date_filter.date
|
|
76
147
|
|
|
77
148
|
and_filters = [
|
|
78
|
-
|
|
149
|
+
date_filter_query_constructor(
|
|
150
|
+
'e.valid_at', f'$valid_at_{j}', date_filter.comparison_operator
|
|
151
|
+
)
|
|
79
152
|
for j, date_filter in enumerate(or_list)
|
|
80
153
|
]
|
|
81
154
|
and_filter_query = ''
|
|
82
155
|
for j, and_filter in enumerate(and_filters):
|
|
83
156
|
and_filter_query += and_filter
|
|
84
|
-
if j != len(
|
|
157
|
+
if j != len(and_filters) - 1:
|
|
85
158
|
and_filter_query += ' AND '
|
|
86
159
|
|
|
87
160
|
valid_at_filter += and_filter_query
|
|
88
161
|
|
|
89
|
-
if i == len(
|
|
162
|
+
if i == len(filters.valid_at) - 1:
|
|
90
163
|
valid_at_filter += ')'
|
|
91
164
|
else:
|
|
92
165
|
valid_at_filter += ' OR '
|
|
93
166
|
|
|
94
|
-
|
|
167
|
+
filter_queries.append(valid_at_filter)
|
|
95
168
|
|
|
96
169
|
if filters.invalid_at is not None:
|
|
97
|
-
invalid_at_filter = '
|
|
170
|
+
invalid_at_filter = '('
|
|
98
171
|
for i, or_list in enumerate(filters.invalid_at):
|
|
99
172
|
for j, date_filter in enumerate(or_list):
|
|
100
|
-
|
|
173
|
+
if date_filter.comparison_operator not in [
|
|
174
|
+
ComparisonOperator.is_null,
|
|
175
|
+
ComparisonOperator.is_not_null,
|
|
176
|
+
]:
|
|
177
|
+
filter_params['invalid_at_' + str(j)] = date_filter.date
|
|
101
178
|
|
|
102
179
|
and_filters = [
|
|
103
|
-
|
|
180
|
+
date_filter_query_constructor(
|
|
181
|
+
'e.invalid_at', f'$invalid_at_{j}', date_filter.comparison_operator
|
|
182
|
+
)
|
|
104
183
|
for j, date_filter in enumerate(or_list)
|
|
105
184
|
]
|
|
106
185
|
and_filter_query = ''
|
|
107
186
|
for j, and_filter in enumerate(and_filters):
|
|
108
187
|
and_filter_query += and_filter
|
|
109
|
-
if j != len(
|
|
188
|
+
if j != len(and_filters) - 1:
|
|
110
189
|
and_filter_query += ' AND '
|
|
111
190
|
|
|
112
191
|
invalid_at_filter += and_filter_query
|
|
113
192
|
|
|
114
|
-
if i == len(
|
|
193
|
+
if i == len(filters.invalid_at) - 1:
|
|
115
194
|
invalid_at_filter += ')'
|
|
116
195
|
else:
|
|
117
196
|
invalid_at_filter += ' OR '
|
|
118
197
|
|
|
119
|
-
|
|
198
|
+
filter_queries.append(invalid_at_filter)
|
|
120
199
|
|
|
121
200
|
if filters.created_at is not None:
|
|
122
|
-
created_at_filter = '
|
|
201
|
+
created_at_filter = '('
|
|
123
202
|
for i, or_list in enumerate(filters.created_at):
|
|
124
203
|
for j, date_filter in enumerate(or_list):
|
|
125
|
-
|
|
204
|
+
if date_filter.comparison_operator not in [
|
|
205
|
+
ComparisonOperator.is_null,
|
|
206
|
+
ComparisonOperator.is_not_null,
|
|
207
|
+
]:
|
|
208
|
+
filter_params['created_at_' + str(j)] = date_filter.date
|
|
126
209
|
|
|
127
210
|
and_filters = [
|
|
128
|
-
|
|
211
|
+
date_filter_query_constructor(
|
|
212
|
+
'e.created_at', f'$created_at_{j}', date_filter.comparison_operator
|
|
213
|
+
)
|
|
129
214
|
for j, date_filter in enumerate(or_list)
|
|
130
215
|
]
|
|
131
216
|
and_filter_query = ''
|
|
132
217
|
for j, and_filter in enumerate(and_filters):
|
|
133
218
|
and_filter_query += and_filter
|
|
134
|
-
if j != len(
|
|
219
|
+
if j != len(and_filters) - 1:
|
|
135
220
|
and_filter_query += ' AND '
|
|
136
221
|
|
|
137
222
|
created_at_filter += and_filter_query
|
|
138
223
|
|
|
139
|
-
if i == len(
|
|
224
|
+
if i == len(filters.created_at) - 1:
|
|
140
225
|
created_at_filter += ')'
|
|
141
226
|
else:
|
|
142
227
|
created_at_filter += ' OR '
|
|
143
228
|
|
|
144
|
-
|
|
229
|
+
filter_queries.append(created_at_filter)
|
|
145
230
|
|
|
146
231
|
if filters.expired_at is not None:
|
|
147
|
-
expired_at_filter = '
|
|
232
|
+
expired_at_filter = '('
|
|
148
233
|
for i, or_list in enumerate(filters.expired_at):
|
|
149
234
|
for j, date_filter in enumerate(or_list):
|
|
150
|
-
|
|
235
|
+
if date_filter.comparison_operator not in [
|
|
236
|
+
ComparisonOperator.is_null,
|
|
237
|
+
ComparisonOperator.is_not_null,
|
|
238
|
+
]:
|
|
239
|
+
filter_params['expired_at_' + str(j)] = date_filter.date
|
|
151
240
|
|
|
152
241
|
and_filters = [
|
|
153
|
-
|
|
242
|
+
date_filter_query_constructor(
|
|
243
|
+
'e.expired_at', f'$expired_at_{j}', date_filter.comparison_operator
|
|
244
|
+
)
|
|
154
245
|
for j, date_filter in enumerate(or_list)
|
|
155
246
|
]
|
|
156
247
|
and_filter_query = ''
|
|
157
248
|
for j, and_filter in enumerate(and_filters):
|
|
158
249
|
and_filter_query += and_filter
|
|
159
|
-
if j != len(
|
|
250
|
+
if j != len(and_filters) - 1:
|
|
160
251
|
and_filter_query += ' AND '
|
|
161
252
|
|
|
162
253
|
expired_at_filter += and_filter_query
|
|
163
254
|
|
|
164
|
-
if i == len(
|
|
255
|
+
if i == len(filters.expired_at) - 1:
|
|
165
256
|
expired_at_filter += ')'
|
|
166
257
|
else:
|
|
167
258
|
expired_at_filter += ' OR '
|
|
168
259
|
|
|
169
|
-
|
|
260
|
+
filter_queries.append(expired_at_filter)
|
|
170
261
|
|
|
171
|
-
return
|
|
262
|
+
return filter_queries, filter_params
|
|
@@ -14,9 +14,8 @@ See the License for the specific language governing permissions and
|
|
|
14
14
|
limitations under the License.
|
|
15
15
|
"""
|
|
16
16
|
|
|
17
|
-
import json
|
|
18
|
-
|
|
19
17
|
from graphiti_core.edges import EntityEdge
|
|
18
|
+
from graphiti_core.prompts.prompt_helpers import to_prompt_json
|
|
20
19
|
from graphiti_core.search.search_config import SearchResults
|
|
21
20
|
|
|
22
21
|
|
|
@@ -57,16 +56,16 @@ def search_results_to_context_string(search_results: SearchResults) -> str:
|
|
|
57
56
|
These are the most relevant facts and their valid and invalid dates. Facts are considered valid
|
|
58
57
|
between their valid_at and invalid_at dates. Facts with an invalid_at date of "Present" are considered valid.
|
|
59
58
|
<FACTS>
|
|
60
|
-
|
|
59
|
+
{to_prompt_json(fact_json)}
|
|
61
60
|
</FACTS>
|
|
62
61
|
<ENTITIES>
|
|
63
|
-
|
|
62
|
+
{to_prompt_json(entity_json)}
|
|
64
63
|
</ENTITIES>
|
|
65
64
|
<EPISODES>
|
|
66
|
-
|
|
65
|
+
{to_prompt_json(episode_json)}
|
|
67
66
|
</EPISODES>
|
|
68
67
|
<COMMUNITIES>
|
|
69
|
-
|
|
68
|
+
{to_prompt_json(community_json)}
|
|
70
69
|
</COMMUNITIES>
|
|
71
70
|
"""
|
|
72
71
|
|