Ë
    tPêj¾Ê  ã                   ó(  — U d Z ddlZddlmZmZmZ ddlmZ ddlm	Z	m
Z
mZmZmZmZ ddlmZ ddlmZmZmZ ddlZddlmZ dd	lmZmZmZmZ dd
lmZ ddlm Z  ddl!m"Z"m#Z#m$Z$m%Z% ddl&m'Z' ddl(m)Z)m*Z* ddl+m,Z,m-Z-m.Z.m/Z/ ddl0m1Z1m2Z2m3Z3 ddl4m5Z5 e	r4ddl6m7Z8 ddl0m9Z: ddl0m;Z< ddl0m=Z> ddl?m@ZA ddlBmCZD e8e
z  Z7eAZ@eDZCe>ZEe<Z;e:Z9ne
Z7e
Z@e
ZCe
ZEeFeGe
f   Z;eFeGe
f   Z9 eeFeGeHf   «      ZIeeJd<   eFed   eKf   ZLeeJd<    G d„ de«      ZM G d„ de «      ZNy)aø  
Batch Rate Limiter Hook

This hook implements rate limiting for batch API requests by:
1. Reading batch input files to count requests and estimate tokens at submission
2. Validating actual usage from output files when batches complete
3. Integrating with the existing parallel request limiter infrastructure

## Integration & Calling
This hook is automatically registered and called by the proxy system.
See BATCH_RATE_LIMITER_INTEGRATION.md for complete integration details.

Quick summary:
- Add to PROXY_HOOKS in litellm/proxy/hooks/__init__.py
- Gets auto-instantiated on proxy startup via _add_proxy_hooks()
- async_pre_call_hook() fires on POST /v1/batches (batch submission)
- async_log_success_event() fires on GET /v1/batches/{id} (batch completion)
é    N)ÚIterableÚMappingÚSequence)ÚMappingProxyType)ÚTYPE_CHECKINGÚAnyÚFinalÚLiteralÚNoReturnÚ	TypeAlias)ÚHTTPException)Ú	BaseModelÚFieldÚTypeAdapter)Úverbose_proxy_logger)Ú_count_entry_tokensÚ_estimate_batch_entry_tokensÚ _extract_file_access_credentialsÚ_iter_batch_input_lines)ÚRateLimitErrorCategory)ÚCustomLogger)ÚProxyErrorTypesÚProxyExceptionÚSpecialModelNamesÚUserAPIKeyAuth)Ú"get_model_rate_limit_from_metadata)ÚProxyRateLimitErrorÚmap_v3_rate_limit_type)ÚBatchEnqueuedTokenOverLimitÚBatchEnqueuedTokenReservationÚBatchEnqueuedTokenScopeÚ#resolve_batch_enqueued_token_scopes)ÚPROJECT_ITPM_DESCRIPTOR_KEYÚPROJECT_OTPM_DESCRIPTOR_KEYÚget_or_create_request_stash)Ú#resolve_llm_provider_for_rate_limit)ÚSpan)ÚRateLimitDescriptor)ÚRateLimitStatus)Ú$_PROXY_MaxParallelRequestsHandler_v3)ÚInternalUsageCache)ÚRouterÚ_BATCH_BODY_ADAPTER©ÚrequestsÚtokensÚIncrementAmountsc                   ód   — e Zd ZU dZeed<   eed<   dZeed<    ee¬«      Z	ee
ee
ef   f   ed<   y)	ÚBatchFileUsagezT
    Internal model for batch file usage tracking, used for batch rate limiting
    Útotal_tokensÚrequest_countr   Úoutput_tokens)Údefault_factoryÚper_model_usageN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__ÚintÚ__annotations__r6   r   Údictr8   Ústr© ó    úk/home/oem/CyberBrain26-unified/.venv/lib/python3.12/site-packages/litellm/proxy/hooks/batch_rate_limiter.pyr3   r3   a   sG   … ñð ÓØÓØ€M�3Óñ 27Øô2€O�T˜#˜t C¨ H™~Ð-Ñ.ô rB   r3   c                   ó  — e Zd ZdZdedefd„Zdededz  fd„Z	dededz  fd	„Z
d
edz  dedz  fd„Zdededed   fd„Zededefd„«       Zdedeeeeef   f   deed   ee   f   fd„Z	 d4dedededeeed   dz  f   fd„Zdeddfd„Zededefd„«       Zdeeef   dedz  defd„Zeded   defd„«       Zdedededeeeeef   f   fd„Zdedeeef   ded ee d!f   ddf
d"„Z!d#e"deeef   dede#fd$„Z$	 d5d%d&ded   ded'ed(edz  de#fd)„Z%	 d5dedededed   dz  ddf
d*„Z&	 	 	 	 d6dede'd+   dedz  dedz  de(d   dz  defd,„Z)	 	 d7ded-e*e   dz  d.ee   dz  ddfd/„Z+dededefd0„Z,ded1eded2ede-ez  ez  dz  f
d3„Z.y)8Ú_PROXY_BatchRateLimiterzâ
    Rate limiter for batch API requests.

    Handles rate limiting at two points:
    1. Batch submission - reads input file and reserves capacity
    2. Batch completion - reads output file and adjusts for actual usage
    Úinternal_usage_cacheÚparallel_request_limiterc                 ó.   — || _         || _        d| _        y)aº  
        Initialize the batch rate limiter.

        Note: These dependencies are automatically injected by ProxyLogging._add_proxy_hooks()
        when this hook is registered in PROXY_HOOKS. See BATCH_RATE_LIMITER_INTEGRATION.md.

        Args:
            internal_usage_cache: Cache for storing rate limit data (auto-injected)
            parallel_request_limiter: Existing rate limiter to integrate with (needs custom injection)
        FN)rF   rG   Ú_warned_unsupported_model_skip)ÚselfrF   rG   s      rC   Ú__init__z _PROXY_BatchRateLimiter.__init__}   s   € ð %9ˆÔ!Ø(@ˆÔ%Ø.3ˆÕ+rB   ÚdataÚreturnNc                 óª   — |j                  d«      }t        |t        «      r|syddlm}m}m}  ||«      }|r|S  ||«      }|r ||«      }|r|d   S y)a¯  Resolve the model bound to the batch input file ID.

        ``create_batch`` routes a file-bound id (model-embedded ``file-...`` or
        unified managed file) on that bound model and ignores the top-level
        ``model``, so this is the authoritative routing model whenever the file
        binds one. The provider is then read from that deployment's trusted
        credentials for the provider-level skip decision.
        Úinput_file_idNr   )Ú"_is_base64_encoded_unified_file_idÚdecode_model_from_file_idÚget_models_from_unified_file_id)ÚgetÚ
