From f249223743dc55b53c249ad7c0b18ff4efe4e981 Mon Sep 17 00:00:00 2001 From: Brian Sam-Bodden Date: Sun, 9 Feb 2025 08:38:05 -0700 Subject: [PATCH] refactor: use ULIDs instead of uuids --- langgraph/store/redis/__init__.py | 4 ++-- langgraph/store/redis/aio.py | 4 ++-- poetry.lock | 17 ++++++++++++++++- pyproject.toml | 1 + tests/test_async_store.py | 4 ++-- tests/test_store.py | 4 ++-- 6 files changed, 25 insertions(+), 9 deletions(-) diff --git a/langgraph/store/redis/__init__.py b/langgraph/store/redis/__init__.py index c66c2cb..488554f 100644 --- a/langgraph/store/redis/__init__.py +++ b/langgraph/store/redis/__init__.py @@ -5,7 +5,6 @@ import asyncio import json import math -import uuid from contextlib import contextmanager from datetime import datetime, timezone from typing import Any, Iterable, Iterator, Optional, Sequence, cast @@ -14,6 +13,7 @@ from redisvl.query import FilterQuery, VectorQuery from redisvl.redis.connection import RedisConnectionFactory from redisvl.utils.token_escaper import TokenEscaper +from ulid import ULID from langgraph.store.base import ( BaseStore, @@ -223,7 +223,7 @@ def _batch_put_ops( # Generate IDs for PUT operations for _, op in put_ops: if op.value is not None: - generated_doc_id = uuid.uuid4().hex + generated_doc_id = str(ULID()) namespace = _namespace_to_text(op.namespace) doc_ids[(namespace, op.key)] = generated_doc_id diff --git a/langgraph/store/redis/aio.py b/langgraph/store/redis/aio.py index fa88e8f..5cb3093 100644 --- a/langgraph/store/redis/aio.py +++ b/langgraph/store/redis/aio.py @@ -2,7 +2,6 @@ import asyncio import json -import uuid import weakref from contextlib import asynccontextmanager from datetime import datetime, timezone @@ -13,6 +12,7 @@ from redisvl.query import FilterQuery, VectorQuery from redisvl.redis.connection import RedisConnectionFactory from redisvl.utils.token_escaper import TokenEscaper +from ulid import ULID from langgraph.store.base import ( BaseStore, @@ -398,7 +398,7 @@ async def _batch_put_ops( # Generate IDs for PUT operations for _, op in put_ops: if op.value is not None: - generated_doc_id = uuid.uuid4().hex + generated_doc_id = str(ULID()) namespace = _namespace_to_text(op.namespace) doc_ids[(namespace, op.key)] = generated_doc_id diff --git a/poetry.lock b/poetry.lock index 6471e3b..ea76f34 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1542,6 +1542,21 @@ files = [ [package.extras] cli = ["click (>=5.0)"] +[[package]] +name = "python-ulid" +version = "3.0.0" +description = "Universally unique lexicographically sortable identifier" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "python_ulid-3.0.0-py3-none-any.whl", hash = "sha256:e4c4942ff50dbd79167ad01ac725ec58f924b4018025ce22c858bfcff99a5e31"}, + {file = "python_ulid-3.0.0.tar.gz", hash = "sha256:e50296a47dc8209d28629a22fc81ca26c00982c78934bd7766377ba37ea49a9f"}, +] + +[package.extras] +pydantic = ["pydantic (>=2.0)"] + [[package]] name = "pywin32" version = "308" @@ -2299,4 +2314,4 @@ files = [ [metadata] lock-version = "2.1" python-versions = ">=3.9,<3.13" -content-hash = "443ac01afc2e48351fca7c178dc7fe4057a05ff0e2340b5abe6a3a31abe35188" +content-hash = "8d7ab239e98778cd2b9c64066eca21e790ea991f7d929cae3c623d2ffd399919" diff --git a/pyproject.toml b/pyproject.toml index 15a0150..a8fa98a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,6 +13,7 @@ python = ">=3.9,<3.13" langgraph-checkpoint = "^2.0.10" redisvl = "^0.3.7" redis = "^5.2.1" +python-ulid = "^3.0.0" [tool.poetry.group.dev.dependencies] ruff = "^0.6.2" diff --git a/tests/test_async_store.py b/tests/test_async_store.py index 0168e3a..6c3bf43 100644 --- a/tests/test_async_store.py +++ b/tests/test_async_store.py @@ -1,6 +1,5 @@ """Tests for AsyncRedisStore.""" -import uuid from typing import Any, AsyncGenerator, Dict, Sequence, cast import pytest @@ -9,6 +8,7 @@ from langchain_core.runnables import RunnableConfig from langchain_openai import OpenAIEmbeddings from redis.asyncio import Redis +from ulid import ULID from langgraph.checkpoint.redis import AsyncRedisSaver from langgraph.constants import START @@ -525,7 +525,7 @@ def call_model( # Store new memories if the user asks the model to remember if "remember" in last_message.content.lower(): # type:ignore[union-attr] memory = "User name is Bob" - store.put(namespace, str(uuid.uuid4()), {"data": memory}) + store.put(namespace, str(ULID()), {"data": memory}) messages = [{"role": "system", "content": system_msg}] messages.extend([msg.model_dump() for msg in state["messages"]]) diff --git a/tests/test_store.py b/tests/test_store.py index fe25e10..e47e958 100644 --- a/tests/test_store.py +++ b/tests/test_store.py @@ -1,4 +1,3 @@ -import uuid from typing import Any, Dict, Sequence, cast import pytest @@ -7,6 +6,7 @@ from langchain_core.runnables import RunnableConfig from langchain_openai import OpenAIEmbeddings from redis import Redis +from ulid import ULID from langgraph.checkpoint.redis import RedisSaver from langgraph.graph import START, MessagesState, StateGraph @@ -464,7 +464,7 @@ def call_model( # Store new memories if the user asks the model to remember if "remember" in last_message.content.lower(): # type:ignore[union-attr] memory = "User name is Bob" - store.put(namespace, str(uuid.uuid4()), {"data": memory}) + store.put(namespace, str(ULID()), {"data": memory}) messages = [{"role": "system", "content": system_msg}] messages.extend([msg.model_dump() for msg in state["messages"]])