o
    پiN                     @   sl  d Z ddlZddlZddlZddlZddlZddlZddlZddlZddl	Z	ddl
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 ddlmZ ddlmZmZmZmZmZmZm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) ddl*m+Z+ e,e-Z.dd Z/e/de0fddZ1dee2e0ee( f de0fddZ3dd Z4de5fddZ6de0fddZ7dmde0de5d e0fd!d"Z8G d#d$ d$Z9		%			dnd&ee0 fd'd(Z:d)ee0e;f fd*d+Z<d,d- Z=dod/e0d0e>fd1d2Z?d3e>fd4d5Z@d6e0fd7d8ZAG d9d: d:ZBdpd;e0dee0 fd<d=ZCdeDfd>d?ZEd@e0fdAdBZFeG ZHdqdEdFZIdGdH ZJdIe0dejKfdJdKZLdrdIe0dMe0dNe>fdOdPZMdQdR ZNdSee ddfdTdUZOdVePdWee> deDfdXdYZQ				Zdsd;e0dWee> dSee d[ee2 d\e>ddfd]d^ZR		dtd_e0dWe>dSeejK ddfd`daZSG dbdc dcZTddde ZUdfdg ZVdhdi ZWdje0defdkdlZXdS )uzCommon utilities    N)OrderedDict)ThreadPoolExecutorwraps)BytesIO)dumps)AnyCallableListOptionalTupleTypeUnion)HTMLdisplay)	BaseModel)tqdm)envsc                    s   d t   fdd}|S )Nc                     s   s | i | dd S d S )NT )argskwargsfunchas_runr   @/home/ubuntu/.local/lib/python3.10/site-packages/sglang/utils.pywrapper&   s   zexecute_once.<locals>.wrapperr   )r   r   r   r   r   execute_once#   s   r   messagec                 C   s   t |  d S N)loggerinfo)r   r   r   r   	info_once0   s   r!   json_schemareturnc                 C   s^   t | trt| }|S t | tr| }|S t| tr#t|  }|S td|  dd d )a+  Convert a JSON schema to a string.
    Parameters
    ----------
    json_schema
        The JSON schema.
    Returns
    -------
    str
        The JSON schema converted to a string.
    Raises
    ------
    ValueError
        If the schema is not a dictionary, a string or a Pydantic class.
    zCannot parse schema z. The schema must be either zBa Pydantic class, a dictionary or a string that contains the JSON zschema specification)	
isinstancedictjsonr   str
issubclassr   model_json_schema
ValueError)r"   
schema_strr   r   r   convert_json_schema_to_str5   s    


	

r,   c                  C   s&   t  \} }}dt| ||}|S )N )sysexc_infojoin	tracebackformat_exception)etypevaluetberr_strr   r   r   get_exception_tracebackS   s   r7   valuesc                    s:   t | dkrdS t| d  t fdd| dd D S )z;Return whether the elements in values are of the same type.   Tr   c                 3   s    | ]}t | V  qd S r   )r$   ).0vtr   r   	<genexpr>_   s    zis_same_type.<locals>.<genexpr>N)lentypeall)r8   r   r<   r   is_same_typeY   s   rB   filenamec                 c   sR    t | }|D ]}|drqt|V  qW d   dS 1 s"w   Y  dS )zRead a JSONL file.#N)open
startswithr&   loads)rC   finliner   r   r   
read_jsonlb   s   

"rJ   wstatesmodec                 C   s   ddl m} t| |=}t|D ]/\}}t|trnt||r$| }nt|}|dd| d d d | d d d  qW d   dS 1 sKw   Y  dS )	z"Dump program state in a text file.r   )ProgramStatez(======================================== 
zP================================================================================z

N)sglang.lang.interpreterrN   rE   	enumerater$   r'   textwrite)rC   rL   rM   rN   foutisr   r   r   dump_state_textk   s   


