Ë
    tPêj„3  ã                   óÄ   — d Z ddlmZmZmZm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mZmZ d
dlmZ erddlmZ ddlmZ  G d„ dee«      Zy)z5
OpenAI Moderation Guardrail Integration for LiteLLM
é    )ÚTYPE_CHECKINGÚFinalÚLiteralÚOptional)ÚHTTPException)Úverbose_proxy_logger)ÚCustomGuardrailÚlog_guardrail_information)ÚLogging)Úget_async_httpx_clientÚhttpxSpecialProvider)ÚGuardrailEventHooks)ÚGenericGuardrailAPIInputsÚGuardrailStatusÚGuardrailTracingDetailé   )ÚOpenAIGuardrailBase©ÚOpenAIModerationResponse)ÚGuardrailConfigModelc                   óÌ  ‡ — e Zd ZdZ	 	 	 	 	 d&dededz  dedz  ded   dz  dedz  d	edz  fˆ fd
„Zdedz  fd„Z	deddfd„Z
d'd„Ze	 d(dededed   ded   def
d„«       Z	 	 	 	 	 d&dedz  dededz  dedz  dedz  dedz  dedz  fd„Z	 	 	 	 d)dedededz  dedz  dedz  dedz  fd „Zed!eez  ez  dedz  fd"„«       Zeded#   dz  fd$„«       Zedee   fd%„«       Zˆ xZS )*ÚOpenAIModerationGuardrailaè  
    LiteLLM Built-in Guardrail for OpenAI Content Moderation.

    This guardrail scans prompts and responses using the OpenAI Moderation API to detect
    harmful content, including violence, hate, harassment, self-harm, sexual content, etc.

    Configuration:
        guardrail_name: Name of the guardrail instance
        api_key: OpenAI API key
        api_base: OpenAI API endpoint
        model: OpenAI moderation model to use
        default_on: Whether to enable by default
    NÚguardrail_nameÚapi_keyÚapi_baseÚmodel)úomni-moderation-latestztext-moderation-latestÚstreaming_end_of_stream_onlyÚstreaming_sampling_ratec                 ó�  •— t        ‰| �  d
|t        | j                  «       «      dœ|¤Ž t	        t
        j                  ¬«      | _        |xs | j                  «       | _	        |xs d| _
        |xs d| _        |€dn|| _        |€dn|| _        | j                  st        d«      ‚t        j                   d	|| j                  «       y)z/Initialize OpenAI Moderation guardrail handler.)r   Úsupported_event_hooks)Úllm_providerzhttps://api.openai.com/v1r   NFé   zlOpenAI Moderation: api_key is required. Set OPENAI_API_KEY environment variable or pass it in configuration.z:Initialized OpenAI Moderation Guardrail: %s with model: %s© )ÚsuperÚ__init__ÚlistÚget_supported_event_hooksr   r   ÚGuardrailCallbackÚasync_handlerÚ_get_api_keyr   r   r   r   r   Ú
ValueErrorr   Údebug)	Úselfr   r   r   r   r   r   ÚkwargsÚ	__class__s	           €ú€/home/oem/CyberBrain26-unified/.venv/lib/python3.12/site-packages/litellm/proxy/guardrails/guardrail_hooks/openai/moderations.pyr&   z"OpenAIModerationGuardrail.__init__1   sÙ   ø€ ô 	‰Ñð 	
Ø)Ü"& t×'EÑ'EÓ'GÓ"Hñ	
ð ò	
ô 4ÔAU×AgÑAgÔhˆÔð Ò5 $×"3Ñ"3Ó"5ˆŒØ Ò?Ð$?ˆŒØRWÒRsÐ[sˆŒ
ð
 2Ð9‰EÐ?[ð 	Ô)ð 2IÐ1P©AÐVmˆÔ$à�|Š|ÜØ~óð ô 	×"Ñ"ØHÈ.ÐZ^×ZdÑZdõ	
