
    hz                        d dl Z d dlZej                  j                  d e j                  j	                  d             d dlZd dlZd dlmZmZm	Z	m
Z
mZmZmZ d dl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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. dZ/ G d dee      Z0y)    Nz../..)AnyAsyncGeneratorListLiteralOptionalTupleUnion)HTTPException)verbose_proxy_logger)	DualCache)CustomGuardraillog_guardrail_information)
BaseAWSLLM)get_async_httpx_clienthttpxSpecialProvider)UserAPIKeyAuthGuardrailEventHooks)AllMessageValues)BedrockContentItemBedrockGuardrailOutputBedrockGuardrailResponseBedrockRequestBedrockTextContent)ChoicesModelResponseModelResponseStreamStreamingChoicesTextChoicesbedrockc                       e Zd Z	 	 	 d-dee   dee   dee   f fdZdeee      de	fdZ
d	eeef   de	fd
Z	 	 d.ded   deee      d	eeeef      de	fdZd Z	 d/dedededee   fdZ	 	 	 d0ded   deee      d	eeeej                  f      dee   def
dZd	edefdZd	edefdZededededed   deeeedf   f
d       Zedededed   fd       Zededefd       Z dee   d edee   fd!Z!ded	edede"e#df   fd"Z$d edee   fd#Z%dee   d$ee   dee   fd%Z&d&ee   d$ee   d'e'de(ee   e'f   fd(Z)d)edeee      fd*Z*d	eeef   d eddfd+Z+d	ej                  d$ee   ddfd,Z, xZ-S )1BedrockGuardrailNguardrailIdentifierguardrailVersiondisable_exception_on_blockc                 $   t        t        j                        | _        || _        || _        || _        |xs d| _        	 t        | $  di | t        j                  |        t        j                  d| j                  | j
                         y )N)llm_providerFzPBedrock Guardrail initialized with guardrailIdentifier: %s, guardrailVersion: %s )r   r   GuardrailCallbackasync_handlerr#   r$   optional_paramsr%   super__init__r   r   debug)selfr#   r$   r%   kwargs	__class__s        w/var/www/Befach/backend/env/lib/python3.12/site-packages/litellm/proxy/guardrails/guardrail_hooks/bedrock_guardrails.pyr-   zBedrockGuardrail.__init__6   s     4-??
 $7  0  &0J0Se'	
 	"6"D!""^$$!!	
    messagesreturnc                     t        d      }g }||S |D ]E  }| j                  |      }||D ])  }t        t        |            }|j	                  |       + G ||d<   |S )zS
        Create a bedrock request for the input content - the LLM request.
        INPUTsource)messagetextcontent)r   get_content_for_messager   r   append)r/   r4   bedrock_requestbedrock_request_contentr:   message_text_contenttext_contentbedrock_content_items           r2   %_create_bedrock_input_content_requestz6BedrockGuardrail._create_bedrock_input_content_requestV   s     +9*H<>""G,,W,= ! $+ 4'9+>($ (../CD	 !5   &=	"r3   responsec                    t        d      }g }t        |t        j                        r|j                  D ]  }t        |t        j
                        s|j                  j                  s5t        |j                  j                  t              sZt        t        |j                  j                              }|j                  |        ||d<   |S )zU
        Create a bedrock request for the output content - the LLM response.
        OUTPUTr8   r;   r=   )r   
isinstancelitellmr   choicesr   r:   r=   strr   r   r?   )r/   rF   r@   rA   choicerD   s         r2   &_create_bedrock_output_content_requestz7BedrockGuardrail._create_bedrock_output_content_requestm   s     +9*I<>h 5 56"**fgoo6~~--*..3 0B!39O9O!P0, 0667KL + *AOI&r3   r9   )r7   rH   c                 ~    t        |      }|dk(  r| j                  |      }|S |dk(  r| j                  |      }|S )a  
        Convert the litellm messages/response to the bedrock request format.

        If source is "INPUT", then messages is required.
        If source is "OUTPUT", then response is required.

        Returns:
            BedrockRequest: The bedrock request object.
        r8   r7   )r4   rH   )rF   )r   rE   rN   )r/   r9   r4   rF   r@   s        r2   convert_to_bedrock_formatz*BedrockGuardrail.convert_to_bedrock_format   sV     +9*GW"HHRZH[O  x"IIS[I\Or3   c                    	 ddl m} | j                  j	                  dd       }| j                  j	                  dd       }| j                  j	                  dd       }| j                  j	                  dd       }| j                  j	                  dd       }| j                  j	                  d	d       }| j                  j	                  d
