
    h                    |   d dl Z d dlZd dlZd dlZd dlZd dlmZ d dlmZ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Zd dl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% d dl&m'Z'm(Z( d dl)m*Z*m+Z+m,Z,m-Z-m.Z. d dl/ ddl0 ddl1m2Z2m3Z3 ddl4m5Z5 er	d dl6m7Z8 e8Z7neZ7 G d de      Z9y)    N)	timedelta)TYPE_CHECKINGAnyDictListLiteralOptionalTupleUnion)APIError)verbose_loggerverbose_proxy_logger)	DualCache)HOURS_IN_A_DAY)CustomBatchLogger)get_budget_alert_type)AlertingHangingRequestCheck)duration_in_seconds)_add_key_name_and_team_to_alert)get_async_httpx_clienthttpxSpecialProvider)	AlertTypeCallInfoLitellm_EntityTypeVirtualKeyEventWebhookEvent)*      )send_to_webhooksquash_payloads) process_slack_alerting_variables)Routerc                       e Zd ZdZddg edi dfdee   dee   dee   dee	   dee
e	eee   ef   f      dee   f fd	Z	 	 	 	 	 	 dZdee   dee   deee	      dee
e	eee   ef   f      d
ee
   dee   fdZd Zd Zd Zd Zd[dZd ZdedefdZdefdZ	 d[dee   fdZdedefdZded   defdZ ded eed!      d"ede!eed!      ef   fd#Z"dedefd$Z#dedefd%Z$d&ee   d'ee   d(ee   d)ee   d*ee   f
d+Z%d,ee   defd-Z&d.ed/   d0ed1   d2ed3ed4ee   d5e'defd6Z(d7e)d8eddfd9Z*d7e)d8eddfd:Z+d;ed<ed=e,fd>Z-d;efd?Z.d@e/defdAZ0	 	 d\dBedCee   dDee   fdEZ1d@e/defdFZ2d@e/d.edefdGZ3	 d[dHedIedJ   d.e	dKedee/   f
dLZ4dM Z5dN Z6dO Z7defdPZ8d[dee,   fdQZ9	 d]dRefdSZ:dT Z;dU Z<dVe=d.e	dWefdXZ>dee   defdYZ? xZ@S )^SlackAlertingz(
    Class for sending Slack Alerts
    Ninternal_usage_cachealerting_thresholdalertingalert_typesalert_to_webhook_urldefault_webhook_urlc                    |d}|| _         || _        || _        |xs
 t               | _        t        t        j                        | _        t        |      | _
        d| _        t        di || _        || _        t        j                          | _        d| _        t'        |       | _        t+        	| X  di |d| j"                  i y )Ni,  )llm_providerr*   F)slack_alerting_object
flush_lock )r'   r(   r)   r   r&   r   r   LoggingCallbackasync_http_handlerr"   r*   
is_runningSlackAlertingArgsalerting_argsr+   asyncioLockr0   periodic_startedr   hanging_request_checksuper__init__)
selfr&   r'   r(   r)   r*   r6   r+   kwargs	__class__s
            m/var/www/Befach/backend/env/lib/python3.12/site-packages/litellm/integrations/SlackAlerting/slack_alerting.pyr<   zSlackAlerting.__init__<   s     %!$"4 &$8$GIK!"8-==#
 %E!5%
!  .??#6 !,,. %%@"&&
" 	>6>doo>    r6   
llm_routerc                    |1|| _         t        j                  | j                                d| _        ||| _        ||| _        |Ft        di || _        | j                  s*t        j                  | j                                d| _        |I| j                  t        |      | _	        n+t        |      xs i }| j                  j                  |       ||| _        y y )NTr.   r1   )r(   r7   create_taskperiodic_flushr9   r'   r)   r5   r6   r*   r"   updaterB   )r=   r(   r'   r)   r*   r6   rB   _new_valuess           r@   update_valueszSlackAlerting.update_valuesa   s     $DM 3 3 56$(D!)&8D#"*D$!2!C]!CD((##D$7$7$9:(,%+((0,L)=-)
 5-A  	  ))00=!(DO "rA   c                    K   y wNr1   r=   s    r@   deployment_in_cooldownz$SlackAlerting.deployment_in_cooldown   	        c                    K   y wrJ   r1   rK   s    r@    deployment_removed_from_cooldownz.SlackAlerting.deployment_removed_from_cooldown   rM   rN   c                      t        t              S rJ   )listr   rK   s    r@   _all_possible_alert_typesz'SlackAlerting._all_possible_alert_types   s     IrA   c                 >   	 ||z
  }|j                         }|j                  di       }|j                  dd      }t        j                  ||      }|j                  dd       }	|	|j                  dd       }	t	        |	      d d }
||||
fS # t
        $ r}|d }~ww xY w)Nlitellm_paramsmodel rV   optional_paramsmessagesinputd   )total_secondsgetlitellmget_api_basestr	Exception)r=   r>   
