
    i                        d Z ddlZddlmZmZmZ ddlmZmZmZm	Z	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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dl"m#Z# ddl"m#Z$ ddl"m%Z%m&Z& dZ' G d d      Z( G d de      Z)y)a  
Provider budget limiting

Use this if you want to set $ budget limits for each provider.

Note: This is a filter, like tag-routing. Meaning it will accept healthy deployments and then filter out deployments that have exceeded their budget limit.

This means you can use this with weighted-pick, lowest-latency, simple-shuffle, routing etc

Example:
```
openai:
	budget_limit: 0.000000000001
	time_period: 1d
anthropic:
	budget_limit: 100
	time_period: 7d
```
    N)datetime	timedeltatimezone)AnyDictListOptionalTupleUnion)verbose_router_logger)	DualCache)RedisPipelineIncrementOperation)CustomLoggerSpan)duration_in_seconds)_get_tags_from_request_kwargs)%_get_prometheus_logger_from_callbacks)AllMessageValues)DeploymentTypedDictLiteLLM_ParamsRouterErrors)BudgetConfig)GenericBudgetConfigTypeStandardLoggingPayload   c                       e Zd ZdZdZdeeef   fdZdedefdZ	dedefdZ
dedefd	ZddededefdZd Zd Zd Zd ZdefdZdeeef   fdZdeeef   fdZy
)_LiteLLMParamsDictViewz
    Lightweight attribute view over `litellm_params` dict.

    This avoids pydantic construction in request hot-path while preserving
    attribute-style access used by `litellm.get_llm_provider(...)`.
    _paramsparamsc                     || _         y Nr   )selfr    s     w/Users/manta/Documents/Projects/TheRoad-I1/.venv/lib/python3.12/site-packages/litellm/router_strategy/budget_limiter.py__init__z_LiteLLMParamsDictView.__init__6   s	        keyreturnc                 8    | j                   j                  |      S r"   r   getr#   r'   s     r$   __getattr__z"_LiteLLMParamsDictView.__getattr__9       ||$$r&   c                 8    | j                   j                  |      S r"   r*   r,   s     r$   __getitem__z"_LiteLLMParamsDictView.__getitem__<   r.   r&   c                     || j                   v S r"   r   r,   s     r$   __contains__z#_LiteLLMParamsDictView.__contains__?   s    dll""r&   Ndefaultc                 :    | j                   j                  ||      S r"   r*   )r#   r'   r3   s      r$   r+   z_LiteLLMParamsDictView.getB   s    ||W--r&   c                 6    | j                   j                         S r"   )r   keysr#   s    r$   r6   z_LiteLLMParamsDictView.keysE   s    ||  ""r&   c                 6    | j                   j                         S r"   )r   valuesr7   s    r$   r9   z_LiteLLMParamsDictView.valuesH   s    ||""$$r&   c                 6    | j                   j                         S r"   )r   itemsr7   s    r$   r;   z_LiteLLMParamsDictView.itemsK   s    ||!!##r&   c                 ,    t        | j                        S r"   )iterr   r7   s    r$   __iter__z_LiteLLMParamsDictView.__iter__N       DLL!!r&   c                 ,    t        | j                        S r"   )lenr   r7   s    r$   __len__z_LiteLLMParamsDictView.__len__Q   s    4<<  r&   c                 ,    t        | j                        S r"   dictr   r7   s    r$   rE   z_LiteLLMParamsDictView.dictT   r?   r&   c                 ,    t        | j                        S r"   rD   r7   s    r$   
model_dumpz!_LiteLLMParamsDictView.model_dumpW   r?   r&   r"   )__name__
__module____qualname____doc__	__slots__r   strr   r%   r-   r0   boolr2   r+   r6   r9   r;   r>   intrB   rE   rG    r&   r$   r   r   ,   s     ItCH~ %s %s %%s %s %# # #.s .S .C .#%$"! !"d38n ""DcN "r&   r   c                   8   e Zd Z	 d6dedee   deeee   ee	e
ef      f      fdZ	 	 d7de
dedeee      d	ee   d
ee   dee   fdZdee	e
ef      dee	e
ef      de	e
ef   de	e
ef   deee
      de	e
ef   dee
   deee	e
ef      e
f   fdZ	 d6dee	e
ef      d	ee	   deee
   e	e
