Skip to content

Commit d265400

Browse files
authored
update summary character limit (#1073)
* update * update tests
1 parent 8b7ad6f commit d265400

File tree

10 files changed

+91
-87
lines changed

10 files changed

+91
-87
lines changed

‎examples/azure-openai/azure_openai_neo4j.py‎

Lines changed: 55 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -40,29 +40,29 @@
4040
# Configure logging
4141
logging.basicConfig(
4242
level=INFO,
43-
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
44-
datefmt="%Y-%m-%d %H:%M:%S",
43+
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
44+
datefmt='%Y-%m-%d %H:%M:%S',
4545
)
4646
logger = logging.getLogger(__name__)
4747

4848
load_dotenv()
4949

5050
# Neo4j connection parameters
5151
# Make sure Neo4j Desktop is running with a local DBMS started
52-
neo4j_uri = os.environ.get("NEO4J_URI", "bolt://localhost:7687")
53-
neo4j_user = os.environ.get("NEO4J_USER", "neo4j")
54-
neo4j_password = os.environ.get("NEO4J_PASSWORD", "password")
52+
neo4j_uri = os.environ.get('NEO4J_URI', 'bolt://localhost:7687')
53+
neo4j_user = os.environ.get('NEO4J_USER', 'neo4j')
54+
neo4j_password = os.environ.get('NEO4J_PASSWORD', 'password')
5555

5656
# Azure OpenAI connection parameters
57-
azure_endpoint = os.environ.get("AZURE_OPENAI_ENDPOINT")
58-
azure_api_key = os.environ.get("AZURE_OPENAI_API_KEY")
59-
azure_deployment = os.environ.get("AZURE_OPENAI_DEPLOYMENT", "gpt-4.1")
57+
azure_endpoint = os.environ.get('AZURE_OPENAI_ENDPOINT')
58+
azure_api_key = os.environ.get('AZURE_OPENAI_API_KEY')
59+
azure_deployment = os.environ.get('AZURE_OPENAI_DEPLOYMENT', 'gpt-4.1')
6060
azure_embedding_deployment = os.environ.get(
61-
"AZURE_OPENAI_EMBEDDING_DEPLOYMENT", "text-embedding-3-small"
61+
'AZURE_OPENAI_EMBEDDING_DEPLOYMENT', 'text-embedding-3-small'
6262
)
6363

6464
if not azure_endpoint or not azure_api_key:
65-
raise ValueError("AZURE_OPENAI_ENDPOINT and AZURE_OPENAI_API_KEY must be set")
65+
raise ValueError('AZURE_OPENAI_ENDPOINT and AZURE_OPENAI_API_KEY must be set')
6666

6767

6868
async def main():
@@ -76,7 +76,7 @@ async def main():
7676

7777
# Initialize Azure OpenAI client
7878
azure_client = AsyncOpenAI(
79-
base_url=f"{azure_endpoint}/openai/v1/",
79+
base_url=f'{azure_endpoint}/openai/v1/',
8080
api_key=azure_api_key,
8181
)
8282

@@ -112,40 +112,40 @@ async def main():
112112
# Episodes list containing both text and JSON episodes
113113
episodes = [
114114
{
115-
"content": "Kamala Harris is the Attorney General of California. She was previously "
116-
"the district attorney for San Francisco.",
117-
"type": EpisodeType.text,
118-
"description": "podcast transcript",
115+
'content': 'Kamala Harris is the Attorney General of California. She was previously '
116+
'the district attorney for San Francisco.',
117+
'type': EpisodeType.text,
118+
'description': 'podcast transcript',
119119
},
120120
{
121-
"content": "As AG, Harris was in office from January 3, 2011 – January 3, 2017",
122-
"type": EpisodeType.text,
123-
"description": "podcast transcript",
121+
'content': 'As AG, Harris was in office from January 3, 2011 – January 3, 2017',
122+
'type': EpisodeType.text,
123+
'description': 'podcast transcript',
124124
},
125125
{
126-
"content": {
127-
"name": "Gavin Newsom",
128-
"position": "Governor",
129-
"state": "California",
130-
"previous_role": "Lieutenant Governor",
131-
"previous_location": "San Francisco",
126+
'content': {
127+
'name': 'Gavin Newsom',
128+
'position': 'Governor',
129+
'state': 'California',
130+
'previous_role': 'Lieutenant Governor',
131+
'previous_location': 'San Francisco',
132132
},
133-
"type": EpisodeType.json,
134-
"description": "podcast metadata",
133+
'type': EpisodeType.json,
134+
'description': 'podcast metadata',
135135
},
136136
]
137137

138138
# Add episodes to the graph
139139
for i, episode in enumerate(episodes):
140140
await graphiti.add_episode(
141-
name=f"California Politics {i}",
141+
name=f'California Politics {i}',
142142
episode_body=(
143-
episode["content"]
144-
if isinstance(episode["content"], str)
145-
else json.dumps(episode["content"])
143+
episode['content']
144+
if isinstance(episode['content'], str)
145+
else json.dumps(episode['content'])
146146
),
147-
source=episode["type"],
148-
source_description=episode["description"],
147+
source=episode['type'],
148+
source_description=episode['description'],
149149
reference_time=datetime.now(timezone.utc),
150150
)
151151
print(f'Added episode: California Politics {i} ({episode["type"].value})')
@@ -161,18 +161,18 @@ async def main():
161161

162162
# Perform a hybrid search combining semantic similarity and BM25 retrieval
163163
print("\nSearching for: 'Who was the California Attorney General?'")
164-
results = await graphiti.search("Who was the California Attorney General?")
164+
results = await graphiti.search('Who was the California Attorney General?')
165165

166166
# Print search results
167-
print("\nSearch Results:")
167+
print('\nSearch Results:')
168168
for result in results:
169-
print(f"UUID: {result.uuid}")
170-
print(f"Fact: {result.fact}")
171-
if hasattr(result, "valid_at") and result.valid_at:
172-
print(f"Valid from: {result.valid_at}")
173-
if hasattr(result, "invalid_at") and result.invalid_at:
174-
print(f"Valid until: {result.invalid_at}")
175-
print("---")
169+
print(f'UUID: {result.uuid}')
170+
print(f'Fact: {result.fact}')
171+
if hasattr(result, 'valid_at') and result.valid_at:
172+
print(f'Valid from: {result.valid_at}')
173+
if hasattr(result, 'invalid_at') and result.invalid_at:
174+
print(f'Valid until: {result.invalid_at}')
175+
print('---')
176176

177177
#################################################
178178
# CENTER NODE SEARCH
@@ -187,26 +187,26 @@ async def main():
187187
# Get the source node UUID from the top result
188188
center_node_uuid = results[0].source_node_uuid
189189

190-
print("\nReranking search results based on graph distance:")
191-
print(f"Using center node UUID: {center_node_uuid}")
190+
print('\nReranking search results based on graph distance:')
191+
print(f'Using center node UUID: {center_node_uuid}')
192192

193193
reranked_results = await graphiti.search(
194-
"Who was the California Attorney General?",
194+
'Who was the California Attorney General?',
195195
center_node_uuid=center_node_uuid,
196196
)
197197

198198
# Print reranked search results
199-
print("\nReranked Search Results:")
199+
print('\nReranked Search Results:')
200200
for result in reranked_results:
201-
print(f"UUID: {result.uuid}")
202-
print(f"Fact: {result.fact}")
203-
if hasattr(result, "valid_at") and result.valid_at:
204-
print(f"Valid from: {result.valid_at}")
205-
if hasattr(result, "invalid_at") and result.invalid_at:
206-
print(f"Valid until: {result.invalid_at}")
207-
print("---")
201+
print(f'UUID: {result.uuid}')
202+
print(f'Fact: {result.fact}')
203+
if hasattr(result, 'valid_at') and result.valid_at:
204+
print(f'Valid from: {result.valid_at}')
205+
if hasattr(result, 'invalid_at') and result.invalid_at:
206+
print(f'Valid until: {result.invalid_at}')
207+
print('---')
208208
else:
209-
print("No results found in the initial search to use as center node.")
209+
print('No results found in the initial search to use as center node.')
210210

211211
finally:
212212
#################################################
@@ -218,8 +218,8 @@ async def main():
218218

219219
# Close the connection
220220
await graphiti.close()
221-
print("\nConnection closed")
221+
print('\nConnection closed')
222222

223223

224-
if __name__ == "__main__":
224+
if __name__ == '__main__':
225225
asyncio.run(main())

‎graphiti_core/driver/neo4j_driver.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ async def build_indices_and_constraints(self, delete_existing: bool = False):
106106
for query in index_queries
107107
]
108108
)
109-
109+
110110
async def health_check(self) -> None:
111111
"""Check Neo4j connectivity by running the driver's verify_connectivity method."""
112112
try:

‎graphiti_core/embedder/azure_openai.py‎

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class AzureOpenAIEmbedderClient(EmbedderClient):
3333
def __init__(
3434
self,
3535
azure_client: AsyncAzureOpenAI | AsyncOpenAI,
36-
model: str = "text-embedding-3-small",
36+
model: str = 'text-embedding-3-small',
3737
):
3838
self.azure_client = azure_client
3939
self.model = model
@@ -44,22 +44,18 @@ async def create(self, input_data: str | list[str] | Any) -> list[float]:
4444
# Handle different input types
4545
if isinstance(input_data, str):
4646
text_input = [input_data]
47-
elif isinstance(input_data, list) and all(
48-
isinstance(item, str) for item in input_data
49-
):
47+
elif isinstance(input_data, list) and all(isinstance(item, str) for item in input_data):
5048
text_input = input_data
5149
else:
5250
# Convert to string list for other types
5351
text_input = [str(input_data)]
5452

55-
response = await self.azure_client.embeddings.create(
56-
model=self.model, input=text_input
57-
)
53+
response = await self.azure_client.embeddings.create(model=self.model, input=text_input)
5854

5955
# Return the first embedding as a list of floats
6056
return response.data[0].embedding
6157
except Exception as e:
62-
logger.error(f"Error in Azure OpenAI embedding: {e}")
58+
logger.error(f'Error in Azure OpenAI embedding: {e}')
6359
raise
6460

