o
    ZhfQ                     @   s  d dl Z d dlZd dlZd dlmZmZ d dlmZmZm	Z	m
Z
mZmZ d dlZd dlm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gZG d	d
 d
eeZde	eef defddZde	eef defddZde	eef defddZG dd deZ G dd deZ!defddZ"defddZ#defddZ$dede%fddZ&ded ee% defd!d"Z'd#edefd$d%Z(ed&d'd(d)G d*d deZ)dS )+    N)ABCabstractmethod)AnyCallableDictListMappingOptional)
deprecated)CallbackManagerForLLMRun)LLM)	BaseModel
ConfigDictFieldPrivateAttrmodel_validator
Databricksc                	   @   s   e Zd ZU dZeed< eed< dedededefdd	Zdedefd
dZdededefddZ	e
	ddedeedef  defddZedefddZdS )_DatabricksClientBasez0A base JSON API client that talks to Databricks.api_url	api_tokenmethodurlrequestreturnc                 C   sH   dd| j  i}tj||||d}|js td|j d|j | S )NAuthorizationzBearer )r   r   headersjsonzHTTP z error: )r   requestsr   ok
ValueErrorstatus_codetextr   )selfr   r   r   r   response r$   Z/var/www/html/lang_env/lib/python3.10/site-packages/langchain_community/llms/databricks.pyr      s   z_DatabricksClientBase.requestc                 C   s   |  d|d S )NGETr   )r"   r   r$   r$   r%   _get&      z_DatabricksClientBase._getc                 C   s   |  d||S )NPOSTr'   )r"   r   r   r$   r$   r%   _post)   r)   z_DatabricksClientBase._postNtransform_output_fn.c                 C   s   d S Nr$   )r"   r   r,   r$   r$   r%   post,      z_DatabricksClientBase.postc                 C      dS )NFr$   r"   r$   r$   r%   llm1   s   z_DatabricksClientBase.llmr-   )__name__
__module____qualname____doc__str__annotations__r   r   r(   r+   r   r	   r   r.   propertyboolr2   r$   r$   r$   r%   r      s$   
 
r   r#   r   c                 C      | d d d S )Nchoicesr   r!   r$   r#   r$   r$   r%   _transform_completions6      r>   c                 C   r;   )N
candidatesr   r!   r$   r=   r$   r$   r%   _transform_llama2_chat:   r?   rA   c                 C   s   | d d d d S )Nr<   r   messagecontentr$   r=   r$   r$   r%   _transform_chat>   s   rD   c                       s   e Zd ZU dZeed< eed< eed< dZeed< dZe	ed< dZ
ee ed	< d
ef fddZede	fddZeddedeeef defddZ	ddedeedef  defddZ  ZS ) _DatabricksServingEndpointClientz:An API client that talks to a Databricks serving endpoint.hostendpoint_namedatabricks_uriNclientFexternal_or_foundationtaskdatac              
      s   t  jdi | zddlm} || j| _W n ty( } ztd|d }~ww | j| j}|	dd
 dv | _| jd u rH|	d| _d S d S )	Nr   )get_deploy_clientzMFailed to create the client. Please install mlflow with `pip install mlflow`.Zendpoint_type )Zexternal_modelZfoundation_model_apirK   r$   )super__init__Zmlflow.deploymentsrM   rH   rI   ImportErrorZget_endpointrG   getlowerrJ   rK   )r"   rL   rM   eendpoint	__class__r$   r%   rP   L   s"   
z)_DatabricksServingEndpointClient.__init__r   c                 C   s
   | j dv S )N)llm/v1/chatllm/v1/completionsllama2/chat)rK   r1   r$   r$   r%   r2   a   s   
