Skip to content

Commit c0ac6a2

Browse files
committed
Pin redisvl to 0.11.1
1 parent 6b4b05b commit c0ac6a2

File tree

4 files changed

+25
-154
lines changed

4 files changed

+25
-154
lines changed

libs/redis/langchain_redis/cache.py

Lines changed: 4 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -720,37 +720,6 @@ async def aclear(self, **kwargs: Any) -> None:
720720
await self.cache.aclear()
721721

722722

723-
_LLM_STRING_ENCODE_TRANS = str.maketrans(
724-
{
725-
",": ",", # FULLWIDTH COMMA, U+FF0C
726-
"/": "∕", # DIVISION SLASH, U+2215
727-
}
728-
)
729-
730-
731-
def _encode_llm_string_for_attributes(llm_string: str) -> str:
732-
"""Encode an llm_string for use as a LangCache attribute value.
733-
734-
LangCache enforces validation rules on the ``llm_string`` attribute:
735-
736-
- It cannot contain commas (",") – attempts to store such values
737-
result in ``400 Bad Request`` responses from the LangCache API.
738-
- Attribute filtering on ``llm_string`` does not reliably match values
739-
containing slashes ("/") even though they can be stored.
740-
741-
To ensure round-trippable, attribute-filterable values, we replace these
742-
characters with visually similar Unicode variants that are accepted by
743-
LangCache and precompute a translation table so we only scan the string
744-
once.
745-
746-
The encoded value is only used for attribute storage and filtering; the
747-
original ``llm_string`` is preserved inside the serialized Generation
748-
payload, so no decoding step is required.
749-
"""
750-
751-
return llm_string.translate(_LLM_STRING_ENCODE_TRANS)
752-
753-
754723
class LangCacheSemanticCache(BaseCache):
755724
"""Managed LangCache-backed semantic cache.
756725
@@ -851,12 +820,11 @@ def __init__(
851820

852821
def lookup(self, prompt: str, llm_string: str) -> Optional[RETURN_VAL_TYPE]:
853822
"""Lookup using LangCache's check API."""
854-
safe_llm_string = _encode_llm_string_for_attributes(llm_string)
855823
results = self.cache.check(
856824
prompt=prompt,
857825
num_results=1,
858826
distance_threshold=self._distance_threshold,
859-
attributes={"llm_string": safe_llm_string},
827+
attributes={"llm_string": llm_string},
860828
)
861829
return self._process_lookup_results(results, llm_string)
862830