ó    Úreturnc                 ó    — ddl }ddl}ddlm} |j                  j                  d«      xs$ |j                  xs |j                  xs  |d«      S )z?Get API key from environment variables or litellm configurationr   N)Úget_secret_strÚOPENAI_API_KEY)ÚosÚlitellmÚlitellm.secret_managers.mainr5   ÚenvironÚgetr   Ú
openai_key)r.   r7   r8   r5   s       r1   r+   z&OpenAIModerationGuardrail._get_api_keyY   sM   € ããÝ?ð �J‰J�N‰NÐ+Ó,ò 0Ø�‰ò0à×!Ñ!ò0ñ Ð.Ó/ð		
r2   Ú
input_textr   c              ƒ   óÄ  K  — | j                   |dœ}t        j                  d|«       | j                  j	                  | j
                  › d�d| j                  › �ddœ|¬«      ƒ d{  –—† }t        j                  d	|j                  «       «       |j                  d
k7  r$t        |j                  d|j                  dœ¬«      ‚ddlm}  |di |j                  «       ¤ŽS 7 Œw­w)z>
        Make a request to the OpenAI Moderation API.
        )r   Úinputz#OpenAI Moderation guard request: %sz/moderationszBearer zapplication/json)ÚAuthorizationzContent-Type)ÚurlÚheadersÚjsonNz$OpenAI Moderation guard response: %séÈ   z$OpenAI Moderation API request failed)ÚerrorÚdetails©Ústatus_codeÚdetailr   r   r$   )r   r   r-   r*   Úpostr   r   rC   rH   r   ÚtextÚlitellm.types.llms.openair   )r.   r=   Úrequest_bodyÚresponser   s        r1   Úasync_make_requestz,OpenAIModerationGuardrail.async_make_requestg   sÛ   è ø€ ð )-¯
©
¸ZÑHˆä×"Ñ"Ð#HÈ,ÔWà $× 2Ñ 2× 7Ñ 7Ø—=‘=�/ Ð.à#*¨4¯<©<¨.Ð!9Ø 2ñð ð !8ó !
÷ 
ˆô 	×"Ñ"Ð#IÈ8Ï=É=Ë?Ô[à×Ñ 3Ò&ÜØ$×0Ñ0àCØ'Ÿ}™}ñôð õ 	Gá'Ñ:¨(¯-©-«/Ñ:Ð:ð-
ús   ‚A$C Á&CÁ'A8C c                 óN  — |j                   sy|j                   d   }|j                  r}g }|j                  r6|j                  j                  «       D ]  \  }}|sŒ	|j	                  |«       Œ ||j
                  xs i dœ}t        j                  d|«       t        dd|dœ¬«      ‚y)	zk
        Check if the moderation response indicates harmful content and raise exception if needed.
        Nr   )Úviolated_categoriesÚcategory_scoresz5OpenAI Moderation: Content flagged for violations: %si�  z!Violated OpenAI moderation policy)rE   Úmoderation_resultrG   )	ÚresultsÚflaggedÚ
