
    ^h                         S SK r S SKJrJr  S SK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	KJrJrJr  S
r " S S\5      rg)    N)ListOptional)verbose_proxy_logger)	DualCache)Span)UserAPIKeyAuth)RouterBudgetLimiting)AllMessageValues)GenericBudgetConfigTypeGenericBudgetInfoStandardLoggingPayloadvirtual_key_spendc                       \ rS rSrSrS\4S jrS\S\S\	4S jr
S	\\   S\S
\S\\   4S jrS\S\S\\   4S jrS\S\4S jr  SS\S\S\\\      S\\   S\\   S\\   4S jjrS rSrg)&_PROXY_VirtualKeyModelMaxBudgetLimiter   zs
Handles budgets for model + virtual key

Example: key=sk-1234567890, model=gpt-4o, max_budget=100, time_period=1d

dual_cachec                     Xl         / U l        g Nr   redis_increment_operation_queue)selfr   s     f/home/james-whalen/.local/lib/python3.13/site-packages/litellm/proxy/hooks/model_max_budget_limiter.py__init__/_PROXY_VirtualKeyModelMaxBudgetLimiter.__init__   s    $/1,    user_api_key_dictmodelreturnc           	        #    UR                   n0 nUR                  5        H8  u  pV[        UR                  S5      [	        UR                  S5      5      S9XE'   M:     [
        R                  " S[        R                  " US[        S95        U R                  X$S9nUc  [
        R                  " S	U S
35        gUR                  S:  ar  U R                  UR                  UUS9I Sh  vN nUbL  XR                  :  a=  [        R                  " SUR                   SUR                    SU 3UUR                  S9eg NT7f)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
time_periodbudget_limitr    r!   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   getfloatr   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_budgetA_PROXY_VirtualKeyModelMaxBudgetLimiter.is_key_within_model_budget   sw     .>>=?! %6$;$;$= F0A(,,];"<#3#3N#CD1%- %> 	""*JJ0CH	
 &*%J%J &K &
" &- &&FG  &22Q6#'#H#H"3"9"9"< $I $ N *"%L%LL1134E4K4K3LMZkZuZuYv  wS  TY  SZ  [!/9FF  s   C%D>'D<(AD>r(   r)   c                 *  #    [          SU SU SUR                   3nU R                  R                  US9I Sh  vN nUcK  [          SU SU R	                  U5       SUR                   3nU R                  R                  US9I Sh  vN nU$  NT N7f)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_PREFIXr    r   async_get_cache&_get_model_without_custom_llm_provider)r   r(   r   r)   !virtual_key_model_spend_cache_keyr?   s         r   r6   G_PROXY_VirtualKeyModelMaxBudgetLimiter._get_virtual_key_spend_for_modelV   s     0R.RRSTeSffghmgnno  qB  qN  qN  pO  -P)#>>1  ?  
 
 ! 4V2VVWXiWjjklp  mX  mX  Y^  m_  l`  `a  bs  b  b  a@  1A-#'??#B#B5 $C $ N 
s"   8BBABB	BBr'   c                 v    UR                  US5      =(       d!    UR                  U R                  U5      S5      $ )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)r/   rG   )r   r   r'   s      r   r5   G_PROXY_VirtualKeyModelMaxBudgetLimiter._get_request_model_budget_configs   s?     ),,4
 
&**77>
	
r   c                 :    SU;   a  UR                  S5      S   $ U$ )N/)split)r   r   s     r   rG   M_PROXY_VirtualKeyModelMaxBudgetLimiter._get_model_without_custom_llm_provider   s"    %<;;s#B''r   Nhealthy_deploymentsmessagesrequest_kwargsparent_otel_spanc                    #    U$ 7fr    )r   r   rQ   rR   rS   rT   s         r   async_filter_deployments?_PROXY_VirtualKeyModelMaxBudgetLimiter.async_filter_deployments   s      #"s   c           	        #    [         R                  " S5        UR                  SS5      nUc  [        S5      eUR                  S0 5      nUR                  S0 5      nUR                  SS5      nUb  [	        U5      S:X  a  [         R                  " S	U5        gUR                  S
S5      n	UR                  S5      n
UR                  S5      R                  S5      nUR                  S5      n
UbD  [        SSS9n[         SU SU
 SUR                   3nSU 3nU R                  UUUU	S9I Sh  vN   [         R                  " S[        R                  " U R                  R                  R                  S[        S95        g NR7f)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?r"   rC   zvirtual_key_budget_start_time:)budget_config	spend_keystart_time_keyr^   z#current state of in memory cache %sr#   r$   )r   r1   r/   
ValueErrorlenr   rE   r    _increment_spend_for_keyr2   r3   r   in_memory_cache
cache_dictr4   )r   kwargsresponse_obj
start_timeend_timestandard_logging_payload_litellm_params	_metadatar]   r^   r   virtual_keyr`   virtual_spend_keyvirtual_start_time_keys                  r   async_log_success_event>_PROXY_VirtualKeyModelMaxBudgetLimiter.async_log_success_event   s     	""#TUEKZZ%tF
  $+CDD **%5r:#''
B7	8A+T9
% *101Q6 && x- 7;;OQO(,,W5.22:>BBCVW(,,W5"-$SQM#E"Fa}TUV[U\\]^k^w^w]x y'Ek]%S"//++5+	 0    	""1JJ//::1c	
s   D-F/F0AFr   )NN)__name__
__module____qualname____firstlineno____doc__r   r   r   r4   boolr@   r   r   r0   r6   r   r5   rG   r   r
   dictr   rW   rr   __static_attributes__rV   r   r   r   r      s   29 25)5 5 
	5n#C=  -	
 
%:

5L
	#	$
C C  *.+/## "# 4 012	#
 !# #4.# 
d#/
r   r   )r2   typingr   r   r8   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   rE   r   rV   r   r   <module>r      sA     !  1 - 3 / G 6  &9 "l
-A l
r   