o
    ưi/                     @   s   d dl Z d dlZd dlmZmZmZ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 ddlmZ G dd dZG dd deZdS )    N)ListOptionalTupleUnion)HTTPException)ModelResponseRouter)verbose_proxy_logger)	DualCache)CustomLogger)UserAPIKeyAuth)ModelGroupInfo)CallTypesLiteral)get_utc_datetime   )convert_priority_to_percentc                   @   sJ   e Zd ZdZdeddfddZdedee fdd	Z	ded
e
fddZdS )DynamicRateLimiterCachezh
    Thin wrapper on DualCache for this file.

    Track number of active projects calling a model.
    cachereturnNc                 C   s   || _ d| _d S )N<   )r   ttl)selfr    r   _/home/app/Keep/.python/lib/python3.10/site-packages/litellm/proxy/hooks/dynamic_rate_limiter.py__init__   s   
z DynamicRateLimiterCache.__init__modelc                    sJ   t  }|d}d||}| jj|dI d H }d }|d ur#t|}|S )N%H-%M{}:{})key)r   strftimeformatr   async_get_cachelen)r   r   dtcurrent_minutekey_name	_responseresponser   r   r   r!   #   s   
z'DynamicRateLimiterCache.async_get_cachevaluec              
      sp   zt  }|d}d||}| jj||| jdI dH  W dS  ty7 } ztdt	| |d}~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 - {})
r   r   r    r   async_set_cache_saddr   	Exceptionr	   	exceptionstr)r   r   r(   r#   r$   r%   er   r   r   r)   -   s"   
z,DynamicRateLimiterCache.async_set_cache_sadd)__name__
__module____qualname____doc__r
   r   r,   r   intr!   r   r)   r   r   r   r   r      s
    
r   c                       s   e Zd ZdefddZdefddZ	dded	ee d
e	ee
 ee
 ee
 ee
 ee
 f fddZdedededed
eeeeef  f
ddZdedef fddZ  ZS )_PROXY_DynamicRateLimitHandlerinternal_usage_cachec                 C   s   t |d| _d S )N)r   )r   r4   )r   r4   r   r   r   r   N   s   z'_PROXY_DynamicRateLimitHandler.__init__
llm_routerc                 C   s
   || _ d S N)r5   )r   r5   r   r   r   update_variablesQ   s   
z/_PROXY_DynamicRateLimitHandler.update_variablesNr   priorityr   c              
      s
  z| j j|d}d}tjdu s|tjvr td|tj n!|durAtjdurAtdddu r7td n
tj| }t	||}| j
j|dI dH }| j j|dI dH \}}d}	d}
|duro|jdurg|j}	|jduro|j}
d}|	dur~|dur~|	| }n|	dur|	}d}|
dur|dur|
| }n|
dur|
}d}|dur|durt|| | }nt|| }|dur|dk rd}d}|dur|durt|| | }nt|| }|dur|dk rd}|||||fW S  ty } ztd	t| W Y d}~d
S d}~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
        )Zmodel_groupr   NzRPriority Reservation not set. priority={}, but litellm.priority_reservation is {}.Z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   r   z[litellm.proxy.hooks.dynamic_rate_limiter.py::check_available_usage: Exception occurred - {})NNNNN)r5   Zget_model_group_infolitellmZpriority_reservationr	   errorr    osgetenvr   r4   r!   Zget_model_group_usageZtpmZrpmr2   r*   r+   r,   )r   r   r8   Zmodel_group_infoweightr(   active_projectsZcurrent_model_tpmZcurrent_model_rpmZtotal_model_tpmZtotal_model_rpmZremaining_model_tpmZremaining_model_rpmavailable_tpmavailable_rpmr-   r   r   r   check_available_usageT   s   







z4_PROXY_DynamicRateLimitHandler.check_available_usageuser_api_key_dictr   data	call_typec              	      s   d|v rd|j dd}| j|d |dI dH \}}}}	}
|dur4|dkr4tddd|j|||
id	|durK|dkrKtddd
|j||	|
id	|dusS|durdt| jj	|d |j
p_dgd dS )z
        - For a model group
        - Check if tpm/rpm available
        - Raise RateLimitError if no tpm/rpm available
        r   r8   Nr   r8   r   i  r:   z:Key={} over available TPM={}. Model TPM={}, Active keys={})status_codedetailz:Key={} over available RPM={}. Model RPM={}, Active keys={}Zdefault_key)r   r(   )metadatagetrA   r   r    Zapi_keyasynciocreate_taskr4   r)   token)r   rB   r   rC   rD   key_priorityr?   r@   	model_tpm	model_rpmr>   r   r   r   async_pre_call_hook   sX   	

z2_PROXY_DynamicRateLimitHandler.async_pre_call_hookc              
      s   zSt |trH| jj|jd d}|d usJ d|jd |jdd }| j|d |dI d H \}}}}	}
|d ||||	|
d|jd< |W S t	 j
|||d	I d H W S  tyr } ztd
t| |W  Y d }~S d }~ww )NZmodel_id)idz'Model info for model with id={} is Noner8   Z
model_namerE   )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-projectsZadditional_headers)rC   rB   r'   zclitellm.proxy.hooks.dynamic_rate_limiter.py::async_post_call_success_hook(): Exception occured - {})
isinstancer   r5   Zget_model_infoZ_hidden_paramsr    rH   rI   rA   superasync_post_call_success_hookr*   r	   r+   r,   )r   rC   rB   r'   Z
model_inforM   r?   r@   rN   rO   r>   r-   	__class__r   r   rT      s\   

	
z;_PROXY_DynamicRateLimitHandler.async_post_call_success_hookr6   )r.   r/   r0   r
   r   r   r7   r,   r   r   r2   rA   r   dictr   r   r*   rP   rT   __classcell__r   r   rU   r   r3   L   s>     
l
?r3   )rJ   r;   typingr   r   r   r   Zfastapir   r9   r   r   Zlitellm._loggingr	   Zlitellm.caching.cachingr
   Z"litellm.integrations.custom_loggerr   Zlitellm.proxy._typesr   Zlitellm.types.routerr   Zlitellm.types.utilsr   Zlitellm.utilsr   Zrate_limiter_utilsr   r   r3   r   r   r   r   <module>   s    4