z$_DatabricksServingEndpointClient.llmbeforemodevaluesc                 C   s6   d|vr|d }|d }d| d| d}||d< |S )Nr   rF   rG   https://z/serving-endpoints/z/invocationsr$   )clsr^   rF   rG   r   r$   r$   r%   set_api_urle   s   z,_DatabricksServingEndpointClient.set_api_urlr   r,   .c                 C   s   | j r&| jj| j|d}|r||S | jdkrt|S | jdkr$t|S |S d|gi}| jj| j|d}|d }t|trA|d n|}| jdkrLt	|S |rR||S |S )N)rU   ZinputsrX   rY   Zdataframe_recordsZpredictionsr   rZ   )
rJ   rI   ZpredictrG   rK   rD   r>   
isinstancelistrA   )r"   r   r,   respZwrapped_requestr#   predspredr$   r$   r%   r.   o   s$   



z%_DatabricksServingEndpointClient.postr-   )r3   r4   r5   r6   r7   r8   rI   r   rJ   r:   rK   r	   rP   r9   r2   r   classmethodr   ra   r   r.   __classcell__r$   r$   rV   r%   rE   B   s,   
 	rE   c                   @   sx   e Zd ZU dZeed< eed< eed< eddedeee	f de	fd	d
Z
	dde	deedef  de	fddZdS )#_DatabricksClusterDriverProxyClientzBAn API client that talks to a Databricks cluster driver proxy app.rF   
cluster_idcluster_driver_portr[   r\   r^   r   c                 C   sB   d|vr|d }|d }|d }d| d| d| }||d< |S )Nr   rF   rj   rk   r_   z/driver-proxy-api/o/0//r$   )r`   r^   rF   rj   portr   r$   r$   r%   ra      s   z/_DatabricksClusterDriverProxyClient.set_api_urlNr   r,   .c                 C   s   |  | j|}|r||S |S r-   )r+   r   )r"   r   r,   rd   r$   r$   r%   r.      s   z(_DatabricksClusterDriverProxyClient.postr-   )r3   r4   r5   r6   r7   r8   r   rg   r   r   ra   r	   r   r.   r$   r$   r$   r%   ri      s    
 
ri   c                  C   s,   z
ddl m}  |  W S  ty   tdw )zgGet the notebook REPL context if running inside a Databricks notebook.
    Returns None otherwise.
    r   get_contextzBCannot access dbruntime, not running inside a Databricks notebook.)Z!dbruntime.databricks_repl_contextro   rQ   rn   r$   r$   r%   get_repl_context   s   rp   c               
   C   sh   t d} | s'zt j} | stdW n ty& } ztd| d}~ww | ddd} | S )z{Get the default Databricks workspace hostname.
    Raises an error if the hostname cannot be automatically determined.
    ZDATABRICKS_HOSTz(context doesn't contain browserHostName.zshost was not set and cannot be automatically inferred. Set environment variable 'DATABRICKS_HOST'. Received error: Nr_   zhttp://rl   )osgetenvrp   ZbrowserHostNamer   	Exceptionlstriprstrip)rF   rT   r$   r$   r%   get_default_host   s"   
rv   c               
   C   sT   t d } r	| S zt j} | stdW | S  ty) } ztd| d}~ww )z{Get the default Databricks personal access token.
    Raises an error if the token cannot be automatically determined.
    ZDATABRICKS_TOKENz!context doesn't contain apiToken.zyapi_token was not set and cannot be automatically inferred. Set environment variable 'DATABRICKS_TOKEN'. Received error: N)rq   rr   rp   ZapiTokenr   rs   )r   rT   r$   r$   r%   get_default_api_token   s    rw   rL   c                 C   s"   t | tsdS d}tt|| S )zJChecks if a data is a valid hexadecimal string using a regular expression.Fz^[0-9a-fA-F]+$)rb   r7   r:   rematch)rL   patternr$   r$   r%   _is_hex_string   s   
r{   allow_dangerous_deserializationc              
   C   sz   |st dzddl}W n ty } zt d| d}~ww z	|t| W S  ty< } zt d| d}~ww )z3Loads a pickled function from a hexadecimal string.aW  This code relies on the pickle module. You will need to set allow_dangerous_deserialization=True if you want to opt-in to allow deserialization of data using pickle.Data can be compromised by a malicious actor if not handled properly to include a malicious payload that when deserialized with pickle can execute arbitrary code on your machine.r   N*Please install cloudpickle>=2.0.0. Error: zFFailed to load the pickled function from a hexadecimal string. Error: )r   cloudpicklers   loadsbytesfromhex)rL   r|   r~   rT   r$   r$   r%    _load_pickled_fn_from_hex_string   s$   