isinstancer@   Ú1litellm.proxy.openai_files_endpoints.common_utilsrP   rQ   rR   )	rJ   rL   rO   rP   rQ   rR   Úmodel_from_file_idÚunified_file_idÚtarget_model_namess	            rC   Ú_get_file_bound_batch_modelz3_PROXY_BatchRateLimiter._get_file_bound_batch_model�   sj   € ð  $Ÿx™x¨Ó8ˆÜ˜-¬Ô-±]Ø÷	
ñ 	
ñ %>¸mÓ$LÐÙØ%Ð%á!CÀMÓ!RˆÙÙ(GÈÓ(XÐÙ!Ø)¨!Ñ,Ð,àrB   c                 óx   — | j                  |«      }|r|S |j                  d«      }t        |t        «      r|r|S y)aÕ  Resolve the deployment/model used for this batch from request data.

        Mirrors ``create_batch`` routing precedence: a model bound to the input
        file id wins over the top-level ``model``, because the batch endpoint
        ignores the top-level model for file-bound ids. Resolving the provider
        skip from the top-level model first would let a caller point ``model``
        at a skip-listed provider while the file routes a rate-limited one.
        ÚmodelN)rY   rS   rT   r@   )rJ   rL   Úfile_bound_modelr[   s       rC   Ú_get_batch_routing_modelz0_PROXY_BatchRateLimiter._get_batch_routing_model¯   s@   € ð #'×"BÑ"BÀ4Ó"HÐÙØ#Ð#à—x‘x Ó(ˆÜ�eœSÔ!¡eØˆLàrB   Úbatch_modelc                 óª   — |syddl m} ddlm} |€y	  |||d¬«      }|j                  d«      }t        |t        «      r|r|S dS # t        $ r Y yw xY w)a0  Resolve the provider from the deployment that serves ``batch_model``.

        The provider is read from trusted router credentials rather than the
        user-supplied ``custom_llm_provider`` request field, so a caller cannot
        spoof a skip-listed provider to bypass batch rate limiting.
        Nr   )Úget_credentials_for_model©Ú
llm_routerú%batch input file read (rate limiting)©rb   Úmodel_idÚoperation_contextÚcustom_llm_provider)rU   r`   Úlitellm.proxy.proxy_serverrb   r   rS   rT   r@   )rJ   r^   r`   rb   ÚcredentialsÚproviders         rC   Ú_resolve_batch_providerz/_PROXY_BatchRateLimiter._resolve_batch_providerÂ   sp   € ñ Øõ	
õ 	:àÐØð	Ù!:Ø%Ø$Ø"Iô"ˆKð &Ÿ/™/Ð*?Ó@ˆÜ% h´Ô4¹ˆxÐKÀtÐKøô	 ò 	Ùð	ús   ”A Á	AÁAÚuser_api_key_dictr(   c                 óB   — | j                   j                  ||ddd¬«      S )a  Build the standard key/user/team/model descriptor list a batch is charged against.

        Deliberately excludes the project-scoped ITPM/OTPM descriptors: those
        are charged per the JSONL row's own `body.model` once the file is
        parsed (`_create_project_io_descriptors_for_models`), not the
        file-bound/top-level routing model this function resolves. Charging
        project quotas here would let a caller bind the file to a model
        without a quota while rows execute against a quota-limited model.
        NF)rl   rL   Úrpm_limit_typeÚtpm_limit_typeÚmodel_has_failures)rG   Ú_create_rate_limit_descriptors)rJ   rl   rL   s      rC   Ú$_create_batch_rate_limit_descriptorsz<_PROXY_BatchRateLimiter._create_batch_rate_limit_descriptorsà   s2   € ð ×,Ñ,×KÑKØ/ØØØØ$ð Ló 
ð 	
rB   c                 óx   — | j                   €yt        t        | dd«      «      xs t        t        | dd«      «      S )aþ  True when the project has any per-model ITPM/OTPM quota configured.

        Used to stop the "skip batch input file processing" fast path from
        bypassing a project quota configured for a model other than the
        batch's file-bound/top-level routing model: the row models that
        actually drive execution and billing aren't known until the JSONL
        is parsed, so the file must be read whenever *any* model could be
        quota-limited, not only when the routing model itself is.
        FÚproject_metadataÚmodel_itpm_limitÚmodel_otpm_limit)Ú
project_idÚboolr   )rl   s    rC   Ú _project_has_any_io_token_limitsz8_PROXY_BatchRateLimiter._project_has_any_io_token_limitsö   sK   € ð ×'Ñ'Ð/ØÜÜ.Ð/@ÐBTÐVhÓió
ò qäÔ4Ð5FÐHZÐ\nÓoÓpð	qrB   r8   c           	      ó6  — g }g }|j                  «       D ]  \  }}g }| j                  j                  |||¬«       |D ]U  }|j                  |«       |j                  d|d   t        k(  r|j                  dd«      n|j                  dd«      dœ«       ŒW Œ� ||fS )a§  Build project ITPM/OTPM descriptors charged against each row's own model.

        One descriptor pair per distinct `body.model` found in the JSONL,
        each incremented only by that model's own counted usage -- never the
        whole-batch total -- so a quota-limited model can't hide behind an
        unlimited routing model, and an unrelated model's rows can't inflate
        a different model's counter.
        )rl   Úrequested_modelÚdescriptorsr   Úkeyr6   r4   r.   )ÚitemsrG   Ú9add_project_io_token_rate_limit_descriptors_from_metadataÚappendr$   rS   )	rJ   rl   r8   Úextra_descriptorsÚextra_incrementsr[   ÚusageÚmodel_descriptorsÚ
descriptors	            rC   Ú)_create_project_io_descriptors_for_modelszA_PROXY_BatchRateLimiter._create_project_io_descriptors_for_models  sÅ   € ð ?AÐØ:<ÐØ+×1Ñ1Ó3ò 	‰LˆE�5Ø;=ÐØ×)Ñ)×cÑcØ"3Ø %Ø-ð dô ð
 0ò 	�
Ø!×(Ñ(¨Ô4Ø ×'Ñ'à$%à% eÑ,Ô0KÒKð #(§)¡)¨O¸QÔ"?à"ŸY™Y ~°qÓ9ñ	õñ	ð	ð" !Ð"2Ð2Ð2rB   Úhas_enqueued_scopesc                 óÆ  — ddl m} | j                  |«       | j                  |«      ry|j	                  d«      du ry|j	                  d«      xs g }|r=| j                  | j                  |«      «      }|r||v rt        j                  d|«       y| j                  ||¬	«      }|s8| j                  |«      s'| j                  |«      st        j                  d
«       yd|fS )a�  
        Skip downloading batch input files when the operator disabled batch
        input-file rate limiting, when the batch runs entirely on a skip-listed
        provider, or when there is nothing to enforce (no applicable rate
        limits).

        A skip is only honored for keys with unrestricted model access. When
        the key has a model allowlist, the JSONL must still be downloaded so
        ``_enforce_batch_file_model_access`` can validate every ``body.model``
        entry, otherwise a restricted key could smuggle unauthorized models
        into the file via an admin-configured skip.

        The skip is never keyed on a specific model name. The models a batch
        actually runs are its JSONL ``body.model`` entries, and any model
        identifier the caller can influence (the top-level ``model`` or the
        unsigned model embedded in a ``file-...`` id) can be pointed at a
        skip-listed deployment while the file routes a different, rate-limited
        model. The provider skip is safe because the provider is read from the
        routing deployment's trusted credentials and the batch is constrained
        to run on that provider.

        The no-limits check also treats any project-configured ITPM/OTPM
        quota as an applicable limit, even when it isn't scoped to the
        routing model: a row can target a different, quota-limited model,
        and that isn't knowable without parsing the JSONL.

        Returns ``(should_skip, descriptors)`` where ``descriptors`` is the
        rate-limit descriptor list computed for the no-limits check, so the
        caller can reuse it for counter enforcement without recomputing.
        r   )Úgeneral_settings)FNÚ&disable_batch_input_file_rate_limitingT)TNÚ1skip_batch_input_file_rate_limiting_for_providersz4Skipping batch input file processing for provider=%s©rl   rL   z?Skipping batch input file processing: no rate limits configuredF)rh   r‰   Ú*_warn_if_unsupported_model_skip_configuredÚ&_key_requires_batch_model_access_checkrS   rk   r]   r   Údebugrr   Ú!_has_applicable_batch_rate_limitsry   )rJ   rL   rl   r‡   r‰   Úskip_providersÚbatch_providerr|   s           rC   Ú(_should_skip_batch_input_file_processingz@_PROXY_BatchRateLimiter._should_skip_batch_input_file_processing)  sñ   € õH 	@à×7Ñ7Ð8HÔIà×6Ñ6Ð7HÔIØà×ÑÐ HÓIÈTÑQØà 0× 4Ñ 4Ð5hÓ iÒ oÐmoˆÙØ$(×$@Ñ$@À×A^ÑA^Ð_cÓAdÓ$eˆNÙ .°NÑ"BÜ$×*Ñ*Ð+aÐcqÔrØ!à!×FÑFØ/Øð Gó 
ˆñ
 $Ø×:Ñ:¸;ÔGØ×9Ñ9Ð:KÔLä ×&Ñ&Ð'hÔiØà�kÐ!Ð!rB   r‰   c                 óz   — | j                   ry|j                  d«      rd| _         t        j                  d«       yy)a;  Warn once that ``skip_batch_input_file_rate_limiting_for_models`` is a no-op.

        A per-model skip is intentionally not honored because the model a batch
        runs on is caller-influenced and can be pointed at a skip-listed
        deployment while the JSONL routes a different, rate-limited model.
        NÚ.skip_batch_input_file_rate_limiting_for_modelsTzÌgeneral_settings.skip_batch_input_file_rate_limiting_for_models is not supported and has no effect. Use skip_batch_input_file_rate_limiting_for_providers or disable_batch_input_file_rate_limiting instead.)rI   rS   r   Úwarning)rJ   r‰   s     rC   r�   zB_PROXY_BatchRateLimiter._warn_if_unsupported_model_skip_configuredl  sA   € ð ×.Ò.ØØ×ÑÐ PÔQØ26ˆDÔ/Ü ×(Ñ(ðBõð RrB   c                 óˆ   — | j                   xs g }d|v ryt        j                  j                  |v ry| j                  ry|syy)zKTrue when the key may only call a subset of models (JSONL must be checked).Ú*FT)Úmodelsr   Úall_proxy_modelsÚvalueÚaccess_group_ids)rl   r™   s     rC   rŽ   z>_PROXY_BatchRateLimiter._key_requires_batch_model_access_check~  sJ   € ð
 *×0Ñ0Ò6°BˆØ�&‰=ØÜ×-Ñ-×3Ñ3°vÑ=ØØ×-Ò-ØÙØØrB   ÚentryÚmin_configured_otpm_limitc                 óD  — |j                  d«      }t        |t        «      rd|v ry|j                  d«      }t        |t        «      rt	        t
        j                  |«      «      n
t	        i «      }t        d„ |j                  d«      |j                  d«      |j                  d«      fD «       d	«      }| j                  j                  |«      }|�	 t        dt        |«      «      |z  S | j                  j                  |«      |z  S # t        t        t        f$ r Y Œ4w xY w)
ah  Conservative per-row output-token estimate for the project OTPM reservation.

        Batch completion never reconciles actual usage back into the rate
        limiter, so this pre-call estimate is the only OTPM enforcement a
        batch gets. Mirrors the real-time no-``max_tokens`` floor so a row
        that omits an output cap can't be used to bypass OTPM the way an
        unbounded streaming request could.

        Embeddings rows are identified by the row's own ``url`` (the OpenAI
        batch schema puts the target route there, e.g. ``/v1/embeddings``),
        never by body shape: a `/v1/responses` row also carries `body.input`
        with no `messages`/`prompt`, so guessing from body shape alone would
        misclassify a token-generating Responses row as a zero-output
        embeddings row and let it skip the OTPM reservation entirely.
        ÚurlÚ
embeddingsr   Úbodyc              3   ó$   K  — | ]  }|�|–— Œ
 y ­w©NrA   ©Ú.0Úvs     rC   ú	<genexpr>zH_PROXY_BatchRateLimiter._estimate_entry_output_tokens.<locals>.<genexpr>¯  s   è ø€ ò àð
 �=ô ñùs   ‚Ú