6561
async def create_batch(self, input_data_list: list[str]) -> list[list[float]]:
@@ -71,5 +67,5 @@ async def create_batch(self, input_data_list: list[str]) -> list[list[float]]:
7167

7268
return [embedding.embedding for embedding in response.data]
7369
except Exception as e:
74-
logger.error(f"Error in Azure OpenAI batch embedding: {e}")
70+
logger.error(f'Error in Azure OpenAI batch embedding: {e}')
7571
raise

‎graphiti_core/llm_client/azure_openai_client.py‎

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -66,21 +66,21 @@ async def _create_structured_completion(
6666
"""Create a structured completion using Azure OpenAI's responses.parse API."""
6767
supports_reasoning = self._supports_reasoning_features(model)
6868
request_kwargs = {
69-
"model": model,
70-
"input": messages,
71-
"max_output_tokens": max_tokens,
72-
"text_format": response_model, # type: ignore
69+
'model': model,
70+
'input': messages,
71+
'max_output_tokens': max_tokens,
72+
'text_format': response_model, # type: ignore
7373
}
7474

7575
temperature_value = temperature if not supports_reasoning else None
7676
if temperature_value is not None:
77-
request_kwargs["temperature"] = temperature_value
77+
request_kwargs['temperature'] = temperature_value
7878

7979
if supports_reasoning and reasoning:
80-
request_kwargs["reasoning"] = {"effort": reasoning} # type: ignore
80+
request_kwargs['reasoning'] = {'effort': reasoning} # type: ignore
8181

8282
if supports_reasoning and verbosity:
83-
request_kwargs["text"] = {"verbosity": verbosity} # type: ignore
83+
request_kwargs['text'] = {'verbosity': verbosity} # type: ignore
8484

8585
return await self.client.responses.parse(**request_kwargs)
8686

@@ -96,20 +96,20 @@ async def _create_completion(
9696
supports_reasoning = self._supports_reasoning_features(model)
9797

9898
request_kwargs = {
99-
"model": model,
100-
"messages": messages,
101-
"max_tokens": max_tokens,
102-
"response_format": {"type": "json_object"},
99+
'model': model,
100+
'messages': messages,
101+
'max_tokens': max_tokens,
102+
'response_format': {'type': 'json_object'},
103103
}
104104

105105
temperature_value = temperature if not supports_reasoning else None
106106
if temperature_value is not None:
107-
request_kwargs["temperature"] = temperature_value
107+
request_kwargs['temperature'] = temperature_value
108108

109109
return await self.client.chat.completions.create(**request_kwargs)
110110

111111
@staticmethod
112112
def _supports_reasoning_features(model: str) -> bool:
113113
"""Return True when the Azure model supports reasoning/verbosity options."""
114-
reasoning_prefixes = ("o1", "o3", "gpt-5")
114+
reasoning_prefixes = ('o1', 'o3', 'gpt-5')
115115
return model.startswith(reasoning_prefixes)

‎graphiti_core/llm_client/openai_base_client.py‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,13 +166,17 @@ async def _generate_response(
166166
except openai.RateLimitError as e:
167167
raise RateLimitError from e
168168
except openai.AuthenticationError as e:
169-
logger.error(f'OpenAI Authentication Error: {e}. Please verify your API key is correct.')
169+
logger.error(
170+
f'OpenAI Authentication Error: {e}. Please verify your API key is correct.'
171+
)
170172
raise
171173
except Exception as e:
172174
# Provide more context for connection errors
173175
error_msg = str(e)
174176
if 'Connection error' in error_msg or 'connection' in error_msg.lower():
175-
logger.error(f'Connection error communicating with OpenAI API. Please check your network connection and API key. Error: {e}')
177+
logger.error(
178+
f'Connection error communicating with OpenAI API. Please check your network connection and API key. Error: {e}'
179+
)
176180
else:
177181
logger.error(f'Error in generating LLM response: {e}')
178182
raise

‎graphiti_core/llm_client/openai_client.py‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,9 @@ async def _create_structured_completion(
7474
):
7575
"""Create a structured completion using OpenAI's beta parse API."""
7676
# Reasoning models (gpt-5 family) don't support temperature
77-
is_reasoning_model = model.startswith('gpt-5') or model.startswith('o1') or model.startswith('o3')
77+
is_reasoning_model = (
78+
model.startswith('gpt-5') or model.startswith('o1') or model.startswith('o3')
79+
)
7880

7981
response = await self.client.responses.parse(
8082
model=model,
@@ -100,7 +102,9 @@ async def _create_completion(
100102
):
101103
"""Create a regular completion with JSON format."""
102104
# Reasoning models (gpt-5 family) don't support temperature
103-
is_reasoning_model = model.startswith('gpt-5') or model.startswith('o1') or model.startswith('o3')
105+
is_reasoning_model = (
106+
model.startswith('gpt-5') or model.startswith('o1') or model.startswith('o3')
107+
)
104108

105109
return await self.client.chat.completions.create(
106110
model=model,

‎graphiti_core/utils/text_utils.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import re
1818

1919
# Maximum length for entity/node summaries
20-
MAX_SUMMARY_CHARS = 250
20+
MAX_SUMMARY_CHARS = 500
2121

2222

2323
def truncate_at_sentence(text: str, max_chars: int) -> str:

‎pyproject.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[project]
22
name = "graphiti-core"
33
description = "A temporal graph building library"
4-
version = "0.24.0"
4+
version = "0.24.1"
55
authors = [
66
{ name = "Paul Paliychuk", email = "paul@getzep.com" },
77
{ name = "Preston Rasmussen", email = "preston@getzep.com" },

‎tests/test_text_utils.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ def test_truncate_at_sentence_strips_trailing_whitespace():
8787

8888
def test_max_summary_chars_constant():
8989
"""Test that MAX_SUMMARY_CHARS is set to expected value."""
90-
assert MAX_SUMMARY_CHARS == 250
90+
assert MAX_SUMMARY_CHARS == 500
9191

9292

9393
def test_truncate_at_sentence_realistic_summary():

‎uv.lock‎

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)