r   fnc              
   C   sl   zddl }W n ty } ztd| d}~ww z||  W S  ty5 } ztd| d}~ww )z6Pickles a function and returns the hexadecimal string.r   Nr}   zFailed to pickle the function: )r~   rs   r   dumpshex)r   r~   rT   r$   r$   r%   _pickle_fn_to_hex_string   s   r   z0.3.3z1.0z#databricks_langchain.ChatDatabricks)ZsinceZremovalZalternative_importc                       s*  e Zd ZU dZeedZeed< 	 ee	dZ
eed< 	 dZee ed< 	 dZee ed< 	 dZee ed< 	 dZeeeef  ed	< 	 dZee ed
< 	 dZeedef  ed< 	 dZeed< 	 dZeed< 	 dZeed< 	 dZeee  ed< 	 dZee ed< 	 eedZeeef ed< 	 dZee ed< 	 dZ e!ed< 	 e" Z#e$ed< e%ddZ&e'deeef fddZ(e)dd e*d!eeef defd"d#Z+d$ef fd%d&Z,e'deeef fd'd(Z-e'de.eef fd)d*Z/e'defd+d,Z0		d2d-edeee  d.ee1 d/edef
d0d1Z2  Z3S )3r   a	  Databricks serving endpoint or a cluster driver proxy app for LLM.

    It supports two endpoint types:

    * **Serving endpoint** (recommended for both production and development).
      We assume that an LLM was deployed to a serving endpoint.
      To wrap it as an LLM you must have "Can Query" permission to the endpoint.
      Set ``endpoint_name`` accordingly and do not set ``cluster_id`` and
      ``cluster_driver_port``.

      If the underlying model is a model registered by MLflow, the expected model
      signature is:

      * inputs::

          [{"name": "prompt", "type": "string"},
           {"name": "stop", "type": "list[string]"}]

      * outputs: ``[{"type": "string"}]``

      If the underlying model is an external or foundation model, the response from the
      endpoint is automatically transformed to the expected format unless
      ``transform_output_fn`` is provided.

    * **Cluster driver proxy app** (recommended for interactive development).
      One can load an LLM on a Databricks interactive cluster and start a local HTTP
      server on the driver node to serve the model at ``/`` using HTTP POST method
      with JSON input/output.
      Please use a port number between ``[3000, 8000]`` and let the server listen to
      the driver IP address or simply ``0.0.0.0`` instead of localhost only.
      To wrap it as an LLM you must have "Can Attach To" permission to the cluster.
      Set ``cluster_id`` and ``cluster_driver_port`` and do not set ``endpoint_name``.
      The expected server schema (using JSON schema) is:

      * inputs::

          {"type": "object",
           "properties": {
              "prompt": {"type": "string"},
              "stop": {"type": "array", "items": {"type": "string"}}},
           "required": ["prompt"]}`

      * outputs: ``{"type": "string"}``

    If the endpoint model signature is different or you want to set extra params,
    you can use `transform_input_fn` and `transform_output_fn` to apply necessary
    transformations before and after the query.
    )default_factoryrF   r   NrG   rj   rk   model_kwargstransform_input_fn.r,   
databricksrH   g        temperature   nstop
max_tokensextra_paramsrK   Fr|   _clientZforbid)extrar   c                 C   s6   | j | jd}| jr| j|d< | jd ur| j|d< |S )N)r   r   r   r   )r   r   r   r   )r"   paramsr$   r$   r%   _llm_params  s   


zDatabricks._llm_paramsr[   r\   r^   c              
   C   s  | d}| d}|r|rtd|rd |d< n%|rn"zt j }r'||d< td ty= } ztd| d }~ww | d}|rK|rKtd|rRd |d< n|d u rZtdt|d	krgtd
| 	 | d }rd|vswJ dd|vsJ d|S )Nrj   rG   z-Cannot set both endpoint_name and cluster_id.z"Context doesn't contain clusterId.zuNeither endpoint_name nor cluster_id was set. And the cluster_id cannot be automatically determined. Received error: rk   z6Cannot set both endpoint_name and cluster_driver_port.z<Must set cluster_driver_port to connect to a cluster driver.r   zInvalid cluster_driver_port: r   promptz*model_kwargs must not contain key 'prompt'r   z(model_kwargs must not contain key 'stop')rR   r   rp   Z	clusterIdrs   int)r`   r^   rj   rG   Zcontext_cluster_idrT   rk   r   r$   r$   r%   set_cluster_id  sP   