max_tokensÚmax_completion_tokensÚmax_output_tokensN)rS   rT   r@   r   r   r-   Úvalidate_pythonÚnextrG   Úget_output_candidate_countÚmaxr=   Ú	TypeErrorÚ
ValueErrorÚOverflowErrorÚno_max_tokens_output_floor)rJ   r�   rž   r    Úraw_bodyr¢   Úexplicit_capÚcandidate_counts           rC   Ú_estimate_entry_output_tokensz5_PROXY_BatchRateLimiter._estimate_entry_output_tokensŽ  s!  € ð( —Y‘Y˜uÓ%ˆÜ�cœ3Ô L°CÑ$7ØØŸ)™) FÓ+ˆô ˜(¤GÔ,ô Ô0×@Ñ@ÀÓJÔKä! "Ó%ð 	ô #ñð —H‘H˜\Ó*Ø—H‘HÐ4Ó5Ø—H‘HÐ0Ó1ðôð ó
ˆð "&×!>Ñ!>×!YÑ!YÐZ^Ó!_ˆØÐ#ðÜ˜1œc ,Ó/Ó0°?ÑBÐBð ×,Ñ,×GÑGÐHaÓbÐetÑtÐtøô œz¬=Ð9ò Ùðús   ÃD ÄDÄDr|   c                 ó¦   — | D ]L  }|j                  d«      xs i }|j                  d«      €#|j                  d«      €|j                  d«      €ŒL y y)NÚ
rate_limitÚrequests_per_unitÚtokens_per_unitÚmax_parallel_requestsTF©rS   )r|   r…   r¹   s      rC   r�   z9_PROXY_BatchRateLimiter._has_applicable_batch_rate_limitsÂ  s^   € ð &ò 	ˆJØ#Ÿ™¨Ó5Ò;¸ˆJà—‘Ð2Ó3Ð?Ø—>‘>Ð"3Ó4Ð@Ø—>‘>Ð"9Ó:ÑFáð	ð rB   Úfile_idrg   c                 óþ  — ddl m}m}m} ddlm} d|i} ||«      }	|	rO|�C	  |||	d¬«      }
|j                  t        |
«      «       |	|d<   |
j                  d«      }|r||d<    ||«      |fS |j                  d«      }t        |t        «      rK|rI|�G	  |||d¬«      }
|j                  t        |
«      «       ||d<   |
j                  d«      }|r||d<   ||fS ||fS # t        $ r Y Œ…w xY w# t        $ r Y ||fS w xY w)a!  
        Map proxy-facing file IDs to provider file IDs and credentials.

        Model-embedded IDs (``file-<base64>``) are not unified managed-file IDs;
        without decoding them, ``afile_content`` is called with the encoded ID
        and the upstream provider returns 404.
        r   )rQ   r`   Úget_original_file_idra   rg   rc   rd   r[   )rU   rQ   r`   rÀ   rh   rb   Úupdater   rS   r   rT   r@   )rJ   r¾   rg   rL   rQ   r`   rÀ   rb   Úfetch_kwargsrV   ri   rj   Úrequest_models                rC   Ú&_resolve_batch_input_file_fetch_paramsz>_PROXY_BatchRateLimiter._resolve_batch_input_file_fetch_paramsÐ  sZ  € ÷	
ñ 	
õ
 	:ð "Ð#6ð/
ˆñ %>¸gÓ$FÐÙØÐ%ðÙ";Ø#-Ø!3Ø*Qô#�Kð
 !×'Ñ'Ô(HÈÓ(UÔVØ,>�L Ñ)Ø*Ÿ™Ð/DÓE�HÙØ>F˜Ð%:Ñ;ñ (¨Ó0°,Ð>Ð>à#Ÿx™x¨Ó0ˆÜ�m¤SÔ)©mÀ
Ð@VðÙ7Ø)Ø*Ø&Mô�ð
 ×#Ñ#Ô$DÀ[Ó$QÔRØ(5�˜WÑ%Ø&Ÿ?™?Ð+@ÓA�ÙØ:B�LÐ!6Ñ7ð ˜Ð$Ð$ˆw˜Ð$Ð$øô) %ò Ùðûô" !ò Øà˜Ð$Ð$ðús%   ¢AC ÂAC- Ã	C*Ã)C*Ã-	C<Ã;C<Úbatch_usageÚscopes.c              ƒ   ó  K  — | j                   j                  j                  |j                  ||j                  ¬«      ƒ d{  –—† }|xt
        d˜ x�\    | j                  |||¬«       y t        d˜ x�\   |t        «       _	        y y7 ŒE­w)a³  Reserve the batch's estimated tokens against the caller's enqueued-token allowance.

        Runs instead of the per-minute counter charge when the key or team
        opted in via ``batch_enqueued_token_limit`` metadata. The reservation
        is stashed on the request so the v3 limiter's post-call hooks can
        persist it (keyed by the provider batch id) and refund it when the
        batch reaches a terminal state.
        )r0   rÆ   Úlitellm_parent_otel_spanNrA   )Ú
over_limitrL   rÅ   )
rG   Úbatch_enqueued_token_storeÚreserver4   Úparent_otel_spanr   Ú_raise_enqueued_limit_errorr    r%   Úbatch_enqueued_reservation)rJ   rl   rL   rÅ   rÆ   Úoutcomes         rC   Ú_reserve_batch_enqueued_tokensz6_PROXY_BatchRateLimiter._reserve_batch_enqueued_tokens  s‰   è ø€ ð  $×<Ñ<×WÑW×_Ñ_Ø×+Ñ+ØØ%6×%GÑ%Gð  `ó  
÷ 
ˆð
 Ø.Ô,Ö.Ø×0Ñ0¸GÈ$Ð\gÐ0Õhð /ä.Õ0ØKRÔ+Ó-ÕHñ 1ð
ús   ‚A B
ÁBÁAB
rÉ   c                 óœ  — |j                   }t        d|j                  |j                  z
  «      }d|j                  › d|j
                  › d|j                  › d|› d|j                  › d�}|j                  d«      }t        t        |t        «      r|nd «      \  }}	t        |t        d	d
i«      t        j                  t        d
«      ||	¬«      ‚)Nr   z(Batch enqueued token limit exceeded for ú: z. Batch requires ú tokens but only z" enqueued tokens remaining out of zS enqueued token limit. Tokens free up as running batches complete or are cancelled.r[   Úrate_limit_typer0   ©ÚdetailÚheadersÚcategoryrÔ   r[   Úllm_provider)Úscoper¯   ÚlimitÚenqueuedr}   r›   r4   rS   r&   rT   r@   r   r   r   ÚLITELLM_BATCH_RATE_LIMITr   )
rJ   rÉ   rL   rÅ   rÚ   Ú	remainingrÖ   Ú	raw_modelÚresolved_modelrÙ   s
             rC   rÍ   z3_PROXY_BatchRateLimiter._raise_enqueued_limit_error&  sÜ   € ð "×'Ñ'ˆÜ˜q %§+¡+°
×0CÑ0CÑ"CÓDˆ	à6°u·y±y°kÀÀEÇKÁKÀ=ð QØ)×6Ñ6Ð7Ð7HÈÈð TØ—k‘k�]ð #KðLð 	ð  Ÿ8™8 GÓ,ˆ	Ü'JÜ# I¬sÔ3‰I¸ó(
Ñ$ˆ˜ô "ØÜ$Ð&7¸Ð%BÓCÜ+×DÑDÜ2°8Ó<Ø Ø%ô
ð 	
rB   Ústatusr)   Ú
limit_typer{   c                 óœ  ‡‡— ddl m } ‰j                  d«      Št        ˆˆfd„t        |«      D «       d«      }|r||   nddddœ}|j	                  «       j                  «       }	| j                  j                  }
|	|
z   }|j                  |«      j                  d«      }t        d‰d	   «      }‰d
   }|dk(  r@d|j                  dd«      › d|j                  dd«      › d|j                  › d|› d|› d|› �}�n|j                  d«      t        t        fv r%|j                  dd«      j                  dd«      d   nd}|r|j                  j                  |«      nd}|j                  d«      t        k(  r |xs i j                  d|j                   «      nC|j                  d«      t        k(  r |xs i j                  d|j"                  «      n|j"                  }d|j                  dd«      › d|j                  dd«      › d|› d|› d|› d|› �}t%        |«      \  }}t'        |t)        |
