Ë
    tPêj‰.  ã                   óö   — d dl Z d dlZd dlmZ d dlmZ d dlmZ d dlZd dlmZm	Z	 d dl
mZ d dlmZ d dlmZ d d	lmZ d d
lmZ d dlmZ d dlmZmZ d dlmZ d dlmZ d dlmZ  G d„ d«      Z G d„ de«      Z y)é    N)ÚCallable)Údatetime)ÚFinal)ÚModelResponseÚRouter)Úverbose_proxy_logger)Ú	DualCache)ÚRateLimitType)ÚCustomLogger)ÚUserAPIKeyAuth)ÚProxyRateLimitError)Úconvert_priority_to_percentÚ#resolve_llm_provider_for_rate_limit)ÚModelGroupInfo)ÚCallTypesLiteral)Úget_utc_datetimec                   óX   — e Zd ZdZefdedeg ef   ddfd„Zde	de
dz  fd„Zde	d	efd
„Zy)ÚDynamicRateLimiterCachezh
    Thin wrapper on DualCache for this file.

    Track number of active projects calling a model.
    ÚcacheÚtime_fnÚreturnNc                 ó.   — || _         d| _        || _        y )Né<   )r   Úttlr   )Úselfr   r   s      úm/home/oem/CyberBrain26-unified/.venv/lib/python3.12/site-packages/litellm/proxy/hooks/dynamic_rate_limiter.pyÚ__init__z DynamicRateLimiterCache.__init__#   s   € ØˆŒ
ØˆŒØˆ�ó    Úmodelc              ƒ   óÈ   K  — | j                  «       }|j                  d«      }|› d|› �}| j                  j                  |¬«      ƒ d {  –—† }d }|�t	        |«      }|S 7 Œ­w)Nú%H-%Mú:)Úkey)r   Ústrftimer   Úasync_get_cacheÚlen)r   r   ÚdtÚcurrent_minuteÚkey_nameÚ	_responseÚresponses          r   r%   z'DynamicRateLimiterCache.async_get_cache(   si   è ø€ Ø—L‘L“NˆØ "§¡¨GÓ 4ˆØ+Ð,¨A¨e¨WÐ5ˆØ!%§¡×!;Ñ!;ÀÐ!;Ó!I×Iˆ	Ø#ˆØÐ Ü˜9“~ˆHØˆð	 Jús   ‚AA"Á
A ÁA"Úvaluec              ƒ   ó  K  — 	 | j                  «       }|j                  d«      }|› d|› �}| j                  j                  ||| j                  ¬«      ƒ d{  –—†  y7 Œ# t
        $ r}t        j                  d|«       |‚d}~ww xY w­w)a  
        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 - %s)r   r$   r   Úasync_set_cache_saddr   Ú	Exceptionr   Ú	exception)r   r   r,   r'   r(   r)   Úes          r   r.   z,DynamicRateLimiterCache.async_set_cache_sadd2   s…   è ø€ ð
	ØŸ™›ˆBØ$&§K¡K°Ó$8ˆNà!/Ð 0°°%°Ð9ˆHØ—*‘*×1Ñ1°hÀeÐQU×QYÑQYÐ1ÓZ×ZÒZùÜò 	Ü ×*Ñ*ØmÐopôð ˆGûð		üs;   ‚B„AA ÁAÁA ÁBÁA Á	BÁ(B Â BÂB)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r	   r   r   r   ÚstrÚintr%   Úlistr.   © r   r   r   r      s\   „ ñð L\ñ ˜ið °(¸2¸x¸<Ñ2Hð Ð`dó ð
¨3ð °3¸±:ó ð°ð ¸Dô r   r   c                   óÌ   ‡ — e Zd Zefdedeg ef   fd„Zdefd„Z		 dde
de
dz  d	eedz  edz  edz  edz  edz  f   fd
„Zdedededed	ee
z  ez  dz  f
d„Zdedefˆ fd„Zˆ xZS )Ú_PROXY_DynamicRateLimitHandlerÚinternal_usage_cacher   c                 ó(   — t        ||¬«      | _        y )N)r   r   )r   r<   )r   r<   r   s      r   r   z'_PROXY_DynamicRateLimitHandler.__init__O   s   € Ü$;ÐBVÐ`gÔ$hˆÕ!r   Ú
llm_routerc                 ó   — || _         y ©N)r>   )r   r>   s     r   Úupdate_variablesz/_PROXY_DynamicRateLimitHandler.update_variablesR   s	   € Ø$ˆ�r   Nr   Úpriorityr   c              ƒ   óþ  K  — 	 | j                   j                  |¬«      }d}t        j                  �|t        j                  vr&t	        j
                  d|t        j                  «       n]|�[t        j                  �Kt        j                  dd«      €t	        j
                  d«       nt        j                  |   }t        ||«      }| j                  j                  |¬«      ƒ d{  –—† }| j                   j                  |¬«      ƒ d{  –—† \  }}d}	d}
