o
    پi4                     @   s   d Z ddlZddlZddlZddlZddlmZmZ ddlm	Z	 ddl
mZmZmZmZ ddlmZmZmZmZmZ ddlmZ eeZG dd	 d	ZdS )
z
Centralized template management for chat templates and completion templates.

This module provides a unified interface for managing both chat conversation templates
and code completion templates, eliminating global state and improving modularity.
    N)DictOptional)TokenizerManager)CompletionTemplateFimPositioncompletion_template_existsregister_completion_template)ConversationSeparatorStylechat_template_existsget_conv_template_by_model_pathregister_conv_template)$detect_jinja_template_content_formatc                   @   sp  e Zd ZdZdd Zedee fddZedee fddZ	edee fd	d
Z
edefddZdedefddZdedee deddfddZdededdfddZdeddfddZdeddfddZ		d-dededee dee ddf
dd Zded!eddfd"d#Zd!eddfd$d%Zd!eddfd&d'Zdedee fd(d)Zd*eeef dedefd+d,ZdS ).TemplateManagerz
    Centralized manager for chat and completion templates.

    This class encapsulates all template-related state and operations,
    eliminating the need for global variables and providing a clean
    interface for template management.
    c                 C   s   d | _ d | _d| _d| _d S )NopenaiF)_chat_template_name_completion_template_name_jinja_template_content_format_force_reasoningself r   X/home/ubuntu/.local/lib/python3.10/site-packages/sglang/srt/managers/template_manager.py__init__7   s   
zTemplateManager.__init__returnc                 C      | j S )z#Get the current chat template name.)r   r   r   r   r   chat_template_name=      z"TemplateManager.chat_template_namec                 C   r   )z)Get the current completion template name.)r   r   r   r   r   completion_template_nameB   r   z(TemplateManager.completion_template_namec                 C   r   )zHGet the detected template content format ('string' or 'openai' or None).)r   r   r   r   r   jinja_template_content_formatG   r   z-TemplateManager.jinja_template_content_formatc                 C   r   )z
        Check if the current chat template enforces reasoning/thinking.

        Returns:
            True if the template contains reasoning patterns like <think> tags
        )r   r   r   r   r   force_reasoningL   s   zTemplateManager.force_reasoningtemplatec                 C   s2   |du rdS d}t ||du}|rtd |S )zS
        Detect if the chat template contains reasoning/thinking patterns.
        NFz$<\|im_start\|>assistant\\n<think>\\nz6Detected the force reasoning pattern in chat template.)researchloggerinfo)r   r!   force_reasoning_patternhas_reasoningr   r   r   _detect_reasoning_patternV   s   
z)TemplateManager._detect_reasoning_patterntokenizer_managerchat_template_arg
model_pathNc                 C   s   |r	|  || n/| | | jdu r8| |}|r0|jr!||j_t|| _t	d| j  nd| _t	d |jrE| 
|jj| _dS dS )a  
        Load a chat template from various sources.

        Args:
            tokenizer_manager: The tokenizer manager instance
            chat_template_arg: Template name, file path, or None to auto-detect
            model_path: Path to the model
        NzFUsing default HuggingFace chat template with detected content format: stringz=No chat template found, defaulting to 'string' content format)_load_explicit_chat_template#guess_chat_template_from_model_pathr   _resolve_hf_chat_template	tokenizerchat_templater   r   r$   r%   r(   r   )r   r)   r*   r+   hf_templater   r   r   load_chat_templatef   s,   




z"TemplateManager.load_chat_templatec                 C   sf   t d|  t|r|| _dS tj|std| d|dr,| 	|| dS | 
| dS )z(Load explicitly specified chat template.z%Loading chat template from argument: NzChat template zD is not a built-in template name or a valid chat template file path.z.jinja)r$   r%   r   r   ospathexistsRuntimeErrorendswith_load_jinja_template_load_json_chat_template)r   r)   r*   r   r   r   r-      s   

z,TemplateManager._load_explicit_chat_templatec                 C   s.   t |}|durtd|  || _dS dS )zt
        Infer chat template name from model path.

        Args:
            model_path: Path to the model
        Nz(Inferred chat template from model path: )r   r$   r%   r   )r   r+   template_namer   r   r   r.      s
   
