U
    hcP                     @   sV  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mZmZ d dlmZ d dlmZ d dlmZmZ d dlmZmZmZmZ d d	lmZmZ d
ZG dd deZG dd de eZ!G dd dZ"G dd de"Z#G dd de#Z$G dd de"Z%G dd de"Z&G dd de"Z'G dd de'Z(G dd deZ)G dd  d ee)Z*dS )!    N)abstractmethod)Enum)AnyDictListMappingOptional)CallbackManagerForLLMRun)BaseLLM)
Generation	LLMResult)	BaseModel	SecretStrroot_validator	validator)convert_to_secret_strget_from_dict_or_env2   c                   @   sF   e Zd ZdZdefeeeeddddZd
ee	e
 eeddd	ZdS )AzureMLEndpointClientz AzureML Managed Endpoint client. N)endpoint_urlendpoint_api_keydeployment_nametimeoutreturnc                 C   s,   |r|st d|| _|| _|| _|| _dS )zInitialize the class.zXA key/token and REST endpoint should 
                be provided to invoke the endpointN)
ValueErrorr   r   r   r   )selfr   r   r   r    r   M/tmp/pip-unpacked-wheel-9gdii04g/langchain_community/llms/azureml_endpoint.py__init__   s    zAzureMLEndpointClient.__init__)bodyrun_managerkwargsr   c                 K   s\   dd| j  d}| jdkr$| j|d< tj| j||}tjj||d| jd}|	 }|S )zcall.application/jsonzBearer )zContent-TypeAuthorizationr   zazureml-model-deploymentr   )r   )
r   r   urllibrequestRequestr   urlopengetr   read)r   r    r!   r"   headersreqresponseresultr   r   r   call&   s    

 zAzureMLEndpointClient.call)N)__name__
__module____qualname____doc__DEFAULT_TIMEOUTstrintr   bytesr   r	   r   r/   r   r   r   r   r      s"    r   c                   @   s   e Zd ZdZdZdZdZdS )AzureMLEndpointApiTypezAzure ML endpoints API types. Use `dedicated` for models deployed in hosted
    infrastructure (also known as Online Endpoints in Azure Machine Learning),
    or `serverless` for models deployed as a service with a
    pay-as-you-go billing or PTU.
    	dedicatedrealtime
serverlessN)r0   r1   r2   r3   r9   r:   r;   r   r   r   r   r8   @   s   r8   c                   @   s   e Zd ZU dZdZee ed< dZee ed< dZ	eed< e
eeddd	Zeee d
ddZejfeeeedddZeejfeeedddZdS )ContentFormatterBasezZTransform request and response of AzureML endpoint to match with
    required schema.
    r#   content_typeacceptszError while formatting response payload for chat model of type  `{api_type}`. Are you using the right formatter for the deployed  model and endpoint type?format_error_msg)promptr   c                 C   s6   dddddddd}|  D ]\}}| ||} q| S )	z*Escapes any special characters in `prompt`z\\z\"z\bz\fz\nz\rz\t)\"
	)itemsreplace)r@   Z
escape_mapZescape_sequenceZescaped_sequencer   r   r   escape_special_charactersy   s    z.ContentFormatterBase.escape_special_charactersr   c                 C   s   t jgS )zSupported APIs for the given formatter. Azure ML supports
        deploying models using different hosting methods. Each method may have
        a different API structure.r8   r9   r   r   r   r   supported_api_types   s    z(ContentFormatterBase.supported_api_typesr@   model_kwargsapi_typer   c                 C   s
   t  dS )zFormats the request body according to the input schema of
        the model. Returns bytes or seekable file like object in the
        format specified in the content_type request header.
        N)NotImplementedError)r   r@   rP   rQ   r   r   r   format_request_payload   s    
z+ContentFormatterBase.format_request_payloadoutputrQ   r   c                 C   s   dS )zFormats the response body according to the output
        schema of the model. Returns the data type that is
        received from the response.
        Nr   )r   rU   rQ   r   r   r   format_response_payload   s    z,ContentFormatterBase.format_response_payloadN)r0   r1   r2   r3   r=   r   r5   __annotations__r>   r?   staticmethodrJ   propertyr   r8   rN   r9   r   r   rS   r   r7   r   rV   r   r   r   r   r<   L   s.   
 
r<   c                   @   sL   e Zd ZdZeee dddZee	ee
dddZe
eedd	d
ZdS )GPT2ContentFormatterzContent handler for GPT2rK   c                 C   s   t jgS NrL   rM   r   r   r   rN      s    z(GPT2ContentFormatter.supported_api_typesrO   c                 C   s2   t |}tdd| dgi|d}t|S )Ninput_stringrB   inputs
parametersr<   rJ   jsondumpsr5   encoder   r@   rP   rQ   request_payloadr   r   r   rS      s
    
z+GPT2ContentFormatter.format_request_payloadrT   c              
   C   s^   zt |d d }W n< tttfk
