U
    h/                     @  s  d dl mZ d dlZd dlZd dlmZmZmZmZm	Z	m
Z
mZmZmZmZ d dlmZ d dlmZmZmZ d dlmZmZmZ d dlmZmZmZmZmZmZ e e!Z"dd	d
ddZ#ddd
ddZ$dddddZ%ddddddZ&ddddddZ'G dd deeZ(dS )    )annotationsN)
AnyCallableDictListLiteralOptionalSequenceSetTupleUnion)
Embeddings)	BaseModelFieldroot_validator)get_from_dict_or_envget_pydantic_field_namespre_init)AsyncRetryingbefore_sleep_logretryretry_if_exception_typestop_after_attemptwait_exponentialLocalAIEmbeddingszCallable[[Any], Any])
embeddingsreturnc                 C  sr   dd l }d}d}tdt| jtd||dt|jjt|jjB t|jj	B t|jj
B t|jjB tttjdS )Nr      
   T   Z
multiplierminmaxreraisestopwaitr   Zbefore_sleep)openair   r   max_retriesr   r   errorTimeoutAPIErrorAPIConnectionErrorRateLimitErrorServiceUnavailableErrorr   loggerloggingWARNING)r   r'   min_secondsmax_seconds r4   J/tmp/pip-unpacked-wheel-9gdii04g/langchain_community/embeddings/localai.py_create_retry_decorator%   s$    





r6   r   c                   s   dd l }d}d}tdt| jtd||dt|jjt|jjB t|jj	B t|jj
B t|jjB tttjd ddd	 fd
d}|S )Nr   r   r   Tr   r    r#   r   )funcr   c                   s   dddd fdd}|S )Nr   r   )argskwargsr   c                    s2    2 z3 d H W }| |I d H   S 6 t dd S )Nzthis is unreachable)AssertionError)r8   r9   _)async_retryingr7   r4   r5   	wrapped_fQ   s    z7_async_retry_decorator.<locals>.wrap.<locals>.wrapped_fr4   )r7   r=   r<   )r7   r5   wrapP   s    z$_async_retry_decorator.<locals>.wrap)r'   r   r   r(   r   r   r)   r*   r+   r,   r-   r.   r   r/   r0   r1   )r   r'   r2   r3   r?   r4   r>   r5   _async_retry_decorator;   s(    





r@   dict)responser   c                 C  s.   t dd | d D r*dd l}|jd| S )Nc                 s  s   | ]}t |d  dkV  qdS )	embeddingr   N)len).0dr4   r4   r5   	<genexpr>]   s     z"_check_response.<locals>.<genexpr>datar   z'LocalAI API returned an empty embedding)anyr'   r)   r+   )rB   r'   r4   r4   r5   _check_response\   s    rJ   )r   r9   r   c                   s*   t  }|ddd fdd}|f |S ))Use tenacity to retry the embedding call.r   r9   r   c                    s    j jf | }t|S N)clientcreaterJ   r9   rB   r   r4   r5   _embed_with_retryh   s    z+embed_with_retry.<locals>._embed_with_retry)r6   )r   r9   Zretry_decoratorrR   r4   rQ   r5   embed_with_retryd   s    rS   c                   s,   t  ddd fdd}|f |I dH S )rK   r   rL   c                    s    j jf | I d H }t|S rM   )rN   ZacreaterJ   rP   rQ   r4   r5   _async_embed_with_retrys   s    z7async_embed_with_retry.<locals>._async_embed_with_retryN)r@   )r   r9   rT   r4   rQ   r5   async_embed_with_retryp   s    rU   c                   @  s  e Zd ZU dZded< dZded< eZded< dZd	ed
< dZd	ed< dZ	d	ed< dZ
ded< dZd	ed< dZd	ed< e Zded< dZded< dZded< dZded< dZded< dZded< dZded < eed!Zd"ed#< G d$d% d%Zed&d'd"d"d(d)d*Zed+d+d(d,d-Zed+d.d/d0Zddd1d2d3d4Zddd1d2d5d6Z dEd8d9d:d;d<d=Z!dFd8d9d:d;d>d?Z"dd1d@dAdBZ#dd1d@dCdDZ$dS )Gr   a  LocalAI embedding models.

    Since LocalAI and OpenAI have 1:1 compatibility between APIs, this class
    uses the ``openai`` Python package's ``openai.Embedding`` as its client.
    Thus, you should have the ``openai`` python package installed, and defeat
    the environment variable ``OPENAI_API_KEY`` by setting to a random string.
    You also need to specify ``OPENAI_API_BASE`` to point to your LocalAI
    service endpoint.

    Example:
        .. code-block:: python

            from langchain_community.embeddings import LocalAIEmbeddings
            openai = LocalAIEmbeddings(
                openai_api_key="random-string",
                openai_api_base="http://localhost:8080"
            )

    r   rN   ztext-embedding-ada-002strmodel
deploymentNzOptional[str]openai_api_versionopenai_api_baseopenai_proxyi  intembedding_ctx_lengthopenai_api_keyopenai_organizationzUnion[Literal['all'], Set[str]]allowed_specialallz.Union[Literal['all'], Set[str], Sequence[str]]disallowed_speciali  
chunk_size   r(   z+Optional[Union[float, Tuple[float, float]]]request_timeoutheadersFboolshow_progress_bar)default_factoryzDict[str, Any]model_kwargsc                   @  s   e Zd ZdZdS )zLocalAIEmbeddings.ConfigZforbidN)__name__
__module____qualname__extrar4   r4   r4   r5   Config   s   ro   T)pre)valuesr   c              
   C  s   t | }|di }t|D ]P}||kr8td| d||krtd| d| d| d ||||< q|| }|rtd| d	||d< |S )