«      ||dœt*        j,                  t/        |«      ||¬«      ‚)zIRaise :class:`ProxyRateLimitError` (a 429) for batch rate limit exceeded.r   )ÚdatetimeÚdescriptor_valuec              3   óš   •K  — | ]B  \  }}|j                  d «      ‰j                  d«      k(  r‰�|j                  d«      ‰k(  r|–— ŒD y­w)r}   Údescriptor_keyNr›   r½   )r¦   ÚiÚdrá   Ústatus_descriptor_values      €€rC   r¨   zB_PROXY_BatchRateLimiter._raise_rate_limit_error.<locals>.<genexpr>V  sM   øè ø€ ò á�A�qØ—5‘5˜“< 6§:¡:Ð.>Ó#?Ò?Ø,Ð4¸¿¹¸g»ÐJaÒ8aô ñùs   ƒAAÚ N)r}   r›   r¹   z%Y-%m-%d %H:%M:%S UTCÚlimit_remainingÚcurrent_limitr/   zBatch rate limit exceeded for r}   ÚunknownrÒ   r›   z. Batch contains z requests but only z requests remaining out of z RPM limit. Limit resets at: ú:é   éÿÿÿÿr6   r4   rÓ   z tokens remaining out of z TPM limit. Limit resets at: )zretry-afterrÔ   Úreset_atrÕ   )rä   rS   r­   Ú	enumerateÚnowÚ	timestamprG   Úwindow_sizeÚfromtimestampÚstrftimer¯   r5   r#   r$   Úsplitr8   r6   r4   r&   r   r@   r   rÝ   r   )rJ   rá   r|   rÅ   râ   r{   rä   Údescriptor_indexr…   rô   rö   Ú
reset_timeÚreset_time_formattedÚremaining_displayrí   rÖ   Údescriptor_modelÚmodel_usageÚbatch_token_countrà   rÙ   rê   s    `                   @rC   Ú_raise_rate_limit_errorz/_PROXY_BatchRateLimiter._raise_rate_limit_errorA  s¶  ù€ õ 	&ð *0¯©Ð4FÓ)GÐÜ"&ôä% kÓ2ôð ó#
Ðñ .9ˆKÐ(Ò)ÀbÐSUÐeiÑ>jð 	ð —\‘\“^×-Ñ-Ó/ˆØ!×:Ñ:×FÑFˆØ +Ñ-ˆ
Ø&.×&<Ñ&<¸ZÓ&H×&QÑ&QÐRiÓ&jÐä#& q¨&Ð1BÑ*CÓ#DÐØ% oÑ6ˆà˜Ò#à0°·±ÀÀyÓ1QÐ0RÐRTÐU_×UcÑUcÐdkÐmvÓUwÐTxð y"Ø"-×";Ñ";Ð!<Ð<OÐPaÐObð cØ'˜ð )$Ø$8Ð#9ð;ò ð —>‘> %Ó(Ô-HÔJeÐ,fÑfð —‘˜w¨Ó+×1Ñ1°#°qÓ9¸"Ò=àð ñ
 Wg ×!<Ñ!<×!@Ñ!@ÐAQÔ!RÐlpˆKð —>‘> %Ó(Ô,GÒGð Ò" ×'Ñ'¨¸×9RÑ9RÔSð —>‘> %Ó(Ô,GÒGð "Ò' R×,Ñ,¨^¸[×=UÑ=UÔVà ×-Ñ-ð ð 1°·±ÀÀyÓ1QÐ0RÐRTÐU_×UcÑUcÐdkÐmvÓUwÐTxð y"Ø"3Ð!4Ð4EÐFWÐEXð YØ'˜ð )$Ø$8Ð#9ð;ð ô (KÈ?Ó'[Ñ$ˆ˜Ü!Øä" ;Ó/Ø#-Ø0ñô
 ,×DÑDÜ2°:Ó>Ø Ø%ô
ð 	
rB   c              ƒ   óÜ  K  — |€| j                  ||¬«      }|D �cg c]  }|j                  |j                  dœ‘Œ }}| j                  ||j                  ¬«      \  }}g |¢|¢}g |¢|¢}| j
                  j                  |||j                  ¬«      ƒ d{  –—† }	|	d   dk(  rB|r|j                  d«      nd}
|	d	   D ]$  }|d
   dk(  sŒ| j                  ||||d   |
¬«       Œ& yyc c}w 7 ŒT­w)a  
        Atomically check + increment rate-limit counters by the batch amounts.

        Raises HTTPException if any descriptor would exceed its limit; in that
        case no counter is modified. Backed by `atomic_check_and_increment_by_n`
        which uses a Redis Lua script when available (multi-process atomic) and
        falls back to a per-process asyncio.Lock + in-memory operation.

        ``descriptors`` may be passed in by the pre-call hook to reuse the list
        already computed when deciding whether to skip file processing. It
        never contains project ITPM/OTPM descriptors (those are model-specific
        and only knowable once ``batch_usage.per_model_usage`` is populated by
        parsing the JSONL), so this always builds and appends them here.
        NrŒ   r.   )rl   r8   )r|   Ú
incrementsrÌ   Úoverall_codeÚ
OVER_LIMITr[   ÚstatusesÚcoderÔ   )r{   )
rr   r5   r4   r†   r8   rG   Úatomic_check_and_increment_by_nrÌ   rS   r  )rJ   rl   rL   rÅ   r|   Ú_dr  Úproject_io_descriptorsÚproject_io_incrementsÚrate_limit_responser{   rá   s               rC   Ú#_check_and_increment_batch_countersz;_PROXY_BatchRateLimiter._check_and_increment_batch_counters™  sU  è ø€ ð* ÐØ×CÑCØ"3Øð Dó ˆKð "ö.
ð
 ð (×5Ñ5Ø%×2Ñ2óð.
ˆ
ð .
ð 9=×8fÑ8fØ/Ø'×7Ñ7ð 9gó 9
Ñ5ÐÐ 5ð >˜Ð=Ð&<Ð=ˆØ:�zÐ:Ð$9Ð:ˆ
à+/×+HÑ+H×+hÑ+hØ#Ø!Ø.×?Ñ?ð ,ió ,
÷ &
Ðð ˜~Ñ.°,Ò>Ù:> T§X¡X¨gÔ%6ÀDˆOØ-¨jÑ9ò �Ø˜&‘> \Ó1Ø×0Ñ0ØØ#Ø#ØÐ0Ñ1Ø(7ð 1õ ñð ?ùò+.
ð&
ús"   ‚C,œ C%¼AC,ÂC*Â1C,Ã#C,)ÚopenaiÚazureÚ	vertex_aic              ƒ   óž  K  — t        d„ |xs dD «       «      }|�/t        |dd«      x}r t        d„ |j                  «       D «       «      nd}t        g |¢|¢­d¬«      }		 dd	lm}
m}  |
|«      }|r ||«      ng }|r|�| j                  ||¬
«      ƒ d{  –—† }n;| j                  |||xs i ¬«      \  }}t        j                  d||d
œ|¤Žƒ d{  –—† }t        |dd«      }t        |t        «      st        d|› dt        |«      › �«      ‚t!        «       }i }d}d}d}t#        |«      D ]ú  }|dz  }	 t%        j&                  |«      }t        |t0        «      r$|j3                  d«      xs i j3                  d«      nd}|r|j5                  |«       t        |t0        «      r| j7                  ||	«      }n| j,                  j/                  |	«      }||z  }	 t9        |«      }||z  }|sŒ¾|j;                  |ddddœ«      }|dxx   |z  cc<   |dxx   |z  cc<   |dxx   dz  cc<   Œü |� | j=                  |||xs d¬«      ƒ d{  –—†  t?        ||||¬«      S 7 �ŒÃ7 �ŒŠ# t(        $ r4 t+        |«      }| j,                  j/                  |	«      }||z  }||z  }Y �Œpw xY w# t(        $ r t+        |«      }Y ŒÔw xY w7 Œs# t@        $ rc}|jB                  dk(  r"tE        jF                  d||jH                  «       ‚ tE        jJ                  d||jB                  |jH                  «       ‚ d}~wt(        $ r}tE        jJ                  d||«       ‚ d}~ww xY w­w)a§  
        Count number of requests and tokens in a batch input file.

        Args:
            file_id: The file ID to read
            custom_llm_provider: The custom LLM provider to use for token encoding
            user_api_key_dict: User authentication information for file access (required for managed files)
            descriptors: Rate limit descriptors already computed for this batch, so the
                configured project OTPM limit can scale the no-``max_tokens`` output floor

        Returns:
            BatchFileUsage with total_tokens, output_tokens, request_count, and
            per_model_usage (each row's own totals, keyed by its `body.model`)
        c              3   ó²   K  — | ]O  }|j                  d «      t        k(  r5|j                  d«      }|�|j                  d«      nd}|�t        |«      –— ŒQ y­w)r}   r¹   Nr»   )rS   r$   r=   )r¦   ré   r¹   r§   s       rC   r¨   zA_PROXY_BatchRateLimiter.count_input_file_usage.<locals>.<genexpr>ë  sW   è ø€ ò .
àØ�u‰u�U‹|Ô:Ò:Ø Ÿu™u \Ó2�
Ø;EÐ;Q�j—n‘nÐ%6Ô7ÐW[�Øˆ}ô ��Fñ.
ùs   ‚AArA   Nrt   rv   c              3   ó2   K  — | ]  }t        |«      –— Œ y ­wr¤   )r=   r¥   s     rC   r¨   zA_PROXY_BatchRateLimiter.count_input_file_usage.<locals>.<genexpr>ù  s   è ø€ ÒB˜Q”#�a—&ÑBùs   ‚)Údefaultr   )rP   rR   )r¾   rl   )r¾   rg   rL   Úcontentz/Expected bytes content from file retrieval for z, got rð   r¢   r[   )r4   r6   r5   r4   r6   r5   )rl   r™   rX   )r4   r5   r6   r8   é“  zABatch rejected: caller not authorized for a model named in %s: %sz5Batch input file rejected for %s: status=%s detail=%sz*Error counting input file usage for %s: %s)&Útupler   ÚvaluesÚminrU   rP   rR   Ú_fetch_managed_file_contentrÄ   ÚlitellmÚafile_contentÚgetattrrT   Úbytesr±   ÚtypeÚsetr   ÚjsonÚloadsÚ	Exceptionr   rG   r³   r?   rS   Úaddr·   r   Ú
setdefaultÚ _enforce_batch_file_model_accessr3   r   Ústatus_coder   r–   rÖ   Úerror)rJ   r¾   rg   rl   rL   r|   Údescriptor_otpm_limitsÚproject_otpm_limit_mapÚproject_otpm_limitsrž   rP   rR   Úis_managed_filerX   Úfile_contentÚprovider_file_idrÂ   Úfile_content_bytesr™   r8   r4   r6   r5   Úraw_liner�   Úentry_total_tokensÚentry_output_tokensr[   rÿ   Úes                                 rC   Úcount_input_file_usagez._PROXY_BatchRateLimiter.count_input_file_usageÕ  s"  è ø€ ô, ).ñ .
à!Ò' Rô.
ó )
Ðð !Ð,ä*LØ%Ð'9Ð;Mó+ð Ð&ð ô ÑBÐ"8×"?Ñ"?Ó"AÔBÔBð ð 	ô ,/Ð/^Ð1GÐ/^ÐJ]Ñ/^ÐhlÔ+mÐ!ðC	÷ñ &HÈÓ%PˆOñ ]lÑ(GÈÔ(XÐqsÐÙÐ#4Ð#@Ø%)×%EÑ%EØ#Ø&7ð &Fó &÷  ‘ð
 26×1\Ñ1\Ø#Ø(;Øš ð 2]ó 2Ñ.Ð  ,ô &-×%:Ñ%:ð &Ø,Ø&7ñ&ð #ñ&÷  �ô )0°¸iÈÓ(NÐÜÐ0´%Ô8Ü ØEÀgÀYÈfÔUYÐZlÓUmÐTnÐoóð ô" "%£ˆFð ACˆOØˆLØˆMØˆMÜ3Ð4FÓGò %6�Ø Ñ"�ð	Ü ŸJ™J xÓ0�Eô OYÐY^Ô`dÔNe U§Y¡Y¨vÓ%6Ò%<¸"×$AÑ$AÀ'Ô$JÐko�ÙØ—J‘J˜uÔ%ä˜e¤TÔ*Ø*.×*LÑ*LÈUÐTmÓ*nÑ'à*.×*GÑ*G×*bÑ*bØ1ó+Ð'ð Ð!4Ñ4�ðPÜ)<¸UÓ)CÐ&ð Ð 2Ñ2�âØ"1×"<Ñ"<Ø°ÀAÐXYÑZó#�Kð   Ó/Ð3EÑEÓ/Ø Ó0Ð4GÑGÓ0Ø Ó0°AÑ5Ô0ðK%6ðX !Ð,Ø×;Ñ;Ø&7Ø!Ø'9Ò'A¸Tð <ó ÷ ð ô "Ø)Ø+Ø+Ø /ô	ð ð ùð úôJ !ò Ü)EÀhÓ)OÐ&Ø*.×*GÑ*G×*bÑ*bØ1ó+Ð'ð !Ð$6Ñ6�LØ!Ð%8Ñ8�MÚðûô. !ò PÜ)EÀhÓ)OÒ&ðPúð$ùô ò 	ð �}‰} Ò#Ü$×,Ñ,ØWÐY`Ðbc×bjÑbjôð ô %×*Ñ*ØKÈWÐVW×VcÑVcÐef×emÑemôð ûÜò 	Ü ×&Ñ&Ð'SÐU\Ð^_Ô`Øûð	üs¸   ‚AMÁ6J: ÂIÂ;J: ÃIÃA J: Ä3IÅBJ: ÇJÇ J: Ç(AJ: ÉJ8ÉJ: ÉMÉJ: ÉJ: É9JÊJ: ÊJÊJ: ÊJ5Ê2J: Ê4J5Ê5J: Ê:	M
