o
    5ti	W                     @  s*  U d Z ddlmZ ddlZddlmZ ddlZddl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mZmZmZmZ eeZer\ddl
mZmZ dd	lmZ dd
lmZ g dZedZ edZ!e"ej#B Z$e% Z&de'd< eddd`ddZ(	dadbdd Z)dcd$d%Z*G d&d' d'ee  Z+e+d(Z,d)e'd*< e+d+Z-d,e'd-< e+d.Z.d/e'd0< e+d1Z/d2e'd3< e+d4Z0d2e'd5< e+d6Z1d7e'd8< d9d: Z2e/Z3e0Z4e.Z5e1Z6d;d<gg d=d<d>gd?gd@Z7dAdB Z8dddDdEZ9e,Z:dedFdGZ;dfdKdLZ<e-Z=dMdN Z>dgdhdSdTZ?dedUdVZ@didXdYZAdidZd[ZBdjd^d_ZCdS )ka  Registry system for lm_eval components.

This module provides a centralized registration system for models, tasks, metrics,
filters, and other components in the lm_eval framework.

## Usage Examples

### Registering a Model
```python
from lm_eval.api.registry import register_model
from lm_eval.api.model import LM

@register_model("my-model")
class MyModel(LM):
    def __init__(self, **kwargs):
        ...
```

### Registering with Lazy Loading
```python
# Register without importing the actual implementation
model_registry.register("lazy-model", target="my_package.models: LazyModel")
```

### Looking up Components
```python
from lm_eval.api.registry import get_model

# Get a model class
model_cls = get_model("gpt-j")
model = model_cls(**config)
```
    )annotationsN)Callable)	lru_cache)MappingProxyType)TYPE_CHECKINGAnyGenericTypeVarcastoverload)r   Iterable)FilterLM)Registrymodel_registryfilter_registryaggregation_registrymetric_registrymetric_agg_registryhigher_is_better_registry
freeze_allregister_model	get_modelregister_metric
get_metricregister_aggregationget_aggregationget_metric_aggregationis_higher_betterregister_filter
get_filterMODEL_REGISTRYFILTER_REGISTRYMETRIC_REGISTRYMETRIC_AGGREGATION_REGISTRYAGGREGATION_REGISTRYHIGHER_IS_BETTER_REGISTRYDEFAULT_METRIC_REGISTRYTDr   _MISSING   )maxsizephPlaceholderreturnc                 C  sF   t | tr| d\}}}|std|  dtt||S |  S )a  Materialize a lazy placeholder into the actual object.

    This is at module level to avoid memory leaks from lru_cache on instance methods.

    Args:
        ph: Either a string path "module:object" or an EntryPoint instance

    Returns:
        The loaded object

    Raises:
        ValueError: If the string format is invalid
        ImportError: If the module cannot be imported
        AttributeError: If the object doesn't exist in the module
    :zInvalid lazy path 'z', expected 'module:object')
isinstancestr	partition
ValueErrorgetattr	importlibimport_moduleload)r.   mod_attr r=   H/home/ubuntu/.local/lib/python3.10/site-packages/lm_eval/api/registry.py_materialise_placeholderd   s   
r?      queryr3   optionsIterable[str]max_suggestionsint	list[str]c                 C  sd   |   }g }|D ]'}|  }||v s!t|dkr/||dd r/|| t||kr/ |S q|S )z<Return similar option names using prefix/substring matching.r@   N)lowerlen
startswithappend)rA   rB   rD   query_lowersuggestionsopt	opt_lowerr=   r=   r>   _suggest_similar}   s   
 rO   namealiaskeysc                 C  s~   t ||}t|}d|  d| d}|r|dd| d7 }|dd|dd	  7 }t|d	kr=|d