d       }| j                  j	                  dd       }	| j                  j	                  dd       }
| j                  |      }| j                  ||||||||	|
	      }||fS # t        $ r t        d      w xY w)Nr   )Credentials7Missing boto3 to call bedrock. Run 'pip install boto3'.aws_secret_access_keyaws_access_key_idaws_session_tokenaws_region_nameaws_role_nameaws_session_nameaws_profile_nameaws_web_identity_tokenaws_sts_endpoint)rW   )	rU   rT   rV   rW   rY   rZ   rX   r[   r\   )botocore.credentialsrR   ImportErrorr+   get)get_aws_region_name_for_non_llm_api_callsget_credentials)r/   rR   rT   rU   rV   rW   rX   rY   rZ   r[   r\   credentialss               r2   _load_credentialsz"BedrockGuardrail._load_credentials   sr   	Y8 !% 4 4 8 89PRV W 00445H$O 00445H$O..223DdK,,00$G//334FM//334FM!%!5!5!9!9$d"
  //334FM HH+ I 
 $(#7#7/"7/+--'#9- $8 
$
 O++?  	YWXX	Ys   D4 4E	datar+   rW   extra_headersc                    	 ddl m} ddlm}  ||d|      }d| d| j
                   d| j                   d	}	t        j                  |      j                  d
      }
ddi}|ddi|} |d|	|
|      }|j                  |       |d|v r|d   |j                  d<   |j                         }|S # t        $ r t	        d      w xY w)Nr   )	SigV4Auth)
AWSRequestrS   r    zhttps://bedrock-runtime.z.amazonaws.com/guardrail/z	/version/z/applyzutf-8zContent-Typezapplication/jsonPOST)methodurlrd   headersAuthorization)botocore.authrg   botocore.awsrequestrh   r^   r#   r$   jsondumpsencodeadd_authrl   prepare)r/   rb   rd   r+   rW   re   rg   rh   sigv4api_baseencoded_datarl   requestprepped_requests                 r2   _prepare_requestz!BedrockGuardrail._prepare_request   s   	Y/6 +y/B-o->>WX\XpXpWqqz{  |Q  |Q  {R  RX  Yzz$'..w7!#56$%'9K]KGxlG
 	w%/]*J/<_/MGOOO,!//+-  	YWXX	Ys   B/ /Crequest_datac                   K   | j                         \  }}t        | j                  |||            }t               }|r!|j	                  | j                  |             | j                  ||| j                  |      }	t        j                  d||	j                  |	j                         | j                  j                  |	j                  |	j                  |	j                         d {   }t        j                  d|j                         |j                   dk(  r?|j#                         }
t        d	i |
}| j%                  |      r| j'                  |      |S t        j(                  d|j                   |j                         |S 7 w)
N)r9   r4   rF   )r{   )rb   rd   r+   rW   z0Bedrock AI request body: %s, url %s, headers: %s)rk   rd   rl   zBedrock AI response: %s   z<Bedrock AI: error in response. Status code: %s, response: %sr(   )rc   dictrP   r   update)get_guardrail_dynamic_request_body_paramsrz   r+   r   r.   rk   rl   r*   postbodyr<   status_coderp   )_should_raise_guardrail_blocked_exception)_get_http_exception_for_blocked_guardrailerror)r/   r9   r4   rF   r{   rb   rW   bedrock_request_databedrock_guardrail_responseprepared_request_json_responses              r2   make_bedrock_api_requestz)BedrockGuardrail.make_bedrock_api_request   s     (,'='='?$_%)**!! + &
 %& 	#  ''>>L>Y  00#% 00+	 1 
 	"">   $$		
 ++00 $$!&&$,, 1 
 

 	""#<hmmL3&%]]_N)A)SN)S&==* DD.  *) !&&N$$ *)/
s   C(F*F
+B Fc                     d}|j                  dg       xs g }|r1|D ],  }|j                  d      s||j                  d      xs dz  }. t        dd|d      S )zA
        Get the HTTP exception for a blocked guardrail.
         outputsr<   i  zViolated guardrail policy)r   r   )r   detail)r_   r
   )r/   rF   bedrock_guardrail_output_textr   outputs        r2   r   z:BedrockGuardrail._get_http_exception_for_blocked_guardrail  ss     .0%LLB'-2 	 !::f%1VZZ5G5M2M1 "
 4.K
 	
