o
    پi`<                     @   s   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
G dd	 d	e
ZG d
d de
ZG dd de
ZG dd de
ZG dd de
ZG dd de
ZG dd dZdS )    )DictOptionalTupleType)ChatCompletionRequest)HarmonyParserc                   @   s0   e Zd ZdZ		ddee dee fddZdS )StreamingParseResultz(Result of streaming incremental parsing.Nnormal_textreasoning_textc                 C   s   |pd| _ |pd| _d S )N r	   r
   )selfr	   r
    r   V/home/ubuntu/.local/lib/python3.10/site-packages/sglang/srt/parser/reasoning_parser.py__init__
   s   
zStreamingParseResult.__init__)NN)__name__
__module____qualname____doc__r   strr   r   r   r   r   r      s    r   c                   @   s`   e Zd ZdZ				ddedededed	ed
efddZdedefddZdedefddZ	dS )BaseReasoningFormatDetectorzPBase class providing two sets of interfaces: one-time and streaming incremental.FTr   think_start_tokenthink_end_tokenforce_reasoningstream_reasoningcontinue_final_messageprevious_contentc                 C   sz   || _ || _|| _|| _d| _d| _|| _| jr!|| _t|| _	nd| _d| _	| j | jv r0d| _| j| jv r;d| _d S d S )Nr   Fr   T)
r   r   _in_reasoningr   _bufferstripped_think_startr   r   lenprevious_count)r   r   r   r   r   r   r   r   r   r   r      s"   	
z$BaseReasoningFormatDetector.__init__textreturnc                 C   s   | j p| j|v }|st|dS || jd }| j|vr(| j| jvr(t|dS | j|v rE|j| jdd}|d }|d  }t||dS t|dS )z
        One-time parsing: Detects and parses reasoning sections in the provided text.
        Returns both reasoning content and normal text separately.
        r	   r   r
      )maxsplitr   r   )r   r   r   replacestripr   r   split)r   r"   in_reasoningprocessed_textsplitsr
   r	   r   r   r   detect_and_parse4   s   




z,BaseReasoningFormatDetector.detect_and_parsenew_textc                    s   |  j |7  _ | j  t fdd| j| jfD rt S | js1| j v r1 | jd d| _d| _| jr^| j v r^ | j} d| }d| _ d| _ |t	| j d }t||
 dS | jro| jrld| _ t dS t S | jszd| _ t d	S t S )
a?  
        Streaming incremental parsing for reasoning content.
        Handles partial reasoning tags and content.

        If stream_reasoning is False:
            Accumulates reasoning content until the end tag is found
        If stream_reasoning is True:
            Streams reasoning content as it arrives
        c                 3   s"    | ]}|  o| kV  qd S )N)
startswith).0tokencurrent_textr   r   	<genexpr>c   s
    
zHBaseReasoningFormatDetector.parse_streaming_increment.<locals>.<genexpr>r   TNFr   r%   r$   )r   anyr   r   r   r   r(   r   findr    rstripr   )r   r/   end_idxr
   r	   r   r3   r   parse_streaming_incrementU   s8   



z5BaseReasoningFormatDetector.parse_streaming_incrementN)FTFr   )
r   r   r   r   r   boolr   r   r.   r:   r   r   r   r   r      s*    
!r   c                	       s<   e Zd ZdZ				ddedededef fd	d
Z  ZS )DeepSeekR1Detectora  
    Detector for DeepSeek-R1 model.
    Assumes reasoning format:
      (<think>)*(.*)</think>
    Returns all the text before the </think> tag as `reasoning_text`
    and the rest of the text as `normal_text`.

    Supported models:
      - DeepSeek-R1: Always generates thinking content without <think> start tag
      - DeepSeek-R1-0528: Generates thinking content with <think> start tag

    Format patterns:
      - DeepSeek-R1: "I need to think about this...</think>The answer is 42."
      - DeepSeek-R1-0528: "<think>I need to think about this...</think>The answer is 42."

    Args:
        stream_reasoning (bool): If False, accumulates reasoning content until the end tag.
            If True, streams reasoning content as it arrives.
    TFr   r   r   r   r   c                       t  jddd|||d d S )N<think></think>Tr   r   r   r   superr   r   r   r   r   r   	__class__r   r   r      s   
zDeepSeekR1Detector.__init__TTFr   r   r   r   r   r;   r   r   __classcell__r   r   rD   r   r<      s    r<   c                	       <   e Zd ZdZ				ddedededef fd	d
Z  ZS )Qwen3Detectora^  
    Detector for Qwen3 models (e.g., Qwen/Qwen3-235B-A22B).
    Assumes reasoning format:
      (<think>)*(.*)</think>

    Qwen3 models released before 07/2025 supports switching between thinking mode and normal
    mode using `enable_thinking` parameter in the request parameter.
      - enable_thinking=True: "<think>reasoning content</think>The answer is 42."
      - enable_thinking=False: "The answer is 42." (no thinking tokens)

    Args:
        stream_reasoning (bool): If False, accumulates reasoning content until the end tag.
            If True, streams reasoning content as it arrives.
    TFr   r   r   r   r   c                       t  jdd||||d d S Nr>   r?   r@   rA   rC   rD   r   r   r         
