update context string (#346)

* update context string

* Update graphiti_core/search/search_helpers.py

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>

* remove unused imports

* bump version

---------

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
This commit is contained in:
Preston Rasmussen 2025-04-10 06:57:58 -04:00 committed by GitHub
parent 502b6da1c7
commit 6aa25a1901
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 39 additions and 31 deletions

View file

@ -26,7 +26,7 @@ from graphiti_core.search.search_utils import (
MAX_SEARCH_DEPTH, MAX_SEARCH_DEPTH,
) )
DEFAULT_SEARCH_LIMIT = 20 DEFAULT_SEARCH_LIMIT = 10
class EdgeSearchMethod(Enum): class EdgeSearchMethod(Enum):

View file

@ -14,6 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
""" """
import json
from graphiti_core.edges import EntityEdge from graphiti_core.edges import EntityEdge
from graphiti_core.search.search_config import SearchResults from graphiti_core.search.search_config import SearchResults
@ -25,23 +27,37 @@ def format_edge_date_range(edge: EntityEdge) -> str:
def search_results_to_context_string(search_results: SearchResults) -> str: def search_results_to_context_string(search_results: SearchResults) -> str:
"""Reformats a set of SearchResults into a single string to pass directly to an LLM as context""" """Reformats a set of SearchResults into a single string to pass directly to an LLM as context"""
context_string = """FACTS and ENTITIES represent relevant context to the current conversation. fact_json = [
COMMUNITIES represent a cluster of closely related entities. {
'fact': edge.fact,
'valid_at': str(edge.valid_at),
'invalid_at': str(edge.invalid_at or 'Present'),
}
for edge in search_results.edges
]
entity_json = [
{'entity_name': node.name, 'summary': node.summary} for node in search_results.nodes
]
community_json = [
{'community_name': community.name, 'summary': community.summary}
for community in search_results.communities
]
# These are the most relevant facts and their valid date ranges context_string = f"""
# format: FACT (Date range: from - to) FACTS and ENTITIES represent relevant context to the current conversation.
""" COMMUNITIES represent a cluster of closely related entities.
context_string += '<FACTS>\n'
for edge in search_results.edges: These are the most relevant facts and their valid and invalid dates. Facts are considered valid
context_string += f'- {edge.fact} ({format_edge_date_range(edge)})\n' between their valid_at and invalid_at dates. Facts with an invalid_at date of "Present" are considered valid.
context_string += '</FACTS>\n' <FACTS>
context_string += '<ENTITIES>\n' {json.dumps(fact_json, indent=12)}
for node in search_results.nodes: </FACTS>
context_string += f'- {node.name}: {node.summary}\n' <ENTITIES>
context_string += '</ENTITIES>\n' {json.dumps(entity_json, indent=12)}
context_string += '<COMMUNITIES>\n' </ENTITIES>
for community in search_results.communities: <COMMUNITIES>
context_string += f'- {community.name}: {community.summary}\n' {json.dumps(community_json, indent=12)}
context_string += '</COMMUNITIES>\n' </COMMUNITIES>
"""
return context_string return context_string

View file

@ -1,7 +1,7 @@
[project] [project]
name = "graphiti-core" name = "graphiti-core"
description = "A temporal graph building library" description = "A temporal graph building library"
version = "0.9.5" version = "0.9.6"
authors = [ authors = [
{ "name" = "Paul Paliychuk", "email" = "paul@getzep.com" }, { "name" = "Paul Paliychuk", "email" = "paul@getzep.com" },
{ "name" = "Preston Rasmussen", "email" = "preston@getzep.com" }, { "name" = "Preston Rasmussen", "email" = "preston@getzep.com" },

View file

@ -26,8 +26,7 @@ from graphiti_core.edges import EntityEdge, EpisodicEdge
from graphiti_core.graphiti import Graphiti from graphiti_core.graphiti import Graphiti
from graphiti_core.helpers import semaphore_gather from graphiti_core.helpers import semaphore_gather
from graphiti_core.nodes import EntityNode, EpisodicNode from graphiti_core.nodes import EntityNode, EpisodicNode
from graphiti_core.search.search_config_recipes import COMBINED_HYBRID_SEARCH_CROSS_ENCODER from graphiti_core.search.search_helpers import search_results_to_context_string
from graphiti_core.search.search_filters import SearchFilters
pytestmark = pytest.mark.integration pytestmark = pytest.mark.integration
@ -66,18 +65,11 @@ async def test_graphiti_init():
logger = setup_logging() logger = setup_logging()
graphiti = Graphiti(NEO4J_URI, NEO4j_USER, NEO4j_PASSWORD) graphiti = Graphiti(NEO4J_URI, NEO4j_USER, NEO4j_PASSWORD)
results = await graphiti._search( results = await graphiti.search_(
'My name is Alice', query="Who is Alice's friend?",
COMBINED_HYBRID_SEARCH_CROSS_ENCODER,
group_ids=['test'],
search_filter=SearchFilters(node_labels=['Entity']),
) )
pretty_results = { pretty_results = search_results_to_context_string(results)
'edges': [edge.fact for edge in results.edges],
'nodes': [node.name for node in results.nodes],
'communities': [community.name for community in results.communities],
}
logger.info(pretty_results) logger.info(pretty_results)