a
    bg'                     @   s   d Z ddlZddlmZ ddlmZmZmZmZm	Z	m
Z
 ddlZddlZddlZddlmZ ddlmZ ddlmZmZmZ dgZG d	d deeZG d
d dZdS )z-written under MIT Licence, Michael Feil 2023.    N)ThreadPoolExecutor)AnyCallableDictListOptionalTuple)
Embeddings)get_from_dict_or_env)	BaseModel
ConfigDictmodel_validatorInfinityEmbeddingsc                   @   s   e Zd ZU dZeed< dZeed< dZeed< e	ddZ
ed	d
eeedddZee eee  dddZee eee  dddZeee dddZeee dddZdS )r   aB  Self-hosted embedding models for `infinity` package.

    See https://github.com/michaelfeil/infinity
    This also works for text-embeddings-inference and other
    self-hosted openai-compatible servers.

    Infinity is a package to interact with Embedding Models on https://github.com/michaelfeil/infinity


    Example:
        .. code-block:: python

            from langchain_community.embeddings import InfinityEmbeddings
            InfinityEmbeddings(
                model="BAAI/bge-small",
                infinity_api_url="http://localhost:7997",
            )
    modelzhttp://localhost:7997infinity_api_urlNclientZforbid)extrabefore)mode)valuesreturnc                 C   s&   t |dd|d< t|d d|d< |S )z?Validate that api key and python package exists in environment.r   ZINFINITY_API_URL)hostr   )r
   &TinyAsyncOpenAIInfinityEmbeddingClient)clsr    r   u/var/www/html/cobodadashboardai.evdpl.com/venv/lib/python3.9/site-packages/langchain_community/embeddings/infinity.pyvalidate_environment3   s    
z'InfinityEmbeddings.validate_environmenttextsr   c                 C   s   | j j| j|d}|S )zCall out to Infinity's embedding endpoint.

        Args:
            texts: The list of texts to embed.

        Returns:
            List of embeddings, one for each text.
        r   r   )r   embedr   selfr   
embeddingsr   r   r   embed_documentsA   s
    	z"InfinityEmbeddings.embed_documentsc                    s   | j j| j|dI dH }|S )zAsync call out to Infinity's embedding endpoint.

        Args:
            texts: The list of texts to embed.

        Returns:
            List of embeddings, one for each text.
        r   N)r   aembedr   r!   r   r   r   aembed_documentsP   s
    	z#InfinityEmbeddings.aembed_documents)textr   c                 C   s   |  |gd S )zCall out to Infinity's embedding endpoint.

        Args:
            text: The text to embed.

        Returns:
            Embeddings for the text.
        r   )r$   )r"   r'   r   r   r   embed_query_   s    	zInfinityEmbeddings.embed_queryc                    s   |  |gI dH }|d S )zAsync call out to Infinity's embedding endpoint.

        Args:
            text: The text to embed.

        Returns:
            Embeddings for the text.
        Nr   )r&   )r"   r'   r#   r   r   r   aembed_queryj   s    	zInfinityEmbeddings.aembed_query)__name__
__module____qualname____doc__str__annotations__r   r   r   r   Zmodel_configr   classmethodr   r   r   floatr$   r&   r(   r)   r   r   r   r   r      s   
c                   @   s,  e Zd ZdZdeeej ddddZe	e
fee eeee ef ddd	Zee eee  d
ddZe	eee  ee dddZeee eeef dddZeee eee  dddZeee eee  dddZejeeef eee  dddZeee eee  dddZdS )r   a
  Helper tool to embed Infinity.

    It is not a part of Langchain's stable API,
    direct use discouraged.

    Example:
        .. code-block:: python


            mini_client = TinyAsyncInfinityEmbeddingClient(
            )
            embeds = mini_client.embed(
                model="BAAI/bge-small",
                text=["doc1", "doc2"]
            )
            # or
            embeds = await mini_client.aembed(
                model="BAAI/bge-small",
                text=["doc1", "doc2"]
            )

    http://localhost:7797/v1N)r   
aiosessionr   c                 C   s6   || _ || _| j d u s$t| j dk r,tdd| _d S )N   z( param `host` must be set to a valid url   )r   r3   len
ValueError_batch_size)r"   r   r3   r   r   r   __init__   s
    z/TinyAsyncOpenAIInfinityEmbeddingClient.__init__)r   sorterr   c                    sR   t dkrdd fS tfddD  fdd D }| fddfS )a  Sort texts in ascending order, and
        delivers a lambda expr, which can sort a same length list
        https://github.com/UKPLab/sentence-transformers/blob/
        c5f93f70eca933c78695c5bc686ceda59651ae3b/sentence_transformers/SentenceTransformer.py#L156

        Args:
            texts (List[str]): _description_
            sorter (Callable, optional): _description_. Defaults to len.

        Returns:
            Tuple[List[str], Callable]: _description_

        Example:
            ```
            texts = ["one","three","four"]
            perm_texts, undo = self._permute(texts)
            texts == undo(perm_texts)
            ```
           c                 S   s   | S )Nr   )tr   r   r   <lambda>       zATinyAsyncOpenAIInfinityEmbeddingClient._permute.<locals>.<lambda>c                    s   g | ]} | qS r   r   ).0Zsen)r:   r   r   
