
    ^h                         S r SSKrSSKJrJrJr  SSKJrJrJrJ	r	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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!J"r"J#r#  SSK$J%r%J&r&  Sr' " S S\5      r(g)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GenericBudgetConfigTypeGenericBudgetInfoLiteLLM_ParamsRouterErrors)BudgetConfigStandardLoggingPayload   c                   P   \ rS rSr S7S\S\\   S\\\\	   \\
\\4      4      4S jjr  S8S\S\S	\\\      S
\\   S\\   S\\   4S jjrS\\
\\4      S\\
\\4      S\
\\4   S\
\\4   S\
\\4   S\\   S\\\
\\4      \4   4S jr S7S\\
\\4      S
\\
   S\\\   \
\\4   \
\\4   4   4S jjrS\S\S\S\4S jrS\S\S\S\S\S\4S jrS\S\S\4S jrS rS\S\S\S\4S  jrS! rS" rS# rS$\S\\   4S% jrS&\S\\   4S' jr S(\S\\   4S) jr!S*\
S\\   4S+ jr"S&\S,\S-\4S. jr#S&\S\\   4S/ jr$S&\S\\   4S0 jr%S&\S\4S1 jr&\' S7S\\   S\\\\	   \\
\\4      4      4S2 jj5       r(S3 r) S7S\\\\	   \\
\\4      4      4S4 jjr*S5 r+S6r,g)9RouterBudgetLimiting0   N
dual_cacheprovider_budget_config
model_listc                 t   Xl         / U l        [        R                  " U R	                  5       5        UU l        S U l        S U l        U R                  5         U R                  US9  U R                  5         [        [        R                  [        5      (       a   [        R                  R                  U 5        g g )N)r"   )r    redis_increment_operation_queueasynciocreate_task(periodic_sync_in_memory_spend_with_redisr!   deployment_budget_configtag_budget_config_init_provider_budgets_init_deployment_budgets_init_tag_budgets
isinstancelitellm	callbackslistappend)selfr    r!   r"   s       `/home/james-whalen/.local/lib/python3.13/site-packages/litellm/router_strategy/budget_limiter.py__init__RouterBudgetLimiting.__init__1   s     %VX,DIIKL" 	# LP%DH##%%%%<  g''..$$T* /    modelhealthy_deploymentsmessagesrequest_kwargsparent_otel_spanreturnc                 <  #    [        U[        5      (       a  U/n[        U5      S:X  a  U$ / nU R                  UUS9I Sh  vN u  pxn	[        U5      S:  a  U R                  R                  UUS9I Sh  vN n
U
=(       d    S/[        U5      -  n0 n[        U5       H  u  p[        X   =(       d    S5      X'   M     U R                  UUU	UU[        US9S9u  po[        U5      S:X  a(  [        [        R                  R                   SU 35      eU$ U$  N N7f)	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   )r8   r:   N)keysr;           r:   )r8   provider_configsdeployment_configs	spend_mappotential_deploymentsrequest_tags: )r-   dictlen0_async_get_cache_keys_for_router_budget_limitingr    async_batch_get_cache	enumeratefloat$_filter_out_deployments_above_budgetr   
ValueErrorr   +no_deployments_with_provider_budget_routingvalue)r2   r7   r8   r9   r:   r;   rD   
cache_keysrA   rB   _current_spendscurrent_spendsrC   idxkeydeployment_above_budget_infos                   r3   async_filter_deployments-RouterBudgetLimiting.async_filter_deploymentsI   sg    & )400#6"7 "#q(&&,. GG$7- H   	9
&8 z?Q$(OO$I$I!1 %J % O $3#Msec*o6MN +-I%j1!&~':'Ac!B	 2 99(;%5'9'*?!>'5" : 	 @! ()Q. #OOUUVVXYuXvw  )(&&Os$   ?DD3D5D6B#DDrD   rA   rB   rC   rE   c                    SnU GHI  nSn	U R                   (       a  U R                  U5      n
X;   ap  X:   nUR                  SU
 SUR                   3S5      nU R	                  U
UUR
                  S9  XR
                  :  a   SU
 SU S	UR
                   3nX} S
3-  nSn	M  U R                  (       a  U	(       a  UR                  S5      nUR                  S5      =(       d    0 nUR                  S5      nUR                  S0 5      R                  S5      nUU;   as  UU   nUR                  SU SUR                   3S5      nXR
                  :  a=  SU SU SU SU S	UR
                   3
n[        R                  " U5        X} S
3-  nSn	GM  U R                  (       a  U	(       a  U H  nU R                  U5      nU(       d  M  UR                  SU SUR                   3S5      nUUR
                  :  d  MQ  SU SU SUR
                   3n[        R                  " U5        X} S
3-  nSn	M     U	(       d  GM8  UR                  U5        GML     X4$ )as  
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::r?   providerspendbudget_limitzExceeded budget for provider rF   z >= 
F
model_namelitellm_paramsr7   
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=)r!    _get_llm_provider_for_deploymentgettime_period+_track_provider_remaining_budget_prometheusr`   r(   r   debugr)   _get_budget_config_for_tagr1   )r2   rD   r8   rA   rB   rC   rE   rV   
deploymentis_within_budgetr^   configcurrent_spend	debug_msg_model_name_litellm_params_litellm_model_namemodel_id_tag_tag_budget_config
_tag_spends                        r3   rM   9RouterBudgetLimiting._filter_out_deployments_above_budget   s   * -/$-J# **@@L/-7F$-MM)(1V5G5G4HI3%M DD!)+%+%8%8 E  %(;(;;&CH:RP]^bcicvcvbw$x	4+R8HH4+0(  ,,1A(nn\:",..1A"B"Hb&5&9&9'&B#%>>,;??E11/9F$-MM+H:Qv7I7I6JKS%M %(;(;;&QR]Q^^v  xK  wL  LX  Ya  Xb  bd  er  ds  sw  x~  xK  xK  wL  %M	-33I>4+R8HH4+0(  %%*:(D)-)H)H)N&))%.]](a0B0N0N/OPRU&
 &);)H)HH*CD6WaVbbu  wI  wV  wV  vW  )XI177	B8k<LL8/4,$ )  %,,Z8s .v %BBr6   c                   #    / n0 n0 nU GH0  nU R                   (       aM  U R                  U5      nUb9  U R                  U5      nUb%  XU'   UR                  SU SUR                   35        U R
                  (       a]  UR                  S0 5      R                  S5      n	U	b9  U R                  U	5      nUb%  XU	'   UR                  SU	 SUR                   35        U R                  (       d  M  [        US9n
U
 H>  nU R                  U5      nU(       d  M  UR                  SU SUR                   35        M@     GM3     X4U4$ 7f)a  
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 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`
r[   r\   rd   re   rf   r@   rh   )r!   ri   _get_budget_config_for_providerr1   rk   r(   rj   !_get_budget_config_for_deploymentr)   r   rn   )r2   r8   r:   rQ   rA   rB   ro   r^   budget_configrw   rE   rx   ry   s                r3   rI   ERouterBudgetLimiting._async_get_cache_keys_for_router_budget_limiting   sf     !#
9;;=-J**@@L'$($H$H$RM$05B2"))-hZq9R9R8ST
 ,,%>>,;??E'$($J$J8$TM$07D84"))/z=;T;T:UV %%%<#1  )D)-)H)H)N&))"))(a0B0N0N/OP )7 .B -???s   C(E.$E.Estart_time_keycurrent_timettl_secondsc                    #    U R                   R                  U5      I Sh  vN nUc$  U R                   R                  XUS9I Sh  vN   U$ [        U5      $  N6 N7f)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rU   rP   ttl)r    async_get_cacheasync_set_cacherL   )r2   r   r   r   budget_starts        r3   _get_or_set_budget_start_time2RouterBudgetLimiting._get_or_set_budget_start_time  sh      "__<<^LL//11"K 2     \"" Ms!   AA$AAAA	spend_keyresponse_costc                    #    U R                   R                  XUS9I Sh  vN   U R                   R                  X#US9I Sh  vN   U$  N( N7f)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)r    r   )r2   r   r   r   r   r   s         r3   _handle_new_budget_window.RouterBudgetLimiting._handle_new_budget_window(  sg     ( oo--K . 
 	
 	
 oo-- . 
 	
 	
 	
	
s!   AA	!AAAAr   c                    #    U R                   R                  R                  UUUS9I Sh  vN   [        UUUS9nU R                  R                  U5        g N+7f)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)rU   increment_valuer   )r    in_memory_cacheasync_incrementr   r$   r1   )r2   r   r   r   increment_ops        r3   "_increment_spend_in_current_window7RouterBudgetLimiting._increment_spend_in_current_windowD  sg      oo--== > 
 	
 	

 7)

 	,,33LA	
s   )AA,Ac                 @  #    [         R                  " S5        UR                  SS5      nUc  [        S5      eUR                  SS5      n[	        UR                  SS5      5      nUR                  S	0 5      R                  S
S5      nUc  [        S5      eU R                  U5      n	U	(       a1  SU SU	R                   3n
SU 3nU R                  U	U
UUS9I Sh  vN   U R                  U5      nU(       a1  SU SUR                   3nSU 3nU R                  UUUUS9I Sh  vN   [        U5      n[        U5      S:  aU  U HN  nU R                  U5      nU(       d  M  SU SUR                   3nSU 3nU R                  UUUUS9I Sh  vN   MP     gg N Nv N7f)z)Original method now uses helper functionsz/in RouterBudgetLimiting.async_log_success_eventstandard_logging_objectNz$standard_logging_payload is requiredr   r   rw   rZ   rc   custom_llm_providerzcustom_llm_provider is requiredr[   r\   provider_budget_start_time:)r   r   r   r   rf   zdeployment_budget_start_time:rh   ztag_budget_start_time:)r   rm   rj   rN   strr}   rk   _increment_spend_for_keyr~   r   rH   rn   )r2   kwargsresponse_obj
start_timeend_timestandard_logging_payloadr   rw   r   r   r   r   r(   deployment_spend_keydeployment_start_time_keyrE   rx   ry   _tag_spend_key_tag_start_time_keys                       r3   async_log_success_event,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8Q8Q7RS   ;;N:OPN//+#-+	 0    $(#I#I(#S # $H:Q/G/S/S.TU ! +Hz(R%//6.8+	 0    5V<|q $%)%D%DT%J"%%$TF!,>,J,J+KL # -C4&*I'77&8"0':&3	 8    % !- s=   CFFAF#F$9F!,FFFFFr   c                   #    [         R                  " [        R                  5      R	                  5       n[        UR                  5      nU R                  UUUS9I S h  vN nUc  U R                  UUUUUS9I S h  vN nOdXW-
  U:  a2  [        R                  " S5        U R                  UUUUUS9I S h  vN nO*XeU-
  -
  n[        U5      n	U R                  X$U	S9I S h  vN   [        R                  " SU SU 35        g  N N NP N'7f)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   nowr   utc	timestampr   rk   r   r   r   rm   intr   )
r2   r   r   r   r   r   r   r   remaining_timettl_for_increments
             r3   r   -RouterBudgetLimiting._increment_spend_for_key  s@      ||HLL1;;=)-*C*CD!??)%# @ 
 
 !%!?!?#-)+' "@ " L )[8!''(VW!%!?!?#-)+' "@ " L )<,GHN #N 399#FW :    	##$YKtM?C	
E
sH   ADDD<D=9D6D7*D!D	""DDD	Dc                 F  #      U R                  5       I Sh  vN   [        R                  " [        5      I Sh  vN   M=   N( N! [         aO  n[
        R                  " S[        U5       35        [        R                  " [        5      I Sh  vN     SnANZSnAff = f7f)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_redisr%   sleepDEFAULT_REDIS_SYNC_INTERVAL	Exceptionr   errorr   r2   es     r3   r'   =RouterBudgetLimiting.periodic_sync_in_memory_spend_with_redis  s      	;;===mm/   =  %++.KCPQF8,TUmm/  sY   B!A A!A AA B!A A 
B?BBBB!BB!c                   #     U R                   R                  (       d  g[        R                  " SU R                  5        [        U R                  5      S:  aA  [        R                  " U R                   R                  R                  U R                  S95        / U l        g! [         a,  n[        R                  " S[        U5       35         SnAgSnAff = f7f)z
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: )r    redis_cacher   rm   r$   rH   r%   r&   async_increment_pipeliner   r   r   r   s     r3   #_push_in_memory_increments_to_redis8RouterBudgetLimiting._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                 V  #     U R                   R                  c  gU R                  5       I Sh  vN   / nU R                  bI  U R                  R	                  5        H+  u  p#Uc  M
  UR                  SU SUR                   35        M-     U R                  bI  U R                  R	                  5        H+  u  pCUc  M
  UR                  SU SUR                   35        M-     U R                  bI  U R                  R	                  5        H+  u  pSUc  M
  UR                  SU SUR                   35        M-     U R                   R                  R                  US9I Sh  vN n[        U[        5      (       ap  UR	                  5        H[  u  pxUc  M
  U R                   R                  R                  U[        U5      S9I Sh  vN   [        R                   " SU S	U 35        M]     gg GN N N+! ["         a,  n	[        R$                  " S
['        U	5       35         Sn	A	gSn	A	ff = f7f)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\   rf   rh   )key_list)rU   rP   zUpdated in-memory cache for rF   r   )r    r   r   r!   itemsr1   rk   r(   r)   rJ   r-   rG   r   r   rL   r   rm   r   r   r   )
r2   rQ   r^   rq   rw   tagredis_valuesrU   rP   r   s
             r3   r   5RouterBudgetLimiting._sync_in_memory_spend_with_redis  s"    2	**2 ::<<< J**6(,(C(C(I(I(K$H~ %%z6CUCUBV&WX )L
 ,,8(,(E(E(K(K(M$H~ %%+H:Qv7I7I6JK )N %%1#'#9#9#?#?#AKC~ %%
3%q9K9K8L&MN $B "&!<!<!R!R# "S " L
 ,--"."4"4"6JC("oo==MM #5< N    .33:3%r%I #7 .? =4  	!''<SVHE 	ss   H)G0 H)G0 G)D.G0 G,/G0 0G0 G.$G0 'H))G0 ,G0 .G0 0
H&:"H!H)!H&&H)rw   c                 V    U R                   c  g U R                   R                  US 5      $ N)r(   rj   )r2   rw   s     r3   r~   6RouterBudgetLimiting._get_budget_config_for_deployment9  s,     ((0,,004@@r6   r^   c                 V    U R                   c  g U R                   R                  US 5      $ r   )r!   rj   )r2   r^   s     r3   r}   4RouterBudgetLimiting._get_budget_config_for_providerA  s,     &&.**..x>>r6   r   c                 V    U R                   c  g U R                   R                  US 5      $ r   )r)   rj   )r2   r   s     r3   rn   /RouterBudgetLimiting._get_budget_config_for_tagH  s*    !!)%%))#t44r6   ro   c           	           [        S0 UR                  SSS05      D6n[        R                  " UR                  US9u  p4  nU$ ! [
         a    [        R                  " SU 35         g f = f)Nrc   r7   rZ   )r7   rc   z+Error getting LLM provider for deployment:  )r   rj   r.   get_llm_providerr7   r   r   r   )r2   ro   ru   _r   s        r3   ri   5RouterBudgetLimiting._get_llm_provider_for_deploymentM  s    	.< /..!1GR=A/O ,3+C+C%++.,(AAq #"  	!''=j\J 		s   A A #A*)A*r_   r`   c                 J    [        5       nU(       a  UR                  UUUS9  gg)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)r2   r^   r_   r`   prometheus_loggers        r3   rl   @RouterBudgetLimiting._track_provider_remaining_budget_prometheus]  s2     BC==!) >  r6   c                 X  #    U R                  U5      nUc  gSU SUR                   3nU R                  R                  (       a.  U R                  R                  R	                  U5      I Sh  vN nO#U R                  R	                  U5      I Sh  vN nUb  [        U5      $ S$  N8 N7f)a*  
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\   r?   )r}   rk   r    r   r   rL   )r2   r^   r   r   rr   s        r3   _get_current_provider_spend0RouterBudgetLimiting._get_current_provider_spendn  s      <<XF %hZq1J1J0KL	??&&"&//"="="M"Mi"XXM #'//"A"A)"LLM'4'@u]#IcI	 Y Ms$   A+B*-B&.#B*B(B*(B*c                   #    U R                  U5      nUc  g SU SUR                   3nU R                  R                  (       a.  U R                  R                  R	                  U5      I S h  vN nO#U R                  R	                  U5      I S h  vN nUc  g [
        R                  " [        R                  5      [        US9-   R                  5       $  Nh NF7f)Nr[   r\   )seconds)r}   rk   r    r   async_get_ttlr   r   r   r   r   	isoformat)r2   r^   r   r   r   s        r3   %_get_current_provider_budget_reset_at:RouterBudgetLimiting._get_current_provider_budget_reset_at  s      <<XF %hZq1J1J0KL	??&& $ ; ; 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                   #    SU SUR                    3nSU 3n[        UR                   5      nU R                  R                  U5      I Sh  vN nUcT  [        R
                  " [        R                  5      R                  5       nU R                  R                  XFUS9I Sh  vN   U R                  R                  U5      I Sh  vN nUc$  U R                  R                  USUS9I Sh  vN   gg N NQ N0 N7f)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   r?   )
rk   r   r    r   r   r   r   r   r   r   )r2   r^   r   r   r   r   r   
_spend_keys           r3   _init_provider_budget_in_cache3RouterBudgetLimiting._init_provider_budget_in_cache  s      &hZq1J1J0KL	6xjA)-*C*CD!__<<^LL#<<5??AL//11"K 2     ??::9EE
//11Sk 2     M FsI   AC<C4AC<$C6%"C<C8%C<-C:.C<6C<8C<:C<c                     U b  g[         R                  b  gUc  gU H?  nUR                  S0 5      nUR                  S5      (       d  UR                  S5      c  M?    g   g)z
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
TFrc   
max_budgetbudget_duration)r.   r)   rj   )r!   r"   _modelru   s       r3   !should_init_router_budget_limiter6RouterBudgetLimiting.should_init_router_budget_limiter  sk     "-$$0 F$jj)92>O##L11"&&'89E ! r6   c                    U R                   b  U R                   R                  5        H  u  pUc  [        SU SU R                    35      e[        U[        5      (       d5  [	        UR                  S5      UR                  S5      S9U R                   U'   [        R                  " U R                  UU R                   U   S95        M     [        R                  " SU R                    35        g g )Nz$No budget config found for provider z, provider_budget_config: r`   rk   )r`   rk   )r^   r   z#Initalized Provider budget config: )r!   r   rN   r-   r   rj   r%   r&   r   r   rm   )r2   r^   rq   s      r3   r*   +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) 3r6   c           	         Uc  g U H  nUR                  S0 5      nUR                  S0 5      nUR                  S5      nUR                  S5      nUR                  S5      n[        R                  " SU SU SU 35        Uc  M~  Uc  M  Uc  M  [        UUS	9nU R                  c  0 U l        XR                  U'   M     [        R                  " S
U R                   35        g )Nrc   rd   re   r   r   z$Init Deployment Budget: max_budget: z, budget_duration: rg   rk   r`   z&Initialized Deployment Budget Config: )rj   r   rm   r   r(   )	r2   r"   r   ru   _model_info	_model_id_max_budget_budget_duration_budget_configs	            r3   r+   -RouterBudgetLimiting._init_deployment_budgets  s      F$jj)92>O **\26K#-I)--l;K.223DE!''6{mCVWgVhhtu~t  A '$0)!2 0!," 00846D1;I--i8+ !. 	##4T5R5R4ST	
r6   c                    [         R                  c  g SSKJnJn  USLa  [        SUR                   35      eU R                  c  0 U l        [         R                  R                  5        HQ  u  p4[        U[        5      (       a  [        S0 UD6n[        UR                  UR                  S9nXPR                  U'   MS     [        R                  " SU R                   35        g )Nr   )CommonProxyErrorspremium_userTz,Tag budgets are an Enterprise only feature, r   zInitialized Tag Budget Config: r   )r.   r)   litellm.proxy.proxy_serverr   r   rN   not_premium_userr   r-   rG   r   r   r   r   r   rm   )r2   r   r   rx   ry   _generic_budget_configs         r3   r,   &RouterBudgetLimiting._init_tag_budgets  s    $$,Nt#>?P?a?a>bc  !!)%'D"(/(A(A(G(G(I$D,d33%1%G4F%G"%6.>>/::&" ,B""4( )J 	##-d.D.D-EF	
r6   )r(   r    r!   r$   r)   r   )NN)-__name__
__module____qualname____firstlineno__r   r	   rG   r   r   r   r   r   r   r4   r   r   rW   r   rL   r
   rM   rI   r   r   r   r   r   r   r'   r   r   r~   r}   rn   ri   rl   r   r   r   staticmethodr   r*   r+   r,   __static_attributes__r   r6   r3   r   r   0   s    ++ !)+ $*+T$sCx.-AAB
	+: *.+/D'D' "D' 4 012	D'
 !D' #4.D' 
dD'LQC#DcN3QC "$sCx.1QC s$556	QC
 !&7!78QC U
#QC 3iQC 
tDcN#S(	)QCl *.3@!$sCx.13@ !3@ 
tCy$s$556SBS=S8TT	U	3@j#!#16#EH#	#"  	
   
8BB-2B9<B.;z.
(.
 .
 	.

 .
`$<?BAA 
#	$A??	#	$?5c 5h?P6Q 5
#4 #HSM # $)9>"J# J(5/ J4YY	#Y$,=2 
 	 ($*+T$sCx.-AAB
 @: 	!
$*+T$sCx.-AAB
!
F
r6   r   ))__doc__r%   r   r   r   typingr   r   r   r	   r
   r   r.   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   r   r   litellm.types.utilsr   r   r   r   r   r6   r3   <module>r     s^   (  2 2 : :  2 - G A J S 7  E x
< x
r6   