o
    پi$                     @   s   d Z ddlZddlZddlm  mZ ddlmZ e	e
ZdejjdedefddZdejjded	edefd
dZ	ddejjded	edefddZdefddZdedefddZ	ddedededededededefddZdS )zTemplate utilities for Jinja template processing.

This module provides utilities for analyzing and processing Jinja chat templates,
including content format detection and message processing.
    N)	ImageDatanodevarnamereturnc                 C   s&   t | tjjr| jdko| j|kS dS )z5Check if node is a variable access like {{ varname }}loadF)
isinstancejinja2nodesNamectxname)r   r    r   Z/home/ubuntu/.local/lib/python3.10/site-packages/sglang/srt/parser/jinja_template_utils.py_is_var_access   s   r   keyc                 C   s^   t | tjjrt| j|ot | jtjjo| jj|kS t | tjj	r-t| j|o,| j
|kS dS )zSCheck if node is an attribute access like {{ varname['key'] }} or {{ varname.key }}F)r   r   r	   Getitemr   r   argConstvalueGetattrattrr   r   r   r   r   r   _is_attr_access#   s   
r   c                 C   s   t | tjjr| jduot| j||S t | tjjr!t| j||S t | tjjr7t | jtjj	r7t| j||S |r?t
| ||S t| |S )zACheck if node accesses varname or varname[key] with filters/testsN)r   r   r	   Filterr   _is_var_or_elems_accessTestr   r   Slicer   r   r   r   r   r   r   2   s   
r   chat_templatec              
   C   sP   zt | }|j| W S  ty' } ztd|  W Y d}~dS d}~ww )z+Try to parse the Jinja template into an ASTz%Error when compiling Jinja template: N)hf_chat_utils_compile_jinja_templateenvironmentparse	Exceptionloggerdebug)r   jinja_compileder   r   r   _try_extract_astG   s   
r'   c              
      s   t  fdddD rdS t }|du rdS z*|tjjD ]}|j}t|ddr. W dS t|d	ds:t|d
dr> W dS qW dS  ty\ } zt	
d|  W Y d}~dS d}~ww )ut  
    Detect whether a chat template expects 'string' or 'openai' content format.

    - 'string': content is a simple string (like DeepSeek templates)
    - 'openai': content is a list of structured dicts (like Llama4 templates)

    Detection logic:
    - If template has loops like {%- for content in message['content'] -%} → 'openai'
    - Otherwise → 'string'
    c                 3   s    | ]}| v V  qd S Nr   ).0keywordr   r   r   	<genexpr>]   s    
z7detect_jinja_template_content_format.<locals>.<genexpr>)imageaudiovideovisionopenaiNstringmessagecontentmsgmz*Error when parsing AST of Jinja template: )anyr'   find_allr   r	   Foriterr   r"   r#   r$   )r   	jinja_astloop_ast	loop_iterr&   r   r+   r   $detect_jinja_template_content_formatQ   s2   
r>   Fmsg_dictcontent_format
image_data
video_data
audio_data
modalitiesuse_dpsk_v32_encodingc              	   C   sV  t | dtsdd |  D S |dks|rg }g }| d D ]}	t |	tr|	d}
|
dkra|	dp5i }|dd}|t|d	 |d
d|d |	drY||	d |ddi q|
dkr|	dpki }|dd}|du r||	d d	  n
||d	 |d |	dr||	d |ddi q|
dkr||	d d	  |ddi q|
dkr|r||	d  q||	 qdd |  D }|r|rd|nd|d< |S ||d< |S |dkr$g }| d D ]}	t |	tr|	ddkr||	d  q|  }|rd|nd|d< dd | D }|S t	d| )aN  
    Process message content based on detected template format.

    Args:
        msg_dict: Message dictionary with content
        content_format: 'string' or 'openai' (detected via AST analysis)
        image_data: List to append extracted image URLs
        video_data: List to append extracted video URLs
        audio_data: List to append extracted audio URLs
        modalities: List to append modalities
        use_dpsk_v32_encoding: If True, extract multimodal data and convert content to string (for DeepSeek-V3.2 encoding)

    Returns:
        Processed message dictionary
    r4   c                 S      i | ]\}}|d ur||qS r(   r   r)   kvr   r   r   
<dictcomp>       z7process_content_for_template_format.<locals>.<dictcomp>r1   type	image_urlmax_dynamic_patchNurldetailauto)rO   rP   rN   rD   r-   	video_url)rO   rN   r/   	audio_urlr.   textc                 S   s&   i | ]\}}|d ur|dkr||qS )Nr4   r   rG   r   r   r   rJ      s       r2   c                 S   rF   r(   r   rG   r   r   r   rJ      rK   zInvalid content format: )
r   getlistitemsdictappendr   joincopy
ValueError)r?   r@   rA   rB   rC   rD   rE   processed_content_parts
text_partschunk
chunk_type	image_objmdp	video_objnew_msgr   r   r   #process_content_for_template_format{   sz   






rg   r(   )F)__doc__loggingr   &transformers.utils.chat_template_utilsutilschat_template_utilsr   sglang.srt.utilsr   	getLogger__name__r#   r	   Nodestrboolr   r   r   r'   r>   rZ   rX   rg   r   r   r   r   <module>   sL    


1