r3   c                 $   | j                   s| j                  ry| j                  du ry|j                  d      dk7  ry|j                  dg       }|sy|D ]  }|j                  d      }|r0|j                  dg       }|D ]  }|j                  d      dk(  s  y |j                  d	      }|r0|j                  d
g       }|D ]  }	|	j                  d      dk(  s  y |j                  d      }
|
r`|
j                  dg       }|D ]  }|j                  d      dk(  s  y |
j                  dg       }|D ]  }|j                  d      dk(  s  y |j                  d      }|rd|j                  dg       }|r|D ]  }|j                  d      dk(  s  y |j                  dg       }|r|D ]  }|j                  d      dk(  s  y |j                  d      }|s|j                  d
g       }|D ]  }|j                  d      dk(  s  y  y)a  
        Only raise exception for "BLOCKED" actions, not for "ANONYMIZED" actions.

        If `self.mask_request_content` or `self.mask_response_content` is set to `True`, then use the output from the guardrail to mask the request or response content.
        FTactionGUARDRAIL_INTERVENEDassessmentstopicPolicytopicsBLOCKEDcontentPolicyfilters
wordPolicycustomWordsmanagedWordListssensitiveInformationPolicypiiEntitiesregexescontextualGroundingPolicy)mask_request_contentmask_response_contentr%   r_   )r/   rF   r   
assessmenttopic_policyr   topiccontent_policyr   filter_itemword_policycustom_wordscustom_wordmanaged_wordsmanaged_wordsensitive_info_policypii_entities
pii_entityr   regexcontextual_grounding_policygrounding_filtersgrounding_filters                          r2   r   z:BedrockGuardrail._should_raise_guardrail_blocked_exception4  s'    $$(B(B**d2 <<!%;; ll="5%J%>>-8L%))(B7#Eyy*i7# $
 (^^O<N(,,Y;#*K"x0I=# $+
 %..6K*}bA#/K"x0I=# $0 !,0BB G$1L#''1Y># %2
 %/NN3O$P!$488K&2
%>>(3y@#' '3 033IrB!( 99X.);#' ")
 +5..9T*U'*$?$C$CIr$R!(9$'++H5B# ):_ &j r3   user_api_key_dictcache	call_type)
completiontext_completion
embeddingsimage_generation
moderationaudio_transcriptionpass_through_endpointrerankc                 v  K   t        j                  d       ddlm} t        j
                  }| j                  ||      dur|S |j                  d      }|t        j                  d       |S | j                  d||	       d {   }| j                  ||
      |d<    ||| j                         |S 7 0w)NzInside AIM Pre-Call Hookr   *add_guardrail_to_applied_guardrails_headerrd   
event_typeTr4   6Bedrock AI: not running guardrail. No messages in datar7   r9   r4   r{   r4   r   r{   guardrail_name)r   r.   )litellm.proxy.common_utils.callback_utilsr   r   pre_callshould_run_guardrailr_   warningr   8_update_messages_with_updated_bedrock_guardrail_responser   )	r/   r   r   rd   r   r   r   new_messagesr   s	            r2   async_pre_call_hookz$BedrockGuardrail.async_pre_call_hook  s     " 	""#=>	
 +>*F*F
$$$:$FdRK9=*9M ((H K
 ,0+H+H\ ,I ,
 &
" II%+E J  	Z 	3d.A.A	
 -&
s   BB9B71B9)r   r   r   r   r   	responsesc                 H  K   ddl m} t        j                  }| j	                  ||      dury |j                  d      }|t        j                  d       y | j                  d||       d {   }| j                  ||	      |d<    ||| j                  
       |S 7 0w)Nr   r   r   Tr4   r   r7   r   r   r   )r   r   r   during_callr   r_   r   r   r   r   r   )r/   rd   r   r   r   r   r   r   s           r2   async_moderation_hookz&BedrockGuardrail.async_moderation_hook  s     	
 +>*I*I
$$$:$FdR9=*9M ((H 
 ,0+H+H\ ,I ,
 &
" II%+E J  	Z 	3d.A.A	
 -&
s   A-B"/B 01B"c                 @  K   ddl m} ddlm} | j	                  ||j
                        dury |j                  d      }|t        j                  d       y | j                  d||	       d {   }| j                  ||
        ||| j                         y 7 ,w)Nr   r   r   r   Tr4   r   rH   )r9   rF   r{   rF   r   r   )r   r   litellm.types.guardrailsr   r   	post_callr_   r   r   r   _apply_masking_to_responser   )r/   rd   r   rF   r   r   r   output_content_bedrocks           r2   async_post_call_success_hookz-BedrockGuardrail.async_post_call_success_hook  s     	
 	A %%&9&C&C &  
 9=*9M ((H 
 (,'D'D (E (
 "
 	'''= 	( 	
 	3d.A.A	
#"
s   A-B/B0-Br   c                     | j                  |      }|r(t        j                  d       | j                  ||      S | j                  s| j
                  rt        j                  d       |S )af  
        Use the output from the bedrock guardrail to mask sensitive content in messages.

        Args:
            messages: Original list of messages
            bedrock_guardrail_response: Response from Bedrock guardrail containing masked content

        Returns:
            List of messages with content masked according to guardrail response
        z>Bedrock guardrail provided masked output, applying to messages)r4   masked_textszPMasking enabled but no masked output from guardrail, returning original messages)#_extract_masked_texts_from_responser   r.   _apply_masking_to_messagesr   r   )r/   r4   r   r   s       r2   r   zIBedrockGuardrail._update_messages_with_updated_bedrock_guardrail_response/  sw      ??&
  &&P 22! 3   $$(B(B &&b r3   c                  K   ddl }ddlm} ddlm} ddlm} g }|2 3 d{   }	|j                  |	       7 6  ||      }
t        |
t              r| j                  d|j                  d      |	      }| j                  d
|
      }|j                  ||       d{  7  \  }}| j                  |
|        ||
      }|2 3 d{  7  }	|	 6 y|D ]  }	|	 	 yw)z
        Process streaming response chunks.

        Collect content from the stream and make parallel bedrock api requests to get the guardrail responses.
        r   N)MockResponseIterator)stream_chunk_builder)TextCompletionResponse)chunksr7   r4   r   rH   )r9   rF   r   )model_response)asyncio)litellm.llms.base_llm.base_model_iteratorr   litellm.mainr   litellm.types.utilsr   r?   rI   r   r   r_   gatherr   )r/   r   rF   r{   r   r   r   r   
all_chunkschunkassembled_model_response
input_taskoutput_task_output_guardrail_responsemock_responses                   r2   'async_post_call_streaming_iterator_hookz8BedrockGuardrail.async_post_call_streaming_iterator_hookV  s!     	R5> 13
# 	% 	%%e$	%8
 !
 	!
 .> 66)9)9*)ET` 7 J 77*B 8 K
 29K2 , ,(A( ++1+D ,  17M
  -  e  - $ $sD   C%:8:C%:A%C%B" &C%C
CCC%c                     g }|j                  dg       xs g }|st        j                  d       g S |D ]'  }|j                  d      }||j                  |       ) |S )z
        Extract all masked text outputs from the guardrail response.

        Args:
            bedrock_guardrail_response: Response from Bedrock guardrail

        Returns:
            List of masked text strings
        r   z-No masked outputs found in guardrail responser<   )r_   r   r.   r?   )r/   r   masked_output_textmasked_outputsr   rC   s         r2   r   z4BedrockGuardrail._extract_masked_texts_from_response  sq     )+&**9b9?R 	  &&'VWI$F*0**V*<L'")),7 %
 "!r3   r   c                 T   g }d}|D ]  }|j                         }|j                  d      }||j                  |       8t        |t              r|t        |      k  r8||   |d<   |dz  }n*t        |t              r| j                  |||      \  |d<   }|j                  |        |S )a  
        Apply masked texts to message content using index tracking.

        Args:
            messages: Original messages
            masked_texts: List of masked text strings from guardrail

        Returns:
            Updated messages with masked content
        r   r=      )content_listr   masking_index)copyr_   r?   rI   rL   lenlist_mask_content_list)r/   r4   r   updated_messagesr   r:   new_messager=   s           r2   r   z+BedrockGuardrail._apply_masking_to_messages  s     G!,,.K!ooi0G  ''4 '3' 3|#44-9--HK	*!Q&MGT*8<8O8O!(!-"/ 9P 95I& ##K0-  0  r3   r   r   c                 8   g }|D ]  }t        |t              rAd|v r=|j                         }|t        |      k  r||   |d<   |dz  }|j	                  |       Tt        |t
              se|t        |      k  r
