diff --git a/graphiti_core/llm_client/anthropic_client.py b/graphiti_core/llm_client/anthropic_client.py
index 17956cc2..1f2916b3 100644
--- a/graphiti_core/llm_client/anthropic_client.py
+++ b/graphiti_core/llm_client/anthropic_client.py
@@ -349,7 +349,9 @@ class AnthropicClient(LLMClient):
# Common retry logic
retry_count += 1
messages.append(Message(role='user', content=error_context))
- logger.warning(f'Retrying after error (attempt {retry_count}/{max_retries}): {e}')
+ logger.warning(
+ f'Retrying after error (attempt {retry_count}/{max_retries}): {e}'
+ )
# If we somehow get here, raise the last error
span.set_status('error', str(last_error))
diff --git a/graphiti_core/llm_client/openai_base_client.py b/graphiti_core/llm_client/openai_base_client.py
index 3a5552e9..66419819 100644
--- a/graphiti_core/llm_client/openai_base_client.py
+++ b/graphiti_core/llm_client/openai_base_client.py
@@ -209,7 +209,11 @@ class BaseOpenAIClient(LLMClient):
# These errors should not trigger retries
span.set_status('error', str(last_error))
raise
- except (openai.APITimeoutError, openai.APIConnectionError, openai.InternalServerError):
+ except (
+ openai.APITimeoutError,
+ openai.APIConnectionError,
+ openai.InternalServerError,
+ ):
# Let OpenAI's client handle these retries
span.set_status('error', str(last_error))
raise
diff --git a/graphiti_core/llm_client/openai_generic_client.py b/graphiti_core/llm_client/openai_generic_client.py
index 41bd7d5a..c2ee9691 100644
--- a/graphiti_core/llm_client/openai_generic_client.py
+++ b/graphiti_core/llm_client/openai_generic_client.py
@@ -161,7 +161,11 @@ class OpenAIGenericClient(LLMClient):
# These errors should not trigger retries
span.set_status('error', str(last_error))
raise
- except (openai.APITimeoutError, openai.APIConnectionError, openai.InternalServerError):
+ except (
+ openai.APITimeoutError,
+ openai.APIConnectionError,
+ openai.InternalServerError,
+ ):
# Let OpenAI's client handle these retries
span.set_status('error', str(last_error))
raise
diff --git a/graphiti_core/prompts/dedupe_edges.py b/graphiti_core/prompts/dedupe_edges.py
index c5b55427..2d9bc042 100644
--- a/graphiti_core/prompts/dedupe_edges.py
+++ b/graphiti_core/prompts/dedupe_edges.py
@@ -67,13 +67,13 @@ def edge(context: dict[str, Any]) -> list[Message]:
Given the following context, determine whether the New Edge represents any of the edges in the list of Existing Edges.
- {to_prompt_json(context['related_edges'], indent=2)}
+ {to_prompt_json(context['related_edges'])}
- {to_prompt_json(context['extracted_edges'], indent=2)}
+ {to_prompt_json(context['extracted_edges'])}
-
+
Task:
If the New Edges represents the same factual information as any edge in Existing Edges, return the id of the duplicate fact
as part of the list of duplicate_facts.
@@ -98,7 +98,7 @@ def edge_list(context: dict[str, Any]) -> list[Message]:
Given the following context, find all of the duplicates in a list of facts:
Facts:
- {to_prompt_json(context['edges'], indent=2)}
+ {to_prompt_json(context['edges'])}
Task:
If any facts in Facts is a duplicate of another fact, return a new fact with one of their uuid's.
diff --git a/graphiti_core/prompts/dedupe_nodes.py b/graphiti_core/prompts/dedupe_nodes.py
index 9ecc926a..ec1b0fe0 100644
--- a/graphiti_core/prompts/dedupe_nodes.py
+++ b/graphiti_core/prompts/dedupe_nodes.py
@@ -64,20 +64,20 @@ def node(context: dict[str, Any]) -> list[Message]:
role='user',
content=f"""
- {to_prompt_json([ep for ep in context['previous_episodes']], indent=2)}
+ {to_prompt_json([ep for ep in context['previous_episodes']])}
{context['episode_content']}
- {to_prompt_json(context['extracted_node'], indent=2)}
+ {to_prompt_json(context['extracted_node'])}
- {to_prompt_json(context['entity_type_description'], indent=2)}
+ {to_prompt_json(context['entity_type_description'])}
- {to_prompt_json(context['existing_nodes'], indent=2)}
+ {to_prompt_json(context['existing_nodes'])}
Given the above EXISTING ENTITIES and their attributes, MESSAGE, and PREVIOUS MESSAGES; Determine if the NEW ENTITY extracted from the conversation
@@ -125,13 +125,13 @@ def nodes(context: dict[str, Any]) -> list[Message]:
role='user',
content=f"""
- {to_prompt_json([ep for ep in context['previous_episodes']], indent=2)}
+ {to_prompt_json([ep for ep in context['previous_episodes']])}
{context['episode_content']}
-
-
+
+
Each of the following ENTITIES were extracted from the CURRENT MESSAGE.
Each entity in ENTITIES is represented as a JSON object with the following structure:
{{
@@ -142,11 +142,11 @@ def nodes(context: dict[str, Any]) -> list[Message]:
}}
- {to_prompt_json(context['extracted_nodes'], indent=2)}
+ {to_prompt_json(context['extracted_nodes'])}
- {to_prompt_json(context['existing_nodes'], indent=2)}
+ {to_prompt_json(context['existing_nodes'])}
Each entry in EXISTING ENTITIES is an object with the following structure:
@@ -197,7 +197,7 @@ def node_list(context: dict[str, Any]) -> list[Message]:
Given the following context, deduplicate a list of nodes:
Nodes:
- {to_prompt_json(context['nodes'], indent=2)}
+ {to_prompt_json(context['nodes'])}
Task:
1. Group nodes together such that all duplicate nodes are in the same list of uuids
diff --git a/graphiti_core/prompts/extract_edges.py b/graphiti_core/prompts/extract_edges.py
index 28d9bddc..7e9d6d6c 100644
--- a/graphiti_core/prompts/extract_edges.py
+++ b/graphiti_core/prompts/extract_edges.py
@@ -80,7 +80,7 @@ def edge(context: dict[str, Any]) -> list[Message]:
-{to_prompt_json([ep for ep in context['previous_episodes']], indent=2)}
+{to_prompt_json([ep for ep in context['previous_episodes']])}
@@ -88,7 +88,7 @@ def edge(context: dict[str, Any]) -> list[Message]:
-{to_prompt_json(context['nodes'], indent=2)}
+{to_prompt_json(context['nodes'])}
@@ -141,7 +141,7 @@ def reflexion(context: dict[str, Any]) -> list[Message]:
user_prompt = f"""
-{to_prompt_json([ep for ep in context['previous_episodes']], indent=2)}
+{to_prompt_json([ep for ep in context['previous_episodes']])}
{context['episode_content']}
@@ -175,7 +175,7 @@ def extract_attributes(context: dict[str, Any]) -> list[Message]:
content=f"""
- {to_prompt_json(context['episode_content'], indent=2)}
+ {to_prompt_json(context['episode_content'])}
{context['reference_time']}
diff --git a/graphiti_core/prompts/extract_nodes.py b/graphiti_core/prompts/extract_nodes.py
index 8e85c7a6..1187c039 100644
--- a/graphiti_core/prompts/extract_nodes.py
+++ b/graphiti_core/prompts/extract_nodes.py
@@ -93,7 +93,7 @@ def extract_message(context: dict[str, Any]) -> list[Message]:
-{to_prompt_json([ep for ep in context['previous_episodes']], indent=2)}
+{to_prompt_json([ep for ep in context['previous_episodes']])}
@@ -201,7 +201,7 @@ def reflexion(context: dict[str, Any]) -> list[Message]:
user_prompt = f"""
-{to_prompt_json([ep for ep in context['previous_episodes']], indent=2)}
+{to_prompt_json([ep for ep in context['previous_episodes']])}
{context['episode_content']}
@@ -225,22 +225,22 @@ def classify_nodes(context: dict[str, Any]) -> list[Message]:
user_prompt = f"""
- {to_prompt_json([ep for ep in context['previous_episodes']], indent=2)}
+ {to_prompt_json([ep for ep in context['previous_episodes']])}
{context['episode_content']}
-
+
{context['extracted_entities']}
-
+
{context['entity_types']}
-
+
Given the above conversation, extracted entities, and provided entity types and their descriptions, classify the extracted entities.
-
+
Guidelines:
1. Each entity must have exactly one type
2. Only use the provided ENTITY TYPES as types, do not use additional types to classify entities.
@@ -269,10 +269,10 @@ def extract_attributes(context: dict[str, Any]) -> list[Message]:
2. Only use the provided MESSAGES and ENTITY to set attribute values.
- {to_prompt_json(context['previous_episodes'], indent=2)}
- {to_prompt_json(context['episode_content'], indent=2)}
+ {to_prompt_json(context['previous_episodes'])}
+ {to_prompt_json(context['episode_content'])}
-
+
{context['node']}
@@ -292,12 +292,12 @@ def extract_summary(context: dict[str, Any]) -> list[Message]:
content=f"""
Given the MESSAGES and the ENTITY, update the summary that combines relevant information about the entity
from the messages and relevant information from the existing summary.
-
+
{summary_instructions}
- {to_prompt_json(context['previous_episodes'], indent=2)}
- {to_prompt_json(context['episode_content'], indent=2)}
+ {to_prompt_json(context['previous_episodes'])}
+ {to_prompt_json(context['episode_content'])}
diff --git a/graphiti_core/prompts/prompt_helpers.py b/graphiti_core/prompts/prompt_helpers.py
index 8c4b5123..10e69312 100644
--- a/graphiti_core/prompts/prompt_helpers.py
+++ b/graphiti_core/prompts/prompt_helpers.py
@@ -20,14 +20,14 @@ from typing import Any
DO_NOT_ESCAPE_UNICODE = '\nDo not escape unicode characters.\n'
-def to_prompt_json(data: Any, ensure_ascii: bool = False, indent: int = 2) -> str:
+def to_prompt_json(data: Any, ensure_ascii: bool = False, indent: int | None = None) -> str:
"""
Serialize data to JSON for use in prompts.
Args:
data: The data to serialize
ensure_ascii: If True, escape non-ASCII characters. If False (default), preserve them.
- indent: Number of spaces for indentation
+ indent: Number of spaces for indentation. Defaults to None (minified).
Returns:
JSON string representation of the data
diff --git a/graphiti_core/prompts/summarize_nodes.py b/graphiti_core/prompts/summarize_nodes.py
index 154dc5ed..d771b5c9 100644
--- a/graphiti_core/prompts/summarize_nodes.py
+++ b/graphiti_core/prompts/summarize_nodes.py
@@ -56,11 +56,11 @@ def summarize_pair(context: dict[str, Any]) -> list[Message]:
role='user',
content=f"""
Synthesize the information from the following two summaries into a single succinct summary.
-
+
IMPORTANT: Keep the summary concise and to the point. SUMMARIES MUST BE LESS THAN 250 CHARACTERS.
Summaries:
- {to_prompt_json(context['node_summaries'], indent=2)}
+ {to_prompt_json(context['node_summaries'])}
""",
),
]
@@ -77,28 +77,28 @@ def summarize_context(context: dict[str, Any]) -> list[Message]:
content=f"""
Given the MESSAGES and the ENTITY name, create a summary for the ENTITY. Your summary must only use
information from the provided MESSAGES. Your summary should also only contain information relevant to the
- provided ENTITY.
-
+ provided ENTITY.
+
In addition, extract any values for the provided entity properties based on their descriptions.
If the value of the entity property cannot be found in the current context, set the value of the property to the Python value None.
-
+
{summary_instructions}
- {to_prompt_json(context['previous_episodes'], indent=2)}
- {to_prompt_json(context['episode_content'], indent=2)}
+ {to_prompt_json(context['previous_episodes'])}
+ {to_prompt_json(context['episode_content'])}
-
+
{context['node_name']}
-
+
{context['node_summary']}
-
+
- {to_prompt_json(context['attributes'], indent=2)}
+ {to_prompt_json(context['attributes'])}
""",
),
@@ -118,7 +118,7 @@ def summary_description(context: dict[str, Any]) -> list[Message]:
Summaries must be under 250 characters.
Summary:
- {to_prompt_json(context['summary'], indent=2)}
+ {to_prompt_json(context['summary'])}
""",
),
]
diff --git a/graphiti_core/search/search_helpers.py b/graphiti_core/search/search_helpers.py
index 620f8ceb..5ee530c0 100644
--- a/graphiti_core/search/search_helpers.py
+++ b/graphiti_core/search/search_helpers.py
@@ -56,16 +56,16 @@ def search_results_to_context_string(search_results: SearchResults) -> str:
These are the most relevant facts and their valid and invalid dates. Facts are considered valid
between their valid_at and invalid_at dates. Facts with an invalid_at date of "Present" are considered valid.
- {to_prompt_json(fact_json, indent=12)}
+ {to_prompt_json(fact_json)}
- {to_prompt_json(entity_json, indent=12)}
+ {to_prompt_json(entity_json)}
- {to_prompt_json(episode_json, indent=12)}
+ {to_prompt_json(episode_json)}
- {to_prompt_json(community_json, indent=12)}
+ {to_prompt_json(community_json)}
"""
diff --git a/graphiti_core/utils/maintenance/utils.py b/graphiti_core/utils/maintenance/utils.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/uv.lock b/uv.lock
index 12905404..5c150a85 100644
--- a/uv.lock
+++ b/uv.lock
@@ -783,7 +783,7 @@ wheels = [
[[package]]
name = "graphiti-core"
-version = "0.22.0rc3"
+version = "0.22.0rc4"
source = { editable = "." }
dependencies = [
{ name = "diskcache" },