categoriesÚitemsÚappendrR   r   Úwarningr   )r.   Úmoderation_responseÚresultrQ   ÚcategoryÚis_violatedÚviolation_detailss          r1   Ú_check_moderation_resultz2OpenAIModerationGuardrail._check_moderation_result‡   s½   € ð #×*Ò*Øà+×3Ñ3°AÑ6ˆØ�>Š>à)+ÐØ× Ò Ø-3×->Ñ->×-DÑ-DÓ-Fò =Ñ)�H˜kÚ"Ø+×2Ñ2°8Õ<ð=ð
 (;Ø#)×#9Ñ#9Ò#?¸Rñ(Ðô
 !×(Ñ(ØGØ!ôô
  Øà@Ø):ñôð ð% r2   ÚinputsÚrequest_dataÚ
input_type)ÚrequestrN   Úlogging_objÚLiteLLMLoggingObjc              ƒ   ó¬  K  — d}|j                  d«      x}r| j                  |«      }|s$|j                  d«      x}rdj                  |«      }|st        j                  d«       |S | j                  |¬«      ƒ d{  –—† }t        |t        «      r-|j                  d«      xs i }	|	|d<   |j                  «       |	d<   | j                  |«       |S 7 ŒT­w)	aÍ  
        Apply OpenAI moderation guardrail using the unified guardrail interface.

        This method is called by the UnifiedLLMGuardrails system for all endpoint types
        (chat completions, embeddings, responses API, etc.).

        Args:
            inputs: GenericGuardrailAPIInputs containing texts and/or structured_messages
            request_data: The original request data
            input_type: Whether this is a "request" (pre-call) or "response" (post-call)
            logging_obj: Optional logging object

        Returns:
            The inputs unchanged (moderation doesn't modify content, only blocks)

        Raises:
            HTTPException: If content violates moderation policy
        NÚstructured_messagesÚtextsú
z8OpenAI Moderation: No text content to moderate in inputs)r=   ÚmetadataÚ_openai_moderation_response)
r;   Úget_user_promptÚjoinr   r-   rO   Ú
isinstanceÚdictÚ
model_dumpr_   )
r.   r`   ra   rb   rd   Útext_to_moderaterg   rh   rZ   rj   s
             r1   Úapply_guardrailz)OpenAIModerationGuardrail.apply_guardrail©   sî   è ø€ ð6 (,Ðð #)§*¡*Ð-BÓ"CÐCÐÐCØ#×3Ñ3Ð4GÓHÐñ  ØŸ
™
 7Ó+Ð+ˆuÐ+à#'§9¡9¨UÓ#3Ð áÜ ×&Ñ&Ð'aÔbØˆMð ,0×+BÑ+BÐN^Ð+BÓ+_×%_Ðô �l¤DÔ)Ø*×.Ñ.¨zÓ:Ò@¸bˆHØ'/ˆL˜Ñ$Ø6I×6TÑ6TÓ6VˆHÐ2Ñ3ð 	×%Ñ%Ð&9Ô:ð ˆð &`ús   ‚A;CÁ=CÁ>ACrN   Ú
start_timeÚend_timeÚdurationÚ
event_typeÚoriginal_inputsc                 óÔ   — t        |t        «      r|j                  d«      xs i }||d<   ni }|j                  dd«      }	| j	                  |	|d||||| j                  |	«      ¬«       |S )zÑ
        Override to log the full OpenAI Moderation API response instead of
        the decorator's simplified "allow"/"mask" string.

        Follows the Model Armor pattern (model_armor.py:325-360).
        rj   rk   ÚallowÚsuccess©Úguardrail_json_responsera   Úguardrail_statusru   rs   rt   rv   Útracing_detail)rn   ro   r;   ÚpopÚ:add_standard_logging_guardrail_information_to_request_dataÚ_build_tracing_detail)
r.   rN   ra   rs   rt   ru   rv   rw   rj   Úguardrail_responses
             r1   Ú_process_responsez+OpenAIModerationGuardrail._process_responseä   s†   € ô  �l¤DÔ)Ø#×'Ñ'¨
Ó3Ò9°rˆHØ'/ˆL˜Ò$àˆHð
 %-§L¡LÐ1NÐPWÓ$XÐà×GÑGØ$6Ø%Ø&ØØ!ØØ!Ø×5Ñ5Ð6HÓIð 	Hô 		
ð ˆr2   Úec                 óþ   — | j                  |«      rdnd}t        |t        «      r|j                  d«      xs i }||d<   ni }|j	                  d|«      }	| j                  |	||||||| j                  |	«      ¬«       |‚)z€
        Override to log the full OpenAI Moderation API response on error
        instead of the stringified exception.
        Úguardrail_intervenedÚguardrail_failed_to_respondrj   rk   r{   )Ú_is_guardrail_interventionrn   ro   r;   r   r€   r�   )