t| d7 }|S )z2Build a helpful KeyError message with suggestions.zUnknown z 'z'.z Did you mean: , ?z
Available: N   z... (z total))rO   sortedjoinrH   )rP   rQ   rR   rL   	availablemsgr=   r=   r>   _build_key_error_msg   s   
rZ   c                   @  s   e Zd ZdZddd9d
dZddd:ddZd;ddZed<ddZed=ddZe	fd>d dZd<d!d"Z
d?d$d%Zd&d' Zd(d) Zd@d*d+Zd,d- Zd.d/ Zd0d1 ZdAd3d4Zd5d6 Zd7d8 ZdS )Br   a  Thread-safe dict mapping string aliases to objects or lazy placeholders.

    Lazy placeholders ("module.path:attr" strings or EntryPoints) are
    materialized on first access via `get()`. Optional `base_cls` enforces
    type constraints. Call `freeze()` to make read-only.
    N)base_clsrP   r3   r[   type[T] | Noner0   Nonec                C  s    || _ || _i | _t | _dS )zInitialize a new registry.

        Args:
            name: Human-readable name for error messages (e.g., "model", "metric")
            base_cls: Optional base class that all registered objects must inherit from
        N)_name	_base_cls_objs	threadingRLock_lock)selfrP   r[   r=   r=   r>   __init__   s   zRegistry.__init__targetaliasesrg   T | Placeholder | NoneCallable[[T], T]c                  s   dfdd d fdd}|dur?t dkrtdj  d | W d   dd S 1 s6w   Y  dd S |S )a  Register an object under one or more aliases.

        Can be used as a decorator or called directly for direct registration.

        Args:
            *aliases: Names to register the object under. If empty, uses object's __name__
            target: For direct calls only - a value, placeholder string "module:object",
                or EntryPoint to register under the alias

        Returns:
            Decorator function (or no-op if direct registration)

        Examples:
            >>> # As decorator
            >>> @model_registry.register("name1", "name2")
            >>> class MyModel(LM):
            ...     pass
            >>>
            >>> # Direct registration with a lazy placeholder
            >>> model_registry.register("lazy-name", target="mymodule:MyModel")

        Raises:
            ValueError: If alias is already registered with a different target
            TypeError: If an object doesn't inherit from base_cls (when specified)
        rQ   r3   rg   T | Placeholderr0   r]   c              	     s    j | }|d ur;||kr;t|tr*t|tr*||j d|j kr*| j | < d S t jd|  d| d| d j	d urYt|trYt
| j	sYt| d j	 d j | j | < d S )Nr1   z alias 'z' already registered (existing=z, new=)z must inherit from z	 to be a )r`   getr2   r3   type
__module____name__r5   r^   r_   
issubclass	TypeError)rQ   rg   currentrd   r=   r>   _store   s2   


z!Registry.register.<locals>._storeobjr)   c                   sV   p
t | dt| f}j |D ]} ||  qW d    | S 1 s$w   Y  | S )Nrp   )r6   r3   rc   )rv   namesrP   ru   rh   rd   r=   r>   	decorator   s   
z$Registry.register.<locals>.decoratorN   z/Exactly one alias required when using 'target='r   c                 S  s   | S Nr=   )xr=   r=   r>   <lambda>   s    z#Registry.register.<locals>.<lambda>)rQ   r3   rg   rk   r0   r]   )rv   r)   r0   r)   )rH   r5   rc   )rd   rg   rh   ry   r=   rx   r>   register   s   
zRegistry.registerr.   r/   r)   c                 C  s   t dt|S )zMaterialize a placeholder using the module-level cached function.

        Args:
            ph: Placeholder to materialize

        Returns:
            The materialized object, cast to type T
        r)   )r
   r?   )rd   r.   r=   r=   r>   _materialise  s   	zRegistry._materialiserQ   c                 C     d S r{   r=   rd   rQ   r=   r=   r>   rm        zRegistry.getdefaultr*   T | Dc                 C  r   r{   r=   )rd   rQ   r   r=   r=   r>   rm     r   D | Anyc              
   C  s  z| j | }W n% ty, } z|tur|W  Y d}~S tt| j|| j  |d}~ww t|ttj	frj| j
( | j | }t|ttj	frW| |}t| j tsV|| j |< n|}W d   n1 scw   Y  |}| jdurt|trt|| jst| d| j d| dd|S )aw  Retrieve an object by alias, materializing if needed.

        Thread-safe lazy loading: if the alias points to a placeholder,
        it will be loaded and cached before returning.

        Args:
            alias: The registered name to look up
            default: Default value to return if alias not found (can be None)

        Returns:
            The registered object, or default if not found

        Raises:
            KeyError: If an alias is not found and no default provided
            TypeError: If a materialized object doesn't match base_cls
            ImportError/AttributeError: If lazy loading fails
        Nz does not inherit from z	 (alias 'z'))r`   KeyErrorr+   rZ   r^   rR   r2   r3   md
EntryPointrc   r   r   r_   rn   rq   rr   )rd   rQ   r   rg   excfreshconcreter=   r=   r>   rm     sF   





c                 C  s
   |  |S )z)Allow dict-style access: registry[alias].)rm   r   r=   r=   r>   __getitem__I     