rR } zt| jj|d|W 5 d }~X Y nX t|dS )Nr   0rQ   text	ra   loadsKeyError
IndexError	TypeErrorr   r?   formatr   r   rU   rQ   choiceer   r   r   rV      s
    &z,GPT2ContentFormatter.format_response_payloadNr0   r1   r2   r3   rY   r   r8   rN   r5   r   r7   rS   r   rV   r   r   r   r   rZ      s     
 rZ   c                       s4   e Zd ZU dZdZeed< dd fddZ  ZS )OSSContentFormatterz`Deprecated: Kept for backwards compatibility

    Content handler for LLMs from the OSS catalog.Ncontent_formatterrK   c                    s   t    td d S )Nz`OSSContentFormatter` will be deprecated in the future. 
                      Please use `GPT2ContentFormatter` instead.  
                      superr   warningswarnrM   	__class__r   r   r      s    
zOSSContentFormatter.__init__	r0   r1   r2   r3   ru   r   rW   r   __classcell__r   r   rz   r   rt      s   
rt   c                   @   sL   e Zd ZdZeee dddZee	ee
dddZe
eedd	d
ZdS )HFContentFormatterz6Content handler for LLMs from the HuggingFace catalog.rK   c                 C   s   t jgS r[   rL   rM   r   r   r   rN      s    z&HFContentFormatter.supported_api_typesrO   c                 C   s.   t | td| dg|d}t|S )NrB   r]   r`   rd   r   r   r   rS      s
    
z)HFContentFormatter.format_request_payloadrT   c              
   C   sb   zt |d d d }W n< tttfk
rV } zt| jj|d|W 5 d }~X Y nX t|dS )Nr   rf   generated_textrg   rh   rj   rp   r   r   r   rV      s
    &z*HFContentFormatter.format_response_payloadNrs   r   r   r   r   r~      s     
 r~   c                   @   sL   e Zd ZdZeee dddZee	ee
dddZe
eedd	d
ZdS )DollyContentFormatterz*Content handler for the Dolly-v2-12b modelrK   c                 C   s   t jgS r[   rL   rM   r   r   r   rN      s    z)DollyContentFormatter.supported_api_typesrO   c                 C   s2   t |}tdd| dgi|d}t|S )Nr\   rB   )
input_datar_   r`   rd   r   r   r   rS      s    
z,DollyContentFormatter.format_request_payloadrT   c              
   C   sZ   zt |d }W n< tttfk
rN } zt| jj|d|W 5 d }~X Y nX t|dS )Nr   rg   rh   rj   rp   r   r   r   rV     s
    &z-DollyContentFormatter.format_response_payloadNrs   r   r   r   r   r      s      r   c                   @   sL   e Zd ZdZeee dddZee	ee
dddZe
eedd	d
ZdS )CustomOpenAIContentFormatterzAContent formatter for models that use the OpenAI like API scheme.rK   c                 C   s   t jt jgS r[   )r8   r9   r;   rM   r   r   r   rN     s    z0CustomOpenAIContentFormatter.supported_api_typesrO   c                 C   sr   t |}|tjtjfkr:tdd| dg|di}n.|tjkrXtd|i|}ntd| dt	
|S )z/Formats the request according to the chosen apir   rB   )r\   r_   r@   `api_type` # is not supported by this formatter)r<   rJ   r8   r9   r:   ra   rb   r;   r   r5   rc   rd   r   r   r   rS     s$    


z3CustomOpenAIContentFormatter.format_request_payloadrT   c              
   C   s  |t jt jfkrnzt|d d }W n< tttfk
rb } zt| j	j
|d|W 5 d}~X Y nX t|dS |t jkrz(t|d d }t|tstdW n< tttfk
r } zt| j	j
|d|W 5 d}~X Y nX t|d  t|d	|d
ddS td| ddS )zFormats responser   rf   rg   Nrh   choicesziEndpoint response is not well formed for a chat model. Expected `dict` but `{type(choice)}` was received.ri   finish_reasonlogprobs)r   r   )ri   Zgeneration_infor   r   )r8   r9   r:   ra   rk   rl   rm   rn   r   r?   ro   r   r;   
isinstancedictstripr)   rp   r   r   r   rV   -  s4    &

&
z4CustomOpenAIContentFormatter.format_response_payloadNrs   r   r   r   r   r     s      r   c                       s4   e Zd ZU dZdZeed< dd fddZ  ZS )LlamaContentFormatterzNDeprecated: Kept for backwards compatibility

    Content formatter for Llama.Nru   rK   c                    s   t    td d S )Nz`LlamaContentFormatter` will be deprecated in the future. 
                Please use `CustomOpenAIContentFormatter` instead.  
            rv   rM   rz   r   r   r   V  s    
zLlamaContentFormatter.__init__r|   r   r   rz   r   r   O  s   
r   c                   @   s  e Zd ZU dZdZeed< ejZ	eed< e
dZeed< dZeed< eZeed< dZeed	< d
Zeed< dZeed< dZee ed< eddeedddZedeeedddZedeedddZedeeedddZed	ddeee dddZ!dS )AzureMLBaseEndpointz Azure ML Online Endpoint models.r   r   endpoint_api_typer   r   r   Nhttp_client   max_retriesru   rP   T)pre)valuesr   c                 C   sd   t t|dd|d< t|dd|d< t|ddd|d< t|dd	tj|d< t|d
dtt|d
< |S )Nr   ZAZUREML_ENDPOINT_API_KEYr   ZAZUREML_ENDPOINT_URLr   ZAZUREML_DEPLOYMENT_NAMEr   r   ZAZUREML_ENDPOINT_API_TYPEr   ZAZUREML_TIMEOUT)r   r   r8   r9   r5   r4   )clsr   r   r   r   validate_environ  s6    
     z$AzureMLBaseEndpoint.validate_environ)field_valuer   r   c                 C   s:   | d}||jkr6tdt| d|j d| d|S )z>Validate that content formatter is supported by endpoint type.r   zContent formatter fz8 is not supported by this endpoint. Supported types are z but endpoint is .)r)   rN   r   type)r   r   r   r   r   r   r   validate_content_formatter  s    

z.AzureMLBaseEndpoint.validate_content_formatter)r   r   c                 C   s,   | dr|dd }| dr(td|S )z'Validate that endpoint url is complete./Nzinference.ml.azure.comz`endpoint_url` should contain the full invocation URL including `/score` for `endpoint_api_type='dedicated'` or `/completions` or `/chat/completions` for `endpoint_api_type='serverless'`)endswithr   )r   r   r   r   r   validate_endpoint_url  s    

z)AzureMLBaseEndpoint.validate_endpoint_urlc                 C   sZ   | d}|tjks|tjkr0|ds0td|tjkrV|dsV|dsVtd|S )zBValidate that endpoint api type is compatible with the URL format.r   z/scorezEndpoints of type `dedicated` should follow the format `https://<your-endpoint>.<your_region>.inference.ml.azure.com/score`. If your endpoint URL ends with `/completions` or`/chat/completions`, use `endpoint_api_type='serverless'` instead.z/completionsz/chat/completionszEndpoints of type `serverless` should follow the format `https://<your-endpoint>.<your_region>.inference.ml.azure.com/chat/completions` or `https://<your-endpoint>.<your_region>.inference.ml.azure.com/chat/completions`)r)   r8   r9   r:   r   r   r;   )r   r   r   r   r   r   r   validate_endpoint_api_type  s&    