z3TemplateManager.guess_chat_template_from_model_pathcompletion_template_argc                 C   sL   t d|  t|s!tj|std| d| | dS || _dS )z
        Load completion template for code completion.

        Args:
            completion_template_arg: Template name or file path
        zLoading completion template: zCompletion template zJ is not a built-in template name or a valid completion template file path.N)	r$   r%   r   r4   r5   r6   r7   _load_json_completion_templater   )r   r<   r   r   r   load_completion_template   s   

z(TemplateManager.load_completion_templater1   completion_templatec                 C   s$   |  ||| |r| | dS dS )aF  
        Initialize all templates based on provided configuration.

        Args:
            tokenizer_manager: The tokenizer manager instance
            model_path: Path to the model
            chat_template: Optional chat template name/path
            completion_template: Optional completion template name/path
        N)r3   r>   )r   r)   r+   r1   r?   r   r   r   initialize_templates   s   z$TemplateManager.initialize_templatestemplate_pathc                 C   st   t |d}d| d}W d   n1 sw   Y  |dd|j_d| _t|| _	t
d| j	  dS )zLoad a Jinja template file.r 
Nz\nzADetected user specified Jinja chat template with content format: )openjoin	readlinesstripreplacer0   r1   r   r   r   r$   r%   )r   r)   rA   fr1   r   r   r   r9      s   
z$TemplateManager._load_jinja_templatec                 C   s   | ds	J dt|dL}t|}zt|d  }W n ty-   td|d  dw tt|d |d d	 |	d
d|d |d f||	dd|d ddd W d   n1 s]w   Y  |d | _
dS )zLoad a JSON chat template file..jsonz)unrecognized format of chat template filerB   	sep_stylezUnknown separator style: Nnamesystemz
{system_message}system_messagerC   user	assistantseprD   stop_str)rM   system_templaterO   rolesrL   rR   rS   Toverride)r8   rE   jsonloadr
   KeyError
ValueErrorr   r	   getr   )r   rA   filepr!   rL   r   r   r   r:      s<   



	z(TemplateManager._load_json_chat_templatec              	   C   s   | ds	J dt|d<}t|}zt|d  }W n ty-   td|d  dw tt|d |d |d	 |d
 |ddd W d   n1 sMw   Y  |d | _	dS )z%Load a JSON completion template file.rK   z/unrecognized format of completion template filerB   fim_positionzUnknown fim position: NrM   fim_begin_tokenfim_middle_tokenfim_end_token)rM   r_   r`   ra   r^   TrV   )
r8   rE   rX   rY   r   rZ   r[   r   r   r   )r   rA   r]   r!   r^   r   r   r   r=     s8   
z.TemplateManager._load_json_completion_templatec              
   C   s   z3|j rt|j dd nd p|jrt|jdd nd }|d u r%td W d S t|tr1| ||W S |W S  tyN } ztd|  W Y d }~d S d }~ww )Nr1   z"No HuggingFace chat template foundzError getting chat template: )		processorgetattrr0   r$   warning
isinstancedict_select_named_template	Exception)r   r)   r!   er   r   r   r/   )  s(   


z)TemplateManager._resolve_hf_chat_template	templatesc                 C   s   |st dt| }td|  |jj }r5||vr(t d| d| td| d || S |d }td| d || S )	NzEmpty templates dict providedz/Multiple HuggingFace chat templates available: zSpecified template 'z"' not found. Available templates: z Using specified chat template: ''r   z!Using first available template: ')r[   listkeysr$   r%   server_argshf_chat_template_name)r   rj   r)   available_namespreferred_name
first_namer   r   r   rg   G  s    z&TemplateManager._select_named_template)NN)__name__
__module____qualname____doc__r   propertyr   strr   r   r   boolr    r(   r   r3   r-   r.   r>   r@   r9   r:   r=   r/   r   rg   r   r   r   r   r   .   s    	
/




r   )rv   rX   loggingr4   r"   typingr   r   %sglang.srt.managers.tokenizer_managerr   (sglang.srt.parser.code_completion_parserr   r   r   r   sglang.srt.parser.conversationr	   r
   r   r   r   &sglang.srt.parser.jinja_template_utilsr   	getLoggerrs   r$   r   r   r   r   r   <module>   s   
