o
    ưik                     @   s|  d 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mZmZ ddlZddlmZ ddlmZ ddlmZm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dl#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z) ddl*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1 ddl2m3Z3 ddl4m5Z5 ddl6m7Z7m8Z8 de9e:ef ddfddZ;erddl<m=Z> e>Z?neZ?G dd de7e5e3Z@G dd deZAdS )zT
Translates from OpenAI's `/v1/chat/completions` to Databricks' `/chat/completions`
    N)TYPE_CHECKINGAnyAsyncIterator	CoroutineIteratorListLiteralOptionalTupleUnioncastoverload)	BaseModelRESPONSE_FORMAT_TOOL_NAME)#_handle_invalid_parallel_tool_calls&_should_convert_tool_call_to_json_mode)strip_name_from_message)BaseModelResponseIterator)AllAnthropicToolsValues)AllDatabricksContentValuesDatabricksChoiceDatabricksFunctionDatabricksResponseDatabricksTool)AllMessageValues#ChatCompletionRedactedThinkingBlockChatCompletionThinkingBlock%ChatCompletionToolChoiceFunctionParam#ChatCompletionToolChoiceObjectParamChatCompletionToolParam)ChatCompletionMessageToolCallChoicesMessageModelResponseModelResponseStreamProviderFieldUsage   )AnthropicConfig)OpenAILikeChatConfig   )DatabricksBaseDatabricksExceptionmessage_dictreturnc                 C   s   |  d}|du r| dd dS t|tr!| s| d dS t|trE|s/| d dS dd |D }|s?| d dS || d< dS dS )z
    Remove or filter content so empty text blocks are not sent.
    Databricks Model Serving uses Anthropic Messages API spec and rejects empty text blocks.
    contentNc                 S   s:   g | ]}t |tr|d dkr|dpd r|qS )typetext )
isinstancedictgetstrip).0block r:   b/home/app/Keep/.python/lib/python3.10/site-packages/litellm/llms/databricks/chat/transformation.py
<listcomp>P   s    z+_sanitize_empty_content.<locals>.<listcomp>)r6   popr4   strr7   list)r.   r0   filteredr:   r:   r;   _sanitize_empty_content?   s&   




	rA   )Loggingc                       s(  e Zd ZU dZdZe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 ef  ed< dZee ed< 						dRdee dee dee dee deeee ef  dee d	dfd
dZe fddZd	ee fddZ		dSdededee dededee dee d	efddZ	dTdee dee dedededee d	efddZdTdee d	efddZdee d	ee fdd Zded!ed	ee fd"d#Zded$ee ded%ed	ee f
d&d'Z 	dTdedee d!eed(  d	e!ee eed(  f fd)d*Z"	+dUd,ededed-ed.ed	ef fd/d0Z#ded	efd1d2Z$e%dee ded3e&d+ d	e'e(e(ee f fd4d5Z)e%	6dVdee ded3e&d6 d	ee fd7d5Z)	6dVdee ded3ed	eee e'e(e(ee f f f fd8d5Z)d9ed	efd:d;Z*e+d<ee, d	ee fd=d>Z-e+d<ee, d	e!ee eeee.e/f   f fd?d@Z0e+d<ee, d	eee(  fdAdBZ1	dTdCee2 dDee d	ee3 fdEdFZ4		dSdedGe5j6dHe7dIe8dJedee dededKe(dee dDee d	e7fdLdMZ9	6dVdNee:e e;e e7f dOedDee fdPdQZ<  Z=S )WDatabricksConfigzv
    Reference: https://docs.databricks.com/en/machine-learning/foundation-models/api-reference.html#chat-request
    N
max_tokenstemperaturetop_ptop_kstopnr/   c           
      C   s>   t   }| D ]\}}	|dkr|	d urt| j||	 q	d S )Nself)localscopyitemssetattr	__class__)
rJ   rD   rE   rF   rG   rH   rI   Zlocals_keyvaluer:   r:   r;   __init__s   s   
	zDatabricksConfig.__init__c                    s
   t   S N)super