&"rX   c                   @   s(   e Zd Zdd Zdd Zedd ZdS )HttpResponsec                 C   
   || _ d S r   )resp)selfr[   r   r   r   __init__~      
zHttpResponse.__init__c                 C   s   t | j S r   )r&   rG   r[   readr\   r   r   r   r&      s   zHttpResponse.jsonc                 C   s   | j jS r   )r[   statusr`   r   r   r   status_code   s   zHttpResponse.status_codeN)__name__
__module____qualname__r]   r&   propertyrb   r   r   r   r   rY   }   s
    rY   Fmethodc              
   C   s   ddi}|durd| |d< |rt j| |d|dS tjj| ||d}|du r*d}ntt|d	d
}z/tjdkrT|rFt	|t
rFtj|d}	nt }	tjj|||	d}
n	tjj|||d}
t|
W S  tjjyy } z
t|W  Y d}~S d}~ww )z<A faster version of requests.post with low-level urllib API.zContent-Typezapplication/json; charset=utf-8NzBearer AuthorizationT)r&   streamheaders)rj   rg   utf-8)encoding)      )cafile)datacontext)rp   ro   )requestsposturllibrequestRequestbytesr   r.   version_infor$   r'   sslcreate_default_contexturlopenrY   error	HTTPError)urlr&   ri   api_keyverifyrg   rj   reqrp   rq   r[   er   r   r   http_request   s*   	

r   
image_pathc                 C   s   t | tr(t| d}| }t|dW  d   S 1 s!w   Y  dS t | tr5t| dS | }t }|j	|dd t|
 dS )zEncode an image in base64.rbrk   NPNGformat)r$   r'   rE   r_   pybase64	b64encodedecoderw   r   savegetvalue)r   
image_filerp   imagebufferedr   r   r   encode_image_base64   s   
$
r   c                 C   sL   dd l }ddlm} || |j} || }t }|j|dd | }|S )Nr   )Imager   r   )	cv2PILr   cvtColorCOLOR_BGR2RGB	fromarrayr   r   r   )framer   r   im_pilr   frame_bytesr   r   r   encode_frame   s   
r      
video_path
num_framesc                    s$  dd l }|| }| std|  t||j}td|  tj	d|d |td}g  t
|D ]}| \}}|rD | q4	 q4|   fdd|D  t |k rf  d  t |k sYt }	t|	t }
W d    n1 s|w   Y  d	|
}d
t|d }|S )Nr   zCould not open video file:ztarget_frames: r9   )dtypec                    s    g | ]}|t  k r | qS r   )r?   )r:   rV   framesr   r   
<listcomp>   s     z'encode_video_base64.<locals>.<listcomp>    zvideo:rk   )r   VideoCaptureisOpenedIOErrorintgetCAP_PROP_FRAME_COUNTprintnplinspaceranger_   appendreleaser?   r   listmapr   r0   r   r   r   )r   r   r   captotal_framesframe_indices_retr   executorencoded_framesvideo_bytesvideo_base64r   r   r   encode_video_base64   s0   

r   cpc                 C   s   | dkr| dks@| dkr| dks@| dkr| dks@| dkr | dks@| d	kr(| d
ks@| dkr0| dks@| dkr8| dks@| dkrB| dkrBdS dS )z6Checks whether CP is the codepoint of a CJK character.i N  i  i 4  iM  i   iߦ i  i? i@ i i  i i   i  i  i TFr   )r   r   r   r   _is_chinese_char  s   r   rS   c                 C   sl   |  dr| S t| dkrtt| d r| S t| dkr+tt| d r+| dd S | d| dd  S )zPReturns the longest printable substring of text that contains only entire words.rP   r   r   r9   NrO   )endswithr?   r   ordrfind)rS   r   r   r   find_printable_text  s   
r   c                   @   s@   e Zd ZdZdedefddZdd Zdefd	d
Zdd ZdS )
LazyImportz/Lazy import to make `import sglang` run faster.module_name
class_namec                 C   s   || _ || _d | _d S r   )r   r   _module)r\   r   r   r   r   r   r]   4  s   
zLazyImport.__init__c                 C   s*   | j d u rt| j}t|| j| _ | j S r   )r   	importlibimport_moduler   getattrr   )r\   moduler   r   r   _load9  s   
zLazyImport._loadnamec                 C   s   |   }t||S r   )r   r   )r\   r   r   r   r   r   __getattr__?  s   
zLazyImport.__getattr__c                 O   s   |   }||i |S r   )r   )r\   r   r   r   r   r   r   __call__C  s   zLazyImport.__call__N)	rc   rd   re   __doc__r'   r]   r   r   r   r   r   r   r   r   1  s    r   r~   c              	   C   s  |du rt jd| dd }t j|r|S td|  d|  tj| dd}|  t	|j
d	d
}d}t|d?}t||dddd}|j|dD ]}|| |t| qNW d   n1 sgw   Y  W d   |S W d   |S 1 sw   Y  |S )z!Read and cache a file from a url.Nz/tmp/r   zDownloading from z to Tri   zcontent-lengthr   i   wbB)desctotalunit
unit_scaleunit_divisor)
chunk_size)ospathr0   splitexistsr   rr   r   raise_for_statusr   rj   rE   r   iter_contentrT   updater?   )r~   rC   response
total_sizer   fbarchunkr   r   r   download_and_cache_fileH  s6   
(r   c                   C   s
   t j S r   )r   SGLANG_IS_IN_CIr   r   r   r   r   is_in_cij  r^   r   html_contentc                 C   s:   t  rt| dd} ttd|  d d S t|  d S )NrP   z<br>z <strong style='color: #00008B;'>z	</strong>)r   r'   replacer   r   r   )r   r   r   r   print_highlightn  s   r   0u  @  c              	   C   s   t t||}t| |D ]/}ttjtj}|tjtj	d z|
| |f ||fW   S  tjy=   |  Y qw td)z
    Reserve an available port by trying to bind a socket.
    Returns a tuple (port, lock_socket) where `lock_socket` is kept open to hold the lock.
    r9   zNo free port available.)r   r   randomshufflesocketAF_INETSOCK_STREAM
setsockopt
SOL_SOCKETSO_REUSEADDRbindr|   closeRuntimeError)hoststartend
candidatesportsockr   r   r   reserve_porty  s   
r   c              
   C   sD   z|    W dS  ty! } ztd|  W Y d}~dS d}~ww )z?
    Release the reserved port by closing the lock socket.
    zError closing socket: N)r   	Exceptionr   )lock_socketr   r   r   r   release_port  s   r  commandc                 C   s   |  dd dd} |  }tj }d}|t|k rM|| }d|v rL|dsL|dsL|d\}}}|rL|durL| d	d
 rL|||< |d7 }q	 ||d }|sYt	dt
j|dt
j|dS )z
    Execute a shell command and return its process handle.
    Supports leading KEY=VALUE env vars (e.g. "VAR=1 python script.py") so that
    notebook/CI commands work without requiring shell=True.
    z\
rO   \r   =-r   Nr   r-   r9   zECommand contains only environment variable assignments, no executableT)rS   stderrenv)r   r   r   environcopyr?   rF   	partitionisalnumr*   
subprocessPopenSTDOUT)r  partsr	  rV   partkeyr   r4   r   r   r   execute_shell_command  s&   
r  0.0.0.0r   r   c                 C   sH   |du rt |\}}nd}|  d| }t|}|dur |t|< ||fS )zj
    Launch the server using the given command.
    If no port is specified, a free port is reserved.
    Nz --port )r   r  process_socket_map)r  r   r   r  full_commandprocessr   r   r   launch_server_cmd  s   r  c                 C   s:   ddl m} || j t| d}|durt| dS dS )zL
    Terminate the process and automatically release the reserved port.
    r   )kill_process_treeN)sglang.srt.utilsr  pidr  popr  )r  r  r  r   r   r   terminate_process  s   
r  r  c                 C   s|   | d u rd S t | dr|  }|d urtd| d S t | dr:|  s<t| dd }|d u r3tdtd| d S d S )Npollz Server process exited with code is_aliveexitcodezServer process exited)hasattrr  r   r   r   )r  return_coder   r   r   _raise_if_process_exited  s   
r$  
start_timetimeoutc                 C   s   |d u rdS t  |  |kS )NF)timeperf_counter)r%  r&  r   r   r   _is_wait_timeout  s   r)     rj   request_timeoutc                 C   s|   t  }	 t| ztj| ||d}|jdkrW dS W n tjjy*   t| Y nw t||r8t	d|  dt 
d q)z/Wait for an HTTP endpoint to return status 200.T)rj   r&     Nz	Endpoint z+ did not become ready within timeout periodr9   )r'  r(  r$  rr   r   rb   
exceptionsRequestExceptionr)  TimeoutErrorsleep)r~   r&  r  rj   r+  r%  r   r   r   r   wait_for_http_ready  s"   



r1  base_urlc                 C   s0   t |  d||ddid td td dS )a  Wait for the server to be ready by polling the /v1/models endpoint.

    Args:
        base_url: The base URL of the server.
        timeout: Maximum time to wait in seconds. None means wait forever.
        process: Optional server process used for early-exit checks.
    z
/v1/modelsrh   zBearer None)r~   r&  r  rj   r*  a-  

        NOTE: Typically, the server runs in a separate terminal.
        In this notebook, we run the server and notebook code together, so their outputs are combined.
        To improve clarity, the server logs are displayed in the original black color, while the notebook outputs are highlighted in blue.
        To reduce the log length, we set the log level to warning for the server, the default log level is info.
        We are running those notebooks in a CI environment, so the throughput is not representative of the actual performance.
        N)r1  r'  r0  r   )r2  r&  r  r   r   r   wait_for_server  s   
r3  c                   @   sL   e Zd Zdeeeef  fddZdefddZddd	Z	d
e
fddZdS )TypeBasedDispatchermappingc                 C   s   t || _i | _d | _d S r   )r   _mapping
_mro_cache_fallback_fn)r\   r5  r   r   r   r]      s   

zTypeBasedDispatcher.__init__fallback_fnc                 C   rZ   r   )r8  )r\   r9  r   r   r   add_fallback_fn(  r^   z#TypeBasedDispatcher.add_fallback_fnotherc                 C   s6   |j  D ]\}}|| j vr|| j |< q| j  | S r   )r6  itemsr7  clear)r\   r;  tyfnr   r   r   __iadd__+  s   


zTypeBasedDispatcher.__iadd__objc                 C   s   t |}| j|}|d ur||S | j|}|d ur ||S | j D ]\}}t||r9|| j|< ||  S q%d | j|< | jd urI| |S td| )NzInvalid object: )r@   r6  r   r7  r<  r$   r8  r*   )r\   rA  obj_typer?  	cached_fnr>  r   r   r   r   3  s    




zTypeBasedDispatcher.__call__N)r;  r4  )rc   rd   re   r
   r   r   r	   r]   r:  r@  r   r   r   r   r   r   r4    s
    
r4  c                 C   sN   d}t t| t|}t|ddD ]}| |d| r |} nq||d S )z
    Finds the largest suffix of 'existing_text' that is a prefix of 'new_chunk'
    and removes that overlap from the start of 'new_chunk'.
    r   r   N)minr?   r   r   )existing_text	new_chunkmax_overlapmax_possiblerV   r   r   r   trim_overlapM  s   rI  c                 C   s8   d}| j ||ddD ]}|d }t||}||7 }q
|S )z]
    1) Streams the text,
    2) Removes chunk overlaps,
    3) Returns the merged text.
    r-   Tr   rS   )generaterI  )llmpromptsampling_params
final_textr   
chunk_textcleaned_chunkr   r   r   stream_and_merge[  s   

rQ  c                 C  sT   d}| j ||ddI dH }|2 z3 dH W }|d }t||}||7 }|V  q6 dS )z|
    Streams tokens asynchronously, removes chunk overlaps,
    and yields the cleaned chunk in real time for printing.
    r-   Tr   NrS   )async_generaterI  )rK  rL  rM  rN  	generatorr   rO  rP  r   r   r   async_stream_and_mergei  s   
rT  qualnamec                 C   s$   |  dd\}}t|}t||S )z8
    Resolve an object by its fully qualified name.
    .r9   )rsplitr   r   r   )rU  r   obj_namer   r   r   r   resolve_obj_by_qualnamew  s   

rY  )rK   )NFNNN)r   r   )r   r   )r  N)NNNr*  )NN)Yr   r   r&   loggingr   r   r   ry   r  r.   r'  r1   urllib.requestrt   weakrefcollectionsr   concurrent.futuresr   	functoolsr   ior   r   typingr   r	   r
   r   r   r   r   numpyr   r   rr   IPython.displayr   r   pydanticr   r   sglang.srt.environr   	getLoggerrc   r   r   r'   r!   r%   r,   r7   r   rB   rJ   rX   rY   r   rw   r   r   r   r   r   r   r   r   boolr   r   WeakKeyDictionaryr  r   r  r  r  r  r  r$  floatr)  r1  r3  r4  rI  rQ  rT  rY  r   r   r   r   <module>   s    $
 		
'."



.