o
    ưiI                     @   s   d Z ddl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 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 G dd deZdS )a  
Transformation logic for Perplexity Agent API (Responses API)

This module handles the translation between OpenAI's Responses API format
and Perplexity's Responses API format, which supports:
- Third-party model access (OpenAI, Anthropic, Google, xAI, etc.)
- Presets for optimized configurations
- Web search and URL fetching tools
- Reasoning effort control
- Instructions parameter for system-level guidance
    )AnyDictListOptionalUnionN)verbose_logger)Logging)BaseLLMException)OpenAIResponsesAPIConfigget_secret_str)ResponseAPIUsageResponseInputParam!ResponsesAPIOptionalRequestParamsResponsesAPIResponseResponsesAPIStreamingResponse)GenericLiteLLMParams)LlmProvidersc                   @   s  e Zd ZdZedefddZdedefddZ	de
ded	ee de
fd
dZdee d	e
defddZdedededefddZdeeeef  deeeef  fddZdedeeef ded	ede
defddZdeeef deeeeeef  f fddZdedejdedefddZd eeef deeef fd!d"Zded#e
dede fd$d%Z!d&e
de
fd'd(Z"defd)d*Z#d+S ),PerplexityResponsesConfigz
    Configuration for Perplexity Agent API (Responses API)


    Reference: https://docs.perplexity.ai/docs/agent-api/overview
    returnc                 C   s   t jS )N)r   Z
PERPLEXITYself r   g/home/app/Keep/.python/lib/python3.10/site-packages/litellm/llms/perplexity/responses/transformation.pycustom_llm_provider)   s   z-PerplexityResponsesConfig.custom_llm_providermodelc                 C   s   g dS )z
        Perplexity Responses API supports a different set of parameters

        Ref: https://docs.perplexity.ai/api-reference/responses-post
        Params aligned with response-echo fields and Open Responses spec.
        )max_output_tokensstreamtemperaturetop_ptools	reasoningpresetinstructionsmodelstool_choiceparallel_tool_callsmax_tool_callstextprevious_response_idstore
background
truncationmetadatasafety_identifieruserstream_optionstop_logprobsprompt_cache_keyfrequency_penaltypresence_penaltyservice_tierr   )r   r   r   r   r   get_supported_openai_params-   s   z5PerplexityResponsesConfig.get_supported_openai_paramsheaderslitellm_paramsc                 C   s.   t dpt d}|rd| |d< d|d< |S )z'Validate environment and set up headersZPERPLEXITYAI_API_KEYZPERPLEXITY_API_KEYzBearer Authorizationzapplication/jsonzContent-Typer   )r   r7   r   r8   Zapi_keyr   r   r   validate_environmentQ   s   
z.PerplexityResponsesConfig.validate_environmentapi_basec                 C   s(   |du r
t dp	d}|d}| dS )z5Get the complete URL for the Perplexity Responses APINZPERPLEXITY_API_BASEzhttps://api.perplexity.ai/z/v1/responses)r   rstrip)r   r;   r8   r   r   r   get_complete_urla   s
   


z*PerplexityResponsesConfig.get_complete_urlresponse_api_optional_paramsdrop_paramsc           
      C   sb  i }| dr|d |d< | dr|d |d< | dr#|d |d< | dr.|d |d< | dr9|d |d< | d}|rD||d< | d}|rO||d< | drZ|d |d< | d	}|rod
d |D }| ||d	< | drz|d |d< | ddur|d |d< | dr|d |d< | d}	|	r|	|d< | dr|d |d< | ddur|d |d< | ddur|d |d< | dr|d |d< | dr|d |d< | dr|d |d< | dr|d |d< | ddur|d |d< | dr|d |d< | ddur|d |d< | ddur#|d |d< | dr/|d |d< |S )a0  
        Map OpenAI Responses API parameters to Perplexity format

        Key differences:
        - Supports 'preset' parameter for predefined configurations
        - Supports 'instructions' parameter for system-level guidance
        - Tools are specified differently (web_search, fetch_url)
        r   r   r   r   r0   r"   r#   r!   r    c                 S   s"   g | ]}t |d rt|n|qS )__dict__)hasattrdict).0toolr   r   r   
<listcomp>   s   " z?PerplexityResponsesConfig.map_openai_params.<locals>.<listcomp>r%   r&   Nr'   r(   r)   r*   r+   r,   r-   r.   r/   r1   r2   r3   r4   r5   )get_transform_tools)
r   r?   r   r@   Zmapped_paramsr"   r#   r    Z
tools_listZ
text_paramr   r   r   map_openai_paramsr   s   
















z+PerplexityResponsesConfig.map_openai_paramsr    c                 C   sN   g }|D ] }t |tr$|dd}|dv r|| q|dkr$|| q|S )z
        Transform tools to Perplexity format.

        Perplexity supports (per public OpenAPI spec):
        - web_search: Performs web searches
        - fetch_url: Fetches content from URLs
        - function: Function Calling
        type )Z
web_searchZ	fetch_urlfunction)
isinstancerC   rG   append)r   r    Zperplexity_toolsrE   Z	tool_typer   r   r   rH      s   	

