Add search_ and deprecate _search (#342)
* add search_ and deprecate _search. Add formatting helper * add search helpers file * move SearchResults * Update graphiti_core/search/search_helpers.py Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com> * remove unused imports --------- Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
This commit is contained in:
parent
9b563f5ba9
commit
502b6da1c7
6 changed files with 95 additions and 11 deletions
|
|
@ -33,6 +33,7 @@ from graphiti_core.nodes import CommunityNode, EntityNode, EpisodeType, Episodic
|
|||
from graphiti_core.search.search import SearchConfig, search
|
||||
from graphiti_core.search.search_config import DEFAULT_SEARCH_LIMIT, SearchResults
|
||||
from graphiti_core.search.search_config_recipes import (
|
||||
COMBINED_HYBRID_SEARCH_CROSS_ENCODER,
|
||||
EDGE_HYBRID_SEARCH_NODE_DISTANCE,
|
||||
EDGE_HYBRID_SEARCH_RRF,
|
||||
)
|
||||
|
|
@ -647,7 +648,10 @@ class Graphiti:
|
|||
Perform a hybrid search on the knowledge graph.
|
||||
|
||||
This method executes a search query on the graph, combining vector and
|
||||
text-based search techniques to retrieve relevant facts.
|
||||
text-based search techniques to retrieve relevant facts, returning the edges as a string.
|
||||
|
||||
This is our basic out-of-the-box search, for more robust results we recommend using our more advanced
|
||||
search method graphiti.search_().
|
||||
|
||||
Parameters
|
||||
----------
|
||||
|
|
@ -668,8 +672,7 @@ class Graphiti:
|
|||
Notes
|
||||
-----
|
||||
This method uses a SearchConfig with num_episodes set to 0 and
|
||||
num_results set to the provided num_results parameter. It then calls
|
||||
the hybrid_search function to perform the actual search operation.
|
||||
num_results set to the provided num_results parameter.
|
||||
|
||||
The search is performed using the current date and time as the reference
|
||||
point for temporal relevance.
|
||||
|
|
@ -703,6 +706,27 @@ class Graphiti:
|
|||
bfs_origin_node_uuids: list[str] | None = None,
|
||||
search_filter: SearchFilters | None = None,
|
||||
) -> SearchResults:
|
||||
"""DEPRECATED"""
|
||||
return await self.search_(
|
||||
query, config, group_ids, center_node_uuid, bfs_origin_node_uuids, search_filter
|
||||
)
|
||||
|
||||
async def search_(
|
||||
self,
|
||||
query: str,
|
||||
config: SearchConfig = COMBINED_HYBRID_SEARCH_CROSS_ENCODER,
|
||||
group_ids: list[str] | None = None,
|
||||
center_node_uuid: str | None = None,
|
||||
bfs_origin_node_uuids: list[str] | None = None,
|
||||
search_filter: SearchFilters | None = None,
|
||||
) -> SearchResults:
|
||||
"""search_ (replaces _search) is our advanced search method that returns Graph objects (nodes and edges) rather
|
||||
than a list of facts. This endpoint allows the end user to utilize more advanced features such as filters and
|
||||
different search and reranker methodologies across different layers in the graph.
|
||||
|
||||
For different config recipes refer to search/search_config_recipes.
|
||||
"""
|
||||
|
||||
return await search(
|
||||
self.driver,
|
||||
self.embedder,
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ from graphiti_core.search.search_utils import (
|
|||
MAX_SEARCH_DEPTH,
|
||||
)
|
||||
|
||||
DEFAULT_SEARCH_LIMIT = 10
|
||||
DEFAULT_SEARCH_LIMIT = 20
|
||||
|
||||
|
||||
class EdgeSearchMethod(Enum):
|
||||
|
|
|
|||
47
graphiti_core/search/search_helpers.py
Normal file
47
graphiti_core/search/search_helpers.py
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
"""
|
||||
Copyright 2024, Zep Software, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from graphiti_core.edges import EntityEdge
|
||||
from graphiti_core.search.search_config import SearchResults
|
||||
|
||||
|
||||
def format_edge_date_range(edge: EntityEdge) -> str:
|
||||
# return f"{datetime(edge.valid_at).strftime('%Y-%m-%d %H:%M:%S') if edge.valid_at else 'date unknown'} - {(edge.invalid_at.strftime('%Y-%m-%d %H:%M:%S') if edge.invalid_at else 'present')}"
|
||||
return f'{edge.valid_at if edge.valid_at else "date unknown"} - {(edge.invalid_at if edge.invalid_at else "present")}'
|
||||
|
||||
|
||||
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"""
|
||||
context_string = """FACTS and ENTITIES represent relevant context to the current conversation.
|
||||
COMMUNITIES represent a cluster of closely related entities.
|
||||
|
||||
# These are the most relevant facts and their valid date ranges
|
||||
# format: FACT (Date range: from - to)
|
||||
"""
|
||||
context_string += '<FACTS>\n'
|
||||
for edge in search_results.edges:
|
||||
context_string += f'- {edge.fact} ({format_edge_date_range(edge)})\n'
|
||||
context_string += '</FACTS>\n'
|
||||
context_string += '<ENTITIES>\n'
|
||||
for node in search_results.nodes:
|
||||
context_string += f'- {node.name}: {node.summary}\n'
|
||||
context_string += '</ENTITIES>\n'
|
||||
context_string += '<COMMUNITIES>\n'
|
||||
for community in search_results.communities:
|
||||
context_string += f'- {community.name}: {community.summary}\n'
|
||||
context_string += '</COMMUNITIES>\n'
|
||||
|
||||
return context_string
|
||||
|
|
@ -229,8 +229,8 @@ async def edge_similarity_search(
|
|||
|
||||
query: LiteralString = (
|
||||
"""
|
||||
MATCH (n:Entity)-[r:RELATES_TO]->(m:Entity)
|
||||
"""
|
||||
MATCH (n:Entity)-[r:RELATES_TO]->(m:Entity)
|
||||
"""
|
||||
+ group_filter_query
|
||||
+ filter_query
|
||||
+ """\nWITH DISTINCT r, vector.similarity.cosine(r.fact_embedding, $search_vector) AS score
|
||||
|
|
|
|||
14
poetry.lock
generated
14
poetry.lock
generated
|
|
@ -1030,6 +1030,17 @@ requests = ">=2.28.1,<3.0.0"
|
|||
typing-extensions = ">=4.11.0,<5.0.0"
|
||||
websockets = ">=13.0.0,<15.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "graph-service"
|
||||
version = "1.0.0.7"
|
||||
description = "project descriptions here"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "graph_service-1.0.0.7-py3-none-any.whl", hash = "sha256:d34cd38529ff0704b83fa4e8692b4f8fcf1524dce7110f89d4ee33423eeff0bd"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "groq"
|
||||
version = "0.11.0"
|
||||
|
|
@ -3148,6 +3159,7 @@ optional = false
|
|||
python-versions = ">=3.8"
|
||||
groups = ["main", "dev"]
|
||||
files = [
|
||||
{file = "pyasn1-0.6.1-py3-none-any.whl", hash = "sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629"},
|
||||
{file = "pyasn1-0.6.1.tar.gz", hash = "sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034"},
|
||||
]
|
||||
|
||||
|
|
@ -5316,4 +5328,4 @@ groq = ["groq"]
|
|||
[metadata]
|
||||
lock-version = "2.1"
|
||||
python-versions = ">=3.10,<4"
|
||||
content-hash = "4ffa68a8953cb18a1d2a43335cf2187e609659cd414bcd7f65ab285971ba72aa"
|
||||
content-hash = "fa0608494d973b528ccad56576f42c04cff04a66c1325796d224dedab292aa16"
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
[project]
|
||||
name = "graphiti-core"
|
||||
description = "A temporal graph building library"
|
||||
version = "0.9.4"
|
||||
version = "0.9.5"
|
||||
authors = [
|
||||
{"name" = "Paul Paliychuk", "email" = "paul@getzep.com"},
|
||||
{"name" = "Preston Rasmussen", "email" = "preston@getzep.com"},
|
||||
{"name" = "Daniel Chalef", "email" = "daniel@getzep.com"},
|
||||
{ "name" = "Paul Paliychuk", "email" = "paul@getzep.com" },
|
||||
{ "name" = "Preston Rasmussen", "email" = "preston@getzep.com" },
|
||||
{ "name" = "Daniel Chalef", "email" = "daniel@getzep.com" },
|
||||
]
|
||||
readme = "README.md"
|
||||
license = "Apache-2.0"
|
||||
|
|
@ -19,6 +19,7 @@ dependencies = [
|
|||
"tenacity>=9.0.0",
|
||||
"numpy>=1.0.0",
|
||||
"python-dotenv>=1.0.1",
|
||||
"graph-service (>=1.0.0.7,<2.0.0.0)",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue