o
    ưivm                     @   s$  d dl Z d dlZd dl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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 d d	lmZ d d
lmZmZ d dlmZmZmZm Z m!Z!m"Z"m#Z# d dl$m%Z%m&Z& d dl'm(Z( ddl)m*Z* ddl+m,Z, G dd de*eZ-G dd dZ.dS )    N)AnyDictListOptionalTupleUnion)HeadersResponse)FileDeleted)verbose_logger)uuid)FilesAPIUtils)extract_file_data)BaseLLMException)BaseFilesConfigLiteLLMLoggingObj)AllMessageValuesCreateFileRequest	FileTypesHttpxBinaryResponseContent%OpenAICreateFileRequestOptionalParamsOpenAIFileObjectPathLike)ExtractedFileDataLlmProviders)get_llm_provider   )
BaseAWSLLMBedrockErrorc                       s(  e Zd ZdZ fddZedefddZedefddZ					dOd
e
dedee de
de
dee dee de
fddZdedefddZdeeeef  defddZdededefddZdee dee dededededefddZdedee fd d!Zd"e
de
ded#ede
f
d$d%Zd&Z		dPd'eeef d(ee deeef fd)d*Zdeeeef  deeeef  fd+d,Zded-ede
de
dee ee
f f
d.d/Z!d0edede
de"e
ef fd1d2Z#d3ede$eef fd4d5Z%dee d6e&d7e'de
de(f
d8d9Z)d:ed;e*d
eee+f de,fd<d=Z-d>ede
de
de$ee
f fd?d@Z.d6e/j&d7e'de
de(fdAdBZ0d>ede
de
de$ee
f fdCdDZ1d6e/j&d7e'de
de2fdEdFZ3dee de
de
de$ee
f fdGdHZ4d6e/j&d7e'de
dee( fdIdJZ5de
de
de$ee
f fdKdLZ6d6e/j&d7e'de
de7fdMdNZ8  Z9S )QBedrockFilesConfigzT
    Config for Bedrock Files - handles S3 uploads for Bedrock batch processing
    c                    s   t  | _t   d S N)BedrockJsonlFilesTransformationZjsonl_transformationsuper__init__self	__class__ `/home/app/Keep/.python/lib/python3.10/site-packages/litellm/llms/bedrock/files/transformation.pyr$   (   s   zBedrockFilesConfig.__init__returnc                 C   s   t jS r!   )r   ZBEDROCKr%   r)   r)   r*   custom_llm_provider,   s   z&BedrockFilesConfig.custom_llm_providerc                 C   s   dS )zO
        Bedrock files are uploaded to S3, which requires PUT requests
        PUTr)   r%   r)   r)   r*   file_upload_http_method0   s   z*BedrockFilesConfig.file_upload_http_methodNheadersmodelmessagesoptional_paramslitellm_paramsapi_keyapi_basec                 C   s   |S r!   r)   )r&   r/   r0   r1   r2   r3   r4   r5   r)   r)   r*   validate_environment7   s   z'BedrockFilesConfig.validate_environmentopenai_file_contentc                 C      d}t |tr|d }n|}t |tr|}n2t |tr|}n*t |tr?tt|d}| }W d   n1 s9w   Y  n	t|drH| }t |trR|d}|S a  
        Helper to extract content from various OpenAI file types and return as string.

        Handles:
        - Direct content (str, bytes, IO[bytes])
        - Tuple formats: (filename, content, [content_type], [headers])
        - PathLike objects
               rbNreadutf-8	
isinstancetuplestrbytesr   openr=   hasattrdecoder&   r7   contentfile_contentfr)   r)   r*   _get_content_from_openai_fileF   $   	








z0BedrockFilesConfig._get_content_from_openai_fileopenai_jsonl_contentc                 C   sT   |d  di  dd}|dr|dd }|dd	}d
| d	t  d}|S )z
        Gets a unique S3 object name for the Bedrock batch processing job

        named as: litellm-bedrock-files/{model}/{uuid}
        r   bodyr0    bedrock/   N:-litellm-bedrock-files-.jsonl)get
startswithreplacer   uuid4r&   rM   _modelobject_namer)   r)   r*   $_get_s3_object_name_from_batch_jsonlk   s   	
z7BedrockFilesConfig._get_s3_object_name_from_batch_jsonlextracted_file_datapurposec                 C   sv   | d}|du rtd|dkr*| |}dd | D }t|dkr*| |S | d}|r3|S ttt S )	z5
        Get the object name for the request
        rH   Nfile content is requiredbatchc                 S      g | ]}|  rt|qS r)   stripjsonloads.0liner)   r)   r*   
<listcomp>   
    z6BedrockFilesConfig.get_object_name.<locals>.<listcomp>r   filename)	rV   
ValueErrorrK   
splitlineslenr]   rB   inttime)r&   r^   r_   extracted_file_data_contentrI   rM   rl   r)   r)   r*   get_object_name   s    


z"BedrockFilesConfig.get_object_namedatac                 C   s   | dp	td}|std| ||}| d}	| d}
|	du r(td|
du r0tdt|	}| ||
}| d	pDd
| d}| d| d| S )zE
        Get the complete S3 URL for the file upload request
        Zs3_bucket_nameZAWS_S3_BUCKET_NAMEz`S3 bucket_name is required. Set 's3_bucket_name' in litellm_params or AWS_S3_BUCKET_NAME env varfiler_   Nfile is requiredzpurpose is requireds3_endpoint_urlzhttps://s3.z.amazonaws.com/)rV   osgetenvrm   _get_aws_region_namer   rs   )r&   r5   r4   r0   r2   r3   rt   bucket_nameaws_region_name	file_datar_   r^   r\   rw   r)   r)   r*   get_complete_file_url   s   

z(BedrockFilesConfig.get_complete_file_urlc                 C   s   g S r!   r)   )r&   r0   r)   r)   r*   get_supported_openai_params   s   z.BedrockFilesConfig.get_supported_openai_paramsnon_default_paramsdrop_paramsc                 C   s   |S r!   r)   )r&   r   r2   r0   r   r)   r)   r*   map_openai_params   s   z$BedrockFilesConfig.map_openai_params)Znovaopenai_request_bodyproviderc                 C   s   ddl m} |dd}|dg }dd | D }||jkr<ddlm} | }|ji ||d	d
}	|j|||	i i dS || j	v r]ddl
m}
 |
 }|j|i |d	d
}	|j|||	i i dS d|i|S )a5  
        Transform OpenAI request body to Bedrock-compatible modelInput
        parameters using existing transformation logic.

        Routes to the correct per-provider transformation so that the
        resulting dict matches the InvokeModel body that Bedrock expects
        for batch inference.
        r   )r   r0   rO   r1   c                 S   s   i | ]\}}|d vr||qS ))r0   r1   r)   )rh   kvr)   r)   r*   
<dictcomp>   s
    zDBedrockFilesConfig._map_openai_to_bedrock_params.<locals>.<dictcomp>)AmazonAnthropicClaudeConfigF)r   r2   r0   r   )r0   r1   r2   r3   r/   )AmazonConverseConfig)litellm.types.utilsr   rV   itemsZ	ANTHROPICZQlitellm.llms.bedrock.chat.invoke_transformations.anthropic_claude3_transformationr   r   Ztransform_requestCONVERSE_INVOKE_PROVIDERSZ1litellm.llms.bedrock.chat.converse_transformationr   )r&   r   r   r   r[   r1   r2   r   configZmapped_paramsr   Zconverse_configr)   r)   r*   _map_openai_to_bedrock_params   sT   

z0BedrockFilesConfig._map_openai_to_bedrock_paramsc                 C   s   g }t |D ]]\}}|di }|dd}zt|dd\}}}}W n ty> } ztdt|  W Y d}~nd}~ww | |}	| j||	d}
|dd	t|	d
 }||
d}|
| q|S )aV  
        Transforms OpenAI JSONL content to Bedrock batch format
        
        Bedrock batch format: { "recordId": "alphanumeric string", "modelInput": {JSON body} }
        Example:
        {
            "recordId": "CALL0000001", 
            "modelInput": {
                "anthropic_version": "bedrock-2023-05-31", 
                "max_tokens": 1024,
                "messages": [ 
                    { 
                        "role": "user", 
                        "content": [{"type": "text", "text": "Hello"}]
                    }
                ]
            }
        }
        rN   r0   rO   N)r0   r,   zlitellm.llms.bedrock.files.transformation.py::_transform_openai_jsonl_content_to_bedrock_jsonl_content() - Error inferring custom_llm_provider - )r   r   Z	custom_idCALL   )ZrecordIdZ
modelInput)	enumeraterV   r   	Exceptionr   	exceptionrB   Zget_bedrock_invoke_providerr   zfillappend)r&   rM   bedrock_jsonl_contentidxZ_openai_jsonl_contentZopenai_bodyr0   _er   Zmodel_inputZ	record_idZbedrock_recordr)   r)   r*   8_transform_openai_jsonl_content_to_bedrock_jsonl_content  s0    
zKBedrockFilesConfig._transform_openai_jsonl_content_to_bedrock_jsonl_contentcreate_file_datac                 C   s   | d}|du rtdt|}| d}|du rtdtj||drC| |}dd | D }	| |	}
d	d
d |
D }nt	|t
rN|d}nt	|trV|}ntd| jdd||||d}| j|||d\}}||d< d|||py|dS )z
        Transform file request and return a pre-signed request for S3.
        This keeps the HTTP handler clean by doing all the signing here.
        ru   Nrv   rH   r`   )r   r^   c                 S   rb   r)   rc   rg   r)   r)   r*   rj   q  rk   zDBedrockFilesConfig.transform_create_file_request.<locals>.<listcomp>
c                 s       | ]}t |V  qd S r!   re   dumpsrh   itemr)   r)   r*   	<genexpr>y  s    zCBedrockFilesConfig.transform_create_file_request.<locals>.<genexpr>r>   zUnsupported file content type)r5   r4   r0   r2   r3   rt   )rH   r5   r2   
upload_urlr-   )methodurlr/   rt   )rV   rm   r   r   Zis_batch_jsonl_filerK   rn   r   joinr@   rC   rF   rB   r   _sign_s3_request)r&   r0   r   r2   r3   r~   r^   rr   Zoriginal_file_contentrM   r   rI   r5   Zsigned_headerssigned_bodyr)   r)   r*   transform_create_file_requestT  s\   





z0BedrockFilesConfig.transform_create_file_requestrH   c                 C   sF  zddl }ddl}ddlm} ddlm} W n ty!   tdw | j|dd}| j|	d|	d	|	d
||	d|	d|	d|	d|	dd	}	|
|d }
d|
ddd}|jd|||d}| }||j|j|j|jd}| j|d}||	d|| |j}t|tr|d}n|du r|}t|j|fS )z
        Sign S3 PUT request using the same proven logic as S3Logger.
        Reuses the exact pattern from litellm/integrations/s3_v2.py
        r   N)	SigV4Auth)
AWSRequestz7Missing boto3 to call bedrock. Run 'pip install boto3'.rO   )r2   r0   aws_access_key_idaws_secret_access_keyaws_session_tokenaws_session_nameaws_profile_nameaws_role_nameaws_web_identity_tokenaws_sts_endpoint)	r   r   r   r}   r   r   r   r   r   r>   zapplication/jsonenz0private, immutable, max-age=31536000, s-maxage=0)zContent-Typezx-amz-content-sha256zContent-LanguagezCache-Controlr-   )rt   r/   )r   r   rt   r/   )r}   Zs3)hashlibrequestsZbotocore.authr   Zbotocore.awsrequestr   ImportErrorr{   Zget_credentialsrV   sha256encode	hexdigestRequestpreparer   r   rN   r/   Z)get_aws_region_name_for_non_llm_api_callsZadd_authr@   rC   rF   dict)r&   rH   r5   r2   r   r   r   r   r}   credentialsZcontent_hashZrequest_headersreqZpreppedZaws_requestZsigning_regionr   r)   r)   r*   r     s\   

z#BedrockFilesConfig._sign_s3_request	https_urlc                 C   s   ddl }d}d}|||}|||}|r&| \}}}	d| d|	 }
nE|r8| \}}}	d| d|	 }
n3ddlm} ||}|jddd}t|d	krd|d |d }}	d| d|	 }
nt	d
| d|	v rv|	dd n|	}|
|fS )a  
        Convert HTTPS S3 URL to s3:// URI format.
        
        Args:
            https_url: HTTPS S3 URL (e.g., "https://s3.us-west-2.amazonaws.com/bucket/key")
        
        Returns:
            Tuple of (s3_uri, filename)
        
        Example:
            Input: "https://s3.us-west-2.amazonaws.com/litellm-proxy/file.jsonl"
            Output: ("s3://litellm-proxy/file.jsonl", "file.jsonl")
        r   Nz0https://s3\.([^.]+)\.amazonaws\.com/([^/]+)/(.+)z1https://([^.]+)\.s3\.([^.]+)\.amazonaws\.com/(.+)s3://rx   )urlparser;   r   zUnable to parse S3 URL: )
rematchgroupsurllib.parser   pathlstripsplitro   rm   )r&   r   r   Zpattern1Zpattern2Zmatch1Zmatch2regionZbucketkeyZs3_urir   parsed
path_partsrl   r)   r)   r*   _convert_https_url_to_s3_uri  s(   z/BedrockFilesConfig._convert_https_url_to_s3_uriraw_responselogging_objc           
   	   C   sj   |j }|dd}|d}d}d}	|r| |\}}	td||	tt d| r0t|dd	S ddd	S )
zP
        Transform S3 File upload response into OpenAI-style FileObject
        zContent-Length0r   rO   ra   uploadedr   ru   r_   idrl   Z
created_atstatusrC   object)r/   rV   r   r   rp   rq   isdigit)
r&   r0   r   r   r3   response_headerscontent_lengthr   file_idrl   r)   r)   r*   transform_create_file_response  s&   

z1BedrockFilesConfig.transform_create_file_responseerror_messagestatus_codec                 C   s   t |||dS )N)r   messager/   r   )r&   r   r   r/   r)   r)   r*   get_error_class:  s   z"BedrockFilesConfig.get_error_classr   c                 C      t dNz2BedrockFilesConfig does not support file retrievalNotImplementedErrorr&   r   r2   r3   r)   r)   r*   transform_retrieve_file_requestA     z2BedrockFilesConfig.transform_retrieve_file_requestc                 C   r   r   r   r&   r   r   r3   r)   r)   r*    transform_retrieve_file_responseI  r   z3BedrockFilesConfig.transform_retrieve_file_responsec                 C   r   Nz1BedrockFilesConfig does not support file deletionr   r   r)   r)   r*   transform_delete_file_requestQ  r   z0BedrockFilesConfig.transform_delete_file_requestc                 C   r   r   r   r   r)   r)   r*   transform_delete_file_responseY  r   z1BedrockFilesConfig.transform_delete_file_responsec                 C   r   Nz0BedrockFilesConfig does not support file listingr   )r&   r_   r2   r3   r)   r)   r*   transform_list_files_requesta  r   z/BedrockFilesConfig.transform_list_files_requestc                 C   r   r   r   r   r)   r)   r*   transform_list_files_responsei  r   z0BedrockFilesConfig.transform_list_files_responsec                 C   r   Nz:BedrockFilesConfig does not support file content retrievalr   )r&   Zfile_content_requestr2   r3   r)   r)   r*   transform_file_content_requestq  r   z1BedrockFilesConfig.transform_file_content_requestc                 C   r   r   r   r   r)   r)   r*   transform_file_content_responsey  r   z2BedrockFilesConfig.transform_file_content_response)NNr!   ):__name__
__module____qualname____doc__r$   propertyr   r,   rB   r.   r   r   r   r   r6   r   rK   r   r   r]   r   rs   r   r   r   r   boolr   r   r   r   r   rC   r   r   r   rA   r   r	   r   r   r   rp   r   r   r   r   httpxr   r   r
   r   r   r   r   r   r   __classcell__r)   r)   r'   r*   r    #   s   	
%


 




J
8
H

J2
"












r    c                   @   s   e Zd ZdZ	ddee deeef fddZde	e
eef  fdd	Zde	e
eef  defd
dZdedefddZdede
eef defddZdS )r"   z`
    Transforms OpenAI /v1/files/* requests to Bedrock S3 file uploads for batch processing
    Nr7   r+   c                 C   s^   |du rt d| |}dd | D }| |}ddd |D }| j|d}||fS )	zP
        Transforms OpenAI FileContentRequest to Bedrock S3 file format
        Nzcontents of file are Nonec                 S   rb   r)   rc   rg   r)   r)   r*   rj     rk   ziBedrockJsonlFilesTransformation.transform_openai_file_content_to_bedrock_file_content.<locals>.<listcomp>r   c                 s   r   r!   r   r   r)   r)   r*   r     s    

zhBedrockJsonlFilesTransformation.transform_openai_file_content_to_bedrock_file_content.<locals>.<genexpr>)rM   )rm   rK   rn   r   r   _get_s3_object_name)r&   r7   rI   rM   r   Zbedrock_jsonl_stringr\   r)   r)   r*   5transform_openai_file_content_to_bedrock_file_content  s"   

zUBedrockJsonlFilesTransformation.transform_openai_file_content_to_bedrock_file_contentrM   c                 C   s   t  }||S )zO
        Delegate to the main BedrockFilesConfig transformation method
        )r    r   )r&   rM   r   r)   r)   r*   r     s   
zXBedrockJsonlFilesTransformation._transform_openai_jsonl_content_to_bedrock_jsonl_contentc                 C   sH   |d  di  dd}|dr|dd }d| d	t  d
}|S )z
        Gets a unique S3 object name for the Bedrock batch processing job

        named as: litellm-bedrock-files-{model}-{uuid}
        r   rN   r0   rO   rP   rQ   NrT   rS   rU   )rV   rW   r   rY   rZ   r)   r)   r*   r     s
   	
z3BedrockJsonlFilesTransformation._get_s3_object_namec                 C   r8   r9   r?   rG   r)   r)   r*   rK     rL   z=BedrockJsonlFilesTransformation._get_content_from_openai_filer   s3_upload_responsec              
   C   sl   | dd}| dd}d|v r|dd n|}t| ddd| d| |tt d	| d
dddS )zP
        Transforms S3 Bucket upload file response to OpenAI FileObject
        KeyrO   ZBucketrx   r   r_   ra   r   r   ZContentLengthr   ru   r   )rV   r   r   rp   rq   )r&   r   r   Z
object_keyr|   rl   r)   r)   r*   2transform_s3_bucket_response_to_openai_file_object  s   


zRBedrockJsonlFilesTransformation.transform_s3_bucket_response_to_openai_file_objectr!   )r   r   r   r   r   r   r   rB   r   r   r   r   r   r   rK   r   r   r   r)   r)   r)   r*   r"     s0    


	
%
r"   )/re   ry   rq   typingr   r   r   r   r   r   r   r   r	   Zopenai.types.file_deletedr
   Zlitellm._loggingr   Zlitellm._uuidr   Zlitellm.files.utilsr   Z8litellm.litellm_core_utils.prompt_templates.common_utilsr   Z)litellm.llms.base_llm.chat.transformationr   Z*litellm.llms.base_llm.files.transformationr   r   Zlitellm.types.llms.openair   r   r   r   r   r   r   r   r   r   Zlitellm.utilsr   Zbase_aws_llmr   Zcommon_utilsr   r    r"   r)   r)   r)   r*   <module>   s0     $	    c