start_timeend_timetime_differencetime_difference_floatrU   rV   api_baserZ   	_messageses               r@   )_response_taking_too_long_callback_helperz7SlackAlerting._response_taking_too_long_callback_helper   s    	&3O$3$A$A$C!#ZZ(8"=NJJw+E++%XHzz*d3H!::gt4 Hds+I(%9DD 	G	s   B	B 	BBBc           	      (   |y d|v r|	 d}|d   }t        |      dk(  ry d }	 t        |j                         d       }t        |      }|y |j                         D ]  \  }}|d| dt        |d       d	z  } d
|z   d
z   }|S y # t        $ r Y Gw xY w)N_latency_per_deploymentrW   r   c                     | d   S )Nr   r1   )xs    r@   <lambda>zBSlackAlerting._get_deployment_latencies_to_alert.<locals>.<lambda>   s    1rA   key
: r   sz```)lensorteditemsdictrb   round)r=   metadata_message_to_send_deployment_latencies_deployment_latency_maprg   latencys          r@   "_get_deployment_latencies_to_alertz0SlackAlerting._get_deployment_latencies_to_alert   s    $0
  "$,-F$G!()Q.6:#(.)//1~)% +//D*E' '.%<%B%B%D!' b
"U715E4Fa$HH  &E$'77%?##9 1&  s   'B 	BBc                   K   | j                   | j                  y | j                  |||      \  }}}}t        j                  st        j
                  rd}d| d| d| d}	dt        |d       d	| j                   d
}
i }|| j                  kD  rv|Ed|v rAd|d   v r:|d   d   }t        |	|      }	| j                  |      }||	d| z  }	d|v r|d   }| j                  |
|	z   dt        j                  |       d {    y y 7 w)N)r>   rc   rd   z>Message not logged. litellm.redact_messages_in_exceptions=Truez
Request Model: `z`
API Base: `z`
Messages: ``z`Responses are slow - r   z&s response time > Alerting threshold: zs`rU   rz   )request_inforz   )rz   z 
Available Deployment Latencies
alerting_metadataLowmessagelevel
alert_typer   )r(   r)   rj   r_   turn_off_message_loggingredact_messages_in_exceptionsry   r'   r   r   
send_alertr   llm_too_slow)r=   r>   completion_responserc   rd   rf   rV   rg   rZ   r   slow_messager   	_metadatar}   s                 r@   !response_taking_too_long_callbackz/SlackAlerting.response_taking_too_long_callback   s     == D$4$4$< ::! ; 
	
! ++w/T/TWH+E7.
.YaXbbcd/6KA0N/OOuvz  wN  wN  vO  OQ  R"$ 4#:#:: "$.&)9"::"()9"::"F	>!-	  +/*Q*Q& +R +' +6 <=T<UVL ')3(12E(F%//$|3$11"3	 "   - ;,s   C?D
DD
deployment_metricsreturnc                   K   d}	 |j                   r]| j                  j                  dj                  |j                  t
        j                  j                        dd       d{    |dz  }|j                  g| j                  j                  dj                  |j                  t
        j                  j                        |j                  d       d{    |dz  }|S 7 ~7 # t        $ r Y yw xY ww)ax  
        Store the perf by deployment in cache
        - Number of failed requests per deployment
        - Latency / output tokens per deployment

        'deployment_id:daily_metrics:failed_requests'
        'deployment_id:daily_metrics:latency_per_output_token'

        Returns
            int - count of metrics set (1 - if just latency, 2 - if failed + latency)
        r   {}:{}r   N)rq   valueparent_otel_span)failed_requestr&   async_increment_cacheformatidSlackAlertingCacheKeysfailed_requests_keyr   latency_per_output_tokenlatency_keyrb   )r=   r   
return_vals      r@   async_update_daily_reportsz(SlackAlerting.async_update_daily_reports  s	     
	!00//EE*--.BBHH %) F    a
 "::F//EE*--/E/Q/Q/W/W -EE%) F    a
/  		sN   C7AC( %C$&A2C( C&
C( #C7$C( &C( (	C41C73C44C7c                   K   |j                         }|D cg c],  }dj                  |t        j                  j                        . }}|D cg c],  }dj                  |t        j
                  j                        . }}||z   }| j                  j                  |       d{   }|yd}|D ]  }	|	|	dkD  sd} n |ry|dt        |       }
|t        |      d }d}|
D cg c]  }||n|
 c}t        t        t                    fdd      dd	 }|D cg c]  }|   dkD  s| }}d}|D cg c]  }||n|
 c}t        t        t                    fd
d      dd	 }|D cg c]  }|   dkD  s| }}dt        j                          d}|dz  }|s|dz  }t        t        |            D ]  }|||      j                  d      d   }|j                  |      }t        |t              r|d   j!                  dd      }n yt#        j$                  |||d   ni       }|d}||      }|d|dz    d| d| d| d	z  } |dz  }|s|dz  }t        t        |            D ]  }|||      j                  d      d   }|j                  |      }||d   j!                  dd      }nd}t#        j$                  |||d   ni       }t'        ||      d      }|d|dz    d| d| d| d	z  } |D cg c]  }|df }}|D cg c]  }|df }}||z   }| j                  j)                  |       d{    |d t        j                         | j*                  j,                  z    d!z  }| j/                  |d"t0        j2                  i #       d{    yc c}w c c}w 7 c c}w c c}w c c}w c c}w c c}w c c}w 7 7 2w)$a  
        Send a daily report on:
        - Top 5 deployments with most failed requests
        - Top 5 slowest deployments (normalized by latency/output tokens)

        Get the value from redis cache (if available) or in-memory and send it

        Cleanup:
        - reset values in cache -> prevent memory leak

        Returns:
            True -> if successfuly sent
            False -> if not sent
        r   )keysNFTr   c                     |    S rJ   r1   )ireplaced_failed_valuess    r@   ro   z2SlackAlerting.send_daily_reports.<locals>.<lambda>q  s    03rA   )rq   reverse   c                     |    S rJ   r1   )r   replaced_slowest_valuess    r@   ro   z2SlackAlerting.send_daily_reports.<locals>.<lambda>  s    1!4rA   z	

Time: `u(   `s
Here are today's key metrics 📈: 

u7   

*❗️ Top Deployments with Most Failed Requests:*

z	None
:rU   rV   rW   rX   	r   z. Deployment: `z`, Failed Requests: `z`,  API Base: ``
u#   

*😅 Top Slowest Deployments:*

   z`, Latency per output token: `zs/token`,  API Base: ``

)
cache_listz