ËAL!Ì!M
Ì-MÍM
Í
Mr™   rX   c           
   ƒ   ó:  K  — ddl m}m}m}m}m} ddlm}	m}
m	}m
} |r|}|syd}t        j                  j                  |j                  xs g v r8|j                  �,|
�*	  ||j                  |
||j                   |¬«      ƒ d{  –—† }|	�|	j&                  nd}|D ]R  }|}	 |�7	  ||||	|j(                  ¬
«      ƒ d{  –—†   |||||	|
||¬«      ƒ d{  –—†  n |||||	¬«      ƒ d{  –—†  ŒT y7 Œl# t"        $ r ‚ t$        $ r}t#        dddi¬	«      |‚d}~ww xY w7 Œ_# t*        $ r>}|j,                  t.        j0                  k7  r‚  |||||	¬«      ƒ d{  –—†7  s‚ Y d}~ŒŸd}~ww xY w7 Œ”7 Œ�# t"        $ r ‚ t$        $ r}t#        ddd|› d|› �i¬	«      ‚d}~ww xY w­w)aÖ  Reject the batch if the caller is not authorized for the upload target.

        For managed files, ``target_model_names`` (from the unified file id) is
        the proxy alias the file was uploaded for and is checked directly.
        Otherwise the ``body.model`` values collected from the JSONL (``models``)
        are checked.

        Reuses standard auth helpers so the same model access rules the proxy
        enforces on `/chat/completions` apply here.
        r   )Ú_check_team_member_model_accessÚ_key_access_group_grants_modelÚcan_key_call_modelÚcan_team_access_modelÚget_team_object)rb   Úprisma_clientÚproxy_logging_objÚuser_api_key_cacheN)Úteam_idr;  r=  rÌ   r<  r  r(  zNBatch input file model access could not be validated against the current team.)r'  rÖ   )r[   Úteam_objectrb   Úteam_model_aliases)r[   Úvalid_tokenr?  rb   )r[   r?  rA  rb   r;  r=  r<  )r[   Úllm_model_listrA  rb   zOBatch input file references a model the caller is not authorized to use: model=z	, reason=)Úlitellm.proxy.auth.auth_checksr6  r7  r8  r9  r:  rh   rb   r;  r<  r=  r   Úall_team_modelsr›   r™   r>  rÌ   r   r#  Ú
model_listr@  r   r  r   Úteam_model_access_denied)rJ   rl   r™   rX   r6  r7  r8  r9  r:  rb   r;  r<  r=  r?  r3  rB  r[   Úmodel_to_checkÚteam_denials                      rC   r&  z8_PROXY_BatchRateLimiter._enforce_batch_file_model_accessˆ  s&  è ø€ ÷ 	
õ 	
÷ 	pÓoáØ'ˆFáØàˆä×-Ñ-×3Ñ3Ð8I×8PÑ8PÒ8VÐTVÑWØ!×)Ñ)Ð5ØÐ)ðÙ$3Ø-×5Ñ5Ø"/Ø'9Ø%6×%GÑ%GØ&7ô%÷ �ð" :DÐ9O 
× 5Ò 5ÐUYˆØò 0	ˆEØ"ˆNð.ØÐ*ð"Ù3Ø"0Ø(3Ø'1Ø/@×/SÑ/Sô	÷ ð ñ  :Ø,Ø$/Ø$5Ø#-Ø&3Ø+=Ø*;ô÷ ñ ñ -Ø,Ø'5Ø$5Ø#-ô	÷ ð øñ?0	ð%ùô !ò ØÜò Ü#Ø #àÐ"rðôð
 ðûðúðùô *ò 	"Ø&×+Ñ+¬×/WÑ/WÒWØ!Ù%CØ"0Ø(9Ø(3Ø'1ô	&÷  ñ  ð "ô ûð	"úðøðùô !ò ØÜò 	Ü#Ø #àð<Ø<JÐ;KÈ9ÐUVÐTWðYðôð ûð	üsÆ   ‚AFÁ$C2 ÂC0ÂC2 ÂFÂ E,Â#DÂ<DÂ=DÃE,ÃE(ÃE,Ã(E*Ã)E,Ã-FÃ0C2 Ã2DÄDÄDÄFÄDÄ	E%Ä'-E ÅEÅE ÅE,Å E%Å%E,Å*E,Å,FÅ>FÆFÆFc              ƒ   óZ  K  — ddl m} 	 ddlm}m} |€t        d«      ‚|j                  d«      }|€t        d	«      ‚t        ||«      st        d
