
    g                         d dl Z d dlmZmZ d dl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mZ d
Z G d de      Zy)    N)ListOptional)verbose_proxy_logger)	DualCache)Span)UserAPIKeyAuth)RouterBudgetLimiting)AllMessageValues)BudgetConfigGenericBudgetConfigTypeStandardLoggingPayloadvirtual_key_spendc                       e Zd ZdZdefdZdededefdZ	de
e   ded	ede
e   fd
Zdedede
e   fdZdedefdZ	 	 ddedede
ee      de
e   de
e   dee   fdZd Zy)&_PROXY_VirtualKeyModelMaxBudgetLimiterz
    Handles budgets for model + virtual key

    Example: key=sk-1234567890, model=gpt-4o, max_budget=100, time_period=1d
    
dual_cachec                      || _         g | _        y N)r   redis_increment_operation_queue)selfr   s     a/var/www/openai/venv/lib/python3.12/site-packages/litellm/proxy/hooks/model_max_budget_limiter.py__init__z/_PROXY_VirtualKeyModelMaxBudgetLimiter.__init__   s    $/1,    user_api_key_dictmodelreturnc                 p  K   |j                   }i }|j                         D ]  \  }}t        di |||<    t        j                  dt        j                  |dt                     | j                  ||      }|t        j                  d| d       y|j                  r|j                  d	kD  r| j                  |j                  ||
       d{   }|Z|j                  N||j                  kD  r?t        j                  d|j                   d|j                   d| ||j                        y7 aw)z
        Check if the user_api_key_dict is within the model budget

        Raises:
            BudgetExceededError: If the user_api_key_dict has exceeded the model budget
        zinternal_model_max_budget %s   indentdefault)r   internal_model_max_budgetNzModel z' not found in internal_model_max_budgetTr   )user_api_key_hashr   key_budget_configzLiteLLM Virtual Key: z, key_alias: z, exceeded budget for model=)messagecurrent_cost
max_budget )model_max_budgetitemsr   r   debugjsondumpsstr _get_request_model_budget_configr&    _get_virtual_key_spend_for_modeltokenlitellmBudgetExceededError	key_alias)	r   r   r   _model_max_budgetr!   _model_budget_info_current_model_budget_info_current_spends	            r   is_key_within_model_budgetzA_PROXY_VirtualKeyModelMaxBudgetLimiter.is_key_within_model_budget   sw     .>>=?!$5$;$;$= FL0<0L|0L%f- %> 	""*JJ0CH	
 &*%J%J3L &K &
" &- &&FG  '11*559#'#H#H"3"9"9"< $I $ N *.99E"%?%J%JJ1134E4K4K3LMZkZuZuYv  wS  TY  SZ  [!/9DD  !s   CD6D4A"D6r"   r#   c                 4  K   t          d| d| d|j                   }| j                  j                  |       d{   }|Nt          d| d| j	                  |       d|j                   }| j                  j                  |       d{   }|S 7 V7 w)z
        Get the current spend for a virtual key for a model

        Lookup model in this order:
            1. model: directly look up `model`
            2. If 1, does not exist, check if passed as {custom_llm_provider}/model
        :)keyN)"VIRTUAL_KEY_SPEND_CACHE_KEY_PREFIXbudget_durationr   async_get_cache&_get_model_without_custom_llm_provider)r   r"   r   r#   !virtual_key_model_spend_cache_keyr8   s         r   r/   zG_PROXY_VirtualKeyModelMaxBudgetLimiter._get_virtual_key_spend_for_modelV   s     0R.RRSTeSffghmgnno  qB  qR  qR  pS  -T)#>>1  ?  
 
 ! 4V2VVWXiWjjklp  mX  mX  Y^  m_  l`  `a  bs  bC  bC  aD  1E-#'??#B#B5 $C $ N 
s"   ;BBABBBBr!   c                 l    |j                  |d      xs! |j                  | j                  |      d      S )z
        Get the budget config for the request model

        1. Check if `model` is in `internal_model_max_budget`
        2. If not, check if `model` without custom llm provider is in `internal_model_max_budget`
        N)getr@   )r   r   r!   s      r   r.   zG_PROXY_VirtualKeyModelMaxBudgetLimiter._get_request_model_budget_configs   s?     ),,4
 
&**77>
	
r   c                 6    d|v r|j                  d      d   S |S )N/)split)r   r   s     r   r@   zM_PROXY_VirtualKeyModelMaxBudgetLimiter._get_model_without_custom_llm_provider   s"    %<;;s#B''r   Nhealthy_deploymentsmessagesrequest_kwargsparent_otel_spanc                    K   |S wr   r'   )r   r   rH   rI   rJ   rK   s         r   async_filter_deploymentsz?_PROXY_VirtualKeyModelMaxBudgetLimiter.async_filter_deployments   s      #"s   c                   K   t        j                  d       |j                  dd      }|t        d      |j                  di       xs i }|j                  di       xs i }|j                  dd      }|t	        |      dk(  rt        j                  d	|       y|j                  d
d      }	|j                  d      }
|j                  d      j                  d      }|j                  d      }
|Jt        dd      }t         d| d|
 d|j                   }d| }| j                  ||||	       d{    t        j                  dt        j                  | j                  j                  j                  dt                     y7 Sw)z
        Track spend for virtual key + model in DualCache

        Example: key=sk-1234567890, model=gpt-4o, max_budget=100, time_period=1d
        z/in RouterBudgetLimiting.async_log_success_eventstandard_logging_objectNz$standard_logging_payload is requiredlitellm_paramsmetadatauser_api_key_model_max_budgetr   zNot running _PROXY_VirtualKeyModelMaxBudgetLimiter.async_log_success_event because user_api_key_model_max_budget is None or empty. `user_api_key_model_max_budget`=%sresponse_costr   r"   1dg?)time_periodbudget_limitr;   zvirtual_key_budget_start_time:)budget_config	spend_keystart_time_keyrS   z#current state of in memory cache %sr   r   )r   r*   rC   
ValueErrorlenr   r=   r>   _increment_spend_for_keyr+   r,   r   in_memory_cache
cache_dictr-   )r   kwargsresponse_obj
start_timeend_timestandard_logging_payload_litellm_params	_metadatarR   rS   r   virtual_keyrW   virtual_spend_keyvirtual_start_time_keys                  r   async_log_success_eventz>_PROXY_VirtualKeyModelMaxBudgetLimiter.async_log_success_event   s     	""#TUEKZZ%tF
  $+CDD &

+;R @ FB)--j"=C	8A+T9
% *101Q6 && x- 7;;OQO(,,W5.22:>BBCVW(,,W5"(TLM#E"Fa}TUV[U\\]^k^{^{]| }'Ek]%S"//++5+	 0    	""1JJ//::1c	
s   D5F7F8AF)NN)__name__
__module____qualname____doc__r   r   r   r-   boolr9   r   r   floatr/   r   r.   r@   r   r
   dictr   rM   ri   r'   r   r   r   r      s    29 25)5 5 
	5n#C=  (	
 
%:

5L
	,	
C C  *.+/## "# 4 012	#
 !# #4.# 
d#/
r   r   )r+   typingr   r   r1   litellm._loggingr   litellm.caching.cachingr   "litellm.integrations.custom_loggerr   litellm.proxy._typesr   &litellm.router_strategy.budget_limiterr	   litellm.types.llms.openair
   litellm.types.utilsr   r   r   r=   r   r'   r   r   <module>ry      sA     !  1 - 3 / G 6  &9 "l
-A l
r   