Next Run is at: `z`sr   r   )get_model_idsr   r   r   r   r   r&   async_batch_get_cacheru   rv   rangetimesplitget_model_info
isinstancerx   r^   r_   r`   ry   async_set_cache_pipeliner6   daily_report_frequencyr   r   daily_reports)r=   routeridsr   failed_request_keyslatency_keyscombined_metrics_keyscombined_metrics_valuesall_nonevalfailed_request_valueslatency_valuesplaceholder_valuer   top_5_failedindextop_5_slowestr   r   rq   _deploymentdeployment_namerg   latency_cache_keysfailed_request_cache_keyscombined_metrics_cache_keysr   r   s                             @@r@   send_daily_reportsz SlackAlerting.send_daily_reports4  s%      ""$
 
 NN25IIOOP
 

 TW
MOGNN25AAGGH
 
 !4l B(,(A(A(W(W& )X )
 #
 #**C37  +
  7&c%&!
 15H1I1KL  /"
 &E,=="
 #,-.3
 1	  ,
/Ee/Lq/PE
 
  (#
 &E,==#
 #-./4
 1	  -
0G0NQR0RE
 

  		},WXPPz!Gs<()A%l1o6<<SA!DC //4K+t,"-.>"?"C"CGR"P++%5@5LK 01RTH *<?;EAaC5/@@UV[U\\kltkuuxyyG# *& 	<<z!Gs=)*A}Q/066s;A>C //4K&"-.>"?"C"CGR"P"$++%5@5LK 01RTH 1-2BCQGEAaC5/@@^_d^ee{  }E  |F  FK  L  LG +" 3??3sAh??9L$M#c1X$M!$M&8;T&T#''@@2 A 
 	
 	
 	*499;9K9K9b9b+b*cceff oo .. 	  
 	
 	
 C

#
0"

#

b @$M	
	
s   O!1N2
O!1N7&O!'N<(O!9O!?*O!)N?6-O!#O1O5O!=O	
-O!7OO	FO!OO!O)&O!OAO!,O-O!?O!O!request_datac                    K   | j                   | j                  y t        j                  | j                  vry | j                  j                  |       d {    y 7 w)N)r   )r(   r)   r   llm_requests_hangingr:   $add_request_to_hanging_request_check)r=   r   s     r@   response_taking_too_longz&SlackAlerting.response_taking_too_long  s^      == D$4$4$<))1A1AA((MM% N 
 	
 	
s   AA AA error_messagefailing_modelc                   K   | j                   | j                  yd| j                  vry| j                  }d|z   }dj                  |      }|j	                  |       d{   }|\| j                  |dt        j                  i        d{    |j                  |d| j                  j                  	       d{    yy7 c7 87 
w)
z
        Raise alert when tracking failed for specific model

        Args:
            error_message (str): Error message
            failing_model (str): Model that failed tracking
        Nfailed_tracking_spendzFailed Tracking Cost for z budget_alerts:failed_tracking:{}rp   Highr   SENTrq   r   ttl)r(   r)   r&   r   async_get_cacher   r   r   async_set_cacher6   budget_alert_ttl)r=   r   r   _cacher   
_cache_keyresults          r@   failed_tracking_alertz#SlackAlerting.failed_tracking_alert  s      == D$4$4$<"$*:*:: 55-=7>>}M
--*-==>//$::"$	 "    ((&&77 )     >s6   A C"C#,CC/C?C
 CC
Ctype)token_budgetsoft_budgetuser_budgetteam_budgetproxy_budgetprojected_limit_exceeded	user_infoc                   K   | j                   }| j                  | j                  yd| j                  vryt        |      }|j	                  |      }|j                  d      }| j                  |      }|j                         }|dk(  rdnd}	d}
|j                  |j                  y| j                  |	||      \  }	}|	|j                  dj                  |	|      }|j                  |       d{   }|pt        d|	|d	|}
| j                  |d
z   |z   dt         j"                  |
i        d{    |j%                  |d| j&                  j(                         d{    yy7 x7 87 
w)z
        Send a budget alert on slack or webhook

        Args:
            type: The type of budget alert to send
            user_info: The user info to send the alert for
        Nbudget_alertsTexclude_noner   )eventr   event_messagezbudget_alerts:{}:{}rp   )r   r   

r   )r   r   r   r   r   r   r   r1   )r&   r(   r)   r   get_id
model_dump_get_user_info_strget_event_message
max_budgetr   _get_event_and_event_messageevent_groupr   r   r   r   r   r   r   r6   r   )r=   r   r   r   budget_alert_class_iduser_info_jsonuser_info_strr   r   webhook_eventr   r   s                r@   r   zSlackAlerting.budget_alerts  s    . !55== D$4$4$<$"2"22 348 ''	2"--4-@//	:*<<> +/2L*L&RV 	 15 'I,A,A,I  $@@'  A  
} !6!6!B.55eSAJ!11j1AAF~ , !"/! %!
 oo)F2]B (66+&( &    ,," **;; -    + Bs7   C4E56E/7AE58E19/E5(E3)E51E53E5r   )budget_crossedthreshold_crossedsoft_budget_crossedr   r   c                 f   | j                  |      }|j                  .|j                  |j                  k\  rd}|d|j                   dz  }|j                  V|j                  |j                  k\  rd}|d|j                   dz  }||fS |t        k  rd}|dz  }||fS |t
        k  rd}|d	z  }||fS )
z
        Get the event and event message for a budget alert

        This will append any new information to the event_message

        Handles Max Budget and Soft Budget Alerts
        )r   r   zTotal Soft Budget:`r   r   zBudget Crossed
 Total Budget:`r   z5% Threshold Crossed z15% Threshold Crossed)_get_percent_of_max_budget_leftr   spendr   "SLACK_ALERTING_THRESHOLD_5_PERCENT#SLACK_ALERTING_THRESHOLD_15_PERCENT)r=   r   r   r   percent_lefts        r@   r   z*SlackAlerting._get_event_and_event_messageP  s    < #BBYBW   ,)"7"77-#6y7L7L6MQ!OO +)"6"66(5i6J6J5K1M m## !CC+!88
 m##	 !DD+!88m##rA   c                 `    d}|j                   }|j                  }||S |dk  r|S ||z
  |z  }|S )z@
        Get the percent of the max budget that is left
        g        r   )r  r   )r=   r   r  current_spendr   s        r@   r  z-SlackAlerting._get_percent_of_max_budget_left  sK     "(&/&:&:
?"]2j@rA   c                     |j                  d      }|j                  d       d}|j                         D ]-  \  }}t        |t              r|j
                  }|d| d| dz  }/ |S )z>
        Create a standard message for a budget alert
        Tr   tokenrW   r   :* `r   )r   poprw   r   r   r   )r=   r   _all_fields_as_dictmsgkvs         r@   r   z SlackAlerting._get_user_info_str  sv     (222E('--/DAq!/0GGQqcaS$$C 0
 
rA   r	  	key_aliasend_user_idresponse_costr   c                    K   | j                   id| j                   v rZ|W|T|Qt        ||||d d d |d d dt        j                  dj	                  ||            }| j                  |       d {    y y y y y y 7 
w)Nwebhookspend_trackedz-Customer spend tracked. Customer={}, spend={})r  r   r	  customer_iduser_idteam_id
user_emailr  projected_exceeded_dateprojected_spendr   r   r   r   )r(   r   r   END_USERr   send_webhook_alert)r=   r	  r  r  r  r   r   s          r@   customer_spend_alertz"SlackAlerting.customer_spend_alert  s      MM%T]]*'!) !#%'#(, $%.77MTTE$ )))>>>+ * " ( + &2 ?s   A,A;.A9/A;alertsc                     dddd}|D ]5  }|dk(  r|dxx   dz  cc<   |dk\  r|dxx   dz  cc<   )|dxx   dz  cc<   7 d	}|j                         D ]   \  }}|dkD  s|d
j                  ||      z  }" |S )z
        Parameters:
        - alerts: List[int] -> list of error codes (either 408 or 500+)

        Returns:
        - str -> formatted string. This is an alert message, giving a human-friendly description of the errors.
        r   )Timeout Errors
API ErrorsUnknown Errors  r"  r     r#  r$  rW   z
{}: {}
)rw   r   )r=   r   error_breakdownalert	error_msgrq   r   s          r@   _count_outage_alertsz"SlackAlerting._count_outage_alerts  s     ./aSTUE| 01Q61#-2- 01Q61  	)//1JCqy\00e<<	 2 rA   r   )MajorMinorrq   )ModelRegionkey_valproviderrg   outage_valuec                     | d|d|i}|||d<   d}|j                         D ]  \  }	}
|d|	 d|
 dz  } d| d	| d
| j                  |d          dt        t        j                         |d   z
  d       d	S )z!Format an alert message for slackz NameProviderzAPI Baserr   r   r
  r   u   


*⚠️ z Service Outage*

z

*Errors:*
r   )r   z

*Last Check:* `last_updated_at   z	s ago`


)rw   r*  ry   r   )r=   r   rq   r/  r0  rg   r1  headersheaders_strr  r  s              r@   _outage_alert_msg_factoryz'SlackAlerting._outage_alert_msg_factory  s     U%=':x@"*GJMMODAqQqcaS,,K $		   ,x"89 : ;diikL1B$CCQGH I	 		rA   	exceptiondeployment_idc                   K   | j                   y| j                   j                  |      }|y|j                  j                  }|j                  j                  }|t        j                  |      \  }}}}|j                  j                  }|+t
        j                  j                  ||j                        }|y||z   }| j                  j                  |       d{   }	t        |dd      *|j                  dk7  r|j                  dk  s| j                   y|	t               }
|
j                  |       t!        ||j                  gd	d	t#        j"                         |

      }	| j                  j%                  ||	| j&                  j(                         d{    yt+        |	d         | j&                  j,                  k  r|	d   j/                  |j                         n	 |	d   }
|
j                  |       |
|	d<   t#        j"                         |	d<   |	d   d	u r{t+        |	d         | j&                  j0                  k\  rVt+        |
      dkD  rH| j3                  dd|d|	|      }| j5                  |dt6        j8                  i        d{    d|	d<   n|	d   d	u rzt+        |	d         | j&                  j:                  k\  rUt+        |
      dkD  rG| j3                  dd|d|	|      }| j5                  |dt6        j8                  i        d{    d|	d<   | j                  j%                  ||	       d{    y7 c7 7 7 77 w)z
        Send slack alert if specific provider region is having an outage.

        Track for 408 (Timeout) and >=500 Error codes
        Nmodel_idrV   )custom_llm_providerrU   rp   status_coder%  r&  F)provider_region_idr   minor_alert_sentmajor_alert_sentr4  deployment_idsr   r   rD  r4  rB  r   r,  r.  r   rq   r/  rg   r1  r0  Mediumr   TrC  r+  r   rq   r   )rB   get_deploymentrU   rV   r?  r_   get_llm_providerregion_nameutils_get_model_regionr&   r   getattrr@  setaddProviderRegionOutageModelr   r   r6   region_outage_alert_ttlru   max_outage_alert_list_sizeappendminor_outage_alert_thresholdr8  r   r   outage_alertsmajor_outage_alert_threshold)r=   r9  r:  
deploymentrV   r0  _rJ  	cache_keyr1  _deployment_setr  s               r@   region_outage_alertsz"SlackAlerting.region_outage_alerts  s     ??"__33]3K
))//,,@@$+$<$<5$I!E8Q !//;;!--99$,Z=V=V : K  {*	 ++;;	;JJ 	
 I}d3;%%,))C/&!eO.4#,!--.!&!& $		.L ++;;"&&>> <   
 |H%&););)V)VV")))*?*?@&'78M*)8%&*.))+&' +,5L*+!!>>?O$q(00"#)! 1 C //$22"$	 "    04L+, +,5L*+!!>>?O$q(00"#)! 1 C //$22"$	 "    04L+, ''77 8 
 	
 	
} K4@4	
s]   C M"M#B<MM C3MMBMM)M?M MMMMMc                   K   	 | j                   j                  |       d{   }t        |dd      *|j                  dk7  r|j                  dk  s| j                  y| j                  j                  |      }|y|j                  j                  }|j                  j                  }|	 t        j                  |      \  }}}}t        j                  ||j                  	      }|ht        ||j                  gd
d
t        j                               }| j                   j                  ||| j                   j"                         d{    yt%        |d         | j                   j&                  k  r|d   j)                  |j                         n	 t        j                         |d<   |d   d
u rmt%        |d         | j                   j*                  k\  rH| j-                  dd||||      }	| j/                  |	dt0        j2                  i        d{    d|d<   ns|d   d
u rlt%        |d         | j                   j4                  k\  rG| j-                  dd||||      }	| j/                  |	dt0        j2                  i        d{    d|d<   | j                   j                  ||       d{    y7 # t        $ r d}Y w xY w7 7 7 I7 !# t        $ r Y yw xY ww)a
  
        Send slack alert if model is badly configured / having an outage (408, 401, 429, >=500).

        key = model_id

        value = {
        - model_id
        - threshold
        - alerts []
        }

        ttl = 1hr
        max_alerts_size = 10
        rp   Nr@  r%  r&  r<  r>  rW   rX   F)r=  r   rB  rC  r4  r   r   r4  rB  r,  r-  rE  rF  r   TrC  r+  r   rG  )r&   r   rM  r@  rB   rH  rU   rV   r?  r_   rI  rb   r`   OutageModelr   r   r6   outage_alert_ttlru   rR  rS  rT  r8  r   r   rU  rV  )
r=   r9  r:  r1  rW  rV   r0  rX  rg   r  s
             r@   rU  zSlackAlerting.outage_alerts  sG    &j	8<8Q8Q8a8afs8a8t2tL	=$7?))S0!--3??* 777OJ!--33E!00DDH",3,D,D5,Q)E8Q ++Z-F-FH #**%112%*%*$(IIK  //??%&**;; @   
  L*+$$??@ X&--i.C.CD.2iikL*+ /0E9X./%%BBC 44&!%!-% 5  oo"(66&(	 &    48/0/0E9X./%%BBC 44&!%!-% 5  oo (66&(	 &    48/0 ++;;! <   K 3u* ! "!H" @,  		s   K*K J=;K K* K >K*?.K .K  	BK KK K*CK KA3K K)K 7K8K <K*=K  KK KK K K K 	K'$K*&K''K*
