o
    i)                     @  s   d dl m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 d dlmZ er@d dlmZ d d	lmZ d d
lmZ e	eZG dd dZdS )    )annotationsN)Callable)TYPE_CHECKING)init_logger)
is_list_of)import_from_pathParser)ReasoningParser)
ToolParserc                   @  s   e Zd ZU dZi Zded< i Zded< ed4d
dZed4ddZ	e		d5d6ddZ
ed7ddZe			d8d9ddZed:d!d"Zed;d$d%Ze		&	d<d=d,d-Zed>d0d1Ze			&	d?d@d2d3ZdS )AParserManagerz
    Central registry for Parser implementations.

    Supports two registration modes:
      - Eager registration via `register_module`
      - Lazy registration via `register_lazy_module`
    zdict[str, type[Parser]]parserszdict[str, tuple[str, str]]lazy_parsersnamestrreturntype[Parser]c                 C  sJ   || j v r
| j | S || jv r| |S d|  }td| d| )a  
        Retrieve a registered or lazily registered Parser class.

        Args:
            name: The registered name of the parser.

        Returns:
            The Parser class.

        Raises:
            KeyError: If no parser is found under the given name.
        z, zParser 'z ' not found. Available parsers: )r   r   _load_lazy_parserjoinlist_registeredKeyError)clsr   
registered r   P/home/ubuntu/vllm_env/lib/python3.10/site-packages/vllm/parser/parser_manager.pyget_parser_internal#   s   



z!ParserManager.get_parser_internalc              
   C  s   ddl m} | j| \}}z!t|}t||}t||s't| d| d|| j|< |W S  t	yC } z	t
d|||  d}~ww )z+Import and register a lazily loaded parser.r   r   z in z is not a Parser subclass.z-Failed to import lazy parser '%s' from %s: %sN)vllm.parser.abstract_parserr	   r   	importlibimport_modulegetattr
issubclass	TypeErrorr   	Exceptionlogger	exception)r   r   r	   module_path
class_namemod
parser_clser   r   r   r   :   s*   



zParserManager._load_lazy_parserNTmodulemodule_namestr | list[str] | NoneforceboolNonec                 C  s   ddl m} t||stdt| |du r|jg}nt|tr&|g}nt|tr.|}ntd|D ]}|sL|| j	v rL| j	| }t
| d|j || j	|< q4dS )z$Register a Parser class immediately.r   r   z+module must be subclass of Parser, but got Nz,module_name must be str, list[str], or None.z is already registered at )r   r	   r    r!   type__name__
isinstancer   r   r   r   
__module__)r   r*   r+   r-   r	   module_namesr   existedr   r   r   _register_moduleR   s$   




zParserManager._register_moduler%   r&   c                 C  s   ||f| j |< dS )a"  
        Register a lazy module mapping for delayed import.

        Example:
            ParserManager.register_lazy_module(
                name="minimax_m2",
                module_path="vllm.parser.minimax_m2_parser",
                class_name="MiniMaxM2Parser",
            )
        N)r   )r   r   r%   r&   r   r   r   register_lazy_modulep   s   z"ParserManager.register_lazy_moduletype[Parser] | None5type[Parser] | Callable[[type[Parser]], type[Parser]]c                   sL   t |tstdt| |dur j||d |S d	 fdd}|S )
a*  
        Register a Parser class.

        Can be used as a decorator or called directly.

        Usage:
            @ParserManager.register_module("my_parser")
            class MyParser(Parser):
                ...

        Or:
            ParserManager.register_module(module=MyParser)
        z!force must be a boolean, but got N)r*   r+   r-   objr   r   c                   sP   | j }| j}ttrg}nttr}n|g}|D ]	}||f j|< q| S )N)r3   r1   r2   r   r   r   )r:   r%   r&   namesnr   r   r   r   
_decorator   s   