||   }|dz  }||j	                  |        ||fS )a9  
        Apply masking to a list of content items.

        Args:
            content_list: List of content items
            masked_texts: List of masked text strings
            starting_index: Starting index in the masked_texts list

        Returns:
            Updated content list with masked items
        r<   r   )rI   r~   r   r   r?   rL   )r/   r   r   r   new_contentitemnew_items          r2   r   z#BedrockGuardrail._mask_content_list  s     /1 D$%&D.99; 3|#44'3M'BHV$!Q&M""8,D#& 3|#44'6D!Q&M#&&t, ! M))r3   r:   c                 <   g }|j                  d      }|yt        |t              r|j                  |       |S t        |t              rR|D ]M  }t        |t
              rd|v r|j                  |d          ,t        |t              s=|j                  |       O |S )z
        Get the content for a message.

        For bedrock guardrails we create a list of all the text content in the message.

        If a message has a list of content items, we flatten the list and return a list of text content.
        r=   Nr<   )r_   rI   rL   r?   r   r~   )r/   r:   rB   r=   r  s        r2   r>   z(BedrockGuardrail.get_content_for_message  s      "++i(?gs# ''0 $# &dD)fn(//V=c*(//5	  
 $#r3   c                 ,   | j                  |      }|st        j                  d       yt        j                  dt        |             t	        |t
        j                        r| j                  ||       yt        j                  dt        |             y)a  
        Apply masked content from bedrock guardrail to the response object.
        
        Args:
            response: The response object to modify
            bedrock_guardrail_response: Response from Bedrock guardrail containing masked content
        z2No masked outputs found, skipping response maskingNz1Applying masking to response with %d masked textsz)Unsupported response type for masking: %s)