ef   e	e
ef   eee
      f   fdZde
dededefdZde
de
dedededefdZde
dedefdZd Zdede
de
defd Zd! Zd" Zd# Zd$e
dee   fd%Zd&e
dee   fd'Zd(e
dee   fd)Z d*e	dee
   fd+Z!d&e
d,ed-efd.Z"d&e
dee   fd/Z#d&e
dee
   fd0Z$d&e
defd1Z%e&	 d6dee   deeee   ee	e
ef      f      fd2       Z'd3 Z(	 d6deeee   ee	e
ef      f      fd4Z)d5 Z*y)8RouterBudgetLimitingN
dual_cacheprovider_budget_config
model_listc                 p   || _         g | _        t        j                  | j	                                || _        d | _        d | _        | j                          | j                  |       | j                          t        t        j                  t              r t        j                  j!                  |        y y )N)rU   )rS   redis_increment_operation_queueasynciocreate_task(periodic_sync_in_memory_spend_with_redisrT   deployment_budget_configtag_budget_config_init_provider_budgets_init_deployment_budgets_init_tag_budgets
isinstancelitellm	callbackslistlogging_callback_manageradd_litellm_callback)r#   rS   rT   rU   s       r$   r%   zRouterBudgetLimiting.__init__\   s     %VX,DIIKL # 	# LP%DH##%%%%<  g''.,,AA$G /r&   modelhealthy_deploymentsmessagesrequest_kwargsparent_otel_spanr(   c                 :  K   t        |t              r|g}t        |      dk(  r|S g }| j                  ||       d{   \  }}}	}
t        |      dkD  r| j                  j                  ||       d{   }|xs dgt        |      z  }i }t        |      D ]  \  }}t        ||   xs d      ||<    | j                  |||	|
||t        |            \  }}t        |      dk(  r(t        t        j                  j                   d|       |S |S 7 7 w)	z
        Filter out deployments that have exceeded their provider budget limit.


        Example:
        if deployment = openai/gpt-3.5-turbo
            and openai spend > openai budget limit
                then skip this deployment
        r   )rg   ri   N)r6   rj           ri   )rg   provider_configsdeployment_configsdeployment_providers	spend_mappotential_deploymentsrequest_tags: )r`   rE   rA   0_async_get_cache_keys_for_router_budget_limitingrS   async_batch_get_cache	enumeratefloat$_filter_out_deployments_above_budgetr   
ValueErrorr   +no_deployments_with_provider_budget_routingvalue)r#   rf   rg   rh   ri   rj   rr   
cache_keysrn   ro   rp   _current_spendscurrent_spendsrq   idxr'   deployment_above_budget_infos                    r$   async_filter_deploymentsz-RouterBudgetLimiting.async_filter_deploymentst   sx    & )40#6"7 "#q(&&,. GG 3) H 
 
	
  z?Q$(OO$I$I!1 %J % O $3#Msec*o6MN +-I%j1S!&~c':'Ac!B	# 2 99$7!1#5%9#&;:#1 : 
%, ()Q. #OOUUVVXYuXvw  )(&&Q
s"   <DD7D6D7B!DDrr   rn   ro   rp   rq   rs   c                    d}t        |      D ]c  \  }	}
d}| j                  r|	t        |      k  r||	   }n| j                  |
      }||v r||   }|j                  P|j                  d| d|j                   d      }| j                  |||j                         |j                  r/||j                  k\  r d| d| d	|j                   }|| d
z  }d}| j                  r|r|
j                  d      }|
j                  d      xs i }|j                  d      }|
j                  di       j                  d      }||v r~||   }|j                  d| d|j                   d      }|j                  rK||j                  k\  r<d| d| d| d| d	|j                   
}t        j                  |       || d
z  }d}| j                  r|r|D ]  }| j                  |      }|s|j                  d| d|j                   d      }|j                  sF||j                  k\  sVd| d| d|j                   }t        j                  |       || d
z  }d} |sS|j                  |
       f ||fS )a  
        Filter out deployments that have exceeded their budget limit.
        Follow budget checks are run here:
            - Provider budget
            - Deployment budget
            - Request tags budget
        Returns:
            Tuple[List[Dict[str, Any]], str]:
                - A tuple containing the filtered deployments
                - A string containing debug information about deployments that exceeded their budget limit.
         Tprovider_spend::rl   providerspendbudget_limitzExceeded budget for provider rt   z >= 
F
model_namelitellm_paramsrf   
model_infoiddeployment_spend:z+Exceeded budget for deployment model_name: z, litellm_params.model: , model_id: 
tag_spend:zExceeded budget for tag='z', tag_spend=z, tag_budget_limit=)rw   rT   rA    _get_llm_provider_for_deployment
max_budgetr+   budget_duration+_track_provider_remaining_budget_prometheusr[   r   debugr\   _get_budget_config_for_tagappend)r#   rr   rg   rn   ro   rp   rq   rs   r   r   
deploymentis_within_budgetr   configcurrent_spend	debug_msg_model_name_litellm_params_litellm_model_namemodel_id_tag_tag_budget_config
_tag_spends                          r$   ry   z9RouterBudgetLimiting._filter_out_deployments_above_budget   sP   , -/$()<=OC# **1223C8H#DDZPH//-h7F((0 $-MM)(1V5K5K4LMs%M DD!)+%+%6%6 E  ((]f>O>O-O&CH:RP]^bcictctbu$v	49+R8HH4+0(  ,,1A(nn\:",..1A"B"Hb&5&9&9'&B#%>>,;??E11/9F$-MM+H:Qv7M7M6NOQT%M ((]f>O>O-O&QR]Q^^v  xK  wL  LX  Ya  Xb  bd  er  ds  sw  x~  xN  xN  wO  %P	-33I>49+R8HH4+0( %%*:(D)-)H)H)N&)%.]](a0B0R0R/ST&

 /99 *.@.K.K K*CD6WaVbbu  wI  wT  wT  vU  )VI177	B8yk<LL8/4,$ )   %,,Z8A  >D %&BBBr&   c                   K   g }i }i }g }|D ]5  }| j                   ri| j                  |      }|j                  |       |E| j                  |      }	|	2|	j                  &|	||<   |j                  d| d|	j                          | j
                  r\|j                  di       j                  d      }
|
9| j                  |
      }	|	&|	||
<   |j                  d|
 d|	j                          | j                  st        |      }|D ]7  }| j                  |      }|s|j                  d| d|j                          9 8 ||||fS w)aB  
        Returns list of cache keys to fetch from router cache for budget limiting and provider and deployment configs

        Returns:
            Tuple[List[str], Dict[str, GenericBudgetInfo], Dict[str, GenericBudgetInfo], List[Optional[str]]]:
                - List of cache keys to fetch from router cache for budget limiting
                - Dict of provider budget configs `provider_configs`
                - Dict of deployment budget configs `deployment_configs`
                - List of resolved providers aligned by deployment index `deployment_providers`
        r   r   r   r   r   rm   r   )rT   r   r   _get_budget_config_for_providerr   r[   r+   !_get_budget_config_for_deploymentr\   r   r   )r#   rg   ri   r}   rn   ro   rp   r   r   budget_configr   rs   r   r   s                 r$   ru   zERouterBudgetLimiting._async_get_cache_keys_for_router_budget_limiting  s    ( !#
9;;=46-J**@@L$++H5'$($H$H$RM%1)99E5B(2"))-hZq9V9V8WX
 ,,%>>,;??E'$($J$J8$TM$07D*84"))/z=;X;X:YZ %%<#1  )D)-)H)H)N&)"))(a0B0R0R/ST )? .L  	
 	
s   C8E;$E ,Estart_time_keycurrent_timettl_secondsc                    K   | j                   j                  |       d{   }|(| j                   j                  |||       d{    |S t        |      S 7 97 w)z
        Checks if the key = `provider_budget_start_time:{provider}` exists in cache.

        If it does, return the value.
        If it does not, set the key to `current_time` and return the value.
        Nr'   r|   ttl)rS   async_get_cacheasync_set_cacherx   )r#   r   r   r   budget_starts        r$   _get_or_set_budget_start_timez2RouterBudgetLimiting._get_or_set_budget_start_time_  sl      "__<<^LL//11",K 2     \"" Ms!   AA'A	A
AA	spend_keyresponse_costc                    K   | j                   j                  |||       d{    | j                   j                  |||       d{    |S 7 ,7 w)a  
        Handle start of new budget window by resetting spend and start time

        Enters this when:
        - The budget does not exist in cache, so we need to set it
        - The budget window has expired, so we need to reset everything

        Does 2 things:
        - stores key: `provider_spend:{provider}:1d`, value: response_cost
        - stores key: `provider_budget_start_time:{provider}`, value: current_time.
            This stores the start time of the new budget window
        r   N)rS   r   )r#   r   r   r   r   r   s         r$   _handle_new_budget_windowz.RouterBudgetLimiting._handle_new_budget_windowp  sm     ( oo--K . 
 	
 	
 oo--l . 
 	
 	
 	
	
s!   "AA%A
AAAr   c                    K   | j                   j                  j                  |||       d{    t        |||      }| j                  j                  |       y7 .w)a  
        Increment spend within existing budget window

        Runs once the budget start time exists in Redis Cache (on the 2nd and subsequent requests to the same provider)

        - Increments the spend in memory cache (so spend instantly updated in memory)
        - Queues the increment operation to Redis Pipeline (using batched pipeline to optimize performance. Using Redis for multi instance environment of LiteLLM)
        r   N)r'   increment_valuer   )rS   in_memory_cacheasync_incrementr   rW   r   )r#   r   r   r   increment_ops        r$   "_increment_spend_in_current_windowz7RouterBudgetLimiting._increment_spend_in_current_window  sh      oo--== > 
 	
 	

 7)

 	,,33LA	
s   ,AA/Ac                 &  K   t        j                  d       |j                  dd      }|t        d      |j                  dd      }t	        |j                  dd            }|j                  d	i       j                  d
d      }|t        d      | j                  |      }	|	r4d| d|	j                   }
d| }| j                  |	|
||       d{    | j                  |      }|r4d| d|j                   }d| }| j                  ||||       d{    t        |      }t        |      dkD  rP|D ]J  }| j                  |      }|sd| d|j                   }d| }| j                  ||||       d{    L yy7 7 p7 w)z)Original method now uses helper functionsz/in RouterBudgetLimiting.async_log_success_eventstandard_logging_objectNz$standard_logging_payload is requiredr   r   r   r   r   custom_llm_providerzcustom_llm_provider is requiredr   r   provider_budget_start_time:)r   r   r   r   r   zdeployment_budget_start_time:r   ztag_budget_start_time:)r   r   r+   rz   rM   r   r   _increment_spend_for_keyr   r   rA   r   )r#   kwargsresponse_obj
start_timeend_timestandard_logging_payloadr   r   r   r   r   r   r[   deployment_spend_keydeployment_start_time_keyrs   r   r   _tag_spend_key_tag_start_time_keys                       r$   async_log_success_eventz,RouterBudgetLimiting.async_log_success_event  s    ##$UVEKZZ%tF
  $+CDD7;;OQO488RHI#)::.>#C#G#G!4$
 &>??<<=PQ ""5!6a8U8U7VW   ;;N:OPN//+#-+	 0    $(#I#I(#S #%6xjBZBjBjAk#l *Gz(R%//6.8+	 0    5V<|q $%)%D%DT%J"%$TF!,>,N,N+OP # -C4&*I'77&8"0':&3	 8    % !) s=   CFFAFF5F/FF	FFFr   c                 H  K   |j                   y t        j                  t        j                        j                         }t        |j                         }| j                  |||       d {   }|| j                  |||||       d {   }nk||z
  |kD  r4t        j                  d       | j                  |||||       d {   }n/|||z
  z
  }t        |      }	| j                  |||	       d {    t        j                  d| d|        y 7 7 7 T7 &w)N)r   r   r   )r   r   r   r   r   z,Budget window expired - resetting everything)r   r   r   zIncremented spend for z by )r   r   nowr   utc	timestampr   r   r   r   r   rO   r   )
r#   r   r   r   r   r   r   r   remaining_timettl_for_increments
             r$   r   z-RouterBudgetLimiting._increment_spend_for_key  sY     ((0||HLL1;;=)-*G*GH!??)%# @ 
 
 !%!?!?#-)+' "@ " L \)[8!''(VW!%!?!?#-)+' "@ " L )L<,GHN #N 399#=FW :    	##$YKtM?C	
E
sH   A+D"-D.D"D;D"	D
/D"9D :!D"D"D" D"c                 <  K   	 	 | j                          d{    t        j                  t               d{    ;7 &7 # t        $ rM}t        j                  dt        |              t        j                  t               d{  7   Y d}~Vd}~ww xY ww)z
        Handler that triggers sync_in_memory_spend_with_redis every DEFAULT_REDIS_SYNC_INTERVAL seconds

        Required for multi-instance environment usage of provider budgets
        NzError in periodic sync task: ) _sync_in_memory_spend_with_redisrX   sleepDEFAULT_REDIS_SYNC_INTERVAL	Exceptionr   errorrM   r#   es     r$   rZ   z=RouterBudgetLimiting.periodic_sync_in_memory_spend_with_redis  s      	;;===mm/   =  %++.KCPQF8,TUmm/  sW   BA ? A AA BA A 	B=B	B
BBBBc                   K   	 | j                   j                  syt        j                  d| j                         t        | j                        dkD  rCt        j                  | j                   j                  j                  | j                               g | _        y# t        $ r+}t        j                  dt        |              Y d}~yd}~ww xY ww)a  
        How this works:
        - async_log_success_event collects all provider spend increments in `redis_increment_operation_queue`
        - This function pushes all increments to Redis in a batched pipeline to optimize performance

        Only runs if Redis is initialized
        Nz.Pushing Redis Increment Pipeline for queue: %sr   )increment_list*Error syncing in-memory cache with Redis: )rS   redis_cacher   r   rW   rA   rX   rY   async_increment_pipeliner   r   rM   r   s     r$   #_push_in_memory_increments_to_redisz8RouterBudgetLimiting._push_in_memory_increments_to_redis#  s     	??..!''@44 47781<##OO//HH'+'K'K I  46D0 	!''<SVHE 	s9   CB CBB C	C'!CCCCc                 2  K   	 | j                   j                  y| j                          d{    g }| j                  F| j                  j	                         D ])  \  }}|	|j                  d| d|j                          + | j                  F| j                  j	                         D ])  \  }}|	|j                  d| d|j                          + | j                  F| j                  j	                         D ])  \  }}|	|j                  d| d|j                          + | j                   j                  j                  |       d{   }t        |t              ro|j	                         D ][  \  }}|	| j                   j                  j                  |t        |             d{    t        j                   d| d	|        ] yy7 7 7 (# t"        $ r+}	t        j$                  d
t'        |	              Y d}	~	yd}	~	ww xY ww)a  
        Ensures in-memory cache is updated with latest Redis values for all provider spends.

        Why Do we need this?
        - Optimization to hit sub 100ms latency. Performance was impacted when redis was used for read/write per request
        - Use provider budgets in multi-instance environment, we use Redis to sync spend across all instances

        What this does:
        1. Push all provider spend increments to Redis
        2. Fetch all current provider spend from Redis to update in-memory cache
        Nr   r   r   r   )key_list)r'   r|   zUpdated in-memory cache for rt   r   )rS   r   r   rT   r;   r   r   r[   r\   rv   r`   rE   r   r   rx   r   r   r   r   rM   )