@@ -879,12 +847,11 @@ def _process_lookup_results(
879847
def update(self, prompt: str, llm_string: str, return_val: RETURN_VAL_TYPE) -> None:
880848
"""Store using LangCache's store API via redisvl wrapper."""
881849
serialized_response = json.dumps([dumps(gen) for gen in return_val])
882-
safe_llm_string = _encode_llm_string_for_attributes(llm_string)
883850
# LangCacheSemanticCache ignores per-entry TTL; it uses cache-level TTL if set
884851
self.cache.store(
885852
prompt=prompt,
886853
response=serialized_response,
887-
metadata={"llm_string": safe_llm_string},
854+
metadata={"llm_string": llm_string},
888855
ttl=self.ttl,
889856
)
890857

@@ -897,12 +864,11 @@ def name(self) -> str:
897864

898865
async def alookup(self, prompt: str, llm_string: str) -> Optional[RETURN_VAL_TYPE]:
899866
"""Async lookup through LangCache's acheck API."""
900-
safe_llm_string = _encode_llm_string_for_attributes(llm_string)
901867
results = await self.cache.acheck(
902868
prompt=prompt,
903869
num_results=1,
904870
distance_threshold=self._distance_threshold,
905-
attributes={"llm_string": safe_llm_string},
871+
attributes={"llm_string": llm_string},
906872
)
907873
return self._process_lookup_results(results, llm_string)
908874

@@ -911,11 +877,10 @@ async def aupdate(
911877
) -> None:
912878
"""Async store using LangCache's astore API via redisvl wrapper."""
913879
serialized_response = json.dumps([dumps(gen) for gen in return_val])
914-
safe_llm_string = _encode_llm_string_for_attributes(llm_string)
915880
await self.cache.astore(
916881
prompt=prompt,
917882
response=serialized_response,
918-
metadata={"llm_string": safe_llm_string},
883+
metadata={"llm_string": llm_string},
919884
ttl=self.ttl,
920885
)
921886

libs/redis/poetry.lock

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

libs/redis/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ license = "MIT"
1313
[tool.poetry.dependencies]
1414
python = ">=3.10,<3.14"
1515
langchain-core = "^1.0"
16-
redisvl = ">=0.11.0,<1.0.0"
16+
redisvl = ">=0.11.1"
1717
jinja2 = "^3.1.6"
1818
typing-extensions = "^4.13.2"
1919
anyio = "^4.9.0"

libs/redis/tests/integration_tests/test_langcache_semantic_cache_integration.py

Lines changed: 15 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,6 @@ async def test_async_update_and_lookup_roundtrip(
156156
assert len(hits) == 1
157157
assert hits[0].text == "Redis is an in-memory data store (async)."
158158

159-
@pytest.mark.skip("Waiting on upstream RedisVL release to fix")
160159
def test_clear_removes_entries(
161160
self, langcache_with_attrs: LangCacheSemanticCache
162161
) -> None:
@@ -189,118 +188,25 @@ async def test_aclear_removes_entries(
189188
await langcache_with_attrs.aclear()
190189
assert await langcache_with_attrs.alookup(prompt, llm_string) is None
191190

192-
def test_llm_string_with_comma_roundtrip(
193-
self, langcache_with_attrs: LangCacheSemanticCache
194-
) -> None:
195-
"""llm_string values containing commas should still round-trip.
196-
197-
The client encodes commas as a fullwidth comma when sending attributes
198-
to LangCache for validation/filtering, but lookup() should continue to
199-
work when called with the original llm_string containing commas.
200-
"""
201191

202-
prompt = "Comma llm_string (sync)"
203-
llm_string = "openai/gpt-4o,temperature=0.2,max_tokens=128"
204-
result = [Generation(text="Response for llm_string with commas (sync).")]
205-
206-
langcache_with_attrs.update(prompt, llm_string, result)
207-
hits = langcache_with_attrs.lookup(prompt, llm_string)
192+
@pytest.mark.requires_api_keys
193+
class TestLangCacheSemanticCacheIntegrationWithoutAttributes:
194+
def test_update_errors_when_no_attributes_configured(
195+
self, langcache_no_attrs: LangCacheSemanticCache
196+
) -> None:
197+
"""update() should raise if attributes are not configured on the cache."""
208198

209-
assert hits is not None
210-
assert len(hits) == 1
211-
assert hits[0].text == "Response for llm_string with commas (sync)."
212-
213-
@pytest.mark.asyncio
214-
async def test_llm_string_with_comma_roundtrip_async(
215-
self, langcache_with_attrs: LangCacheSemanticCache
216-
) -> None:
217-
"""Async variant of the comma llm_string round-trip test."""
199+
prompt = "Attributes not configured (sync)"
200+
llm_string = "langchain-redis/tests:no-attributes:sync"
218201

219-
prompt = "Comma llm_string (async)"
220-
llm_string = "openai/gpt-4o,temperature=0.3,max_tokens=256"
221-
result = [Generation(text="Response for llm_string with commas (async).")]
222-
223-
await langcache_with_attrs.aupdate(prompt, llm_string, result)
224-
hits = await langcache_with_attrs.alookup(prompt, llm_string)
225-
226-
assert hits is not None
227-
assert len(hits) == 1
228-
assert hits[0].text == "Response for llm_string with commas (async)."
229-
230-
231-
@pytest.mark.requires_api_keys
232-
class TestRedisVLLangCacheDirectWithoutAttributes:
233-
"""Direct redisvl client behavior without llm_string attribute filters.
234-
235-
These tests verify that the underlying LangCache instance used for
236-
"with attributes" scenarios can successfully round-trip entries when
237-
we do *not* send any attributes in the search request. This helps
238-
distinguish adapter-level issues (llm_string attribute handling) from
239-
underlying LangCache behavior.
240-
"""
241-
242-
def test_direct_store_and_check_without_attributes(
243-
self, rv_langcache_with_attrs: "RedisVLLangCacheSemanticCache"
244-
) -> None:
245-
"""Store and retrieve using the redisvl client, no attributes filter."""
202+
with pytest.raises(RuntimeError) as exc:
203+
langcache_no_attrs.update(
204+
prompt,
205+
llm_string,
206+
[Generation(text="This should not be stored.")],
207+
)
246208

247-
prompt = "RedisVL direct no-attrs (sync)"
248-
response = "Direct response without attributes filter."
249-
250-
entry_id = rv_langcache_with_attrs.store(prompt=prompt, response=response)
251-
assert entry_id
252-
253-
hits = rv_langcache_with_attrs.check(prompt=prompt, num_results=1)
254-
255-
assert hits
256-
assert hits[0]["prompt"] == prompt
257-
assert hits[0]["response"] == response
258-
259-
def test_direct_store_with_metadata_and_check_without_attributes(
260-
self, rv_langcache_with_attrs: "RedisVLLangCacheSemanticCache"
261-
) -> None:
262-
"""Store with metadata but still retrieve without attributes filter.
263-
264-
This ensures that even when we provide metadata (attributes) at
265-
write-time, we can still successfully retrieve the entry without
266-
sending any attributes filter to LangCache.
267-
"""
268-
269-
prompt = "RedisVL direct metadata no-attrs (sync)"
270-
response = "Direct response with metadata but no attributes filter."
271-
272-
entry_id = rv_langcache_with_attrs.store(
273-
prompt=prompt,
274-
response=response,
275-
metadata={"llm_string": "redisvl-direct:no-attrs"},
276-
)
277-
assert entry_id
278-
279-
hits = rv_langcache_with_attrs.check(prompt=prompt, num_results=1)
280-
281-
assert hits
282-
assert hits[0]["prompt"] == prompt
283-
assert hits[0]["response"] == response
284-
285-
286-
@pytest.mark.requires_api_keys
287-
class TestLangCacheSemanticCacheIntegrationWithoutAttributes:
288-
def test_update_errors_when_no_attributes_configured(
289-
self, langcache_no_attrs: LangCacheSemanticCache
290-
) -> None:
291-
"""update() should raise if attributes are not configured on the cache."""
292-
293-
prompt = "Attributes not configured (sync)"
294-
llm_string = "langchain-redis/tests:no-attributes:sync"
295-
296-
with pytest.raises(RuntimeError) as exc:
297-
langcache_no_attrs.update(
298-
prompt,
299-
llm_string,
300-
[Generation(text="This should not be stored.")],
301-
)
302-
303-
assert "attributes are not configured for this cache" in str(exc.value).lower()
209+
assert "attributes are not configured for this cache" in str(exc.value).lower()
304210

305211
def test_lookup_errors_when_no_attributes_configured(
306212
self, langcache_no_attrs: LangCacheSemanticCache

0 commit comments

Comments
 (0)