r.   r„   ra   rs   rt   ru   rv   r}   rj   r‚   s
             r1   Ú_process_errorz(OpenAIModerationGuardrail._process_error  s¢   € ð '+×&EÑ&EÀaÔ&HÑ"ÐNkð 	ô �l¤DÔ)Ø#×'Ñ'¨
Ó3Ò9°rˆHØ'/ˆL˜Ò$àˆHð =E¿L¹LÐIfÐhiÓ<jÐà×GÑGØ$6Ø%Ø-ØØ!ØØ!Ø×5Ñ5Ð6HÓIð 	Hô 		
ð ˆr2   r‚   c           	      ó  — t        | t        «      sy| j                  d«      xs g }|D ���cg c]A  }t        |t        «      r/|j                  d«      xs i j                  «       D ]	  \  }}|r|‘Œ ŒC }}}}|syt	        |¬«      S c c}}}w )a~  
        Pull the flagged category names out of the moderation response so trace
        backends can index a short, queryable ``guardrail_violation_categories``
        attribute instead of the full ``guardrail_response`` blob, whose
        ``category_scores`` map (one float per category) blows past indexed-field
        length limits on backends like ELK (1024 chars).
        NrT   rV   )Úviolation_categories)rn   ro   r;   rW   r   )r‚   rT   r[   r\   Ú
is_flaggedr‹   s         r1   r�   z/OpenAIModerationGuardrail._build_tracing_detail1  s¢   € ô Ð,¬dÔ3Øà+×/Ñ/°	Ó:Ò@¸bˆð "÷'
ð '
àÜ˜&¤$Ô'Ø)/¯©°LÓ)AÒ)GÀR×(NÑ(NÓ(Pò	'
ñ %�˜*Ùò	 ð'
Øð'
Ðò '
ñ $ØÜ%Ð;OÔPÐPùô'
s   ­ABr   c                  ó   — ddl m}  | S )zK
        Get the config model for the OpenAI Moderation guardrail.
        r   ©Ú$OpenAIModerationGuardrailConfigModel)ÚGlitellm.types.proxy.guardrails.guardrail_hooks.openai.openai_moderationr�   rŽ   s    r1   Úget_config_modelz*OpenAIModerationGuardrail.get_config_modelK  s   € õ
	
ð 4Ð3r2   c                 ó`   — t         j                  t         j                  t         j                  gS ©N)r   Úpre_callÚduring_callÚ	post_call)Úclss    r1   r(   z3OpenAIModerationGuardrail.get_supported_event_hooksV  s)   € ô  ×(Ñ(Ü×+Ñ+Ü×)Ñ)ð
ð 	
r2   )NNNNN)rZ   r   r3   Nr“   )NNNN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__Ústrr   ÚboolÚintr&   r+   rO   r_   r
   r   ro   r   rr   Úfloatr   rƒ   Ú	Exceptionr‰   Ústaticmethodr   r�   Útyper‘   Úclassmethodr'   r(   Ú__classcell__)r0   s   @r1   r   r   "   sE  ø„ ñð" #Ø#ØTXØ48Ø.2ñ&
àð&
ð �t‘ð&
ð ˜‘*ð	&
ð
 ÐIÑJÈTÑQð&
ð '+¨T¡kð&
ð "% t¡õ&
ðP
˜c D™jó 
ð;°3ð ;Ð;Uó ;ó@ ðD ð 6:ñ8à)ð8ð ð8ð Ð1Ñ2ð	8ð
 Ð1Ñ2ð8ð 
#ò8ó ð8ð| $(Ø!%Ø!%Ø15Ø'+ñ%à˜‘+ð%ð ð%ð ˜D‘Lð	%ð
 ˜$‘,ð%ð ˜$‘,ð%ð (¨$Ñ.ð%ð  ™ó%ðV $(Ø!%Ø!%Ø15ñ$àð$ð ð$ð ˜D‘Lð	$ð
 ˜$‘,ð$ð ˜$‘,ð$ð (¨$Ñ.ó$ðL ðQØ  3™J¨Ñ2ðQà	 $Ñ	&òQó ðQð2 ð4˜dÐ#9Ñ:¸TÑAò 4ó ð4ð ð
¨$Ð/BÑ*Cò 
ó ô
r2   r   N) r›   Útypingr   r   r   r   Úfastapir   Úlitellm._loggingr   Ú%litellm.integrations.custom_guardrailr	   r
   Ú*litellm.litellm_core_utils.litellm_loggingr   re   Ú&litellm.llms.custom_httpx.http_handlerr   r   Úlitellm.types.guardrailsr   Úlitellm.types.utilsr   r   r   Úbaser   rL   r   Ú3litellm.types.proxy.guardrails.guardrail_hooks.baser   r   r$   r2   r1   ú<module>r¯      sV   ðñ÷ ;Ó :å !å 1÷õ T÷õ 9÷ñ õ &áÝBÝXôz
Ð 3°_õ z
r2   