«      ‚|€t        d«      ‚|j                  ||j                  |¬«      ƒ d{  –—† }|S # t
        $ r}t        d|› d�«      ‚d}~ww xY w7 Œ&­w)a   
        Fetch file content from managed files hook.

        This is needed for managed files because they require proper user context
        to verify file ownership and access permissions.

        Args:
            file_id: The managed file ID (base64 encoded)
            user_api_key_dict: User authentication information

        Returns:
            HttpxBinaryResponseContent with the file content
        r   )ÚBaseFileEndpoints)rb   r<  z)Cannot import proxy_server dependencies: z7. Managed files require proxy_server to be initialized.NzBproxy_logging_obj not available. Cannot access managed files hook.Úmanaged_filesz9Managed files hook not found. Cannot access managed file.z7Managed files hook is not a BaseFileEndpoints instance.z6llm_router not available. Cannot access managed files.)r¾   rÈ   rb   )Ú*litellm.llms.base_llm.files.transformationrJ  rh   rb   r<  ÚImportErrorr±   Úget_proxy_hookrT   r  rÌ   )	rJ   r¾   rl   rJ  rb   r<  r3  Úmanaged_files_objr-  s	            rC   r  z3_PROXY_BatchRateLimiter._fetch_managed_file_contentò  sÚ   è ø€ õ$ 	Qð	ßPð Ð$ÜÐaÓbÐbà#4×#CÑ#CÀOÓ#TÐØÐ$ÜÐXÓYÐYäÐ+Ð->Ô?ÜÐVÓWÐWàÐÜÐUÓVÐVð %6×$CÑ$CØØ%6×%GÑ%GØ!ð %Dó %
