
    ^h.                         S SK r S SKrS SKJrJrJrJrJr  S SKJ	r	  S SK
r
S SK
JrJr  S SKJr  S SKJr  S SKJr  S SKJr  S S	KJr  S S
KJr   " S S5      r " S S\5      rg)    N)ListLiteralOptionalTupleUnion)HTTPException)ModelResponseRouter)verbose_proxy_logger)	DualCache)CustomLogger)UserAPIKeyAuth)ModelGroupInfo)get_utc_datetimec                   T    \ rS rSrSrS\SS4S jrS\S\\	   4S jr
S\S	\4S
 jrSrg)DynamicRateLimiterCache   z\
Thin wrapper on DualCache for this file.

Track number of active projects calling a model.
cachereturnNc                     Xl         SU l        g )N<   r   ttl)selfr   s     b/home/james-whalen/.local/lib/python3.13/site-packages/litellm/proxy/hooks/dynamic_rate_limiter.py__init__ DynamicRateLimiterCache.__init__   s    
    modelc                    #    [        5       nUR                  S5      nSR                  X15      nU R                  R	                  US9I S h  vN nS nUb  [        U5      nU$  N7f)N%H-%M{}:{})key)r   strftimeformatr   async_get_cachelen)r   r   dtcurrent_minutekey_name	_responseresponses          r   r&   'DynamicRateLimiterCache.async_get_cache    sb     W->>.8**444BB	"& 9~H	 Cs   A	A$A"A$valuec                 F  #     [        5       nUR                  S5      nSR                  XA5      nU R                  R	                  XRU R
                  S9I Sh  vN   g N! [         a5  n[        R                  " SR                  [        U5      5      5        UeSnAff = f7f)z
Add value to set.

Parameters:
- model: str, the name of the model group
- value: str, the team id

Returns:
- None

Raises:
- Exception, if unable to connect to cache client (if redis caching enabled)
r!   r"   )r#   r.   r   Nz[litellm.proxy.hooks.dynamic_rate_limiter.py::async_set_cache_sadd(): Exception occured - {})
r   r$   r%   r   async_set_cache_saddr   	Exceptionr   	exceptionstr)r   r   r.   r(   r)   r*   es          r   r0   ,DynamicRateLimiterCache.async_set_cache_sadd*   s     	!#B[[1N~~n<H**11txx 2     	 **mttF
 G	s;   B!AA AA B!A 
B)0BBB!r   )__name__
__module____qualname____firstlineno____doc__r   r   r3   r   intr&   r   r0   __static_attributes__ r   r   r   r      sD    i D 3 8C=  D r   r   c                      ^  \ rS rSrS\4S jrS\4S jr SS\S\	\   S\
\	\   \	\   \	\   \	\   \	\   4   4S	 jjrS
\S\S\S\S   S\	\\\\4      4
S jrS\S
\4U 4S jjrSrU =r$ )_PROXY_DynamicRateLimitHandlerI   internal_usage_cachec                      [        US9U l        g )N)r   )r   rA   )r   rA   s     r   r   '_PROXY_DynamicRateLimitHandler.__init__L   s    $;BV$W!r   
llm_routerc                     Xl         g N)rD   )r   rD   s     r   update_variables/_PROXY_DynamicRateLimitHandler.update_variablesO   s    $r   r   priorityr   c                 J  #     Sn[         R                  b  U[         R                  ;  a5  [        R                  " SR	                  U[         R                  5      5        OVUbS  [         R                  bB  [
        R                  " SS5      c  [        R                  " S5        O[         R                  U   nU R                  R                  US9I Sh  vN nU R                  R                  US9I Sh  vN u  pVU R                  R                  US9nSnSn	Ub2  UR                  b  UR                  nUR                  b  UR                  n	Sn
Ub  Ub  X-
  n
OUb  Un
SnU	b  Ub  X-
  nOU	b  U	nSnU
b!  Ub  [        X-  U-  5      nO[        X-  5      nUb  US:  a  SnSnUb!  Ub  [        X-  U-  5      nO[        X-  5      nUb  US:  a  SnUUU
UU4$  GN N! [         a8  n[        R                   " S	R	                  [#        U5      5      5         SnAg
SnAff = f7f)aD  
For a given model, get its available tpm

Params:
- model: str, the name of the model in the router model_list
- priority: Optional[str], the priority for the request.

Returns
- Tuple[available_tpm, available_tpm, model_tpm, model_rpm, active_projects]
    - available_tpm: int or null - always 0 or positive.
    - available_tpm: int or null - always 0 or positive.
    - remaining_model_tpm: int or null. If available tpm is int, then this will be too.
    - remaining_model_rpm: int or null. If available rpm is int, then this will be too.
    - active_projects: int or null
   NzRPriority Reservation not set. priority={}, but litellm.priority_reservation is {}.LITELLM_LICENSEzPREMIUM FEATURE: Reserving tpm/rpm by priority is a premium feature. Please add a 'LITELLM_LICENSE' to your .env to enable this.
Get a license: https://docs.litellm.ai/docs/proxy/enterprise.)r   )model_groupr   z[litellm.proxy.hooks.dynamic_rate_limiter.py::check_available_usage: Exception occurred - {})NNNNN)litellmpriority_reservationr   errorr%   osgetenvrA   r&   rD   get_model_group_usageget_model_group_infotpmrpmr;   r1   r2   r3   )r   r   rI   weightactive_projectscurrent_model_tpmcurrent_model_rpmmodel_group_infototal_model_tpmtotal_model_rpmremaining_model_tpmremaining_model_rpmavailable_tpmavailable_rpmr4   s                  r   check_available_usage4_PROXY_DynamicRateLimitHandler.check_available_usageR   ss    (R	0F,,47#?#??$**hoo '">">
 %'*F*F*R99.5=(.. Z %99(CF$($=$=$M$M %N % O oo;;;NN 1 444G  .2O-1O+#''3&6&:&:O#''3&6&:&:O15*/@/L&5&I# ,&5#15*/@/L&5&I# ,&5#+/M".".$'(;(D(V$WM$'(;(D$EM(]Q-> !+/M".".$'(;(D(V$WM$'(;(D$EM(]Q-> !## e Oj  	0 **mttF
 0	0sT   H#CG G G 3G4C$G H#G G 
H (.HH#H  H#user_api_key_dictr   data	call_type)
completiontext_completion
embeddingsimage_generation
moderationaudio_transcriptionpass_through_endpointrerankc           
        #    SU;   a  UR                   R                  SS5      nU R                  US   US9I Sh  vN u  pgpn
Ub.  US:X  a(  [        SSSR	                  UR
                  UUU
5      0S	9eUb.  US:X  a(  [        SSS
R	                  UR
                  UU	U
5      0S	9eUc  UbE  [        R                  " U R                  R                  US   UR                  =(       d    S/S95        g N7f)za
- For a model group
- Check if tpm/rpm available
- Raise RateLimitError if no tpm/rpm available
r   rI   Nr   rI   r   i  rP   z:Key={} over available TPM={}. Model TPM={}, Active keys={})status_codedetailz:Key={} over available RPM={}. Model RPM={}, Active keys={}default_key)r   r.   )metadatagetrb   r   r%   api_keyasynciocreate_taskrA   r0   token)r   rd   r   re   rf   key_priorityr`   ra   	model_tpm	model_rpmrX   s              r   async_pre_call_hook2_PROXY_DynamicRateLimitHandler.async_pre_call_hook   s>    . d?*;*D*D*H*HD+L 00w-, 1   PM) (]a-?# #!]!d!d-55)%+	"
 
 *}/A# #!]!d!d-55)%+	"
 
 *m.G##--BB"7m066G-H C  Ms   9C4C2B7C4c                 @  >#     [        U[        5      (       a  U R                  R                  UR                  S   S9nUc#   SR                  UR                  S   5      5       eUR                  R                  SS 5      nU R                  US   US9I S h  vN u  pgpn
US   UUUU	U
S.UR                  S'   U$ [        TU ])  UUUS	9I S h  vN $  N: N! [         a:  n[        R                  " S
R                  [        U5      5      5        Us S nA$ S nAff = f7f)Nmodel_id)idz'Model info for model with id={} is NonerI   
model_namerp   )zx-litellm-model_groupz,x-ratelimit-remaining-litellm-project-tokensz.x-ratelimit-remaining-litellm-project-requestsz"x-ratelimit-remaining-model-tokensz$x-ratelimit-remaining-model-requestsz#x-ratelimit-current-active-projectsadditional_headers)re   rd   r,   zclitellm.proxy.hooks.dynamic_rate_limiter.py::async_post_call_success_hook(): Exception occured - {})
isinstancer	   rD   get_model_info_hidden_paramsr%   rt   ru   rb   superasync_post_call_success_hookr1   r   r2   r3   )r   re   rd   r,   
model_inforz   r`   ra   r{   r|   rX   r4   	__class__s               r   r   ;_PROXY_DynamicRateLimitHandler.async_post_call_success_hook   s^    )	(M22!__;;..z: < 
 *<CC++J7* /@.H.H.L.L/ 44(6 5   TiO 2<L1IHUJW>G@I?N ''(<=  ="3! >   ! 
  	 **u||F
 O	se   DBC C"C ;D<C CC DC C 
D!/DDDDD)rA   rD   rF   )r6   r7   r8   r9   r   r   r
   rG   r3   r   r   r;   rb   r   dictr   r   r1   r}   r   r<   __classcell__)r   s   @r   r?   r?   I   s    XY X%6 % 59f0f0$,SMf0	x}hsmXc]HSMQ
f0PB)B B 	B
 	
B 
id"#
BH,,-;, ,r   r?   )rw   rQ   typingr   r   r   r   r   fastapir   rN   r	   r
   litellm._loggingr   litellm.caching.cachingr   "litellm.integrations.custom_loggerr   litellm.proxy._typesr   litellm.types.routerr   litellm.utilsr   r   r?   r=   r   r   <module>r      sG   
  	 8 8 !  ) 1 - ; / / *1 1ha\ ar   