z1ParserManager.register_module.<locals>._decorator)r:   r   r   r   )r2   r.   r!   r0   r6   )r   r   r-   r*   r>   r   r=   r   register_module~   s   
zParserManager.register_module	list[str]c                 C  s    t t| j t| j B S )z'Return names of all registered parsers.)sortedsetr   keysr   )r   r   r   r   r      s    zParserManager.list_registeredplugin_pathc                 C  sL   t jt j|d }zt|| W dS  ty%   td|| Y dS w )z4Import a user-defined parser from an arbitrary path.r   z#Failed to load module '%s' from %s.N)ospathsplitextbasenamer   r"   r#   r$   )r   rD   r+   r   r   r   import_parser   s   
zParserManager.import_parserFtool_parser_name
str | Noneenable_auto_tools
model_nametype[ToolParser] | Nonec              
   C  s   ddl m} d}|r|du r|S td z|dkr&|r&|dr&td ||}W |S  tyB } z	td| d	|d}~ww )
z&Get the tool parser based on the name.r   )ToolParserManagerNz$"auto" tool choice has been enabled.pythoniczmeta-llama/Llama-3.2z>Llama3.2 models may struggle to emit valid pythonic tool callsz7Error: --enable-auto-tool-choice requires tool_parser:'z' which has not been registered)	vllm.tool_parsersrO   r#   info
startswithwarningget_tool_parserr"   r!   )r   rJ   rL   rM   rO   parserr)   r   r   r   rU      s4   
zParserManager.get_tool_parserreasoning_parser_nametype[ReasoningParser] | Nonec              
   C  s`   ddl m} d}|sdS z||}|dusJ W |S  ty/ } z	td|d|d}~ww )z+Get the reasoning parser based on the name.r   )ReasoningParserManagerNzreasoning_parser_name=z has not been registered)vllm.reasoningrY   get_reasoning_parserr"   r!   )r   rW   rY   rV   r)   r   r   r   r[      s   
z"ParserManager.get_reasoning_parserc           
   	   C  s   ddl m} |s|sdS |r*||kr*z| |}td| |W S  ty)   Y nw ||fD ]}|rLz| |}td| |W   S  tyK   Y q.w q.| |}| |||}	|du rc|	du rcdS ||_|	|_	|S )a  
        Get a unified Parser that handles both reasoning and tool parsing.

        This method checks if a unified Parser exists that can handle both
        reasoning extraction and tool call parsing. If no unified parser
        exists, it creates a DelegatingParser that wraps the individual
        reasoning and tool parsers.

        Args:
            tool_parser_name: The name of the tool parser.
            reasoning_parser_name: The name of the reasoning parser.
            enable_auto_tools: Whether auto tool choice is enabled.
            model_name: The model name for parser-specific warnings.

        Returns:
            A Parser class, or None if neither parser is specified.
        r   )_WrappedParserNz>Using unified parser '%s' for both reasoning and tool parsing.z9Using unified parser '%s' for reasoning and tool parsing.)
r   r\   r   r#   rR   r   r[   rU   reasoning_parser_clstool_parser_cls)
r   rJ   rW   rL   rM   r\   rV   r   r]   r^   r   r   r   
get_parser   sH   



zParserManager.get_parser)r   r   r   r   )NT)r*   r   r+   r,   r-   r.   r   r/   )r   r   r%   r   r&   r   r   r/   )NTN)r   r,   r-   r.   r*   r8   r   r9   )r   r@   )rD   r   r   r/   )NFN)rJ   rK   rL   r.   rM   rK   r   rN   )rW   rK   r   rX   )NNFN)
rJ   rK   rW   rK   rL   r.   rM   rK   r   r8   )r1   r3   __qualname____doc__r   __annotations__r   classmethodr   r   r6   r7   r?   r   rI   rU   r[   r_   r   r   r   r   r      sH   
 .
 r   )
__future__r   r   rE   collections.abcr   typingr   vllm.loggerr   vllm.utils.collection_utilsr   vllm.utils.import_utilsr   r   r	   rZ   r
   rQ   r   r1   r#   r   r   r   r   r   <module>   s   