r   r   r.   r   rI   rJ   r    _apply_masking_to_model_responser   type)r/   rF   r   r   s       r2   r   z+BedrockGuardrail._apply_masking_to_response  s     ??&
  &&'[\""?\AR	

 h 5 5611(LI ((;T(^r3   c                 8   d}|j                   D ]  }t        |t              rz|j                  j                  s+t        |j                  j                  t
              sP|t        |      k  s_||   |j                  _        |dz  }t        j                  d       t        |t              r{|j                  j                  st        |j                  j                  t
              s|t        |      k  s||   |j                  _        |dz  }t        j                  d       t        |t              s+|j                  s9t        |j                  t
              sU|t        |      k  se||   |_        |dz  }t        j                  d        y)z
        Apply masked texts to a ModelResponse object.
        
        Args:
            response: The ModelResponse object to modify in-place
            masked_texts: List of masked text strings from guardrail
        r   r   z)Applied masking to choice message contentz'Applied masking to choice delta contentz&Applied masking to choice text contentN)rK   rI   r   r:   r=   rL   r   r   r.   r   deltar   r<   )r/   rF   r   r   rM   s        r2   r  z1BedrockGuardrail._apply_masking_to_model_response6  s7    &&F&'*>>))j9O9OQT.U$s<'881=m1L.%*,22G F$45<<''Jv||7K7KS,Q$s<'88/;M/J,%*,22E FK0;;:fkk3#?$s<'88&2=&A%*,22D3 'r3   )NNF)NN)N)NNN).__name__
__module____qualname__r   rL   boolr-   r   r   r   rE   r	   r   r   rN   r   rP   rc   r~   rz   rJ   r   r   r
   r   r   r   r   r   	Exceptionr   r   r   r   r   r   r   r   r   intr   r   r>   r   r  __classcell__)r1   s   @r2   r"   r"   5   s    .2*.5:	
%c]
 #3-
 %-TN	
@htL\G]>^ cq .uS-EW?X ]k , 6:8<	)* 4 012 5m!345	
 
.$,X )-! ! 	!
 !  ~!L 6:@D'+:*)*:* 4 012:* 5g&;&;!;<=	:*
 tn:* 
":*z
BZ 
_l 
.N0N	N` :): : 	:
 	
: 
y#tT)	*: :x 55 *5 
	5 5n 0
0
 *0
 0
j%'(% %=% 
		%NC)C C 	C
 
+T1	2CJ"*B"	c"6( -.( >B3i( 		( T* I*59#Y*OR*	tCy#~	*>$/? $HTRUYDW $,s*+ %= 
	B'--'=A#Y'	'r3   r"   )1ossyspathinsertabspathrp   typingr   r   r   r   r   r   r	   fastapir
   rJ   litellm._loggingr   litellm.cachingr   %litellm.integrations.custom_guardrailr   r   !litellm.llms.bedrock.base_aws_llmr   &litellm.llms.custom_httpx.http_handlerr   r   litellm.proxy._typesr   r   r   litellm.types.llms.openair   Alitellm.types.proxy.guardrails.guardrail_hooks.bedrock_guardrailsr   r   r   r   r   r   r   r   r   r   r   GUARDRAIL_NAMEr"   r(   r3   r2   <module>r"     s    
 
 rwww  
 M M M !  1 % 9 0 8 6   h
 hr3   