<listcomp>   r>   zCTinyAsyncOpenAIInfinityEmbeddingClient._permute.<locals>.<listcomp>c                    s   g | ]} | qS r   r   r?   idx)r   r   r   r@      r>   c                    s    fddt D S )Nc                    s   g | ]} | qS r   r   rA   Zunsorted_embeddingsr   r   r@      s   zUTinyAsyncOpenAIInfinityEmbeddingClient._permute.<locals>.<lambda>.<locals>.<listcomp>)npargsortrC   )length_sorted_idxrC   r   r=      s   
)r6   rD   rE   )r   r:   Ztexts_sortedr   )rF   r:   r   r   _permute   s
    z/TinyAsyncOpenAIInfinityEmbeddingClient._permuter   c                 C   sJ   t |dkr|gS g }tdt || jD ]}||||| j   q(|S )aX  
        splits Lists of text parts into batches of size max `self._batch_size`
        When encoding vector database,

        Args:
            texts (List[str]): List of sentences
            self._batch_size (int, optional): max batch size of one request.

        Returns:
            List[List[str]]: Batches of List of sentences
        r;   r   )r6   ranger8   append)r"   r   Zbatchesstart_indexr   r   r   _batch   s    z-TinyAsyncOpenAIInfinityEmbeddingClient._batch)batch_of_textsr   c                 C   s@   t | dkr$t | d dkr$| d S g }| D ]}|| q,|S )Nr;   r   )r6   extend)rL   r   Zsublistr   r   r   _unbatch   s    z/TinyAsyncOpenAIInfinityEmbeddingClient._unbatch)r   r   r   c                 C   s"   t | j dddit ||ddS )zBuild the kwargs for the Post request, used by sync

        Args:
            model (str): _description_
            texts (List[str]): _description_

        Returns:
            Dict[str, Collection[str]]: _description_
        z/embeddingszcontent-typezapplication/json)inputr   )urlheadersjson)dictr   )r"   r   r   r   r   r   _kwargs_post_request   s    

z;TinyAsyncOpenAIInfinityEmbeddingClient._kwargs_post_request)r   batch_textsr   c                 C   sR   t jf i | j||d}|jdkr<td|j d|j dd | d D S )Nr      5Infinity returned an unexpected response with status : c                 S   s   g | ]}|d  qS 	embeddingr   r?   er   r   r   r@      r>   zNTinyAsyncOpenAIInfinityEmbeddingClient._sync_request_embed.<locals>.<listcomp>data)requestspostrT   status_code	Exceptionr'   rR   )r"   r   rU   responser   r   r   _sync_request_embed   s    
z:TinyAsyncOpenAIInfinityEmbeddingClient._sync_request_embedc                 C   s   |  |\}}| |}| j|gt| |f}t|dkrHtt| }n6td}t|j| }W d   n1 st0    Y  | |}	||	}
|
S )zcall the embedding of model

        Args:
            model (str): to embedding model
            texts (List[str]): List of sentences to embed.

        Returns:
            List[List[float]]: List of vectors for each sentence
        r;       N)rG   rK   rc   r6   listmapr   rN   )r"   r   r   
perm_textsunpermute_funcperm_texts_batchedZmap_argsembeddings_batch_permpembeddings_permr#   r   r   r   r       s    


,
z,TinyAsyncOpenAIInfinityEmbeddingClient.embed)sessionkwargsr   c              	      s   |j f i |4 I d H X}|jdkr<td|j d|j | I d H d }dd |D W  d   I d H  S 1 I d H s|0    Y  d S )NrV   rW   rX   r]   c                 S   s   g | ]}|d  qS rY   r   r[   r   r   r   r@   %  r>   zITinyAsyncOpenAIInfinityEmbeddingClient._async_request.<locals>.<listcomp>)r_   statusra   r'   rR   )r"   rm   rn   rb   rZ   r   r   r   _async_request  s    
z5TinyAsyncOpenAIInfinityEmbeddingClient._async_requestc           	   	      s    |\}}|}tjdtjddd4 I dH 8tj fdd|D  I dH }W d  I dH  q1 I dH sz0    Y  |}||}|S )zcall the embedding of model, async method

        Args:
            model (str): to embedding model
            texts (List[str]): List of sentences to embed.

        Returns:
            List[List[float]]: List of vectors for each sentence
        Trd   )limit)	trust_envZ	connectorNc                    s$   g | ]}j j |d dqS )r   )rm   rn   )rp   rT   )r?   r<   r   r"   rm   r   r   r@   9  s
   zATinyAsyncOpenAIInfinityEmbeddingClient.aembed.<locals>.<listcomp>)rG   rK   aiohttpClientSessionZTCPConnectorasynciogatherrN   )	r"   r   r   rg   rh   ri   rj   rl   r#   r   rs   r   r%   '  s    

4

z-TinyAsyncOpenAIInfinityEmbeddingClient.aembed)r2   N)r*   r+   r,   r-   r.   r   rt   ru   r9   staticmethodr6   r   r   r   rG   rK   r   rN   r   rT   r1   rc   r    rp   r%   r   r   r   r   r   w   s4     !	

r   )r-   rv   concurrent.futuresr   typingr   r   r   r   r   r   rt   numpyrD   r^   Zlangchain_core.embeddingsr	   Zlangchain_core.utilsr
   Zpydanticr   r   r   __all__r   r   r   r   r   r   <module>   s    f