z>Build extra kwargs from additional params that were passed in.rj   zFound z supplied twice.z	WARNING! z/ is not default parameter.
                    zJ was transferred to model_kwargs.
                    Please confirm that z is what you intended.zParameters za should be specified explicitly. Instead they were passed in as part of `model_kwargs` parameter.)	r   getlist
ValueErrorwarningswarnpopintersectionkeys)clsrq   Zall_required_field_namesrn   
field_nameZinvalid_model_kwargsr4   r4   r5   build_extra   s"    
zLocalAIEmbeddings.build_extrar   c                 C  s   t |dd|d< t |dddd|d< t |dddd|d< d}t |d	d
|d|d	< t |dddd|d< zddl}|j|d< W n tk
r   tdY nX |S )z?Validate that api key and python package exists in environment.r^   ZOPENAI_API_KEYrZ   ZOPENAI_API_BASE )defaultr[   ZOPENAI_PROXYrY   ZOPENAI_API_VERSIONr_   ZOPENAI_ORGANIZATIONr   NrN   zTCould not import openai python package. Please install it with `pip install openai`.)r   r'   Z	EmbeddingImportError)rz   rq   Zdefault_api_versionr'   r4   r4   r5   validate_environment   sL      




z&LocalAIEmbeddings.validate_environment)r   c                 C  sJ   | j | j| j| j| j| j| jd| j}| jrFdd l	}| j| jd|_
|S )N)rW   re   rf   Zapi_keyZorganizationZapi_baseapi_versionr   )httphttps)rW   re   rf   r^   r_   rZ   rY   rj   r[   r'   proxy)selfZopenai_argsr'   r4   r4   r5   _invocation_params   s     
z$LocalAIEmbeddings._invocation_paramszList[float])textenginer   c                C  s<   | j dr|dd}t| fd|gi| jd d d S ))Call out to LocalAI's embedding endpoint.001
 inputrH   r   rC   )rW   endswithreplacerS   r   r   r   r   r4   r4   r5   _embedding_func  s    z!LocalAIEmbeddings._embedding_funcc                  sB   | j dr|dd}t| fd|gi| jI dH d d d S )	r   r   r   r   r   NrH   r   rC   )rW   r   r   rU   r   r   r4   r4   r5   _aembedding_func  s    
z"LocalAIEmbeddings._aembedding_funcr   z	List[str]zOptional[int]zList[List[float]])textsrc   r   c                   s    fdd|D S )aN  Call out to LocalAI's embedding endpoint for embedding search docs.

        Args:
            texts: The list of texts to embed.
            chunk_size: The chunk size of embeddings. If None, will use the chunk size
                specified by the class.

        Returns:
            List of embeddings, one for each text.
        c                   s   g | ]} j | jd qS )r   r   rX   )rE   r   r   r4   r5   
<listcomp>0  s     z5LocalAIEmbeddings.embed_documents.<locals>.<listcomp>r4   )r   r   rc   r4   r   r5   embed_documents"  s    z!LocalAIEmbeddings.embed_documentsc                   s2   g }|D ]$}| j || jdI dH }|| q|S )aT  Call out to LocalAI's embedding endpoint async for embedding search docs.

        Args:
            texts: The list of texts to embed.
            chunk_size: The chunk size of embeddings. If None, will use the chunk size
                specified by the class.

        Returns:
            List of embeddings, one for each text.
        r   N)r   rX   append)r   r   rc   r   r   rB   r4   r4   r5   aembed_documents2  s
    z"LocalAIEmbeddings.aembed_documents)r   r   c                 C  s   | j || jd}|S )zCall out to LocalAI's embedding endpoint for embedding query text.

        Args:
            text: The text to embed.

        Returns:
            Embedding for the text.
        r   r   r   r   rC   r4   r4   r5   embed_queryE  s    	zLocalAIEmbeddings.embed_queryc                   s   | j || jdI dH }|S )zCall out to LocalAI's embedding endpoint async for embedding query text.

        Args:
            text: The text to embed.

        Returns:
            Embedding for the text.
        r   N)r   rX   r   r4   r4   r5   aembed_queryQ  s    	zLocalAIEmbeddings.aembed_query)r   )r   )%rk   rl   rm   __doc____annotations__rW   rX   rY   rZ   r[   r]   r^   r_   setr`   rb   rc   r(   re   rf   rh   r   rA   rj   ro   r   r|   r   r   propertyr   r   r   r   r   r   r   r4   r4   r4   r5   r   {   sB   
*  ))
__future__r   r0   ru   typingr   r   r   r   r   r   r	   r
   r   r   Zlangchain_core.embeddingsr   Zlangchain_core.pydantic_v1r   r   r   Zlangchain_core.utilsr   r   r   Ztenacityr   r   r   r   r   r   	getLoggerrk   r/   r6   r@   rJ   rS   rU   r   r4   r4   r4   r5   <module>   s   0 	
!