zRegistry.__getitem__boolc                 C  s
   || j v S )zCheck if alias is registered.)r`   r   r=   r=   r>   __contains__M  r   zRegistry.__contains__c                 C  
   t | jS )z Iterate over registered aliases.)iterr`   rt   r=   r=   r>   __iter__Q  r   zRegistry.__iter__c                 C  r   )z(Return the number of registered aliases.)rH   r`   rt   r=   r=   r>   __len__U  r   zRegistry.__len__c                 C  s6   t dd | j D }d| jdt|  d| dS )z6Return a detailed string representation for debugging.c                 s  s$    | ]}t |ttjfsd V  qdS )rz   N)r2   r3   r   r   ).0vr=   r=   r>   	<genexpr>[  s    
z$Registry.__repr__.<locals>.<genexpr>z	Registry(z
, entries=z, materialized=rl   )sumr`   valuesr^   rH   )rd   materializedr=   r=   r>   __repr__Y  s   zRegistry.__repr__c                 C  
   | j  S )zReturn all registered aliases.)r`   rR   rt   r=   r=   r>   rR   `  r   zRegistry.keysc                 C  r   )zvReturn all registered objects.

        Note: Objects may be placeholders that haven't been materialized yet.
        )r`   r   rt   r=   r=   r>   r   d     
zRegistry.valuesc                 C  r   )zuReturn (alias, object) pairs.

        Note: Objects may be placeholders that haven't been materialized yet.
        )r`   itemsrt   r=   r=   r>   r   k  r   zRegistry.items
str | Nonec                 C  s^   | j |}t|ttjfrdS zt|}t|d }| d| W S  t	y.   Y dS w )zGet the source location of a registered object.

        Args:
            alias: The registered name

        Returns:
            "path/to/file.py:line_number" or None if not available
        Nrz   r1   )