r#   r}   r   r   r   tagredis_valuesr'   r|   r   s
             r$   r   z5RouterBudgetLimiting._sync_in_memory_spend_with_redisA  s.    4	**2 ::<<< J**6(,(C(C(I(I(K$Hf~ %%)(1V5K5K4LM )L ,,8(,(E(E(K(K(M$Hf~ %%+H:Qv7M7M6NO )N %%1#'#9#9#?#?#AKC~ %%
3%q9O9O8P&QR $B "&!<!<!R!R# "S " L
 ,-"."4"4"6JC("oo==MM #5< N    .33:3%r%I #7 .C =8  	!''<SVHE 	ss   HG  HG  GD%G  G,G  3G  5G6!G  HG  G  G   	H)!H
HHHr   c                 T    | j                   y | j                   j                  |d       S r"   )r[   r+   )r#   r   s     r$   r   z6RouterBudgetLimiting._get_budget_config_for_deployment  s,     ((0,,004@@r&   r   c                 T    | j                   y | j                   j                  |d       S r"   )rT   r+   )r#   r   s     r$   r   z4RouterBudgetLimiting._get_budget_config_for_provider  s,     &&.**..x>>r&   r   c                 T    | j                   y | j                   j                  |d       S r"   )r\   r+   )r#   r   s     r$   r   z/RouterBudgetLimiting._get_budget_config_for_tag  s*    !!)%%))#t44r&   r   c                    	 |j                  d      xs i }t        |t              r|j                  xs d}|}n>t        |t              r!|j                  d      xs d}t        |      }nd}t        i       }t        j                  t        |      |      \  }}}}|S # t        $ r t        j                  d|        Y y w xY w)Nr   r   rf   )rf   r   z+Error getting LLM provider for deployment: )r+   r`   r   rf   rE   r   ra   get_llm_providerrM   r   r   r   )r#   r   deployment_litellm_paramsrf   provider_resolution_params_r   s          r$   r   z5RouterBudgetLimiting._get_llm_provider_for_deployment  s    	(27G(H(NB%3^D177=22K*5t<155g>D"-C-.* -CB-G*+2+C+C%j9,(A"Aq #"  	!''=j\J 		s   BB !CCr   r   c                 F    t               }|r|j                  |||       yy)z
        Optional helper - emit provider remaining budget metric to Prometheus

        This is helpful for debugging and monitoring provider budget limits.
        r   N)r   track_provider_remaining_budget)r#   r   r   r   prometheus_loggers        r$   r   z@RouterBudgetLimiting._track_provider_remaining_budget_prometheus  s2     BC==!) >  r&   c                 J  K   | j                  |      }|yd| d|j                   }| j                  j                  r.| j                  j                  j	                  |       d{   }n#| j                  j	                  |       d{   }|t        |      S dS 7 77 w)ab  
        GET the current spend for a provider from cache

        used for GET /provider/budgets endpoint in spend_management_endpoints.py

        Args:
            provider (str): The provider to get spend for (e.g., "openai", "anthropic")

        Returns:
            Optional[float]: The current spend for the provider, or None if not found
        Nr   r   rl   )r   r   rS   r   r   rx   )r#   r   r   r   r   s        r$   _get_current_provider_spendz0RouterBudgetLimiting._get_current_provider_spend  s      <<XF %hZq1N1N0OP	??&&"&//"="="M"Mi"XXM #'//"A"A)"LLM'4'@u]#IcI	 Y Ms$   A%B#'B(#B#B!B#!B#c                   K   | j                  |      }|y d| d|j                   }| j                  j                  r.| j                  j                  j	                  |       d {   }n#| j                  j	                  |       d {   }|y t        j                  t        j                        t        |      z   j                         S 7 i7 Gw)Nr   r   )seconds)r   r   rS   r   async_get_ttlr   r   r   r   r   	isoformat)r#   r   r   r   r   s        r$   %_get_current_provider_budget_reset_atz:RouterBudgetLimiting._get_current_provider_budget_reset_at  s      <<XF %hZq1N1N0OP	??&& $ ; ; I I) TTK $ = =i HHKX\\*Y{-KKVVXX UHs%   A%C'C(#CCACCc                    K   d| d|j                    }d| }d}|j                   t        |j                         }| j                  j                  |       d{   }|Wt	        j
                  t        j                        j                         }| j                  j                  |||       d{    | j                  j                  |       d{   }|'| j                  j                  |d|       d{    yy7 7 S7 27 w)a!  
        Initialize provider budget in cache by storing the following keys if they don't exist:
        - provider_spend:{provider}:{budget_config.time_period} - stores the current spend
        - provider_budget_start_time:{provider} - stores the start time of the budget window

        r   r   r   Nr   rl   )
r   r   rS   r   r   r   r   r   r   r   )r#   r   r   r   r   r   r   
_spend_keys           r$   _init_provider_budget_in_cachez3RouterBudgetLimiting._init_provider_budget_in_cache  s     &hZq1N1N0OP	6xjA%)((4-m.K.KLK!__<<^LL#<<5??AL//11",K 2     ??::9EE
//11Sk 2     M FsI   ADDAD4D5"DD
'D?D DD
DDc                     | yt         j                  y|y|D ]8  }|j                  di       }|j                  d      s|j                  d      8 y y)a  
        Returns `True` if the router budget routing settings are set and RouterBudgetLimiting should be initialized

        Either:
         - provider_budget_config is set
         - budgets are set for deployments in the model_list
         - tag_budget_config is set
        TFr   r   r   )ra   r\   r+   )rT   rU   _modelr   s       r$   !should_init_router_budget_limiterz6RouterBudgetLimiting.should_init_router_budget_limiter  sh     "-$$0 F$jj)92>O##L1"&&'89E ! r&   c                    | j                   | j                   j                         D ]  \  }}|t        d| d| j                          t        |t              s8t	        |j                  d      |j                  d            | j                   |<   t        j                  | j                  || j                   |                 t        j                  d| j                           y y )Nz$No budget config found for provider z, provider_budget_config: r   time_period)r   r   )r   r   z#Initalized Provider budget config: )rT   r;   rz   r`   GenericBudgetInfor+   rX   rY   r   r   r   )r#   r   r   s      r$   r]   z+RouterBudgetLimiting._init_provider_budgets.  s    &&2$($?$?$E$E$G &>$>xjHbcgc~c~b  A  "&*;<<M%+ZZ%?$*JJ}$==D//9 ##77!)&*&A&A(&K 8  %H$ "''5d6Q6Q5RS) 3r&   c           	         |y |D ]  }|j                  di       }|j                  d      xs i }|j                  d      }|j                  d      }|j                  d      }t        j                  d| d| d|        |~||t        ||	      }| j                  i | _        || j                  |<    t        j                  d