zDatabricks.set_cluster_idrL   c                    s   d|v rt |d rt|d |dd|d< d|v r.t |d r.t|d |dd|d< t jd
i | | jd urE| jd urEtd| jd urPt	dt
 | jrdt| j| j| j| j| jd| _d S | jry| jryt| j| j| j| jd| _d S td	)Nr   r|   )rL   r|   r,   z.Cannot set both extra_params and extra_params.z<model_kwargs is deprecated. Please use extra_params instead.)rF   r   rG   rH   rK   )rF   r   rj   rk   zDMust specify either endpoint_name or cluster_id/cluster_driver_port.r$   )r{   r   rR   rO   rP   r   r   r   warningswarnDeprecationWarningrG   rE   rF   r   rH   rK   r   rj   rk   ri   )r"   rL   rV   r$   r%   rP     sT   



zDatabricks.__init__c                 C   sf   | j | j| j| j| j| j| j| j| j| j	| j
| j| jdu rdnt| j| jdu r,ddS t| jdS )zReturn default params.N)rF   rG   rj   rk   rH   r   r   r   r   r   r   rK   r   r,   )rF   rG   rj   rk   rH   r   r   r   r   r   r   rK   r   r   r,   r1   r$   r$   r%   _default_params  s(   

zDatabricks._default_paramsc                 C   s   | j S r-   )r   r1   r$   r$   r%   _identifying_params  s   zDatabricks._identifying_paramsc                 C   r0   )zReturn type of llm.r   r$   r1   r$   r$   r%   	_llm_type  r/   zDatabricks._llm_typer   run_managerkwargsc                 K   sl   d|i}| j jr|| j || jp| j || |r"||d< | jr-| jdi |}| j j|| jdS )zAQueries the LLM endpoint with the given prompt and stop sequence.r   r   )r,   Nr$   )	r   r2   updater   r   r   r   r.   r,   )r"   r   r   r   r   r   r$   r$   r%   _call$  s   
zDatabricks._call)NN)4r3   r4   r5   r6   r   rv   rF   r7   r8   rw   r   rG   r	   rj   rk   r   r   r   r   r   r,   rH   r   floatr   r   r   r   r   dictr   rK   r|   r:   r   r   r   r   Zmodel_configr9   r   r   rg   r   rP   r   r   r   r   r   r   rh   r$   r$   rV   r%   r   
  s~   
 1		,.
)*rq   rx   r   abcr   r   typingr   r   r   r   r   r	   r   Zlangchain_core._apir
   Zlangchain_core.callbacksr   Zlangchain_core.language_modelsr   Zpydanticr   r   r   r   r   __all__r   r7   r>   rA   rD   rE   ri   rp   rv   rw   r:   r{   r   r   r   r$   r$   r$   r%   <module>   sF      I