get_config)clsrO   r:   r;   rU      s   
zDatabricksConfig.get_configc                 C   s    t dddddt dddddgS )	zDFor a given provider, return it's required fields with a descriptionapi_keystringzYour Databricks API Key.zdapi...)
field_nameZ
field_typeZfield_descriptionZfield_valueapi_basezYour Databricks API Base.zhttps://adb-..)r&   rJ   r:   r:   r;   get_required_params   s   z$DatabricksConfig.get_required_paramsheadersmodelmessagesoptional_paramslitellm_paramsrX   r[   c           	      C   s\   | dd p| dd p|dptdptd}| j||dd||d\}}d|d	< |S )
N
user_agentZdatabricks_user_agentZLITELLM_USER_AGENTZDATABRICKS_USER_AGENTZchat_completionsF)r[   rX   Zendpoint_typeZcustom_endpointr^   custom_user_agentzapplication/jsonzContent-Type)r=   r6   osgetenvZdatabricks_validate_environment)	rJ   r^   r_   r`   ra   rb   rX   r[   rd   r:   r:   r;   validate_environment   s&   

	z%DatabricksConfig.validate_environmentstreamc                 C   s   |  |}| d}|S )Nz/chat/completions)Z_get_api_base)rJ   r[   rX   r_   ra   rb   rh   Zcomplete_urlr:   r:   r;   get_complete_url   s   
	
z!DatabricksConfig.get_complete_urlc                 C   s   g dS )N)rh   rH   rE   rF   rD   max_completion_tokensrI   response_formattoolstool_choicereasoning_effortthinkingr:   )rJ   r_   r:   r:   r;   get_supported_openai_params   s   z,DatabricksConfig.get_supported_openai_paramstoolc                 C   s^   |d u rd S |d t t|dpi d}|d}|d ur)t tttf ||d< td|dS )NnameZinput_schema)rr   
parametersdescriptionfunctionr1   ru   )r   r5   r6   r   r>   r   )rJ   rq   Zfunction_paramsrt   r:   r:   r;   )convert_anthropic_tool_to_databricks_tool   s   
z:DatabricksConfig.convert_anthropic_tool_to_databricks_toolrl   c                    s2   d|vr|S  j |d\}} fdd|D }|S )Nclaude)rl   c                    s   g | ]
}t t |qS r:   )r   r   rw   )r8   rq   r\   r:   r;   r<          z=DatabricksConfig._map_openai_to_dbrx_tool.<locals>.<listcomp>)Z
_map_tools)rJ   r_   rl   Zanthropic_tools_Zdatabricks_toolsr:   r\   r;   _map_openai_to_dbrx_tool   s   

z)DatabricksConfig._map_openai_to_dbrx_toolrQ   is_thinking_enabledc                 C   s(   |d u rd S |  |||}| |}|S rS   )Z%map_response_format_to_anthropic_toolrw   )rJ   r_   rQ   ra   r|   rq   Zdatabricks_toolr:   r:   r;   &map_response_format_to_databricks_tool   s   
z7DatabricksConfig.map_response_format_to_databricks_toolr    c                 C   s   ||fS )z
        Override the parent class method to preserve cache_control for models on Databricks.
        Databricks supports Anthropic-style cache control for Claude models.
        Databricks ignores the cache_control flag with other models.
        r:   )rJ   r_   r`   rl   r:   r:   r;   1remove_cache_control_flag_from_messages_and_tools
  s   zBDatabricksConfig.remove_cache_control_flag_from_messages_and_toolsTnon_default_paramsdrop_params-replace_max_completion_tokens_with_max_tokensc           
         s  |  |}t ||||}d|v r| j||d d|d< d|v r/|r/|d |d< |dd  d|v rfd|v rf| ||d ||}|d ur`| j||gd d|d	< |s`td
tt	dd}	|	|d< |dd  d|v rd|v rt
j|d|d|d< |dd  | j||d |S )Nrl   )r_   rl   rj   rD   rk   rx   )ra   rl   T	json_moderu   )rr   rv   rm   rn   )rn   r_   ro   )r   ra   )r|   rT   map_openai_paramsr{   r=   r}   Z_add_tools_to_optional_paramsr   r   r   r)   Z_map_reasoning_effortr6   Z+update_optional_params_with_thinking_tokens)
rJ   r   ra   r_   r   r   r|   Zmapped_paramsZ_toolZ_tool_choicerW   r:   r;   r     s`   


z"DatabricksConfig.map_openai_paramsc                 C   s   | ddur	dS dS )zN
        Databricks doesn't support 'response_format' while streaming
        rk   NTF)r6   )rJ   ra   r:   r:   r;   _should_fake_streamX  s   z$DatabricksConfig._should_fake_streamis_asyncc                 C      d S rS   r:   rJ   r`   r_   r   r:   r:   r;   _transform_messagesa  s   z$DatabricksConfig._transform_messagesFc                 C   r   rS   r:   r   r:   r:   r;   r   g  s   c                    s   g }t |D ]:\}}t|tr|jdd}n|}t|dgd}d|v r0t|dtr0| |}tt	t
