o
    Zh'                     @   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dedefddZdee deee  fddZdee deee  fddZdedee fddZdedee f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   ^/var/www/html/lang_env/lib/python3.10/site-packages/langchain_community/embeddings/infinity.pyvalidate_environment3   s   
z'InfinityEmbeddings.validate_environmenttextsc                 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textc                 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                
   @   sP  e Zd ZdZ		d dedeej ddfddZe	e
fd	ee d
edeee ef fddZd	ee deee  fddZe	deee  dee fddZded	ee deeef fddZdedee deee  fddZded	ee deee  fddZdejdeeef deee  fddZded	ee deee  f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/v1Nr   
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   r2   len
ValueError_batch_size)r!   r   r2   r   r   r   __init__   s
   
z/TinyAsyncOpenAIInfinityEmbeddingClient.__init__r   sorterc                    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>   s    zATinyAsyncOpenAIInfinityEmbeddingClient._permute.<locals>.<lambda>c                    s   g | ]} | qS r   r   ).0Zsen)r9   r   r   
<listcomp>   s    zCTinyAsyncOpenAIInfinityEmbeddingClient._permute.<locals>.<listcomp>c                       g | ]} | qS r   r   r=   idx)r   r   r   r>          c                    s    fddt D S )Nc                    r?   r   r   r@   Zunsorted_embeddingsr   r   r>      s    zUTinyAsyncOpenAIInfinityEmbeddingClient._permute.<locals>.<lambda>.<locals>.<listcomp>)npargsortrC   )length_sorted_idxrC   r   r<      s   
 )r5   rD   rE   )r   r9   Ztexts_sortedr   )rF   r9   r   r   _permute   s
   z/TinyAsyncOpenAIInfinityEmbeddingClient._permutec                 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   )r5   ranger7   append)r!   r   Zbatchesstart_indexr   r   r   _batch   s   z-TinyAsyncOpenAIInfinityEmbeddingClient._batchbatch_of_textsc                 C   s@   t | dkrt | d dkr| d S g }| D ]}|| q|S )Nr:   r   )r5   extend)rL   r   Zsublistr   r   r   _unbatch   s   z/TinyAsyncOpenAIInfinityEmbeddingClient._unbatchr   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batch_textsc                 C   sR   t jd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      g | ]}|d  qS 	embeddingr   r=   er   r   r   r>      rB   zNTinyAsyncOpenAIInfinityEmbeddingClient._sync_request_embed.<locals>.<listcomp>datar   )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r$tt| }ntd}t|j| }W d   n1 s:w   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   rd   r5   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kwargsc              	      s   |j di |4 I d H ,}|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?w   Y  d S )NrV   rW   rX   r^   c                 S   rY   rZ   r   r\   r   r   r   r>   %  rB   zITinyAsyncOpenAIInfinityEmbeddingClient._async_request.<locals>.<listcomp>r   )r`   statusrb   r&   rR   )r!   rn   ro   rc   r[   r   r   r   _async_request  s   
0z5TinyAsyncOpenAIInfinityEmbeddingClient._async_requestc           	   	      s    |\}}|}tjdtjddd4 I dH tj fdd|D  I dH }W d  I dH  n1 I dH s>w   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
        Tre   )limit)	trust_envZ	connectorNc                    s$   g | ]}j j |d dqS )r   )rn   ro   )rq   rT   )r=   r;   r   r!   rn   r   r   r>   9  s    zATinyAsyncOpenAIInfinityEmbeddingClient.aembed.<locals>.<listcomp>)rG   rK   aiohttpClientSessionZTCPConnectorasynciogatherrN   )	r!   r   r   rh   ri   rj   rk   rm   r"   r   rt   r   r$   '  s    

(
z-TinyAsyncOpenAIInfinityEmbeddingClient.aembed)r1   N)r)   r*   r+   r,   r-   r   ru   rv   r8   staticmethodr5   r   r   r   rG   rK   r   rN   r   rT   r0   rd   r   rq   r$   r   r   r   r   r   w   sP    
! "	

"


&r   )r,   rw   concurrent.futuresr   typingr   r   r   r   r   r   ru   numpyrD   r_   Zlangchain_core.embeddingsr	   Zlangchain_core.utilsr
   Zpydanticr   r   r   __all__r   r   r   r   r   r   <module>   s     f