model_namelitellm_model_namepassed_model_infoc                   K   t        |dd       }i }d}|'t        j                  j                  |i       }d| d}n t        j                  j                  |i       }d}|j	                         D ]+  \  }}	|dk(  s|dk(  rdj                  |	      }	|| d|	 d	z  }- d
| d| dt        j                  dd       d| d| d}
| j                  |
dt        j                  i       }|!t        j                  |      r| d {    y y y 7 w)N
base_modelrW   zBase Model: `r   input_cost_per_tokenoutput_cost_per_tokenz{:.8f}rs   rr   u%   
*🚅 New Model Added*
Model Name: `zn

Usage OpenAI Python SDK:
```
import openai
client = openai.OpenAI(
    api_key="your_api_key",
    base_url=PROXY_BASE_URLhttp://0.0.0.0:4000z:
)

response = client.chat.completions.create(
    model="z", # model to send to the proxy
    messages = [
        {
            "role": "user",
            "content": "this is a test request, write a short poem"
        }
    ]
)
```

Model Info: 
```
z
```
r   r   )rM  r_   
model_costr^   rw   r   osgetenvr   r   new_model_addedr7   iscoroutine)r=   r_  r`  ra  base_model_from_user
model_inforc  model_info_strr  r  r   	alert_vals               r@   model_added_alertzSlackAlerting.model_added_alert
  s^      ''8,M

+ ++//0DbIJ()=(>cBJ ++//0BBGJ$$&DAq**a3J.JOOA&2aSm+N '\   ii(*?@A B <    5< OO 00 	 $ 
	  W%8%8%COO &D s   D DD
Dc                    K   y wrJ   r1   )r=   r_  s     r@   model_removed_alertz!SlackAlerting.model_removed_alertE  rM   rN   r   c                   K   t        j                  dd      }|t        d      |j                         }ddi}| j                  j                  |||       d{   }|j                  dk(  ryt        d	|j                         y
7 +w)z
        Sends structured alert to webhook, if set.

        Currently only implemented for budget alerts

        Returns -> True if sent, False if not.

        Raises Exception
            - if WEBHOOK_URL is not set
        WEBHOOK_URLNz$Missing webhook_url from environmentContent-typeapplication/json)urlr6  data   Tz#Error sending webhook alert. Error=F)	ri  rj  rb   model_dump_jsonr3   postr@  printtext)r=   r   webhook_urlpayloadr6  responses         r@   r  z SlackAlerting.send_webhook_alertH  s      iit4BCC//1!#560055 6 
 

 3&7G
s   AB	B,B	premium_useremail_logo_urlemail_support_contactc                 p   K   ddl m}m} |dur&||"t        d|j                  j
                         y w)Nr   )CommonProxyErrorsr  Tz$Trying to Customize Email Alerting
 )litellm.proxy.proxy_serverr  r  
ValueErrornot_premium_userr   )r=   r  r  r  r  s        r@   %_check_if_using_premium_email_featurez3SlackAlerting._check_if_using_premium_email_featureg  sJ      	Ot#)-B-N ;<M<^<^<d<d;ef  	s   46c                 x  K   	 ddl m} | j                  d| j                  vr!t        j                  d| j                         yddlm}m} t        j                  dt        j                  dd             }t        j                  d	d       }| j                  |||       d {    |t        }|t        }|j                  }|j                  }|j                  }	|B|	@|>|j                   j"                  j%                  d
|	i       d {   }
|
|
j                  }|j&                  }|j(                  }t        j                  dd      }d}|%t        j                  d|j+                                |j,                  dk(  rt.        j1                  ||||||      }n|j,                  dk(  ro|j2                  }d}|D|B|j                   j4                  j%                  d|i       d {   }||j6                  xs d}t8        j1                  |||||      }n%t        j                  d|j;                                |j=                          |d| |d} ||d   |d   |d          d {    y7 7 q7 7 # t>        $ r)}t        j                  d tA        |             Y d }~yd }~ww xY ww)!Nr   
send_emailemailz;Error sending email alert - 'email' not in self.alerting %sF)r  prisma_clientSMTP_SENDER_LOGOEMAIL_LOGO_URLEMAIL_SUPPORT_CONTACTr  )whererf  rg  Alert from LiteLLM Server*Trying to send email alert to no recipientextrakey_created)r  recipient_email
key_budget	key_tokenbase_urlr  internal_user_createdzDefault Teamr  -)r  r  	team_namer  r  z3Trying to send email alert on unknown webhook event	LiteLLM: tosubjecthtmlr  r  r  receiver_emailr  r  TzError sending email alert %s)!litellm.proxy.utilsr  r(   r   errorr  r  r  ri  rj  r  LITELLM_LOGO_URLLITELLM_SUPPORT_CONTACTr   r  r  dblitellm_usertablefind_uniquer	  r   rx   r   KEY_CREATED_EMAIL_TEMPLATEr   r  litellm_teamtable
team_aliasUSER_INVITED_EMAIL_TEMPLATEr   r{  rb   ra   )r=   r   r  r  r  r  r  
event_namer  recipient_user_iduser_rowr  r  r  email_html_contentr  r  team_rowemail_eventri   s                       r@   &send_key_created_or_user_invited_emailz4SlackAlerting.send_key_created_or_user_invited_emailv  s    c	6}}$t}}(D$**QMM NYY"BII.>$EN %'II.Et$L!<<n.C   %!1$,(?%&44J+66O - 5 5'%1!-!.!1!1!C!C!O!O$&78 "P "  '&.&9&9O%++I&11Jyy!13HIH!<&$**@',,.
 ""m3%?%F%F#1$3)'%*? &G &" $$(??'//*	&=+D%2%5%5%G%G%S%S('2 &T &  H  +$,$7$7$>3	%@%G%G#1$3'%*? &H &" %**I'224
 ))+%&zl3*K *40#I. (   _ @ 2  	 &&'Es1vN	s   J:A J J:AJ #I;$A)J I>C J .J/BJ 5J6J :J:;J >J J J 	J7J2-J:2J77J:c           	        K   ddl m} ddlm} t	        j
                  dt	        j
                  dd            }t	        j
                  dd      }| j                  |||       d{    |t        }|t        }|j                  }|j                  }|j                  }	|j                  }
d}|%t        j                  d	|j                         
       |j                   dk(  rd| d|	 d|
 d| d	}|j#                          |d| |d} ||d   |d   |d          d{    |j$                  dk(  rddlm}  ||       d{    y7 7 -7 	w)z
        Sends structured Email alert to an SMTP server

        Currently only implemented for budget alerts

        Returns -> True if sent, False if not.
        r   )r  r  r  r  Nr  r  r  r  r   z
            <img src="zD" alt="LiteLLM Logo" width="150" height="50" />

            <p> Hi ze, <br/>

            Your LLM API usage this month has reached your account's <b> monthly budget of $a   </b> <br /> <br />

            API requests will be rejected until either (a) you increase your monthly budget or (b) your monthly usage resets at the beginning of the next calendar month. <br /> <br />

            If you have any questions, please send an email to zY <br /> <br />

            Best, <br />
            The LiteLLM team <br />
            r  r  r  r  r  r  team)send_team_budget_alertr  F)r  r  r  r  ri  rj  r  r  r  r   r  r  r   r   r  rx   r   r{  r   #litellm.integrations.email_alertingr  )r=   r   r   r  r  r  r  r  r  	user_namer   r  r  r  s                 r@   send_email_alert_using_smtpz)SlackAlerting.send_email_alert_using_smtp  s     	<2		*:D A
 !#		*A4 H88.*?
 	
 	
 !-N ($;!"00
'22!))	"--
8" &&<MDVDVDX "22&%& '; ]]g\h i@ AV?V W" 	%%'!":,/&
 &t,	*V$
 	
 	

 $$.R(}EEEi	
T	
 Fs7   A#E%E&B;E!E"%EEEEEr   r   )r   rF  r   r   c                   K   | j                   yd| j                   v r!|dk(  r|| j                  |       d{    d| j                   v r"|dk(  r|| j                  ||       d{    d| j                   vry|| j                  vrydd	lm}  |j
                         j                  d
      }t        j                  dd      }	|dk(  s|dk(  r|}
nd| d| d| }
|r$|j                         D ]  \  }}|
d| d| dz  }
 |r$|j                         D ]  \  }}|
d| d| dz  }
 |		|
d|	 dz  }
| j                  || j                  v r| j                  |   }n/| j                  | j                  }nt        j                  dd      }|t        d      d|
i}ddi}t        |t              r(|D ]"  }| j                  j!                  ||||d       $ n | j                  j!                  ||||d       t#        | j                        | j$                  k\  r| j'                          d{    yy7  7 7 w)a  
        Alerting based on thresholds: - https://github.com/BerriAI/litellm/issues/1298

        - Responses taking too long
        - Requests are hanging
        - Calls are failing
        - DB Read/Writes are failing
        - Proxy Close to max budget
        - Key Close to max budget

        Parameters:
            level: str - Low|Medium|High - if calls might fail (Medium) or are failing (High); Currently, no alerts would be 'Low'.
            message: str - what is the alert about
        Nr  r   r  r  )r   r   slackr   )datetimez%H:%M:%Srf  r   rk  zLevel: `z`
Timestamp: `z`

Message: r   : `r   z