zQwen3Detector.__init__TFFr   rG   r   r   rD   r   rJ      s    rJ   c                	       rI   )KimiDetectoru   
    Detector for Kimi Thinking model.
    Assumes reasoning format:
      ◁think▷*(.*)◁/think▷
    Returns all the text before the ◁/think▷ tag as `reasoning_text`
    and the rest of the text as `normal_text`.
    TFr   r   r   r   r   c                    r=   )Nu   ◁think▷u   ◁/think▷Fr@   rA   rC   rD   r   r   r      rM   zKimiDetector.__init__rN   rG   r   r   rD   r   rO      s    
rO   c                	       s`   e Zd ZdZ				ddedededef fd	d
ZdedefddZdedefddZ	  Z
S )GptOssDetectorzT
    Detector for T4-style reasoning format (GPT-OSS), using the HarmonyParser.
    TFr   r   r   r   r   c                    s$   t  jdd||||d t | _d S )Nz<|channel|>analysis<|message|>z<|end|>r@   )rB   r   r   parserrC   rD   r   r   r      s   zGptOssDetector.__init__r"   r#   c                 C   s   | j |}|| j d7 }ddd |D }g }|D ]}|jdkr*||j q|jdkr;||jr7|jn|j qd|}t||dS )Nr   c                 S      g | ]
}|j d kr|jqS 	reasoning
event_typecontentr1   er   r   r   
<listcomp>      z3GptOssDetector.detect_and_parse.<locals>.<listcomp>normal	tool_callr   rQ   parsejoinrV   appendrW   raw_textr   )r   r"   eventsr
   normal_partsrY   r	   r   r   r   r.     s"   


zGptOssDetector.detect_and_parser/   c                 C   s~   | j |}ddd |D }g }|D ]}|jdkr"||j q|jdkr3||jr/|jn|j qd|}t||dS )Nr   c                 S   rR   rS   rU   rX   r   r   r   rZ   "  r[   z<GptOssDetector.parse_streaming_increment.<locals>.<listcomp>r\   r]   r   r^   )r   r/   rc   r
   rd   rY   r	   r   r   r   r:     s    


z(GptOssDetector.parse_streaming_incrementrF   )r   r   r   r   r;   r   r   r   r.   r:   rH   r   r   rD   r   rP      s"    rP   c                	       s`   e Zd ZdZ				ddedededef fd	d
ZdedefddZdedefddZ	  Z
S )MiniMaxAppendThinkDetectorz>
    Append `<think>` token to the beginning of the text.
    TFr   r   r   r   r   c                    s"   t  jdd||||d d| _d S )Nr>   r?   r@   F)rB   r   is_first_chunkrC   rD   r   r   r   8  s   
z#MiniMaxAppendThinkDetector.__init__r/   r#   c                 C   s    | j sd| _ | j| }t|dS )NTr$   )rf   r   r   )r   r/   r   r   r   r:   J  s   

z4MiniMaxAppendThinkDetector.parse_streaming_incrementr"   c                 C   s   t | j| dS )Nr$   )r   r   )r   r"   r   r   r   r.   P  s   z+MiniMaxAppendThinkDetector.detect_and_parserN   )r   r   r   r   r;   r   r   r   r:   r.   rH   r   r   rD   r   re   3  s"    re   c                	       rI   )NanoV3Detectorzo
    Detector for NanoV3 model.
    Uses the same reasoning format as DeepSeek-R1: (<think>)*(.*)</think>

    TFr   r   r   r   r   c                    rK   rL   rA   rC   rD   r   r   r   [  rM   zNanoV3Detector.__init__rN   rG   r   r   rD   r   rg   T  s    rg   c                   @   s   e Zd ZU dZeeeeeeeeeeeee	edZ
eeee f ed< 				ddee dedee d	efd
dZdedeee ee f fddZdedeee ee f fddZdS )ReasoningParserac  
    Parser that handles both streaming and non-streaming scenarios for extracting
    reasoning content from model outputs.

    Args:
        model_type (str): Type of model to parse reasoning from
        stream_reasoning (bool): If False, accumulates reasoning content until complete.
            If True, streams reasoning content as it arrives.
    )zdeepseek-r1zdeepseek-v3glm45gpt-osskimikimi_k2qwen3qwen3-thinkingminimaxzminimax-append-thinkstep3step3p5nano_v3interns1DetectorMapNT
model_typer   r   requestc                 C   s   |st d| j| }|st d| | dv rd}d|i}|d ur+||d< |d urKt|trK|jrK|jd jdkrKd|d	< |jd j	|d
< |di || _
d S )NzModel type must be specifiedzUnsupported model type: >   ro   rj   rn   Tr   r   	assistantr   r   r   )
ValueErrorrt   getlower
isinstancer   r   messagesrolerW   detector)r   ru   r   r   rv   detector_classkwargsr   r   r   r     s&   zReasoningParser.__init__	full_textr#   c                 C      | j |}|j|jfS )z$Non-streaming call: one-time parsing)r   r.   r
   r	   )r   r   retr   r   r   parse_non_stream  s   z ReasoningParser.parse_non_stream
chunk_textc                 C   r   )z#Streaming call: incremental parsing)r   r:   r
   r	   )r   r   r   r   r   r   parse_stream_chunk  s   z"ReasoningParser.parse_stream_chunk)NTNN)r   r   r   r   r<   rJ   rP   rO   re   rg   rt   r   r   r   r   __annotations__r   r;   r   r   r   r   r   r   r   r   r   rh   l  sH   
 
""rh   N)typingr   r   r   r   &sglang.srt.entrypoints.openai.protocolr    sglang.srt.parser.harmony_parserr   r   r   r<   rJ   rO   rP   re   rg   rh   r   r   r   r   <module>   s    {(!B!