÷ 
ˆð Ðøô7 ò 	ÜØ;¸A¸3Ð>uÐvóð ûð	úð*
ús4   ‚B+ŠB	 ’A0B+ÂB)ÂB+Â		B&ÂB!Â!B&Â&B+ÚcacheÚ	call_typec              ƒ   ó’  K  — |dk7  rt        j                  d|«       |S t        j                  d«       	 |j                  d«      }|st        j                  d«       |S t        |«      }| j	                  ||t        |«      ¬«      \  }}|r|S |j                  dd«      }	t        j                  d	|«       | j                  ||	|||¬
«      ƒ d{  –—† }
t        j                  d|
j                  |
j                  «       |
j                  |d<   |
j                  |d<   |r4| j                  |||
|¬«      ƒ d{  –—†  t        j                  d«       |S | j                  |||
|¬«      ƒ d{  –—†  t        j                  d«       |S 7 Œ·7 ŒQ7 Œ# t        $ r ‚ t        $ r$}t        j                  d|d¬«       |cY d}~S d}~ww xY w­w)aJ  
        Pre-call hook for batch operations.

        Only handles batch creation (acreate_batch):
        - Reads input file
        - Counts tokens and requests
        - Reserves rate limit capacity via parallel_request_limiter

        Args:
            user_api_key_dict: User authentication information
            cache: Cache instance (not used directly)
            data: Request data
            call_type: Type of call being made

        Returns:
            Modified data dict or None

        Raises:
            HTTPException: 429 if rate limit would be exceeded
        Úacreate_batchzOBatch rate limiter: Not handling batch creation rate limiting for call type: %sz9Batch rate limiter: Handling batch creation rate limitingrO   z9No input_file_id in batch request, skipping rate limiting)rL   rl   r‡   rg   r  z)Counting tokens from batch input file: %s)r¾   rg   rl   rL   r|   Nz1Batch input file usage - Tokens: %s, Requests: %sÚ_batch_token_countÚ_batch_request_count)rl   rL   rÅ   rÆ   z*Batch enqueued-token reservation succeeded)rl   rL   rÅ   r|   z3Batch rate limit check passed, counters incrementedz Error in batch rate limiting: %sT)Úexc_info)r   r�   rS   r"   r“   rx   r4  r4   r5   rÐ   r  r   r#  r(  )rJ   rl   rP  rL   rQ  rO   Úenqueued_scopesÚshould_skipÚbatch_rate_limit_descriptorsrg   rÅ   r3  s               rC   Úasync_pre_call_hookz+_PROXY_BatchRateLimiter.async_pre_call_hook&  s  è ø€ ð8 ˜Ò'Ü ×&Ñ&ØaÐclôð ˆKä×"Ñ"Ð#^Ô_ð?	à#'§8¡8¨OÓ#<ˆMÙ Ü$×*Ñ*Ð+fÔgØ�ä%HÐIZÓ%[ˆOØ8<×8eÑ8eØÐ->ÔTXÐYhÓTið 9fó 9Ñ5ˆKÐ5ñ Ø�ð *.¯©Ð2GÈÓ)RÐô !×&Ñ&Ð'RÐTaÔbØ'+×'BÑ'BØ%Ø$7Ø"3ØØ8ð (Có (÷ "ˆKô !×&Ñ&ØCÀ[×E]ÑE]Ð_j×_xÑ_xôð
 *5×)AÑ)AˆDÐ%Ñ&Ø+6×+DÑ+DˆDÐ'Ñ(áØ×9Ñ9Ø&7ØØ +Ø*ð	 :ó ÷ ð ô %×*Ñ*Ð+WÔXØ�ð ×:Ñ:Ø"3ØØ'Ø8ð	 ;ó ÷ ð ô !×&Ñ&Ð'\Ô]ØˆKðI"øð"øðùô ò 	àÜò 	Ü ×&Ñ&Ð'IÈ1ÐW[Õ\à�Kûð	üs�   ‚3G¶)F ÁGÁ .F ÂGÂAF ÃFÃA'F Ä8F
Ä9F ÅGÅF Å,FÅ-F ÆGÆF Æ
F ÆF ÆGÆ F?Æ9GÆ:GÆ?GÇG)Fr¤   )r  NNN)NN)/r9   r:   r;   r<   r+   ÚParallelRequestLimiterrK   r?   r@   rY   r]   rk   r   Úlistrr   Ústaticmethodrx   ry   r   r=   r  r1   r†   r“   r�   rŽ   Úobjectr·   r�   r   rÄ   r3   r!   rÐ   r   r   rÍ   r  r  r
   r   r4  r   r&  r  r#  rZ  rA   rB   rC   rE   rE   t   sg  „ ñð4à0ð4ð #9ó4ð&°ð ¸¸t¹ó ð>¨Tð °c¸D±jó ð&L°3¸±:ð LÀ#ÈÁ*ó Lð<
à)ð
ð ð
ð 
Ð#Ñ	$ó	
ð, ðq¸Nð qÈtò qó ðqð  3à)ð 3ð !  g¨c°3¨hÑ&7Ð!7Ñ8ð 3ð 
ˆtÐ)Ñ*¨DÐ1AÑ,BÐBÑ	Có	 3ðL %*ñ	A"àðA"ð *ðA"ð "ð	A"ð
 
ˆt�TÐ/Ñ0°4Ñ7Ð7Ñ	8óA"ðFÈ4ð ÐTXó ð$ ðØ)ðà	òó ðð2uà�s˜F�{Ñ#ð2uð $'¨¡:ð2uð 
ó	2uðh ðØÐ/Ñ0ðà	òó ðð:%àð:%ð !ð:%ð ð	:%ð
 
ˆs�D˜˜c˜‘NÐ"Ñ	#ó:%ðxSà)ðSð �c˜6�kÑ"ðSð $ð	Sð
 Ð-¨sÐ2Ñ3ðSð 
óSð4
à/ð
ð �c˜6�kÑ"ð
ð $ð	
ð
 
ó
ðB '+ñV
à!ðV
ð Ð/Ñ0ðV
ð $ð	V
ð
 ðV
ð ˜t™ðV
ð 
óV
ðz ;?ñ:à)ð:ð ð:ð $ð	:ð
 Ð/Ñ0°4Ñ7ð:ð 
ó:ð~ HPØ37Ø Ø>Bñqàðqð %Ð%CÑDðqð *¨DÑ0ð	qð
 �T‰kðqð Ð3Ñ4°tÑ;ðqð 
óqðl (,Ø/3ñ	hà)ðhð ˜‘ Ñ$ðhð ! ™I¨Ñ,ð	hð
 
óhðT2àð2ð *ð2ð 
ó	2ðhcà)ðcð ðcð ð	cð
 ðcð 
�S‰˜4Ñ	 $Ñ	&ôcrB   rE   )Or<   r!  Úcollections.abcr   r   r   Útypesr   Útypingr   r   r	   r
   r   r   Úfastapir   Úpydanticr   r   r   r  Úlitellm._loggingr   Úlitellm.batches.batch_utilsr   r   r   r   Úlitellm.exceptionsr   Ú"litellm.integrations.custom_loggerr   Úlitellm.proxy._typesr   r   r   r   Úlitellm.proxy.auth.auth_utilsr   Ú1litellm.proxy.common_utils.proxy_rate_limit_errorr   r   Ú)litellm.proxy.hooks.batch_enqueued_tokensr   r    r!   r"   Ú/litellm.proxy.hooks.parallel_request_limiter_v3r#   r$   r%   Ú&litellm.proxy.hooks.rate_limiter_utilsr&   Úopentelemetry.tracer'   Ú_Spanr(   Ú_RateLimitDescriptorr)   Ú_RateLimitStatusr*   Ú_ParallelRequestLimiterÚlitellm.proxy.utilsr+   Ú_InternalUsageCacheÚlitellm.routerr,   Ú_Routerr[  r?   r@   r^  r-   r>   r=   r1   r3   rE   rA   rB   rC   ú<module>rw     s2  ðòó& ß 7Ñ 7Ý "ß J× Jå !ß 2Ñ 2ã Ý 1÷ó õ 6Ý ;÷ó õ M÷÷ó ÷ñ õ
 WáÝ1õõõõ NÝ0à�3‰;€DØ,ÐØ€FØ4ÐØ&€OØ.Ñà€DØÐØ€FØ ÐØ˜3 ˜8‘n€OØ˜s C˜x™.Ðñ )¨¨c°6¨kÑ):Ó;Ð �UÓ ;à" 7Ð+?Ñ#@À#Ð#EÑFÐ �)Ó Fô�Yô ô&U˜lõ UrB   