|�0|j                  �|j                  }	|j                  �|j                  }
d}|	�|�|	|z
  }n|	�|	}d}|
�|�|
|z
  }n|
�|
}d}|�"|�t        ||z  |z  «      }nt        ||z  «      }|�|dk  rd}d}|�"|�t        ||z  |z  «      }nt        ||z  «      }|�|dk  rd}|||||fS 7 Œæ7 ŒÄ# t        $ r }t	        j                   d	|«       Y d}~y
d}~ww xY w­w)a¤  
        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
        )Úmodel_groupé   NzRPriority Reservation not set. priority=%s, but litellm.priority_reservation is %s.ÚLITELLM_LICENSEz¾PREMIUM 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   r   z[litellm.proxy.hooks.dynamic_rate_limiter.py::check_available_usage: Exception occurred - %s)NNNNN)r>   Úget_model_group_infoÚlitellmÚpriority_reservationr   ÚerrorÚosÚgetenvr   r<   r%   Úget_model_group_usageÚtpmÚrpmr7   r/   r0   )r   r   rB   Úmodel_group_infoÚweightr,   Úactive_projectsÚcurrent_model_tpmÚcurrent_model_rpmÚtotal_model_tpmÚtotal_model_rpmÚremaining_model_tpmÚremaining_model_rpmÚavailable_tpmÚavailable_rpmr1   s                   r   Úcheck_available_usagez4_PROXY_DynamicRateLimitHandler.check_available_usageU   sn  è ø€ ð$M	0à=A¿_¹_×=aÑ=aÐnsÐ=aÓ=tÐàˆFÜ×+Ñ+Ð3°xÄw×GcÑGcÑ7cÜ$×*Ñ*ØhØÜ×0Ñ0õð
 Ð%¬'×*FÑ*FÐ*RÜ—9‘9Ð.°Ó5Ð=Ü(×.Ñ.ð Zõô $+×#?Ñ#?ÀÑ#I�EÜ8¸Ð@PÓQ�Fà+/×+DÑ+D×+TÑ+TÐ[`Ð+TÓ+a×%aˆOð —o‘o×;Ñ;ÈÐ;ÓN×NñØ!Ø!à*.ˆOØ*.ˆOØÐ+Ø#×'Ñ'Ð3Ø&6×&:Ñ&:�OØ#×'Ñ'Ð3Ø&6×&:Ñ&:�Oà.2ÐØÐ*Ð/@Ð/LØ&5Ð8IÑ&IÑ#Ø Ð,Ø&5Ð#à.2ÐØÐ*Ð/@Ð/LØ&5Ð8IÑ&IÑ#Ø Ð,Ø&5Ð#à(,ˆMà"Ð.Ø"Ð.Ü$'Ð(;¸fÑ(DÀÑ(VÓ$W‘Mä$'Ð(;¸fÑ(DÓ$E�MàÐ(¨]¸QÒ->Ø !�à(,ˆMà"Ð.Ø"Ð.Ü$'Ð(;¸fÑ(DÀÑ(VÓ$W‘Mä$'Ð(;¸fÑ(DÓ$E�MàÐ(¨]¸QÒ->Ø !�àØØ#Ø#Øðð ð] &bøð Oùôb ò 	0Ü ×*Ñ*ØmÐopôô 0ûð		0üsT   ‚G=„C"G Ã&GÃ'#G Ä
GÄCG ÇG=ÇG ÇG Ç	G:ÇG5Ç0G=Ç5G:Ç:G=Úuser_api_key_dictr   ÚdataÚ	call_typec              ƒ   óŒ  K  — d|v �r8|j                   j                  dd«      }| j                  |d   |¬«      ƒ d{  –—† \  }}}}	}
|�W|dk(  rRt        |j                  d«      «      \  }}t	        dd|j
                  › d|› d	|› d
|
› �it        j                  ||¬«      ‚|�W|dk(  rRt        |j                  d«      «      \  }}t	        dd|j
                  › d|› d|	› d
