o
    ưi"                     @   sp   d Z ddl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 G dd dZG d	d
 d
ZdS )zA
Class to handle llm wildcard routing and regex pattern matching
    N)Match)DictListOptionalTuple)get_llm_provider)verbose_router_loggerc                	   @   s\   e Zd Zededeeef fddZedeee	e f de	eee	e f  fddZ
dS )	PatternUtilspatternreturnc                    s*   g d}t  t fdd|D f}|S )z
        Calculate pattern specificity based on length and complexity.

        Args:
            pattern: Regex pattern to analyze

        Returns:
            Tuple of (length, complexity) for sorting
        )	*+?\^$|()c                 3   s    | ]}  |V  qd S N)count).0charr
    e/home/app/Keep/.python/lib/python3.10/site-packages/litellm/router_utils/pattern_match_deployments.py	<genexpr>   s    

z=PatternUtils.calculate_pattern_specificity.<locals>.<genexpr>)lensum)r
   Zcomplexity_charsZret_valr   r   r   calculate_pattern_specificity   s   z*PatternUtils.calculate_pattern_specificitypatternsc                 C   s   t |  dd ddS )z
        Cached property for patterns sorted by specificity.

        Returns:
            Sorted list of pattern-deployment tuples
        c                 S   s   t | d S )Nr   )r	   r   )xr   r   r   <lambda>/   s    z.PatternUtils.sorted_patterns.<locals>.<lambda>T)keyreverse)sorteditemsr    r   r   r   sorted_patterns#   s
   
zPatternUtils.sorted_patternsN)__name__
__module____qualname__staticmethodstrr   intr   r   r   r(   r   r   r   r   r	      s    r	   c                	   @   s   e Zd ZdZdd ZdedefddZdedefd	d
Zde	de
e de
e fddZ	ddee dee
e  dee
e  fddZede	dedefddZ	ddedee dee
e  fddZ	ddedee de
e fddZdS )PatternMatchRouterz
    Class to handle llm wildcard routing and regex pattern matching

    doc: https://docs.litellm.ai/docs/proxy/configs#provider-specific-wildcard-routing

    This class will store a mapping for regex pattern: List[Deployments]
    c                 C   s
   i | _ d S r   r'   selfr   r   r   __init__=   s   
zPatternMatchRouter.__init__r
   llm_deploymentc                 C   s2   |  |}|| jvrg | j|< | j| | dS )z
        Add a regex pattern and the corresponding llm deployments to the patterns

        Args:
            pattern: str
            llm_deployment: str or List[str]
        N)_pattern_to_regexr    append)r1   r
   r3   regexr   r   r   add_pattern@   s   
	

zPatternMatchRouter.add_patternr   c                 C   s   t |ddS )a0  
        Convert a wildcard pattern to a regex pattern

        example:
        pattern: openai/*
        regex: openai/.*

        pattern: openai/fo::*::static::*
        regex: openai/fo::.*::static::.*

        Args:
            pattern: str

        Returns:
            str: regex pattern
        z\*z(.*))reescapereplace)r1   r
   r   r   r   r4   N   s   z$PatternMatchRouter._pattern_to_regexmatched_patterndeploymentsc                 C   sD   g }|D ]}t |}tj||d d d|d d< || q|S )NZlitellm_paramsmodel)r;    litellm_deployment_litellm_model)copydeepcopyr/   set_deployment_model_namer5   )r1   r;   r<   Znew_deploymentsZ
deploymentZnew_deploymentr   r   r   #_return_pattern_matched_deploymentsf   s   

z6PatternMatchRouter._return_pattern_matched_deploymentsNrequestfiltered_model_namesc           	   
      s   zA|du rW dS t  j}|dur fdd|D ng }|D ]\}}|dur,||vr,qt||}|r> j||d  W S qW dS  ty^ } ztdt	|  W Y d}~dS d}~ww )a  
        Route a requested model to the corresponding llm deployments based on the regex pattern

        loop through all the patterns and find the matching pattern
        if a pattern is found, return the corresponding llm deployments
        if no pattern is found, return None

        Args:
            request: str - the received model name from the user (can be a wildcard route). If none, No deployments will be returned.
            filtered_model_names: Optional[List[str]] - if provided, only return deployments that match the filtered_model_names
        Returns:
            Optional[List[Deployment]]: llm deployments
        Nc                    s   g | ]}  |qS r   )r4   )r   mr0   r   r   
<listcomp>   s    z,PatternMatchRouter.route.<locals>.<listcomp>)r;   r<   z#Error in PatternMatchRouter.route: )
r	   r(   r    r8   matchrB   	Exceptionr   debugr-   )	r1   rC   rD   r(   Zregex_filtered_model_namesr
   Zllm_deploymentspattern_matcher   r0   r   routev   s2   zPatternMatchRouter.router>   c                 C   sL   d|vr|S | d}|  }t||kr| jS |D ]	}|d|d}q|S )a  
        Set the model name for the matched pattern llm deployment

        E.g.:

        Case 1:
        model_name: llmengine/* (can be any regex pattern or wildcard pattern)
        litellm_params:
            model: openai/*

        if model_name = "llmengine/foo" -> model = "openai/foo"

        Case 2:
        model_name: llmengine/fo::*::static::*
        litellm_params:
            model: openai/fo::*::static::*

        if model_name = "llmengine/foo::bar::static::baz" -> model = "openai/foo::bar::static::baz"

        Case 3:
        model_name: *meta.llama3*
        litellm_params:
            model: bedrock/meta.llama3*

        if model_name = "hello-world-meta.llama3-70b" -> model = "bedrock/meta.llama3-70b"
        r      )r   groupsr   stringr:   )r;   r>   Zwildcard_countZdynamic_segmentssegmentr   r   r   rA      s   !
z,PatternMatchRouter.set_deployment_model_namer=   custom_llm_providerc                 C   sP   |du rzt |d\}}}}W n	 ty   Y nw | |p'| | d| S )z
        Check if a pattern exists for the given model and custom llm provider

        Args:
            model: str
            custom_llm_provider: Optional[str]

        Returns:
            bool: True if pattern exists, False otherwise
        N)r=   /)r   rH   rL   )r1   r=   rQ   _r   r   r   get_pattern   s   zPatternMatchRouter.get_patternc                 C   s   |  ||}|r
|S g S )z
        Get the deployments by pattern

        Args:
            model: str
            custom_llm_provider: Optional[str]

        Returns:
            List[Dict]: llm deployments matching the pattern
        )rT   )r1   r=   rQ   rJ   r   r   r   get_deployments_by_pattern   s   z-PatternMatchRouter.get_deployments_by_patternr   )r)   r*   r+   __doc__r2   r-   r   r7   r4   r   r   rB   r   rL   r,   rA   rT   rU   r   r   r   r   r/   4   sX    



*5

r/   )rV   r?   r8   r   typingr   r   r   r   Z1litellm.litellm_core_utils.get_llm_provider_logicr   Zlitellm._loggingr   r	   r/   r   r   r   r   <module>   s    &