ttf | || q|rQt j||t	td ddS t j||t	td ddS )	zP
        Databricks does not support:
        - 'name' in user message.
        T)Zexclude_noneuser)Zallowed_name_rolescache_controlr0   )r`   r_   r   F)	enumerater4   r   Z
model_dumpr   r6   r>   -_move_cache_control_into_string_content_blockrA   r   r5   r   appendrT   r   r   )rJ   r`   r_   r   Znew_messagesidxmessage_messagerW   r:   r;   r   p  s"   

r   c                 C   sF   | d}ttttf | }|d}d||dg|d< tt|S )a  
        Moves message-level cache_control into a content block when content is a string.

        Transforms:
            {"role": "user", "content": "text", "cache_control": {...}}
        Into:
            {"role": "user", "content": [{"type": "text", "text": "text", "cache_control": {...}}]}

        This is required for Anthropic's prompt caching API when cache_control is specified
        at the message level but content is a simple string (not already an array of content blocks).
        r0   r   r2   )r1   r2   r   )r6   r   r5   r>   r   rL   r=   r   )rJ   r   r0   Ztransformed_messager   r:   r:   r;   r     s   


z>DatabricksConfig._move_cache_control_into_string_content_blockr0   c                 C   sz   | d u rd S t | tr| S t | tr4d}| D ]}|ddkr1|dd}||d ur.t|nd7 }q|S tdt|  )Nr3   r1   r2   zUnsupported content type: )r4   r>   r?   r6   	Exceptionr1   )r0   content_stritemZ
text_valuer:   r:   r;   extract_content_str  s   

z$DatabricksConfig.extract_content_strc              	   C   s   | du rdS d}d}t | trQ| D ]?}|ddkrP|dg }t |trP|D ](}|du r/d}||d 7 }td|dd|d	dd
}|du rJg }|| q'q||fS )zN
        Extract and return the reasoning content and thinking blocks
        NNNr1   Z	reasoningsummaryr3   r2   ro   	signature)r1   ro   r   )r4   r?   r6   r   r   )r0   thinking_blocksreasoning_contentr   Zsummary_listsumZthinking_blockr:   r:   r;   extract_reasoning_content  s0   



z*DatabricksConfig.extract_reasoning_contentc                    s^   | d u rd S g }t | tr+| D ]}|dd  |d }r*| fdd|D  q|p.d S )Nr2   	citationsc                    s   g | ]
}i |d  iqS )Zsupported_textr:   )r8   citationr2   r:   r;   r<     ry   z6DatabricksConfig.extract_citations.<locals>.<listcomp>)r4   r?   r6   r   )r0   r   r   Zcitations_itemr:   r   r;   extract_citations  s   

z"DatabricksConfig.extract_citationschoicesr   c              	   C   sR  g }|D ]}|d  dd }|d ur/g }|D ]}tdi |}|| qt|}	|	d ur/|	}d }
d }|rTt||drTt|d d  ddpHd }|d urTt|d}
d	}|
d u rt|d d
 }t	|d  d
\}}t
|d  d
}td||||d  d|d urd|ind d}
|d u r|d }t||d |
d d d}|| q|S )Nr   
tool_calls)r   Zconvert_tool_call_to_json_moder   ru   	argumentsr3   )r0   rH   r0   Z	assistantr   )Zroler0   r   r   r   provider_specific_fieldsfinish_reasonindex)r   r   r   ZlogprobsZenhancementsr:   )r6   r!   r   r   r   r>   r#   rC   r   r   r   r"   )rJ   r   r   Ztransformed_choiceschoicer   Z_openai_tool_calls_tcZ
_openai_tcZfixed_tool_callsZtranslated_messager   Zjson_mode_content_strr   r   r   r   Ztranslated_choicer:   r:   r;   _transform_dbrx_choices  sp   