| j                          y )Nr   r   r   r   r   z$Init Deployment Budget: max_budget: z, budget_duration: r   r   r   z&Initialized Deployment Budget Config: )r+   r   r   r   r[   )	r#   rU   r   r   _model_info	_model_id_max_budget_budget_duration_budget_configs	            r$   r^   z-RouterBudgetLimiting._init_deployment_budgetsG  s     F$jj)92>O &

< 8 >BK#-I)--l;K.223DE!''6{mCVWgVhhtu~t  A '$0)!2 0!," 00846D1;I--i8+ !. 	##4T5R5R4ST	
r&   c                    t         j                  y ddlm}m} |durt        d|j                         | j                  i | _        t         j                  j                         D ]P  \  }}t        |t              rt        di |}t        |j                  |j                        }|| j                  |<   R t        j                  d| j                          y )Nr   )CommonProxyErrorspremium_userTz,Tag budgets are an Enterprise only feature, r  zInitialized Tag Budget Config: rP   )ra   r\   litellm.proxy.proxy_serverr  r	  rz   not_premium_userr;   r`   rE   r   r   r   r   r   r   )r#   r  r	  r   r   _generic_budget_configs         r$   r_   z&RouterBudgetLimiting._init_tag_budgetsj  s    $$,Nt#>?P?a?a>bc  !!)%'D"(/(A(A(G(G(I$D$,d3%1%G4F%G"%6.>>/::&" ,BD""4( )J 	##-d.D.D-EF	
r&   r"   )NN)+rH   rI   rJ   r   r	   rE   r   r   r   r   rM   r   r%   r   r   r   r   rx   r
   ry   ru   rO   r   r   r   r   r   rZ   r   r   r   r   r   r   r   r   r   r   staticmethodr   r]   r^   r_   rP   r&   r$   rR   rR   [   s#    HH !)H $*+T$sCx.-AAB
	H: *.+/I'I' "I' 4 012	I'
 !I' #4.I' 
dI'VYC#DcN3YC "$sCx.1YC s$556	YC
 !&7!78YC #8C=1YC U
#YC 3iYC 
tDcN#S(	)YC| *.C
!$sCx.1C
 !C
 
S	S##$S##$Xc]	
	C
J#!#16#EH#	#"  	
   
8BB-2B9<B.9v1
(1
 1
 	1

 1
f$<AFAA 
#	$A??	#	$?5c 5h?P6Q 5
#4 #HSM #6$)9>"J# J(5/ J4YY	#Y$,=: 
 	 ($*+T$sCx.-AAB
 @: 	!
$*+T$sCx.-AAB
!
F
r&   rR   )*rK   rX   r   r   r   typingr   r   r   r	   r
   r   ra   litellm._loggingr   litellm.caching.cachingr   litellm.caching.redis_cacher   "litellm.integrations.custom_loggerr   r   *litellm.litellm_core_utils.duration_parserr   )litellm.router_strategy.tag_based_routingr   'litellm.router_utils.cooldown_callbacksr   litellm.types.llms.openair   litellm.types.routerr   r   r   litellm.types.utilsr   r   r   r   r   r   rR   rP   r&   r$   <module>r     sh   (  2 2 : :  2 - G A J S 7 R R , A O ," ,"^g
< g
r&   