44managed service via the langcache Python SDK.
55"""
66
7- from typing import Any , Dict , List , Optional
7+ from typing import Any , Dict , List , Literal , Optional
88
99from redisvl .extensions .cache .llm .base import BaseLLMCache
1010from redisvl .extensions .cache .llm .schema import CacheHit
1111from redisvl .query .filter import FilterExpression
1212from redisvl .utils .log import get_logger
13+ from redisvl .utils .utils import denorm_cosine_distance , norm_cosine_distance
1314
1415logger = get_logger (__name__ )
1516
@@ -62,6 +63,7 @@ def __init__(
6263 ttl : Optional [int ] = None ,
6364 use_exact_search : bool = True ,
6465 use_semantic_search : bool = True ,
66+ distance_scale : Literal ["normalized" , "redis" ] = "normalized" ,
6567 ** kwargs ,
6668 ):
6769 """Initialize a LangCache wrapper.
@@ -74,12 +76,19 @@ def __init__(
7476 ttl (Optional[int]): Time-to-live for cache entries in seconds.
7577 use_exact_search (bool): Whether to use exact matching. Defaults to True.
7678 use_semantic_search (bool): Whether to use semantic search. Defaults to True.
79+ distance_scale (str): Threshold scale for distance_threshold:
80+ - "normalized": 0–1 semantic distance (lower is better)
81+ - "redis": Redis COSINE distance 0–2 (lower is better)
7782 **kwargs: Additional arguments (ignored for compatibility).
7883
7984 Raises:
8085 ImportError: If the langcache package is not installed.
8186 ValueError: If cache_id or api_key is not provided.
8287 """
88+ if distance_scale not in {"normalized" , "redis" }:
89+ raise ValueError ("distance_scale must be 'normalized' or 'redis'" )
90+ self ._distance_scale = distance_scale
91+
8392 if not LANGCACHE_AVAILABLE :
8493 raise ImportError (
8594 "The langcache package is required to use LangCacheWrapper. "
@@ -128,10 +137,13 @@ def _convert_to_cache_hit(self, result: Dict[str, Any]) -> CacheHit:
128137 # Extract attributes (metadata) from the result
129138 attributes = result .get ("attributes" , {})
130139
131- # LangCache returns similarity (0-1, higher is better)
132- # Convert to distance (lower is better) for consistency
140+ # LangCache returns similarity in [0,1] (higher is better)
133141 similarity = result .get ("similarity" , 0.0 )
134- distance = 1.0 - similarity if similarity else 0.0
142+ # Convert to the configured distance scale (lower is better)
143+ if self ._distance_scale == "redis" :
144+ distance = denorm_cosine_distance (similarity ) # -> [0,2]
145+ else :
146+ distance = 1.0 - similarity # normalized [0,1]
135147
136148 return CacheHit (
137149 entry_id = result .get ("id" , "" ),
@@ -181,12 +193,15 @@ def check(
181193 if filter_expression is not None :
182194 logger .warning ("LangCache does not support filter expressions" )
183195
184- # Convert distance_threshold to similarity_threshold
185- # Distance: lower is better (0.0 = exact match)
186- # Similarity: higher is better (1.0 = exact match)
196+ # Convert distance threshold to similarity threshold according to configured scale
187197 similarity_threshold = None
188198 if distance_threshold is not None :
189- similarity_threshold = 1.0 - distance_threshold
199+ if self ._distance_scale == "redis" :
200+ similarity_threshold = norm_cosine_distance (
201+ distance_threshold
202+ ) # [0,2] -> [0,1]
203+ else :
204+ similarity_threshold = 1.0 - float (distance_threshold ) # [0,1] -> [0,1]
190205
191206 # Search using the LangCache client
192207 # The client itself is the context manager
@@ -256,12 +271,15 @@ async def acheck(
256271 if filter_expression is not None :
257272 logger .warning ("LangCache does not support filter expressions" )
258273
259- # Convert distance_threshold to similarity_threshold
260- # Distance: lower is better (0.0 = exact match)
261- # Similarity: higher is better (1.0 = exact match)
274+ # Convert distance threshold to similarity threshold according to configured scale
262275 similarity_threshold = None
263276 if distance_threshold is not None :
264- similarity_threshold = 1.0 - distance_threshold
277+ if self ._distance_scale == "redis" :
278+ similarity_threshold = norm_cosine_distance (
279+ distance_threshold
280+ ) # [0,2] -> [0,1]
281+ else :
282+ similarity_threshold = 1.0 - float (distance_threshold ) # [0,1] -> [0,1]
265283
266284 # Search using the LangCache client (async)
267285 # The client itself is the context manager
0 commit comments