z(DatabricksConfig._transform_dbrx_choicesraw_responsemodel_responselogging_objrequest_dataencodingc              
   C   s   |  |}|j|d|jd|id ztdi | }W n! ty= } zt|dd }tdt	||j|j
|dd }~ww |d |_|d |_|d	 |_t|d
tdi |d
  | j|d |d|_|S )Nz
[REDACTED]Zcomplete_input_dict)inputrX   original_responseZadditional_argsr^   z7Unable to get json response - {}, Original Response: {})r   status_coder^   r_   idcreatedusager   )r   r   r:   )Zredact_sensitive_dataZ	post_callr2   r   jsonr   getattrr-   formatr>   r   r_   r   r   rN   r'   r   r   )rJ   r_   r   r   r   r   r`   ra   rb   r   rX   r   Zredacted_request_dataZcompletion_responseeresponse_headersr:   r:   r;   transform_responseD  s:   





z#DatabricksConfig.transform_responsestreaming_responsesync_streamc                 C   s   t |||dS )N)r   r   r   )DatabricksChatResponseIteratorrJ   r   r   r   r:   r:   r;   get_model_response_iteratorv  s
   z,DatabricksConfig.get_model_response_iterator)NNNNNNr   rS   )TF)>__name__
__module____qualname____doc__rD   r	   int__annotations__rE   rF   rG   rH   r   r   r>   rI   rR   classmethodrU   r&   r]   r5   r   rg   boolri   r?   rp   r   r   rw   r{   r}   r
   r~   r   r   r   r   r   r   r   r   staticmethodr   r   r   r   r   r   r   r"   r   httpxResponser$   LiteLLMLoggingObjr   r   r   r   __classcell__r:   r:   rW   r;   rC   g   s  
 
	
(




?		

(

Y	

6rC   c                       sV   e Zd Z	ddeee ee ef dede	e f fddZ
dedefd	d
Z  ZS )r   Fr   r   r   c                    s   t  || || _d | _d S rS   )rT   rR   r   _last_function_namer   rW   r:   r;   rR     s   
z'DatabricksChatResponseIterator.__init__chunkr/   c              
   C   s  zg }|d D ]}|d  d}|rZ| jrZddlm} ddlm} |d  di  d}|d ur3|| _| j|ks<||krY||}|d urY|jd	krLd
|_|j|d d< d |d d< n|rr|D ]}	|	 di  dd	krqd
|	d d< q^t|d  dt	r|d d  }
r|
d  d }r|d |d 
di d< t|d  d}t|d  d\}}||d d< ||d d< ||d d< || qt|d d|d |d |dW S  ty } ztd| d| ddd }~w ty } z|d }~ww )Nr   deltar   r   r   )!_convert_tool_response_to_messageru   rr   z{}r3   r0   r   r   r   r   r   r   r   zchat.completion.chunkr   r_   )r   objectr   r_   r   z
KeyError: z+, Got unexpected response from Databricks: i  )r   r   )r6   r   litellm.constantsr   Z litellm.llms.base_llm.base_utilsr   r   r0   r4   r?   
setdefaultrC   r   r   r   r%   KeyErrorr-   r   )rJ   r   Ztranslated_choicesr   r   r   r   Zfunction_namer   r   r0   r   r   r   r   r   r:   r:   r;   chunk_parser  s   


z+DatabricksChatResponseIterator.chunk_parserr   )r   r   r   r   r   r>   r   r$   r   r	   rR   r5   r%   r   r   r:   r:   rW   r;   r     s    r   )Br   re   typingr   r   r   r   r   r   r   r	   r
   r   r   r   r   Zpydanticr   r   r   ZFlitellm.litellm_core_utils.llm_response_utils.convert_dict_to_responser   r   Z8litellm.litellm_core_utils.prompt_templates.common_utilsr   Z)litellm.llms.base_llm.base_model_iteratorr   Zlitellm.types.llms.anthropicr   Zlitellm.types.llms.databricksr   r   r   r   r   Zlitellm.types.llms.openair   r   r   r   r   r    Zlitellm.types.utilsr!   r"   r#   r$   r%   r&   r'   Zanthropic.chat.transformationr)   Zopenai_like.chat.transformationr*   Zcommon_utilsr,   r-   r5   r>   rA   Z*litellm.litellm_core_utils.litellm_loggingrB   Z_LiteLLMLoggingObjr   rC   r   r:   r:   r:   r;   <module>   s6    8 $
      