From ee8653d1c5e96c170d8028df1d50c55bf916b9a9 Mon Sep 17 00:00:00 2001 From: William FH <13333726+hinthornw@users.noreply.github.com> Date: Wed, 27 Nov 2024 22:50:52 -0800 Subject: [PATCH] [SDK] Add SearchItem (#2567) --- libs/sdk-py/langgraph_sdk/client.py | 32 +++++++++++++++++++++-------- libs/sdk-py/langgraph_sdk/schema.py | 13 +++++++++++- libs/sdk-py/pyproject.toml | 2 +- 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/libs/sdk-py/langgraph_sdk/client.py b/libs/sdk-py/langgraph_sdk/client.py index 6a3bb6c9c..81e8a8506 100644 --- a/libs/sdk-py/langgraph_sdk/client.py +++ b/libs/sdk-py/langgraph_sdk/client.py @@ -18,6 +18,7 @@ Dict, Iterator, List, + Literal, Optional, Sequence, Union, @@ -1946,7 +1947,7 @@ async def create( Example Usage: - cron_run = await client.crons.create( + cron_run = client.crons.create( assistant_id="agent", schedule="27 15 * * *", input={"messages": [{"role": "user", "content": "hello!"}]}, @@ -2070,7 +2071,12 @@ def __init__(self, http: HttpClient) -> None: self.http = http async def put_item( - self, namespace: Sequence[str], /, key: str, value: dict[str, Any] + self, + namespace: Sequence[str], + /, + key: str, + value: dict[str, Any], + index: Optional[Union[Literal[False], list[str]]] = None, ) -> None: """Store or update an item. @@ -2078,6 +2084,7 @@ async def put_item( namespace: A list of strings representing the namespace path. key: The unique identifier for the item within the namespace. value: A dictionary containing the item's data. + index: Controls search indexing - None (use defaults), False (disable), or list of field paths to index. Returns: None @@ -2095,11 +2102,7 @@ async def put_item( raise ValueError( f"Invalid namespace label '{label}'. Namespace labels cannot contain periods ('.')." ) - payload = { - "namespace": namespace, - "key": key, - "value": value, - } + payload = {"namespace": namespace, "key": key, "value": value, "index": index} await self.http.put("/store/items", json=payload) async def get_item(self, namespace: Sequence[str], /, key: str) -> Item: @@ -2167,6 +2170,7 @@ async def search_items( filter: Optional[dict[str, Any]] = None, limit: int = 10, offset: int = 0, + query: Optional[str] = None, ) -> SearchItemsResponse: """Search for items within a namespace prefix. @@ -2175,6 +2179,7 @@ async def search_items( filter: Optional dictionary of key-value pairs to filter results. limit: Maximum number of items to return (default is 10). offset: Number of items to skip before returning results (default is 0). + query: Optional query for natural language search. Returns: List[Item]: A list of items matching the search criteria. @@ -2212,6 +2217,7 @@ async def search_items( "filter": filter, "limit": limit, "offset": offset, + "query": query, } return await self.http.post("/store/items/search", json=_provided_vals(payload)) @@ -4154,7 +4160,12 @@ def __init__(self, http: SyncHttpClient) -> None: self.http = http def put_item( - self, namespace: Sequence[str], /, key: str, value: dict[str, Any] + self, + namespace: Sequence[str], + /, + key: str, + value: dict[str, Any], + index: Optional[Union[Literal[False], list[str]]] = None, ) -> None: """Store or update an item. @@ -4162,6 +4173,7 @@ def put_item( namespace: A list of strings representing the namespace path. key: The unique identifier for the item within the namespace. value: A dictionary containing the item's data. + index: Controls search indexing - None (use defaults), False (disable), or list of field paths to index. Returns: None @@ -4183,6 +4195,7 @@ def put_item( "namespace": namespace, "key": key, "value": value, + "index": index, } self.http.put("/store/items", json=payload) @@ -4250,6 +4263,7 @@ def search_items( filter: Optional[dict[str, Any]] = None, limit: int = 10, offset: int = 0, + query: Optional[str] = None, ) -> SearchItemsResponse: """Search for items within a namespace prefix. @@ -4258,6 +4272,7 @@ def search_items( filter: Optional dictionary of key-value pairs to filter results. limit: Maximum number of items to return (default is 10). offset: Number of items to skip before returning results (default is 0). + query: Optional query for natural language search. Returns: List[Item]: A list of items matching the search criteria. @@ -4295,6 +4310,7 @@ def search_items( "filter": filter, "limit": limit, "offset": offset, + "query": query, } return self.http.post("/store/items/search", json=_provided_vals(payload)) diff --git a/libs/sdk-py/langgraph_sdk/schema.py b/libs/sdk-py/langgraph_sdk/schema.py index 5264ce709..a66d007f5 100644 --- a/libs/sdk-py/langgraph_sdk/schema.py +++ b/libs/sdk-py/langgraph_sdk/schema.py @@ -325,10 +325,21 @@ class ListNamespaceResponse(TypedDict): """A list of namespace paths, where each path is a list of strings.""" +class SearchItem(Item, total=False): + """Item with an optional relevance score from search operations. + + Attributes: + score (Optional[float]): Relevance/similarity score. Included when + searching a compatible store with a natural language query. + """ + + score: Optional[float] + + class SearchItemsResponse(TypedDict): """Response structure for searching items.""" - items: list[Item] + items: list[SearchItem] """A list of items matching the search criteria.""" diff --git a/libs/sdk-py/pyproject.toml b/libs/sdk-py/pyproject.toml index 7c8af51b2..c7776a6cc 100644 --- a/libs/sdk-py/pyproject.toml +++ b/libs/sdk-py/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "langgraph-sdk" -version = "0.1.39" +version = "0.1.40" description = "SDK for interacting with LangGraph API" authors = [] license = "MIT"