graphiti-core 0.24.3__py3-none-any.whl → 0.25.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.
@@ -29,13 +29,13 @@ from graphiti_core.edges import (
29
29
  create_entity_edge_embeddings,
30
30
  )
31
31
  from graphiti_core.graphiti_types import GraphitiClients
32
- from graphiti_core.helpers import MAX_REFLEXION_ITERATIONS, semaphore_gather
32
+ from graphiti_core.helpers import semaphore_gather
33
33
  from graphiti_core.llm_client import LLMClient
34
34
  from graphiti_core.llm_client.config import ModelSize
35
35
  from graphiti_core.nodes import CommunityNode, EntityNode, EpisodicNode
36
36
  from graphiti_core.prompts import prompt_library
37
37
  from graphiti_core.prompts.dedupe_edges import EdgeDuplicate
38
- from graphiti_core.prompts.extract_edges import ExtractedEdges, MissingFacts
38
+ from graphiti_core.prompts.extract_edges import ExtractedEdges
39
39
  from graphiti_core.search.search import search
40
40
  from graphiti_core.search.search_config import SearchResults
41
41
  from graphiti_core.search.search_config_recipes import EDGE_HYBRID_SEARCH_RRF
@@ -94,6 +94,7 @@ async def extract_edges(
94
94
  edge_type_map: dict[tuple[str, str], list[str]],
95
95
  group_id: str = '',
96
96
  edge_types: dict[str, type[BaseModel]] | None = None,
97
+ custom_extraction_instructions: str | None = None,
97
98
  ) -> list[EntityEdge]:
98
99
  start = time()
99
100
 
@@ -129,42 +130,17 @@ async def extract_edges(
129
130
  'previous_episodes': [ep.content for ep in previous_episodes],
130
131
  'reference_time': episode.valid_at,
131
132
  'edge_types': edge_types_context,
132
- 'custom_prompt': '',
133
+ 'custom_extraction_instructions': custom_extraction_instructions or '',
133
134
  }
134
135
 
135
- facts_missed = True
136
- reflexion_iterations = 0
137
- while facts_missed and reflexion_iterations <= MAX_REFLEXION_ITERATIONS:
138
- llm_response = await llm_client.generate_response(
139
- prompt_library.extract_edges.edge(context),
140
- response_model=ExtractedEdges,
141
- max_tokens=extract_edges_max_tokens,
142
- group_id=group_id,
143
- prompt_name='extract_edges.edge',
144
- )
145
- edges_data = ExtractedEdges(**llm_response).edges
146
-
147
- context['extracted_facts'] = [edge_data.fact for edge_data in edges_data]
148
-
149
- reflexion_iterations += 1
150
- if reflexion_iterations < MAX_REFLEXION_ITERATIONS:
151
- reflexion_response = await llm_client.generate_response(
152
- prompt_library.extract_edges.reflexion(context),
153
- response_model=MissingFacts,
154
- max_tokens=extract_edges_max_tokens,
155
- group_id=group_id,
156
- prompt_name='extract_edges.reflexion',
157
- )
158
-
159
- missing_facts = reflexion_response.get('missing_facts', [])
160
-
161
- custom_prompt = 'The following facts were missed in a previous extraction: '
162
- for fact in missing_facts:
163
- custom_prompt += f'\n{fact},'
164
-
165
- context['custom_prompt'] = custom_prompt
166
-
167
- facts_missed = len(missing_facts) != 0
136
+ llm_response = await llm_client.generate_response(
137
+ prompt_library.extract_edges.edge(context),
138
+ response_model=ExtractedEdges,
139
+ max_tokens=extract_edges_max_tokens,
140
+ group_id=group_id,
141
+ prompt_name='extract_edges.edge',
142
+ )
143
+ edges_data = ExtractedEdges(**llm_response).edges
168
144
 
169
145
  end = time()
170
146
  logger.debug(f'Extracted new edges: {edges_data} in {(end - start) * 1000} ms')
@@ -313,6 +289,20 @@ async def resolve_extracted_edges(
313
289
  # Build entity hash table
314
290
  uuid_entity_map: dict[str, EntityNode] = {entity.uuid: entity for entity in entities}
315
291
 
292
+ # Collect all node UUIDs referenced by edges that are not in the entities list
293
+ referenced_node_uuids = set()
294
+ for extracted_edge in extracted_edges:
295
+ if extracted_edge.source_node_uuid not in uuid_entity_map:
296
+ referenced_node_uuids.add(extracted_edge.source_node_uuid)
297
+ if extracted_edge.target_node_uuid not in uuid_entity_map:
298
+ referenced_node_uuids.add(extracted_edge.target_node_uuid)
299
+
300
+ # Fetch missing nodes from the database
301
+ if referenced_node_uuids:
302
+ missing_nodes = await EntityNode.get_by_uuids(driver, list(referenced_node_uuids))
303
+ for node in missing_nodes:
304
+ uuid_entity_map[node.uuid] = node
305
+
316
306
  # Determine which edge types are relevant for each edge.
317
307
  # `edge_types_lst` stores the subset of custom edge definitions whose
318
308
  # node signature matches each extracted edge. Anything outside this subset
@@ -22,7 +22,7 @@ from typing import Any
22
22
  from pydantic import BaseModel
23
23
 
24
24
  from graphiti_core.graphiti_types import GraphitiClients
25
- from graphiti_core.helpers import MAX_REFLEXION_ITERATIONS, semaphore_gather
25
+ from graphiti_core.helpers import semaphore_gather
26
26
  from graphiti_core.llm_client import LLMClient
27
27
  from graphiti_core.llm_client.config import ModelSize
28
28
  from graphiti_core.nodes import (
@@ -43,6 +43,12 @@ from graphiti_core.search.search import search
43
43
  from graphiti_core.search.search_config import SearchResults
44
44
  from graphiti_core.search.search_config_recipes import NODE_HYBRID_SEARCH_RRF
45
45
  from graphiti_core.search.search_filters import SearchFilters
46
+ from graphiti_core.utils.content_chunking import (
47
+ chunk_json_content,
48
+ chunk_message_content,
49
+ chunk_text_content,
50
+ should_chunk,
51
+ )
46
52
  from graphiti_core.utils.datetime_utils import utc_now
47
53
  from graphiti_core.utils.maintenance.dedup_helpers import (
48
54
  DedupCandidateIndexes,
@@ -91,24 +97,67 @@ async def extract_nodes(
91
97
  previous_episodes: list[EpisodicNode],
92
98
  entity_types: dict[str, type[BaseModel]] | None = None,
93
99
  excluded_entity_types: list[str] | None = None,
100
+ custom_extraction_instructions: str | None = None,
94
101
  ) -> list[EntityNode]:
102
+ """Extract entity nodes from an episode with adaptive chunking.
103
+
104
+ For high-density content (many entities per token), the content is chunked
105
+ and processed in parallel to avoid LLM timeouts and truncation issues.
106
+ """
95
107
  start = time()
96
108
  llm_client = clients.llm_client
97
- llm_response = {}
98
- custom_prompt = ''
99
- entities_missed = True
100
- reflexion_iterations = 0
101
109
 
110
+ # Build entity types context
111
+ entity_types_context = _build_entity_types_context(entity_types)
112
+
113
+ # Build base context
114
+ context = {
115
+ 'episode_content': episode.content,
116
+ 'episode_timestamp': episode.valid_at.isoformat(),
117
+ 'previous_episodes': [ep.content for ep in previous_episodes],
118
+ 'custom_extraction_instructions': custom_extraction_instructions or '',
119
+ 'entity_types': entity_types_context,
120
+ 'source_description': episode.source_description,
121
+ }
122
+
123
+ # Check if chunking is needed (based on entity density)
124
+ if should_chunk(episode.content, episode.source):
125
+ extracted_entities = await _extract_nodes_chunked(llm_client, episode, context)
126
+ else:
127
+ extracted_entities = await _extract_nodes_single(llm_client, episode, context)
128
+
129
+ # Filter empty names
130
+ filtered_entities = [e for e in extracted_entities if e.name.strip()]
131
+
132
+ end = time()
133
+ logger.debug(f'Extracted {len(filtered_entities)} entities in {(end - start) * 1000:.0f} ms')
134
+
135
+ # Convert to EntityNode objects
136
+ extracted_nodes = _create_entity_nodes(
137
+ filtered_entities, entity_types_context, excluded_entity_types, episode
138
+ )
139
+
140
+ logger.debug(f'Extracted nodes: {[(n.name, n.uuid) for n in extracted_nodes]}')
141
+ return extracted_nodes
142
+
143
+
144
+ def _build_entity_types_context(
145
+ entity_types: dict[str, type[BaseModel]] | None,
146
+ ) -> list[dict]:
147
+ """Build entity types context with ID mappings."""
102
148
  entity_types_context = [
103
149
  {
104
150
  'entity_type_id': 0,
105
151
  'entity_type_name': 'Entity',
106
- 'entity_type_description': 'Default entity classification. Use this entity type if the entity is not one of the other listed types.',
152
+ 'entity_type_description': (
153
+ 'Default entity classification. Use this entity type '
154
+ 'if the entity is not one of the other listed types.'
155
+ ),
107
156
  }
108
157
  ]
109
158
 
110
- entity_types_context += (
111
- [
159
+ if entity_types is not None:
160
+ entity_types_context += [
112
161
  {
113
162
  'entity_type_id': i + 1,
114
163
  'entity_type_name': type_name,
@@ -116,73 +165,124 @@ async def extract_nodes(
116
165
  }
117
166
  for i, (type_name, type_model) in enumerate(entity_types.items())
118
167
  ]
119
- if entity_types is not None
120
- else []
168
+
169
+ return entity_types_context
170
+
171
+
172
+ async def _extract_nodes_single(
173
+ llm_client: LLMClient,
174
+ episode: EpisodicNode,
175
+ context: dict,
176
+ ) -> list[ExtractedEntity]:
177
+ """Extract entities using a single LLM call."""
178
+ llm_response = await _call_extraction_llm(llm_client, episode, context)
179
+ response_object = ExtractedEntities(**llm_response)
180
+ return response_object.extracted_entities
181
+
182
+
183
+ async def _extract_nodes_chunked(
184
+ llm_client: LLMClient,
185
+ episode: EpisodicNode,
186
+ context: dict,
187
+ ) -> list[ExtractedEntity]:
188
+ """Extract entities from large content using chunking."""
189
+ # Chunk the content based on episode type
190
+ if episode.source == EpisodeType.json:
191
+ chunks = chunk_json_content(episode.content)
192
+ elif episode.source == EpisodeType.message:
193
+ chunks = chunk_message_content(episode.content)
194
+ else:
195
+ chunks = chunk_text_content(episode.content)
196
+
197
+ logger.debug(f'Chunked content into {len(chunks)} chunks for entity extraction')
198
+
199
+ # Extract entities from each chunk in parallel
200
+ chunk_results = await semaphore_gather(
201
+ *[_extract_from_chunk(llm_client, chunk, context, episode) for chunk in chunks]
121
202
  )
122
203
 
123
- context = {
124
- 'episode_content': episode.content,
125
- 'episode_timestamp': episode.valid_at.isoformat(),
126
- 'previous_episodes': [ep.content for ep in previous_episodes],
127
- 'custom_prompt': custom_prompt,
128
- 'entity_types': entity_types_context,
129
- 'source_description': episode.source_description,
130
- }
204
+ # Merge and deduplicate entities across chunks
205
+ merged_entities = _merge_extracted_entities(chunk_results)
206
+ logger.debug(
207
+ f'Merged {sum(len(r) for r in chunk_results)} entities into {len(merged_entities)} unique'
208
+ )
131
209
 
132
- while entities_missed and reflexion_iterations <= MAX_REFLEXION_ITERATIONS:
133
- if episode.source == EpisodeType.message:
134
- llm_response = await llm_client.generate_response(
135
- prompt_library.extract_nodes.extract_message(context),
136
- response_model=ExtractedEntities,
137
- group_id=episode.group_id,
138
- prompt_name='extract_nodes.extract_message',
139
- )
140
- elif episode.source == EpisodeType.text:
141
- llm_response = await llm_client.generate_response(
142
- prompt_library.extract_nodes.extract_text(context),
143
- response_model=ExtractedEntities,
144
- group_id=episode.group_id,
145
- prompt_name='extract_nodes.extract_text',
146
- )
147
- elif episode.source == EpisodeType.json:
148
- llm_response = await llm_client.generate_response(
149
- prompt_library.extract_nodes.extract_json(context),
150
- response_model=ExtractedEntities,
151
- group_id=episode.group_id,
152
- prompt_name='extract_nodes.extract_json',
153
- )
210
+ return merged_entities
154
211
 
155
- response_object = ExtractedEntities(**llm_response)
156
212
 
157
- extracted_entities: list[ExtractedEntity] = response_object.extracted_entities
213
+ async def _extract_from_chunk(
214
+ llm_client: LLMClient,
215
+ chunk: str,
216
+ base_context: dict,
217
+ episode: EpisodicNode,
218
+ ) -> list[ExtractedEntity]:
219
+ """Extract entities from a single chunk."""
220
+ chunk_context = {**base_context, 'episode_content': chunk}
221
+ llm_response = await _call_extraction_llm(llm_client, episode, chunk_context)
222
+ return ExtractedEntities(**llm_response).extracted_entities
158
223
 
159
- reflexion_iterations += 1
160
- if reflexion_iterations < MAX_REFLEXION_ITERATIONS:
161
- missing_entities = await extract_nodes_reflexion(
162
- llm_client,
163
- episode,
164
- previous_episodes,
165
- [entity.name for entity in extracted_entities],
166
- episode.group_id,
167
- )
168
224
 
169
- entities_missed = len(missing_entities) != 0
225
+ async def _call_extraction_llm(
226
+ llm_client: LLMClient,
227
+ episode: EpisodicNode,
228
+ context: dict,
229
+ ) -> dict:
230
+ """Call the appropriate extraction prompt based on episode type."""
231
+ if episode.source == EpisodeType.message:
232
+ prompt = prompt_library.extract_nodes.extract_message(context)
233
+ prompt_name = 'extract_nodes.extract_message'
234
+ elif episode.source == EpisodeType.text:
235
+ prompt = prompt_library.extract_nodes.extract_text(context)
236
+ prompt_name = 'extract_nodes.extract_text'
237
+ elif episode.source == EpisodeType.json:
238
+ prompt = prompt_library.extract_nodes.extract_json(context)
239
+ prompt_name = 'extract_nodes.extract_json'
240
+ else:
241
+ # Fallback to text extraction
242
+ prompt = prompt_library.extract_nodes.extract_text(context)
243
+ prompt_name = 'extract_nodes.extract_text'
244
+
245
+ return await llm_client.generate_response(
246
+ prompt,
247
+ response_model=ExtractedEntities,
248
+ group_id=episode.group_id,
249
+ prompt_name=prompt_name,
250
+ )
170
251
 
171
- custom_prompt = 'Make sure that the following entities are extracted: '
172
- for entity in missing_entities:
173
- custom_prompt += f'\n{entity},'
174
252
 
175
- filtered_extracted_entities = [entity for entity in extracted_entities if entity.name.strip()]
176
- end = time()
177
- logger.debug(f'Extracted new nodes: {filtered_extracted_entities} in {(end - start) * 1000} ms')
178
- # Convert the extracted data into EntityNode objects
253
+ def _merge_extracted_entities(
254
+ chunk_results: list[list[ExtractedEntity]],
255
+ ) -> list[ExtractedEntity]:
256
+ """Merge entities from multiple chunks, deduplicating by normalized name.
257
+
258
+ When duplicates occur, prefer the first occurrence (maintains ordering).
259
+ """
260
+ seen_names: set[str] = set()
261
+ merged: list[ExtractedEntity] = []
262
+
263
+ for entities in chunk_results:
264
+ for entity in entities:
265
+ normalized = entity.name.strip().lower()
266
+ if normalized and normalized not in seen_names:
267
+ seen_names.add(normalized)
268
+ merged.append(entity)
269
+
270
+ return merged
271
+
272
+
273
+ def _create_entity_nodes(
274
+ extracted_entities: list[ExtractedEntity],
275
+ entity_types_context: list[dict],
276
+ excluded_entity_types: list[str] | None,
277
+ episode: EpisodicNode,
278
+ ) -> list[EntityNode]:
279
+ """Convert ExtractedEntity objects to EntityNode objects."""
179
280
  extracted_nodes = []
180
- for extracted_entity in filtered_extracted_entities:
281
+
282
+ for extracted_entity in extracted_entities:
181
283
  type_id = extracted_entity.entity_type_id
182
284
  if 0 <= type_id < len(entity_types_context):
183
- entity_type_name = entity_types_context[extracted_entity.entity_type_id].get(
184
- 'entity_type_name'
185
- )
285
+ entity_type_name = entity_types_context[type_id].get('entity_type_name')
186
286
  else:
187
287
  entity_type_name = 'Entity'
188
288
 
@@ -203,8 +303,6 @@ async def extract_nodes(
203
303
  extracted_nodes.append(new_node)
204
304
  logger.debug(f'Created new node: {new_node.name} (UUID: {new_node.uuid})')
205
305
 
206
- logger.debug(f'Extracted nodes: {[(n.name, n.uuid) for n in extracted_nodes]}')
207
-
208
306
  return extracted_nodes
209
307
 
210
308
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: graphiti-core
3
- Version: 0.24.3
3
+ Version: 0.25.3
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
@@ -132,7 +132,7 @@ while handling changing relationships and maintaining historical context.
132
132
 
133
133
  ## Graphiti and Zep's Context Engineering Platform.
134
134
 
135
- Graphiti powers the core of [Zep](https://www.getzep.com), a turn-key context engineering platform for AI Agents. Zep
135
+ Graphiti powers the core of [Zep's context engineering platform](https://www.getzep.com) for AI Agents. Zep
136
136
  offers agent memory, Graph RAG for dynamic data, and context retrieval and assembly.
137
137
 
138
138
  Using Graphiti, we've demonstrated Zep is
@@ -3,9 +3,9 @@ graphiti_core/decorators.py,sha256=tqSICazrXEzQ96MXKbnl_07Y7ah8OuH8rJqRKEOC0q8,4
3
3
  graphiti_core/edges.py,sha256=JZZGo6G2HTYv-aaE-s8P7yIXkdHaNqg5UGGPDV4nZOI,20201
4
4
  graphiti_core/errors.py,sha256=cH_v9TPgEPeQE6GFOHIg5TvejpUCBddGarMY2Whxbwc,2707
5
5
  graphiti_core/graph_queries.py,sha256=ZWMqAo5pwb8PO5ddg4zZ0ArhHWuWV42g3R9ULIxsHOs,8058
6
- graphiti_core/graphiti.py,sha256=6HsRHx5CFe7D6XhJ_53pVQr5UJlDM-G1QPzUOKklSQE,47700
6
+ graphiti_core/graphiti.py,sha256=KEG-Kdh9OrFAj4f81nTaA25BHBMGfUeqWOBGPyLFIHo,49893
7
7
  graphiti_core/graphiti_types.py,sha256=_v-XsMgV-bBbi5P-PoRVyGJEdHEDJR-Khmv4cU0oZ-4,1094
8
- graphiti_core/helpers.py,sha256=q8kbL9gz8igdlh-oMUS-ylUyeMlXZb-ccf-HQkrES_0,5184
8
+ graphiti_core/helpers.py,sha256=5IsSYXylLjyKVg83DQB7eKBRQ49PbL7AEOQEGZqY3Jg,6258
9
9
  graphiti_core/nodes.py,sha256=W_Lx0x3YbJoNRVDGO2Mf9s3MwDFu2NolQl-15jFpr0U,27383
10
10
  graphiti_core/py.typed,sha256=vlmmzQOt7bmeQl9L3XJP4W6Ry0iiELepnOrinKz5KQg,79
11
11
  graphiti_core/tracer.py,sha256=5L05H8PdJ1eqhmcHuYTtwMThVGVUdUzTdiFd_-07H4E,6149
@@ -18,7 +18,7 @@ graphiti_core/driver/__init__.py,sha256=kCWimqQU19airu5gKwCmZtZuXkDfaQfKSUhMDoL-
18
18
  graphiti_core/driver/driver.py,sha256=BmsOrUoUqfdgd3487Vs4WJtl_srSL-szxGRtVBGUeJc,3789
19
19
  graphiti_core/driver/falkordb_driver.py,sha256=siztncHLSMqn-GbxkW5y2ybS6kEpjrV_2ZTb9t7FSIg,12877
20
20
  graphiti_core/driver/kuzu_driver.py,sha256=SZfbRffC0hz1i5Xnlkx79Z_o4iNKf4barrxdlfrmBgo,5775
21
- graphiti_core/driver/neo4j_driver.py,sha256=mnsAStRAid9Y47-_vW0ccCDV6q48SvVgVjMFUxNkgRc,3893
21
+ graphiti_core/driver/neo4j_driver.py,sha256=QDuQ8TXgqAvUEaaYRVRc_ftpIlSvJ7RxSB5BX21CRtk,4590
22
22
  graphiti_core/driver/neptune_driver.py,sha256=9-MHqgE-Iobzyk1OYO_R1o0AplueSyG25uFYhnCeZi8,11517
23
23
  graphiti_core/driver/graph_operations/graph_operations.py,sha256=9Qxs4za1kUNnpGzkO_z2zX4wPvYq6KWan30WlCH-vw8,5284
24
24
  graphiti_core/driver/search_interface/search_interface.py,sha256=-lnPsXdv_4feULbOnuWUQN2wmLqcUkGMwmR74jaFyMI,2500
@@ -36,8 +36,8 @@ graphiti_core/llm_client/config.py,sha256=pivp29CDIbDPqgw5NF9Ok2AwcqTV5z5_Q1bgNs
36
36
  graphiti_core/llm_client/errors.py,sha256=pn6brRiLW60DAUIXJYKBT6MInrS4ueuH1hNLbn_JbQo,1243
37
37
  graphiti_core/llm_client/gemini_client.py,sha256=xRYeFXhNfzwt2o__Qv5-rCxuub-4-hgvQpaawEhsN0c,18746
38
38
  graphiti_core/llm_client/groq_client.py,sha256=bYLE_cg1QEhugsJOXh4b1vPbxagKeMWqk48240GCzMs,2922
39
- graphiti_core/llm_client/openai_base_client.py,sha256=GY4PIOFeLSFEIBowxk0JJ5LwiXdnDYpYxIWPZclOlXY,10064
40
- graphiti_core/llm_client/openai_client.py,sha256=rNLhYJobsDMa4awO0HgPpePdqKjdDZc-K3WCMlONUtw,4235
39
+ graphiti_core/llm_client/openai_base_client.py,sha256=ZjPiYh9vyrNrkgVHjZoSUH0JgcX7tVzZGf4kK9w6Upk,10068
40
+ graphiti_core/llm_client/openai_client.py,sha256=tijw92l6cgbGv2ES-aVhCH1OB_9h7CZExnQ0799c3uE,4563
41
41
  graphiti_core/llm_client/openai_generic_client.py,sha256=9cXfGQxAxD8hQOXoHTKiPbqKgHzzneaJCgE_WAJ4zzM,8606
42
42
  graphiti_core/llm_client/utils.py,sha256=zKpxXEbKa369m4W7RDEf-m56kH46V1Mx3RowcWZEWWs,1000
43
43
  graphiti_core/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -51,8 +51,8 @@ graphiti_core/prompts/dedupe_edges.py,sha256=nikgVW2P53MtOlT_ycTUyViu2eHFJm2EmQa
51
51
  graphiti_core/prompts/dedupe_nodes.py,sha256=uQrMPAr019KVUzbOslP3VDLaDG4tXp_BqWEtoY0OHbw,8836
52
52
  graphiti_core/prompts/eval.py,sha256=GWFkfZoPfY8U7mV8Ngd_5a2S2fHS7KjajChntxv1UEY,5360
53
53
  graphiti_core/prompts/extract_edge_dates.py,sha256=3Drs3CmvP0gJN5BidWSxrNvLet3HPoTybU3BUIAoc0Y,4218
54
- graphiti_core/prompts/extract_edges.py,sha256=8grBkWBKQXFjUZgUiLSu8c0PMs2v7e-WvJmMQcXxFpk,7073
55
- graphiti_core/prompts/extract_nodes.py,sha256=4424s6Q0617vna1pYfoO4b_nVB4GMZj6LDiqA5cOrq0,10915
54
+ graphiti_core/prompts/extract_edges.py,sha256=BjhnuCrfcCZLQMyPTOmmIfVQwMIDFTe96OaqGYWcR28,7090
55
+ graphiti_core/prompts/extract_nodes.py,sha256=25wStOkbi9kji9j0QSepnqKuyxxcRoqqWrX0KVPSUcc,10966
56
56
  graphiti_core/prompts/invalidate_edges.py,sha256=yfpcs_pyctnoM77ULPZXEtKW0oHr1MeLsJzC5yrE-o4,3547
57
57
  graphiti_core/prompts/lib.py,sha256=DCyHePM4_q-CptTpEXGO_dBv9k7xDtclEaB1dGu7EcI,4092
58
58
  graphiti_core/prompts/models.py,sha256=NgxdbPHJpBEcpbXovKyScgpBc73Q-GIW-CBDlBtDjto,894
@@ -63,24 +63,25 @@ graphiti_core/search/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hS
63
63
  graphiti_core/search/search.py,sha256=pSfyLJDRAv6yF9-A5l43bt0GvtHgCeVQbKQ5XBqDAzU,18436
64
64
  graphiti_core/search/search_config.py,sha256=Q7vFALFqgU-IsDYbGjzcLlHzVIB0ieunPKQHpsk1IVc,5276
65
65
  graphiti_core/search/search_config_recipes.py,sha256=4GquRphHhJlpXQhAZOySYnCzBWYoTwxlJj44eTOavZQ,7443
66
- graphiti_core/search/search_filters.py,sha256=cBp88VvlEsmfiNnXAZG3GleFt8mglQAbttGWYJQos28,9269
66
+ graphiti_core/search/search_filters.py,sha256=QB6-PrH-4CyvkG2B6FFRtsYNEFvL9NTq5IHtbsAjuKs,9305
67
67
  graphiti_core/search/search_helpers.py,sha256=oty-IHVPf_0HxXsSGx21iPML9hMACDcECmdhkGltmVg,2691
68
68
  graphiti_core/search/search_utils.py,sha256=vT0G62T6JXE9bqRJFeLg4dKcHVtJpIOGkmufuvBHw28,71754
69
69
  graphiti_core/telemetry/__init__.py,sha256=5kALLDlU9bb2v19CdN7qVANsJWyfnL9E60J6FFgzm3o,226
70
70
  graphiti_core/telemetry/telemetry.py,sha256=47LrzOVBCcZxsYPsnSxWFiztHoxYKKxPwyRX0hnbDGc,3230
71
71
  graphiti_core/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
72
72
  graphiti_core/utils/bulk_utils.py,sha256=LijfbnUgNfH8BF6DFnmF1YvmKnOIjkJFbcTXo3udzhM,19816
73
+ graphiti_core/utils/content_chunking.py,sha256=T4397f6e4bumXraD0Zi7vTazbsb1mlw383cu7oVLO9w,22173
73
74
  graphiti_core/utils/datetime_utils.py,sha256=J-zYSq7-H-2n9hYOXNIun12kM10vNX9mMATGR_egTmY,1806
74
75
  graphiti_core/utils/text_utils.py,sha256=eHGJwW0jX1CHWBrQy86-KQ-KguzRBNdaLa8zmq8a6bo,1687
75
76
  graphiti_core/utils/maintenance/__init__.py,sha256=vW4H1KyapTl-OOz578uZABYcpND4wPx3Vt6aAPaXh78,301
76
77
  graphiti_core/utils/maintenance/community_operations.py,sha256=OzNo9DW47YWTy67aoq91wRgnKWVelOYduaJpIERdPFY,10803
77
78
  graphiti_core/utils/maintenance/dedup_helpers.py,sha256=B7k6KkB6Sii8PZCWNNTvsNiy4BNTNWpoLeGgrPLq6BE,9220
78
- graphiti_core/utils/maintenance/edge_operations.py,sha256=KuBPlFXHnlWM7smLOfaM-ExhPdlakLdyJV4cxO9U4tI,27187
79
+ graphiti_core/utils/maintenance/edge_operations.py,sha256=YDqmYKSkauQPPW3eXamJMw6G2-bwIavZuBmkqzYmW_M,26907
79
80
  graphiti_core/utils/maintenance/graph_data_operations.py,sha256=vZ1kazYBC-ZRysb13CDFfhoiEH_K_DOW_vfEp1JXEnc,3997
80
- graphiti_core/utils/maintenance/node_operations.py,sha256=70G-Kf1mQJ_9XTi9MJmq5dqC28VJHRxkoAwgMRx4Gvo,20143
81
+ graphiti_core/utils/maintenance/node_operations.py,sha256=ji1uRD8oWAopUnO3OHL0h_iRIF41wwucNBrOH-Bg9q8,23100
81
82
  graphiti_core/utils/maintenance/temporal_operations.py,sha256=LWMw8D8-XOZkl412QKa5qOe9vsX_kOhis_dZlwSXY14,3539
82
83
  graphiti_core/utils/ontology_utils/entity_types_utils.py,sha256=4eVgxLWY6Q8k9cRJ5pW59IYF--U4nXZsZIGOVb_yHfQ,1285
83
- graphiti_core-0.24.3.dist-info/METADATA,sha256=9imUX3fGZvz93AlJH_rKUVH7csX5e6SkMiM4hjKFdZc,27853
84
- graphiti_core-0.24.3.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
85
- graphiti_core-0.24.3.dist-info/licenses/LICENSE,sha256=KCUwCyDXuVEgmDWkozHyniRyWjnWUWjkuDHfU6o3JlA,11325
86
- graphiti_core-0.24.3.dist-info/RECORD,,
84
+ graphiti_core-0.25.3.dist-info/METADATA,sha256=3yAWbzq6O3pmaKV9E4vYgt7A6oCuA3TjK9TobD2ylmk,27843
85
+ graphiti_core-0.25.3.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
86
+ graphiti_core-0.25.3.dist-info/licenses/LICENSE,sha256=KCUwCyDXuVEgmDWkozHyniRyWjnWUWjkuDHfU6o3JlA,11325
87
+ graphiti_core-0.25.3.dist-info/RECORD,,