|
› �it        j                  ||¬«      ‚|€|�Bt        j                  | j                  j                  |d   |j                  xs dg¬«      «       y7 �Œ­w)z�
        - For a model group
        - Check if tpm/rpm available
        - Raise RateLimitError if no tpm/rpm available
        r   rB   N©r   rB   r   rJ   zKey=z over available TPM=z. Model TPM=z, Active keys=)ÚdetailÚrate_limit_typer   Úllm_providerz over available RPM=z. Model RPM=Údefault_key)r   r,   )ÚmetadataÚgetr[   r   r   Úapi_keyr
   ÚTOKENSÚREQUESTSÚasyncioÚcreate_taskr<   r.   Útoken)r   r\   r   r]   r^   Úkey_priorityrY   rZ   Ú	model_tpmÚ	model_rpmrR   Úresolved_modelrc   s                r   Úasync_pre_call_hookz2_PROXY_DynamicRateLimitHandler.async_pre_call_hook¶   sÈ  è ø€ ð �dŠ?Ø.?×.HÑ.H×.LÑ.LÈZÐY]Ó.^ˆLð ×0Ñ0°t¸G±}È|Ð0Ó\×\ñØØØØØð Ð(¨]¸aÒ-?Ü/RÐSW×S[ÑS[Ð\cÓSdÓ/eÑ,� Ü)à 4Ð(9×(AÑ(AÐ'BÐBVÐWdÐVeÐeqÐr{Ðq|ð  }Kð  L[ð  K\ð  "]ðô %2×$8Ñ$8Ø(Ø!-ôð ð Ð*¨}ÀÒ/AÜ/RÐSW×S[ÑS[Ð\cÓSdÓ/eÑ,� Ü)à 4Ð(9×(AÑ(AÐ'BÐBVÐWdÐVeÐeqÐr{Ðq|ð  }Kð  L[ð  K\ð  "]ðô %2×$:Ñ$:Ø(Ø!-ôð ð Ð*¨mÐ.Gä×#Ñ#Ø×-Ñ-×BÑBØ" 7™mØ0×6Ñ6ÒG¸-ÐHð Có ôð ð? ]ûs   ‚;E½E¾DEc              ƒ   ó  •K  — 	 t        |t        «      r©| j                  j                  |j                  d   ¬«      }|€#J dj                  |j                  d   «      «       ‚|j                  j                  dd «      }| j                  |d   |¬«      ƒ d {  –—† \  }}}}	}
|d   ||||	|
dœ|j                  d<   |S t        ‰| �)  |||¬	«      ƒ d {  –—† S 7 Œ?7 Œ# t        $ r"}t        j                  d
|«       |cY d }~S d }~ww xY w­w)NÚmodel_id)Úidz'Model info for model with id={} is NonerB   Ú
model_namer`   )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)r]   r\   r+   zclitellm.proxy.hooks.dynamic_rate_limiter.py::async_post_call_success_hook(): Exception occured - %s)Ú
isinstancer   r>   Úget_model_infoÚ_hidden_paramsÚformatre   rf   r[   ÚsuperÚasync_post_call_success_hookr/   r   r0   )r   r]   r\   r+   Ú
model_inform   rY   rZ   rn   ro   rR   r1   Ú	__class__s               €r   r|   z;_PROXY_DynamicRateLimitHandler.async_post_call_success_hookí   sH  øè ø€ ð!	Ü˜(¤MÔ2Ø$(§O¡O×$BÑ$BÀh×F]ÑF]Ð^hÑFiÐ$BÓ$j�
Ø!Ð-ð Ð/X×/_Ñ/_Ø×+Ñ+¨JÑ7ó0ó Ð-ð 3D×2LÑ2L×2PÑ2PÐQ[Ð]aÓ2b�ð ×4Ñ4¸:ÀlÑ;SÐ^jÐ4Ók×kñØ!Ø!ØØØ#ð .8¸Ñ-EØDQØFSØ:CØ<EØ;JñA�×'Ñ'Ð(<Ñ=ð  �Ü™Ñ=ØØ"3Ø!ð >ó ÷ ð ð løðùô
 ò 	Ü ×*Ñ*ØuÐwxôð �Oûð		üse   ƒD
…BC ÂCÂ$C Â=D
Â>C ÃCÃC ÃD
ÃC ÃC Ã	DÃ%DÃ<DÃ=D
ÄDÄD
r@   )r2   r3   r4   r   r	   r   r   r   r   rA   r6   Útupler7   r[   r   Údictr   r/   rq   r|   Ú__classcell__)r~   s   @r   r;   r;   M   sÝ   ø„ àZjñ i¨Yð iÀÈ"ÈhÈ,ÑAWó ið%¨6ó %ð 26ñ_0Øð_0Ø$'¨$¡Jð_0à	ˆs�T‰z˜3 ™: s¨T¡z°3¸±:¸sÀT¹zÐIÑ	Jó_0ðB5à)ð5ð ð5ð ð	5ð
 $ð5ð 	�C‰˜$Ñ Ñ%ó5ðn"°tð "ÐP^÷ "ñ "r   r;   )!rj   rK   Úcollections.abcr   r   Útypingr   rH   r   r   Úlitellm._loggingr   Úlitellm.caching.cachingr	   Úlitellm.exceptionsr
   Ú"litellm.integrations.custom_loggerr   Úlitellm.proxy._typesr   Ú1litellm.proxy.common_utils.proxy_rate_limit_errorr   Ú&litellm.proxy.hooks.rate_limiter_utilsr   r   Úlitellm.types.routerr   Úlitellm.types.utilsr   Úlitellm.utilsr   r   r;   r9   r   r   ú<module>rŽ      sW   ðó
 Û 	Ý $Ý Ý ã ß )Ý 1Ý -Ý ,Ý ;Ý /Ý Q÷õ 0Ý 0Ý *÷.ñ .ôbB \õ Br   