z*PerplexityResponsesConfig._transform_toolsinput$response_api_optional_request_paramsc           
      C   sx   | dr|dd}|| |d}n|dr%|d| |d}n|| |d}| D ]\}}	|	||< q1|S )zF
        Transform request to Perplexity Responses API format
        zpreset/rK   )r"   rO   r"   )r   rO   )
startswithreplace_format_inputrG   popitems)
r   r   rO   rP   r8   r7   Zpreset_namedatakeyvaluer   r   r   transform_responses_api_request   s   


z9PerplexityResponsesConfig.transform_responses_api_requestc                 C   s`   t |tr|S t |tr,g }|D ]}t |tr)d|d|ddd}|| q|S t|S )z
        Format input for Perplexity Responses API

        The API accepts either:
        - A simple string for single-turn queries
        - An array of message objects for multi-turn conversations
        messagerolecontentrK   )rJ   r[   r\   )rM   strlistrC   rG   rN   )r   rO   Zformatted_messagesitemZformatted_messager   r   r   rS   #  s   





z'PerplexityResponsesConfig._format_inputraw_responselogging_objc              
   C   s   z|  }W n ty } zt|jdt| dd}~ww |d}|dkr;|di }|dd}t|j|d|d	i }	| |	}
|
rOtdi |
nd}t|d
dd|dd|dd|d||dg |d}|S )z\
        Transform Perplexity Responses API response to OpenAI Responses API format
        zFailed to parse response: )status_coderZ   NstatusfailederrorrZ   zUnknown errorusageidrK   response
created_atr   	completedr   output)rg   objectri   rc   r   rk   rf   r   )	json	Exceptionr	   rb   r]   rG   _transform_usager   r   )r   r   r`   ra   Zraw_response_jsonerc   re   error_message
usage_dataZtransformed_usage_dict	usage_objrh   r   r   r   transform_response_api_response?  sB   	







z9PerplexityResponsesConfig.transform_response_api_responserr   c                 C   s   | dd| dd| ddd}| d}t|tr0d|v r0|d |d< td||d  n|d	ur8||d< d
|v rB|d
 |d
< d|v rL|d |d< |S )a<  
        Transform Perplexity usage data to OpenAI format

        Perplexity returns:
        {
            "input_tokens": 100,
            "output_tokens": 200,
            "total_tokens": 300,
            "cost": {
                "currency": "USD",
                "input_cost": 0.0001,
                "output_cost": 0.0002,
                "total_cost": 0.0003
            }
        }

        OpenAI expects:
        {
            "input_tokens": 100,
            "output_tokens": 200,
            "total_tokens": 300,
            "cost": 0.0003
        }
        input_tokensr   output_tokenstotal_tokens)ru   rv   rw   cost
total_cost5Transformed Perplexity cost object to float: %s -> %sNZinput_tokens_detailsZoutput_tokens_details)rG   rM   rC   r   debug)r   rr   Ztransformedcost_objr   r   r   ro   r  s&   



z*PerplexityResponsesConfig._transform_usageparsed_chunkc                 C   s   t d| t|d}tj|d}| |}z#|d}t|tr:|ddu r:t|}t||d< d|d d< W n t	yI   t d Y nw |d	i |S )
zb
        Transform a parsed streaming response chunk into a ResponsesAPIStreamingResponse
        zRaw Perplexity Chunk=%srJ   )
event_typere   codeNZunknown_errorz-Failed to coalesce error.code in parsed_chunkr   )
r   r{   r]   rG   r   Zget_event_model_class_transform_perplexity_chunkrM   rC   rn   )r   r   r}   ra   r~   Zevent_pydantic_modelZ	error_objr   r   r   transform_streaming_response  s"   


z6PerplexityResponsesConfig.transform_streaming_responsechunkc              
   C   s   t |}zV|d}t|t rO|d}t|t rR|d}t|t rUd|v rXt |}t ||d< t ||d d< |d |d d d< td||d  W |S W |S W |S W |S W |S  tys } ztd| W Y d}~|S d}~ww )z
        Transform Perplexity-specific fields in a streaming chunk to OpenAI format.

        This handles:
        - Converting Perplexity's cost object to a simple float
        rh   rf   rx   ry   rz   z.Failed to transform Perplexity cost object: %sN)rC   rG   rM   r   r{   rn   )r   r   Zresponse_objrs   r|   rp   r   r   r   r     s>   




	z5PerplexityResponsesConfig._transform_perplexity_chunkc                 C   s   dS )z>Perplexity does not support native WebSocket for Responses APIFr   r   r   r   r   supports_native_websocket  s   z3PerplexityResponsesConfig.supports_native_websocketN)$__name__
__module____qualname____doc__propertyr   r   r]   r^   r6   rC   r   r   r:   r>   r   boolr   rI   r   r   rH   r   r   rY   rS   httpxResponseLiteLLMLoggingObjr   rt   ro   r   r   r   r   r   r   r   r   r   !   s    $


*s

%


"36
"$r   )r   typingr   r   r   r   r   r   Zlitellm._loggingr   Z*litellm.litellm_core_utils.litellm_loggingr   r   Z)litellm.llms.base_llm.chat.transformationr	   Z,litellm.llms.openai.responses.transformationr
   Zlitellm.secret_managers.mainr   Zlitellm.types.llms.openair   r   r   r   r   Zlitellm.types.routerr   Zlitellm.types.utilsr   r   r   r   r   r   <module>   s    