r`   rm   r2   r3   r   r   inspectgetfilegetsourcelines	Exception)rd   rQ   rv   pathliner=   r=   r>   origint  s   	
zRegistry.originc                 C  s<   | j  tt| j| _W d   dS 1 sw   Y  dS )zMake the registry read-only to prevent further modifications.

        After freezing, attempts to register new objects will fail.
        This is useful for ensuring registry contents don't change after
        initialization.
        N)rc   r   dictr`   rt   r=   r=   r>   freeze  s   "zRegistry.freezec                 C  s.   t | jtrt| j| _| j  t  dS )zErase registry (for isolated tests).

        Clears both the registry contents and the materialization cache.
        Only use this in test code to ensure a clean state between tests.
        N)r2   r`   r   r   clearr?   cache_clearrt   r=   r=   r>   _clear  s   
zRegistry._clear)rP   r3   r[   r\   r0   r]   )rh   r3   rg   ri   r0   rj   )r.   r/   r0   r)   )rQ   r3   r0   r)   )rQ   r3   r   r*   r0   r   )rQ   r3   r   r   r0   r   )rQ   r3   r0   r   )r0   r3   )rQ   r3   r0   r   )rp   ro   __qualname____doc__re   r~   r   r   rm   r+   r   r   r   r   r   rR   r   r   r   r   r   r=   r=   r=   r>   r      s.    
N
3


	r   modelzRegistry[type[LM]]r   filterzRegistry[type[Filter]]r   aggregationzRegistry[Callable[..., float]]r   metriczRegistry[Callable]r   metric_aggregationr   higher_is_betterzRegistry[bool]r   c                  C  s"   t tttttfD ]} |   qdS )zFreeze all registries to prevent further modifications.

    This is useful for ensuring registry contents are immutable after
    initialization, preventing accidental modifications during runtime.
    N)r   r   r   r   r   r   r   )rr=   r=   r>   r     s   
r   
perplexityacc)word_perplexitybyte_perplexitybits_per_byteacc_normexact_match)loglikelihoodloglikelihood_rollingmultiple_choicegenerate_untilc                    s   ddl m   fdd}|S )a  Decorator to register a model class.

    Args:
        *names: One or more names to register the model under

    Returns:
        Decorator function

    Example:
        >>> @register_model("my-model", "my-model-alias")
        >>> class MyModel(LM):
        ...     pass
    r   r   c                   s.   t |  sJ d| j dtj |  | S )NzModel 'z' must extend LM class)rq   rp   r   r~   clsr   rw   r=   r>   decorate  s   z register_model.<locals>.decorate)lm_eval.api.modelr   )rw   r   r=   r   r>   r     s   r   
model_namec                 C  sZ   t tdkr
ddl}zt| W S  ty, } ztd|  ddt  |d}~ww )zGet a model class by name.

    Args:
        model_name: The registered name of the model

    Returns:
        The model class

    Raises:
        ValueError: If model name is not found
    r   NzAttempted to load model 'z<', but no model for this name found! Supported model names: rS   )rH   r   lm_eval.modelsrm   r   r5   rW   rR   )r   lm_evaler=   r=   r>   r     s   r   c                       fdd}|S )zDecorator to register a filter class.

    Args:
        name: Name to register the filter under

    Returns:
        Decorator function
    c                   s,    t v rtd  d t  |  | S )NzRegistering filter `z` that is already in Registry)r   eval_loggerinfor~   r   rP   r=   r>   r     s   z!register_filter.<locals>.decorater=   rP   r   r=   r   r>   r      s   
r    filter_namestr | Callabler   c              
   C  sN   t | r| S z	ttd| W S  ty& } ztd|  d |d}~ww )zGet a filter by name.

    Args:
        filter_name: The registered name of the filter, or a callable

    Returns:
        The filter class/function

    Raises:
        KeyError: If a filter name is not found and is not callable
    r3   zfilter `z` is not registered!N)callabler   rm   r
   r   r   warning)r   r   r=   r=   r>   r!   !  s   r!   c                    r   )aP  Decorator to register a metric function.

    Args:
        **args: Keyword arguments including
            - metric: Name to register the metric under (required)
            - higher_is_better: Whether higher scores are better
            - aggregation: Name of aggregation function to use

    Returns:
        Decorator function
    c                   sd   d v sJ  d }t ||  d v rtj| d d d v r0t d }tj||d | S )Nr   r   rf   r   )r   r~   r   r   rm   r   )fnrP   agg_fnargsr=   r>   r   L  s   z!register_metric.<locals>.decorater=   )r   r   r=   r   r>   r   ?  s   r   Fhf_evaluate_metricr   Callable | Nonec                 C  s|   t tdkr
ddl}|s| tv rt| S td|  d zddl}|| }|jW S  t	y=   t
|  d Y dS w )zGet a metric function by name.

    Args:
        name: The metric name
        hf_evaluate_metric: If True, skip the local registry and use HF evaluate

    Returns:
        The metric compute function, or None if not found
    r   Nz"Could not find registered metric 'z1' in lm-eval, searching in HF Evaluate library...zW not found in the evaluate library! Please check https://huggingface.co/evaluate-metric)rH   r   lm_eval.api.metricsrm   r   r   evaluater9   computer   error)rP   r   r   hf_evaluatemetric_objectr=   r=   r>   r   a  s$   


r   c                   r   )zDecorator to register an aggregation function.

    Args:
        name: Name to register the aggregation under

    Returns:
        Decorator function
    c                   s   t  |  | S r{   )r   r~   )r   r   r=   r>   r     s   z&register_aggregation.<locals>.decorater=   r   r=   r   r>   r     s   
r   Callable[..., float] | Nonec                 C  F   t tdkr
ddl}zt| W S  ty"   t|  d Y dS w )zGet an aggregation function by name.

    Args:
        name: The aggregation name

    Returns:
        The aggregation function, or None if not found
    r   Nz% not a registered aggregation metric!)rH   r   r   rm   r   r   r   rP   r   r=   r=   r>   r        
r   c                 C  r   )zGet the aggregation function for a metric.

    Args:
        name: The metric name

    Returns:
        The aggregation function for that metric, or None if not found
    r   Nz. metric is not assigned a default aggregation!)rH   r   r   rm   r   r   r   r   r=   r=   r>   r     r   r   metric_namebool | Nonec                 C  sH   t tdkr
ddl}zt| W S  ty#   td|  d Y dS w )zCheck if higher values are better for a metric.

    Args:
        metric_name: The metric name

    Returns:
        True if higher is better, False otherwise, None if not found
    r   Nz+higher_is_better not specified for metric 'z'!)rH   r   r   rm   r   r   r   )r   r   r=   r=   r>   r     s   

r   )r.   r/   r0   r   )r@   )rA   r3   rB   rC   rD   rE   r0   rF   )rP   r3   rQ   r3   rR   rC   r0   r3   )r   r3   )rP   r3   )r   r   r0   r   )F)rP   r3   r   r   r0   r   )rP   r3   r0   r   )r   r3   r0   r   )Dr   
__future__r   r7   importlib.metadatametadatar   r   loggingra   collections.abcr   	functoolsr   typesr   typingr   r   r   r	   r
   r   	getLoggerrp   r   r   lm_eval.api.filterr   r   r   __all__r)   r*   r3   r   r/   objectr+   __annotations__r?   rO   rZ   r   r   r   r   r   r   r   r   r$   r%   r&   r'   r(   r   r   r"   r    r!   r#   r   r   r   r   r   r   r=   r=   r=   r>   <module>   sv    " 
"

  


"
"

