
    k
i:                         d Z ddlZddlmZmZmZmZmZ ddlm	Z	  G d d          Z
ddded	ee         d
e
fdZ G d de	          Z	 dded	ee         d
efdZdS )a  Async embedding vectorizer adapter for Redis middleware.

This module provides vectorizer adapters for Redis middleware:

1. AsyncEmbeddingVectorizer: A simple async wrapper for embedding functions
2. LangChainVectorizer: A redisvl-compatible BaseVectorizer that wraps LangChain embeddings

The LangChainVectorizer is the recommended approach for using LangChain embeddings
(OpenAI, Azure OpenAI, etc.) with SemanticCache and SemanticCacheMiddleware.
    N)AnyCallableListOptionalUnion)BaseVectorizerc                   l   e Zd ZdZdddeee         geee                  f         dede	eegee         f                  ddfdZ
edefd	            Zd
eeee         f         deee                  fdZd
eeee         f         deee                  fdZdedee         fdZdedee         fdZdS )AsyncEmbeddingVectorizeraL  Async wrapper for synchronous embedding functions.

    This class wraps synchronous embedding functions (like those from
    langchain-openai) for use in async contexts using asyncio.to_thread().

    Example:
        ```python
        from langchain_openai import OpenAIEmbeddings

        embeddings = OpenAIEmbeddings()
        vectorizer = AsyncEmbeddingVectorizer(
            embed_fn=embeddings.embed_documents,
            dims=1536  # OpenAI ada-002 dimensions
        )

        # Use in async context
        vectors = await vectorizer.aembed(["hello world"])
        ```
    N)embed_query_fnembed_fndimsr   returnc                0    || _         || _        || _        dS )aY  Initialize the async vectorizer.

        Args:
            embed_fn: Synchronous function that embeds a list of texts.
            dims: Dimensionality of the embedding vectors.
            embed_query_fn: Optional separate function for single query embedding.
                If not provided, embed_fn is used with a single-item list.
        N)	_embed_fn_embed_query_fn_dims)selfr   r   r   s       C:\Users\Dell Inspiron 16\Desktop\tws\AgrotaPowerBi\back-agrota-powerbi\mcp-client-agrota\venv\Lib\site-packages\langgraph/middleware/redis/vectorizer.py__init__z!AsyncEmbeddingVectorizer.__init__'   s     "-


    c                     | j         S )z Return the embedding dimensions.)r   )r   s    r   r   zAsyncEmbeddingVectorizer.dims:   s     zr   textsc                 \    t          |t                    r|g}|                     |          S )zSynchronously embed texts.

        Args:
            texts: A single text or list of texts to embed.

        Returns:
            List of embedding vectors.
        )
isinstancestrr   r   r   s     r   embedzAsyncEmbeddingVectorizer.embed?   s/     eS!! 	GE~~e$$$r   c                 v   K   t          |t                    r|g}t          j        | j        |           d{V S )zAsynchronously embed texts using asyncio.to_thread().

        Args:
            texts: A single text or list of texts to embed.

        Returns:
            List of embedding vectors.
        N)r   r   asyncio	to_threadr   r   s     r   aembedzAsyncEmbeddingVectorizer.aembedL   sH       eS!! 	GE&t~u=========r   textc                 r    | j         |                      |          S |                     |g          d         S )zSynchronously embed a single query text.

        Args:
            text: The query text to embed.

        Returns:
            The embedding vector.
        Nr   )r   r   )r   r"   s     r   embed_queryz$AsyncEmbeddingVectorizer.embed_queryY   s:     +''---~~tf%%a((r   c                    K   | j          t          j        | j         |           d{V S t          j        | j        |g           d{V }|d         S )zAsynchronously embed a single query text.

        Args:
            text: The query text to embed.

        Returns:
            The embedding vector.
        Nr   )r   r   r    r   )r   r"   results      r   aembed_queryz%AsyncEmbeddingVectorizer.aembed_queryf   sk       + *4+?FFFFFFFFF($@@@@@@@@ayr   )__name__
__module____qualname____doc__r   r   r   floatintr   r   propertyr   r   r   r!   r$   r'    r   r   r
   r
      sz        2 BF  DI;T%[(99: 
 !3%e*<!=> 
   & c    X%5d3i0 %T$u+5F % % % %>%T#Y"7 >De<M > > > >) )U ) ) ) )s tE{      r   r
   )r   
embeddingsr   r   c                L   |'dD ]$}t          | |          rt          | |          } n%|?t          | dd          pt          | dd          }|rdddd}|                    |          }|t          d          | j        }t          | d	d          }t          |||
          S )a_  Create an AsyncEmbeddingVectorizer from a LangChain Embeddings object.

    Args:
        embeddings: A LangChain Embeddings object (e.g., OpenAIEmbeddings).
        dims: Optional dimensions override. If not provided, will attempt
            to determine from the embeddings object or use a default.

    Returns:
        An AsyncEmbeddingVectorizer wrapping the LangChain embeddings.

    Example:
        ```python
        from langchain_openai import OpenAIEmbeddings

        embeddings = OpenAIEmbeddings()
        vectorizer = create_vectorizer_from_langchain(embeddings, dims=1536)
        ```
    N