z.AzureMLBaseEndpoint.validate_endpoint_api_type)alwaysc                 C   s@   | d}| d}| d}| dt}t|| ||}|S )z?Validate that api key and python package exists in environment.r   r   r   r   )r)   r4   r   Zget_secret_value)r   r   r   r   Zendpoint_keyr   r   r   r   r   r   validate_client  s    


z#AzureMLBaseEndpoint.validate_client)"r0   r1   r2   r3   r   r5   rW   r8   r9   r   r   r   r   r   r4   r   r6   r   r   r   ru   rP   r   r   r   r   r   r   r<   r   r   r   r   r   r   r   r   r   r   _  s4   
  
r   c                   @   sd   e Zd ZdZeeeef dddZeedddZ	de
e ee
e  ee eedd	d
ZdS )AzureMLOnlineEndpointa  Azure ML Online Endpoint models.

    Example:
        .. code-block:: python
            azure_llm = AzureMLOnlineEndpoint(
                endpoint_url="https://<your-endpoint>.<your_region>.inference.ml.azure.com/score",
                endpoint_api_type=AzureMLApiType.dedicated,
                endpoint_api_key="my-api-key",
                timeout=120,
                content_formatter=content_formatter,
            )
    rK   c                 C   s   | j pi }d| jid|iS )zGet the identifying parameters.r   rP   )rP   r   )r   _model_kwargsr   r   r   _identifying_params  s    
z)AzureMLOnlineEndpoint._identifying_paramsc                 C   s   dS )zReturn type of llm.Zazureml_endpointr   rM   r   r   r   	_llm_type  s    zAzureMLOnlineEndpoint._llm_typeN)promptsstopr!   r"   r   c                 K   sv   | j pi }|| |r ||d< g }|D ]B}| j||| j}| jj||d}	| j|	| j}
||
g q(t	|dS )an  Run the LLM on the given prompts.

        Args:
            prompts: The prompt to pass into the model.
            stop: Optional list of stop words to use when generating.
        Returns:
            The string generated by the model.
        Example:
            .. code-block:: python
                response = azureml_model.invoke("Tell me a joke.")
        r   )r    r!   )generations)
rP   updateru   rS   r   r   r/   rV   appendr   )r   r   r   r!   r"   r   r   r@   re   Zresponse_payloadr   r   r   r   	_generate  s*    

    zAzureMLOnlineEndpoint._generate)NN)r0   r1   r2   r3   rY   r   r5   r   r   r   r   r   r	   r   r   r   r   r   r   r     s     
r   )+ra   urllib.requestr%   rx   abcr   enumr   typingr   r   r   r   r   Z langchain_core.callbacks.managerr	   Z#langchain_core.language_models.llmsr
   Zlangchain_core.outputsr   r   Zlangchain_core.pydantic_v1r   r   r   r   Zlangchain_core.utilsr   r   r4   objectr   r5   r8   r<   rZ   rt   r~   r   r   r   r   r   r   r   r   r   <module>   s.   /`B 	