*Alerting Metadata*: 
z

Proxy URL: `r   SLACK_WEBHOOK_URLz*Missing SLACK_WEBHOOK_URL from environmentr~  rv  rw  )rx  r6  r  r   )r(   r  r  r)   r  nowstrftimeri  rj  rw   r*   r+   r  r   rR   	log_queuerS  ru   
batch_sizeflush_queue)r=   r   r   r   r   r   r>   r  current_time_proxy_base_urlformatted_messagerq   r   slack_webhook_urlr  r6  rx  s                    r@   r   zSlackAlerting.send_alert%  s    . ==  &o-%))	)BBB t}}$o-% 22'J 3    $--'T---% $x||~..z:))$4d;(J:K,K ' 5'nWIV  $lln
U!tC5E7%%@@! -/557
U!'B3%s5'QV%WW! 8&#3O3DA!FF %%1d777 ))*5  %%1 $ 8 8 "		*=t D$IJJ,-!#56'.(%%"#*#*&0	 ) NN!!,&&",	 t~~$//1""$$$ 2Y CJ %s4   8IH:/I*H=+GI3I 4I=I Ic           	      $  K   | j                   sy t        | j                         }|j                         D cg c]  }t        | |d   |d          }}t	        j
                  |  d {    | j                   j                          y c c}w 7 $w)Nitemcount)slackAlertingInstancer  r  )r  r!   valuesr    r7   gatherclear)r=   squashed_queuer  taskss       r@   async_send_batchzSlackAlerting.async_send_batch  s     ~~(8
 '--/	
  &*fT']
 
 nne$$$
 	%s   5BB	B)B*%Bc           	        K   	 d| j                   v r-|j                  di       xs i }|j                  di       xs i }|j                  dd      xs d}||z
  }|}	t        |t        j                        rgt        |d      r[|j                  Ot        |j                  d      r9|j                  j                  }
|
!|
d	kD  rt        |j                         |
z        }	t        |	t              r|	j                         }	| j                  t        |d
|	t        j                  j                                      d{    yy7 # t        $ r+}t!        j"                  dt%        |              Y d}~yd}~ww xY ww)zLog deployment latencyr   rU   rn  r   rW   usageNcompletion_tokensr   Fr   r   r   
updated_atzR[Non-Blocking Error] Slack Alerting: Got error in logging LLM deployment latency: )r)   r^   r   r_   ModelResponsehasattrr  r  floatr]   r   r   DeploymentMetricsrK  get_utc_datetimerb   r   r  ra   )r=   r>   response_objrc   rd   rU   rn  r=  
response_sfinal_valuer  ri   s               r@   async_log_success_eventz%SlackAlerting.async_log_success_event  sp    "	$"2"22!',<b!A!GR+//bAGR
%>>$39r(0:(=
(lG,A,ABL'2$**6 2 24GH(4(:(:(L(L%(49JQ9N&+&4469JJ' k95"-";";"=K55%#',1<#*==#A#A#C	  + 3*  	 &&dehijekdlm 		sA   E:D6E :E;E ?E:E 	E7!E2-E:2E77E:c           	        K   |j                  di       }|j                  di       xs i }|j                  dd      }	 d| j                  v rC	 | j                  t        |ddt        j
                  j                                      d{    t        |j                  d
d      t              rZd| j                  v r| j                  |d
   |       d{    d| j                  v r| j                  |d
   |       d{    yyy7 # t        $ r+}t        j                  d	t        |              Y d}~d}~ww xY w7 l7 B# t        $ r Y yw xY ww)z Log failure + deployment latencyrU   rn  r   rW   r   TNr  zException raises -r9  rU  )r9  r:  r[  )r^   r)   r   r  r_   rK  r  rb   r   debugra   r   r   rU  r[  )	r=   r>   r  rc   rd   _litellm_params_model_infor=  ri   s	            r@   async_log_failure_eventz%SlackAlerting.async_log_failure_event  ss     **%5r:%)),;Ar??4,	$"2"22
H99)'+/59'.}}'E'E'G	   &**["5x@"d&6&66,,"("5&. -   
 *T-=-==33"("5X 4    > A ! H"((+=c!fX)FGGH
  		s   ;EE =D 
D
D AE E+E EE E
D 	E !D;6E ;E  E E 	EEEEc                 T  K   d}| j                   j                  t        j                  j                  d       d{   }t        j
                         }|?| j                   j                  t        j                  j                  |       d{    |S t        |t              rw| j                  j                  }||z
  |k\  rY| j                  |       d{    | j                   j                  t        j                  j                  |       d{    d}|S 7 7 7 I7 w)z[
        Returns:
        - True -> report sent
        - False -> report not sent
        FN)rq   r   rG  )r   T)r&   r   r   report_sent_keyr   r   r   r   r  r6   r   r   )r=   rB   report_sent_boolreport_sentr  interval_secondss         r@   _run_scheduler_helperz#SlackAlerting._run_scheduler_helper  s0     ! 55EE&66<<! F 
 

 yy{++;;*::@@" <   $   U+#11HHk)-==--Z-@@@//??.>>DD& @    $( 5
 AsG   ;D(D AD(D"A	D(D$<D(D&	D("D($D(&D(c                 H  K   || j                   yd| j                   v r}	 | j                  |       d{    t        j                  | j                  j
                  dz
  | j                  j
                  dz         }t        j                  |       d{    |y7 g7 w)z
        If 'daily_reports' enabled

        Ping redis cache every 5 minutes to check if we should send the report

        If yes -> call send_daily_report()
        Nr   )rB   r   )r)   r  randomrandintr6   report_check_intervalr7   sleep)r=   rB   intervals      r@   _run_scheduled_daily_reportz)SlackAlerting._run_scheduled_daily_report  s      !1!1!9d...00J0GGG!>>&&<<q@&&<<q@ mmH---  	 H
 .s"   4B"BA B"B B" B"
time_rangec                   K   | j                   d| j                  vry	 ddlm} t	        |dd       }|d   j                         dk7  rt        d      t        j                  j                         j                         }|t        j                  |      z
  }d	|j                  d
       d|j                  d
       }| j                  j                  |       d{   ry ||j                  d
      |j                  d
             d{   }||g g fk(  ry|\  }}	d|j                  d       d|j                  d       d| d}
|3|
dz  }
|D ])  }t        t        |d         d      }|
d|d    d| dz  }
+ |	3|
dz  }
|	D ])  }t        t        |d         d      }|
d|d    d| dz  }
+ | j!                  |
dt"        j$                  i        d{    | j                  j'                  |dt)        |              d{    y7 47 7 :7 # t        $ r"}t+        j,                  d!|        Y d}~yd}~wt.        $ r"}t+        j,                  d"|        Y d}~yd}~ww xY ww)#z
        Send a spend report for a configurable time range.

        Args:
            time_range: A string specifying the time range for the report, e.g., "1d", "7d", "30d"
        Nspend_reportsr    _get_spend_report_for_time_rangedz0Time range must be specified in days, e.g., '7d'daysweekly_spend_report_sent_%Y-%m-%drX  rp   
start_dateend_dateu   *💸 Spend Report for `%m-%d-%Y - z` (z days)*

*Team Spend Report:*
total_spendr5  Team: `r  ` | Spend: `$r   
*Tag Spend Report:*
Tag: `individual_request_tagr   r   r   r   zInvalid time range format: zError sending spend report: )r(   r)   7litellm.proxy.spend_tracking.spend_management_endpointsr  intlowerr  r  r  dater   r  r&   r   ry   r  r   r   r  r   r   r   r  rb   )r=   r  r  r  todays_dater  _event_cache_key_respspend_per_teamspend_per_tag_spend_messager  _team_spend
_tag_spendveri   s                   r@   send_weekly_spend_reportz&SlackAlerting.send_weekly_spend_report!  s     == O4;K;K$K:	K
 z#2'D"~##%, !STT"++//1668K$x'9'9t'DDJ!::;N;Nz;Z:[[\]h]q]qr|]}\~..>>CS>TTT:%..z:$--j9 E }"b 1,1)NM7
8K8KJ8W7XX[\g\p\pq{\|[}  ~A  BF  AG  GP  QN)"<<+E"'eM.B(CQ"GK"!%"5!6mK=PSTN , (";;*E!&uU=-A'BA!FJ"u5M/N.O}]g\hhk&llN + //&$22"$	 "    ++;;$'
3 <   G U2  	K &&)DRD'IJJ 	K &&)EaS'IJJ	Ks   I3B?H HH #I3$+H HH I3B?H H.H HH I3H H H H 	I0%I=I3I0I+&I3+I00I3c                   K   	 ddl m} ddlm} t        j                  j                         j                         }|j                  d      } ||j                  |j                        \  }}|t	        j                  |dz
        z   }d|j                  d       d	|j                  d       }| j                  j                  |
       d{   ry ||j                  d      |j                  d             d{   }||g g fk(  ry|\  }	}
d|j                  d       d|j                  d       d}|	7|dz  }|	D ]-  }|d   }t        |      }t        |d      }|d|d    d| dz  }/ |
7|dz  }|
D ]-  }|d   }t        |      }t        |d      }|d|d    d| dz  }/ | j!                  |dt"        j$                  i        d{    | j                  j'                  |ddt(        z  dz  dz          d{    y7 =7 7 >7 # t*        $ r }t-        j.                  d!|       Y d}~yd}~ww xY ww)" r   )
monthranger  r   )dayr  monthly_spend_report_sent_r  rX  rp   Nr  u    *💸 Monthly Spend Report for `r  r  z` *
r  r  r5  r	  r  r
  r   r  r  r  r   r   r      <   r   $Error sending weekly spend report %s)calendarr  r  r  r  r  r  replaceyearmonthr   r  r&   r   r  ry   r   r   r  r   r   rb   r   r9  )r=   r  r  r  first_day_of_monthrX  last_day_of_monthr  r  monthly_spend_per_teammonthly_spend_per_tagr  r  r  r  ri   s                   r@   send_monthly_spend_reportz'SlackAlerting.send_monthly_spend_reportj  s    @	V+ #++//1668K!,!4!4!4!;#-k.>.>@Q@Q#R A  2X5G5G&*6 ! "<<N<W<WXb<c;ddefw  gA  gA  BL  gM  fN   O..>>CS>TTT:-66zB*33J? E
 }"b 1<A9"$9?@R@[@[\f@g?hhkl}  mG  mG  HR  mS  lT  TY  ZN%1"<<3E"'"6K"'"4K"'Q"7K"!%"5!6mK=PSTN 4 %0";;2E!&}!5J!&z!2J!&z1!5J"u5M/N.O}]g\hhk&llN 3 //&$22"$	 "    ++;;$.(2-2 <   U U@  	V **+QSTUU	Vs   ICH HH I+H  HH ICH H2H HH IH H H H 	H?H:5I:H??Ic                    K   	 ddl m}  |        d{   }d| }| j                  |dt        j                  i        d{    y7 57 # t
        $ r }t        j                  d|       Y d}~yd}~ww xY ww)z
        Helper to send fallback statistics from prometheus server -> to slack

        This runs once per day and sends an overview of all the fallback statistics
        r   )#get_fallback_metric_from_prometheusNz*Fallback Statistics:*
r   r   r#  )6litellm.integrations.prometheus_helpers.prometheus_apir.  r   r   fallback_reportsrb   r   r  )r=   r.  !falllback_success_info_prometheusfallback_messageri   s        r@   #send_fallback_stats_from_prometheusz1SlackAlerting.send_fallback_stats_from_prometheus  s     	R :;; .
 ++L*MN  //($55"$	 "    	# <  	R &&'MqQQ	RsP   A:A A
/A AA 	A:
A A 	A7A2-A:2A77A:	key_eventr  c                   K   	 d| d}|j                         }|dz  }|j                         D ]  \  }}d|v s|| d| dz  } |dz  }|j                  }|j                         D ]  \  }}|dk(  r|| d| dz  } | j                  |d|i 	       d
{    y
7 # t        $ r }	t        j                  d|	       Y d
}	~	y
d
}	~	ww xY ww)z
        Handles sending Virtual Key related alerts

        Example:
        - New Virtual Key Created
        - Internal User Updated
        - Team Created, Updated, Deleted
        r   r   z*Action Done by:*

created_byr  z
*Arguments passed:*
user_api_key_dictr   r   Nz-Error sending send_virtual_key_event_slack %s)r   rw   request_kwargsr   rb   r   r  )
r=   r4  r   r  r   key_event_dictrq   r   r8  ri   s
             r@   send_virtual_key_event_slackz*SlackAlerting.send_virtual_key_event_slack  s    	*S)G&113N ,,G,224
U3&#c%44G 5
 00G&55N,224
U--cU#eWC00 5
 //%"$	 "    	  	 &&?  		sF   C5B! AB! BB! CB! !	C
*C CC

Cc                   K   |y|j                  dd      dk7  rh|j                  dd      dk7  rS|j                  dd      }| j                  j                  dj                  |      d	
       d{   }||dk(  s|dk(  ry	y7 w)z[
        Returns True if the request is completed - either as a success or failure
        NFlitellm_statusrW   successfaillitellm_call_idzrequest_status:{}T)rq   
local_only)r^   r&   r   r   )r=   r   r?  statuss       r@   _request_is_completedz#SlackAlerting._request_is_completed  s       -r2i?  !126&@ +../@"EO*.*C*C*S*S'..?D +T + %F !v':f>N%s   A/B1B2B)NNNNNNrJ   )NN)7d)A__name__
__module____qualname____doc__DEFAULT_ALERT_TYPESr	   r   r  r   r   r   r   ra   r<   r#   rH   rL   rP   rS   rj   r   r   r  r  r   boolr   rx   r   r   r   r   r   r
   r   r  r   r  r*  BaseOutageModelr8  r   r[  rU  r   rq  rs  r   r  r  r  r  r   r  r  r  r  r  r  r,  r3  r   r:  rB  __classcell__)r?   s   @r@   r%   r%   6   s    59 #%': -1#?&y1#? %
#? 4.#? )_#? 'E$s)S.112
#? &c]#?N $(.215QU(,'+&)4.&) %UO&) d9o.	&)
 'tIuT#Y^7L,L'MN&)  ~&) V$&)P2 $D4l,"3,	,\T$ Tp (,
tn
 S >W(
W Wr<$<$ ,
<$ <$ 
,	
 		

<$| e H  "?}"? C="? c]	"?
  "? UO"?H49  0,- &' 	
  3- & 
8G
G
 G
 
	G
R}} } 
	}~99369KN9vC l t D )-/3	 !  (}	f)f	fPE)E7:E	EZ -1l%l% ./l% 	l%
  l% L)l%\$LB"  " HHSM . GKGKRBVH@-"- - 	-^ 4 rA   r%   ):r7   r  ri  r  r   r   typingr   r   r   r   r   r	   r
   r   openair   r_   litellm.litellm_core_utils*litellm.litellm_core_utils.litellm_logginglitellm.typeslitellm._loggingr   r   litellm.caching.cachingr   litellm.constantsr   (litellm.integrations.custom_batch_loggerr   5litellm.integrations.SlackAlerting.budget_alert_typesr   8litellm.integrations.SlackAlerting.hanging_request_checkr   *litellm.litellm_core_utils.duration_parserr   2litellm.litellm_core_utils.exception_mapping_utilsr   &litellm.llms.custom_httpx.http_handlerr   r   litellm.proxy._typesr   r   r   r   r   )litellm.types.integrations.slack_alertingemail_templates.templatesbatching_handlerr    r!   rK  r"   litellm.routerr#   _Routerr%   r1   rA   r@   <module>r`     s      	    R R R   ! 1  A - , F W K  8 ) > 30FFY% YrA   