dimensionsr   embedding_dim	dimensionmodel
model_name      ztext-embedding-ada-002ztext-embedding-3-smallztext-embedding-3-largeSCould not determine embedding dimensions. Please provide dims parameter explicitly.r$   )r   r   r   )hasattrgetattrget
ValueErrorembed_documentsr
   )r0   r   attrr6   
model_dimsr   r   s          r    create_vectorizer_from_langchainrC   u   s    , |H 	 	Dz4(( z400
 |
GT22 
gd7
 7
  	) +/*.*. J
 >>%((D|8
 
 	
 )HZ==N#%   r   c                       e Zd ZU dZdZeed<   ddiZdededed	df fd
Z		 	 dde
dee         deded	eee         ef         f
dZ	 	 	 ddee
         dee         dededed	eeee                  ee         f         fdZ	 	 dde
dee         deded	eee         ef         f
dZ	 	 	 ddee
         dee         dededed	eeee                  ee         f         fdZ xZS )LangChainVectorizera`  A redisvl-compatible vectorizer that wraps LangChain Embeddings.

    This class bridges LangChain embeddings (OpenAI, Azure OpenAI, HuggingFace, etc.)
    with redisvl's SemanticCache by implementing the BaseVectorizer interface.

    Unlike AsyncEmbeddingVectorizer, this class properly extends redisvl's
    BaseVectorizer (a Pydantic model), making it compatible with SemanticCache's
    type validation.

    Example:
        ```python
        from langchain_openai import OpenAIEmbeddings
        from langgraph.middleware.redis import LangChainVectorizer, SemanticCacheConfig

        # Create LangChain embeddings
        embeddings = OpenAIEmbeddings(model="text-embedding-3-small")

        # Wrap in LangChainVectorizer for redisvl compatibility
        vectorizer = LangChainVectorizer(embeddings=embeddings, dims=1536)

        # Use with SemanticCacheMiddleware
        config = SemanticCacheConfig(
            redis_url="redis://localhost:6379",
            vectorizer=vectorizer,
        )
        ```

    For Azure OpenAI:
        ```python
        from langchain_openai import AzureOpenAIEmbeddings

        embeddings = AzureOpenAIEmbeddings(
            azure_deployment="your-embedding-deployment",
            openai_api_version="2024-02-15-preview",
        )
        vectorizer = LangChainVectorizer(embeddings=embeddings, dims=1536)
        ```
    N_embeddingsarbitrary_types_allowedTr0   r   kwargsr   c                 x     t                      j        dd|d| t                              | d|           dS )aN  Initialize the LangChain vectorizer.

        Args:
            embeddings: A LangChain Embeddings object (e.g., OpenAIEmbeddings,
                AzureOpenAIEmbeddings, HuggingFaceEmbeddings).
            dims: The dimensionality of the embedding vectors.
            **kwargs: Additional arguments passed to BaseVectorizer.
        	langchain)r6   r   rF   Nr/   )superr   object__setattr__)r   r0   r   rH   	__class__s       r   r   zLangChainVectorizer.__init__   sG     	@{@@@@@4
;;;;;r   Fr"   
preprocess	as_bufferc                     | ||          }t          | j        d          r| j                            |          }n!| j                            |g          d         }|r|                     |d| j                  S |S )a  Embed a single text using LangChain embeddings.

        Args:
            text: The text to embed.
            preprocess: Optional preprocessing function (applied if provided).
            as_buffer: If True, return as bytes buffer.
            **kwargs: Additional arguments (ignored).

        Returns:
            The embedding vector as a list of floats, or bytes if as_buffer=True.
        Nr$   r   TrP   dtype)r<   rF   r$   r@   _process_embeddingrS   )r   r"   rO   rP   rH   	embeddings         r   r   zLangChainVectorizer.embed   s    $ !:d##D 4#]33 	D(44T::II(88$@@CI 	X**9DJ*WWWr     r   
batch_sizec                      g }                      |||          D ]A} j                            |          }|r fd|D             }|                    |           B|S )a  Embed multiple texts using LangChain embeddings.

        Args:
            texts: List of texts to embed.
            preprocess: Optional preprocessing function (applied to each text).
            batch_size: Batch size for processing (used for batching).
            as_buffer: If True, return as bytes buffers.
            **kwargs: Additional arguments (ignored).

        Returns:
            List of embedding vectors, or list of bytes if as_buffer=True.
        c                 J    g | ]}                     |d j                   S TrR   rT   rS   .0er   s     r   
<listcomp>z2LangChainVectorizer.embed_many.<locals>.<listcomp>$  @        ++ATZ+PP  r   )batchifyrF   r@   extend	r   r   rO   rW   rP   rH   all_embeddingsbatchr0   s	   `        r   
embed_manyzLangChainVectorizer.embed_many  s    ( -/]]5*jAA 	. 	.E)99%@@J    '  
 !!*----r   c                   K   | ||          }t          | j        d          r!| j                            |           d{V }nat          | j        d          r*| j                            |g           d{V }|d         }n"t	          j        | j        |dd           d{V }|r|                     |d| j                  S |S )ak  Asynchronously embed a single text.

        Args:
            text: The text to embed.
            preprocess: Optional preprocessing function.
            as_buffer: If True, return as bytes buffer.
            **kwargs: Additional arguments (ignored).

        Returns:
            The embedding vector as a list of floats, or bytes if as_buffer=True.
        Nr'   aembed_documentsr   FTrR   )	r<   rF   r'   rh   r   r    r   rT   rS   )r   r"   rO   rP   rH   rU   r0   s          r   r!   zLangChainVectorizer.aembed,  s     $ !:d##D 4#^44 	O".;;DAAAAAAAAIIT%'9:: 	O#/@@$HHHHHHHHJ"1II &/
D$NNNNNNNNI 	X**9DJ*WWWr   c                 D   K   g }                      |||          D ]}t           j        d          r! j                            |           d{V }n%t	          j         j        j        |           d{V }|r fd|D             }|                    |           |S )a  Asynchronously embed multiple texts.

        Args:
            texts: List of texts to embed.
            preprocess: Optional preprocessing function.
            batch_size: Batch size for processing.
            as_buffer: If True, return as bytes buffers.
            **kwargs: Additional arguments (ignored).

        Returns:
            List of embedding vectors, or list of bytes if as_buffer=True.
        rh   Nc                 J    g | ]}                     |d j                   S rZ   r[   r\   s     r   r_   z3LangChainVectorizer.aembed_many.<locals>.<listcomp>p  r`   r   )ra   r<   rF   rh   r   r    r@   rb   rc   s	   `        r   aembed_manyzLangChainVectorizer.aembed_manyO  s      ( -/]]5*jAA 	. 	.Et');<< #'#3#D#DU#K#KKKKKKK

 $+#4$4e$ $      
     '  
 !!*----r   )NF)NrV   F)r(   r)   r*   r+   rF   r   __annotations__model_configr-   r   r   r   r   boolr   r   r,   bytesr   rf   r!   rk   __classcell__)rN   s   @r   rE   rE      sI        % %P K-t4L<3 <c <S <T < < < < < <" *.	  X& 	
  
tE{E!	"   D *. Cy X& 	
   
tDK $u+-	.   H *.	! !! X&! 	!
 ! 
tE{E!	"! ! ! !L *.' 'Cy' X&' 	'
 ' ' 
tDK $u+-	.' ' ' ' ' ' ' 'r   rE   c                 "   |+dD ](}t          | |          rt          | |          }||} n)|?t          | dd          pt          | dd          }|rdddd}|                    |          }|t          d          t	          | |	          S )
a  Create a LangChainVectorizer from a LangChain Embeddings object.

    This is the recommended way to use LangChain embeddings with SemanticCache
    and SemanticCacheMiddleware. The returned vectorizer is fully compatible
    with redisvl's BaseVectorizer interface.

    Args:
        embeddings: A LangChain Embeddings object (e.g., OpenAIEmbeddings,
            AzureOpenAIEmbeddings, HuggingFaceEmbeddings).
        dims: The embedding dimensions. If not provided, will attempt to
            infer from the embeddings object or known model dimensions.

    Returns:
        A LangChainVectorizer wrapping the embeddings.

    Raises:
        ValueError: If dimensions cannot be determined.

    Example:
        ```python
        from langchain_openai import OpenAIEmbeddings
        from langgraph.middleware.redis import create_langchain_vectorizer

        embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
        vectorizer = create_langchain_vectorizer(embeddings, dims=1536)
        ```
    Nr2   r6   r7   r8   r9   r:   r;   )r0   r   )r<   r=   r>   r?   rE   )r0   r   rA   valr6   rB   s         r   create_langchain_vectorizerrs   y  s    > |H 	 	Dz4(( j$//?DE |
GT22 
gd7
 7
  	) +/*.*. J
 >>%((D|8
 
 	

 *4@@@@r   )N)r+   r   typingr   r   r   r   r   redisvl.utils.vectorize.baser   r
   r-   rC   rE   rs   r/   r   r   <module>rv      sH  	 	  7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7` ` ` ` ` ` ` `H /39 9 99&sm99 9 9 9xE E E E E. E E ER ,0<A <A<A#C=<A<A <A <A <A <A <Ar   