
    i                    .   S r SSKrSSKrSSKrSSKrSSKrSSKrSSKrSSKJ	r	J
r
JrJrJrJr  SSKJr  SSKrSSKrSSKJr  SSKJr  SSKJrJr  SSKJr  SS	KJrJr  SS
KJr  SSK J!r!  SSK"J#r#J$r$J%r%J&r&J'r'J(r(  SSK)J*r*J+r+J,r,J-r-  Sr.S r/ " S S5      r0g)zk
5Hz LM (Language Model) Handler
Handles all LM-related operations including initialization and generation
    N)OptionalDictAnyTupleListUnion)contextmanager)logger)tqdm)AutoTokenizerAutoModelForCausalLM)BaseStreamer)LogitsProcessorList RepetitionPenaltyLogitsProcessor)get_vllm_preflight_warning)"MetadataConstrainedLogitsProcessor)DEFAULT_LM_INSTRUCTION!DEFAULT_LM_UNDERSTAND_INSTRUCTIONDEFAULT_LM_INSPIRED_INSTRUCTIONDEFAULT_LM_REWRITE_INSTRUCTIONDURATION_MINDURATION_MAX)get_lm_gpu_memory_ratioget_gpu_memory_gbget_lm_model_sizeget_global_gpu_configg       @c            
      (   [         R                  n [        U SS5      S:w  aq  [         R                  R	                  S5      (       aL  [
        R                  " S[         R                  R                  5       S    S[        U SS5       S3[        S	S
9  g g g )NreleaselevelfinallinuxzDetected pre-release Python r   z ( z). This is known to cause segmentation faults with vLLM/nano-vllm on Linux. Please install a stable Python release (e.g. 3.11.12+), or use --backend pt as a workaround.   )
stacklevel)
sysversion_infogetattrplatform
startswithwarningswarnversionsplitRuntimeWarning)vs    4/mnt/workspace/ACE-Step-1.5/acestep/llm_inference.py_warn_if_prerelease_pythonr0   $   s    Aq.'*g5#,,:Q:QRY:Z:Z*3;;+<+<+>q+A*B"WQP^`bEcDd ek k 	
 ;[5    c            2       x   \ rS rSrSrSr\R                  R                  S5      SLr	S}S\
\   4S jjrS~S	 jrS~S
 jrS~S jrS\4S jrS\\   4S jrSS\S\S\S\S\\\4   4
S jjr S}S\
\   S\S\
\   S\4S jjrS\S\4S jrS\S\4S jr   SS\S\S\
\   S\
\\\
\   4      S\S\S \S!\S\S"\S#\
\   S$\
\   S\
\   4S% jjr SS&\S'\S(\S\S\S"\S\4S) jjrS\S*\S\\\4   4S+ jr S,\!RD                  S-\
\   S\!RD                  4S. jr#S,\!RD                  S/\
\   S\!RD                  4S0 jr$S,\!RD                  S1\S\!RD                  4S2 jr%S3\!RD                  S4\S5\
\   S\4S6 jr&S7\
\   S3\!RD                  4S8 jr'S9\(S:\!RD                  S;\\\(4   S<\
\(   S=\S\(4S> jr)S?\*\\\   4   S\\\   \4   4S@ jr+    SSA\SB\SC\S*\SD\SE\
\!RX                     S\\\4   4SF jjr-SS\SG\SH\S\4SI jjr.               SS?\*\\\   4   S1\SJ\S\S-\
\   S/\
\   S\S\S\S#\
\   S$\
\   S\
\   S\
\\\
\   4      S\S\S \S!\S\S&\S'\S(\SK\
\\      S\*\\\   4   4.SL jjr/SM\S1\SJ\S\S-\
\   S/\
\   S\S\S\S\
\   S\
\\\
\   4      S\S\S \S!\S\S&\S'\S(\S\4(SN jr0             SS?\*\\\   4   S1\SJ\S\S-\
\   S/\
\   S\S\S\S\
\   S\
\\\
\   4      S\S\S \S!\S\S&\S'\S(\SK\
\\      S\*\\\   4   4*SO jjr1S\
\\\
\   4      S\4SP jr2SQ\\\(4   S\4SR jr3                SS&\S'\SS\S1\SJ\S\S-\
\   S/\
\   S\S\S\S\
\   S\
\\\
\   4      ST\SU\SV\SW\
\   SK\
\\      S\\\(4   4&SX jjr4SS&\S'\SY\S\S\S\4SZ jjr5SS&\S'\S(\SY\S\S\4S[ jjr6  SS\\SY\S\S\4S] jjr7      SS\\S1\S-\
\   S/\
\   S\S\S\S\\\\(4   \4   4S^ jjr8S_\S\4S` jr9   SSa\Sb\SY\S\S\4
Sc jjr:        SSa\Sb\Sd\
\   S1\S-\
\   S/\
\   S\S\S\S\\\\(4   \4   4Se jjr;  SS&\S'\SY\S\S\4
Sf jjr<       SS&\S'\S\
\\\(4      S1\S-\
\   S/\
\   S\S\S\S\\\\(4   \4   4Sg jjr=    SSM\Sh\
\\\(4      S\S\S\S\\\4   4Si jjr> S}Sj\!RD                  Sk\
\!RD                     Sl\S1\S-\
\   S/\
\   S\S5\Sm\
\?   S7\
\   S\!RD                  4Sn jjr@ S}So\!RD                  Sp\
\!RD                     Sl\S1\SJ\S-\
\   S/\
\   S\S5\Sm\
\?   S7\
\   S\!RD                  4Sq jjrAS_\S\\\\(4   \4   4Sr jrB\CS\4Ss j5       rDS\S\\\4   4St jrESu rF S}SM\SW\S1\SJ\S\S-\
\   S/\
\   S\S\S\S\
\   S&\S'\S(\SK\
\\      S\\   4 Sv jjrGSM\S1\SJ\S\S-\
\   S/\
\   S\S\S\S\
\   S\
\\\
\   4      S\S\S \S!\S\S&\S'\S(\S\4(Sw jrHSM\S1\SJ\S\S-\
\   S/\
\   S\S\S\S\
\   S\
\\\
\   4      S\S\S \S!\S\S&\S'\S(\S\4(Sx jrI             SS?\*\\\   4   S1\SJ\S\S-\
\   S/\
\   S\S\S\S\
\   S\
\\\
\   4      S\S\S \S!\S\S&\S'\S(\SK\
\\      S\*\\\   4   4*Sy jjrJ\KSz 5       rLS{ rMS|rNg)
LLMHandler0   z(5Hz LM Handler for audio code generation</think>SPACE_IDNpersistent_storage_pathc                 ,   SU l         SU l        SU l        SU l        SU l        SU l        [        R                  U l        SU l	        [        R                  R                  SS5      R                  5       S;   =(       dD    [        [        R                   S5      =(       a    [        R                   R#                  5       (       + U l        Uc  U R&                  (       a  S	nXl        SU l        SU l        SU l        SU l        SU l        SU l        SU l        g)
z)Initialize LLMHandler with default valuesNF   cpuACESTEP_DISABLE_TQDMr!   )1trueyesisattyz/data)llmllm_tokenizerllm_initializedllm_backendmax_model_lendevicetorchfloat32dtypeoffload_to_cpuosenvirongetlowerhasattrr$   stderrr?   disable_tqdmIS_HUGGINGFACE_SPACEr7   constrained_processor_hf_model_for_scoring_lm_full_model_path_last_initialize_config
_mlx_model_mlx_model_pathuse_legacy_cfg_prompt)selfr7   s     r/   __init__LLMHandler.__init__8   s'   !$!]]
#JJNN+A2FLLNRff  fovwz  xB  xB  DL  pM  pe  RU  R\  R\  Rc  Rc  Re  kf #*t/H/H&-#'>$ TX" &*"#' '+$ # &+"r1   returnc                 b    [        [        U SS5      5      R                  S5      S   nU(       a  US;   a  [
        R                  R                  5       (       a  SnO[        [
        S5      (       a&  [
        R                  R                  5       (       a  SnON[        [
        R                  S	5      (       a/  [
        R                  R                  R                  5       (       a  S	nUS:X  a`  [
        R                  R                  5       (       a=  [
        R                  R                  5         [
        R                  R                  5         gUS:X  au  [        [
        S5      (       a`  [
        R                  R                  5       (       a=  [
        R                  R                  5         [
        R                  R                  5         gUS	:X  a  [        [
        R                  S	5      (       a  [
        R                  R                  R                  5       (       a|  [        [
        R                  S
5      (       a  [
        R                  R                  5         [        [
        R                  S5      (       a  [
        R                  R                  5         ggggg! [        [        4 a    Sn GNf = f)a  Release freed accelerator memory back to the driver.

Synchronises the device *before* releasing cached blocks so that
every in-flight async write has landed and the freed blocks are
actually reclaimable.  Supports CUDA, XPU (Intel), and MPS
(Apple Silicon) backends.
rE   r:   :r   N)r:   Nonecudaxpumpssynchronizeempty_cache)strr&   r,   	TypeErrorAttributeErrorrF   r`   is_availablerN   ra   backendsrb   rc   rd   )rY   active_devices     r/   _clear_accelerator_cache#LLMHandler._clear_accelerator_cache[   s   	!h >?EEcJ1MM
  @zz&&(( &&&599+A+A+C+C %//ENN4F4F4S4S4U4U %F"uzz'>'>'@'@JJ""$JJ""$e#u(=(=%))BXBXBZBZII!!#II!!#e#(F(F5>>K]K]KjKjKlKluyy-00		%%'uyy-00		%%' 1 Lm(F#% >* 	! M	!s   (J J.-J.c                     U R                   S:X  aF   [        U R                  S5      (       a  U R                  R                  5         U R                  5         SU l        SU l        SU l        SU l        SU l         SU l	        SU l
        [        R                  " 5         [        R                  R                  5       (       a=  [        R                  R!                  5         [        R                  R#                  5         g[        [        S5      (       a  [        R$                  R&                  R                  5       (       a|  [        [        R&                  S5      (       a  [        R&                  R#                  5         [        [        R&                  S5      (       a  [        R&                  R!                  5         gg[        [        S5      (       aa  [        R(                  R                  5       (       a=  [        R(                  R!                  5         [        R(                  R#                  5         ggg! [         a     GNf = f! [         a     gf = f)	z=Release LM weights/tokenizer and clear caches to free memory.vllmresetNFrb   rc   rd   ra   )rC   rN   r@   ro   	Exception _cleanup_torch_distributed_staterA   rR   rB   rV   rW   gccollectrF   r`   rh   rd   rc   ri   rb   ra   )rY   s    r/   unloadLLMHandler.unload}   s   	6)txx11( 557DH!%D)-D&#(D #D"DO#'D JJLzz&&((

&&(

&&(&&5>>+=+=+J+J+L+L599m44II))+599m44II))+ 5&&599+A+A+C+C		%%'		%%' ,D&' ! ,  		sC   I 5H3 B5I >B<I <A4I 3
I=I  II 
IIc                     SSK Jn  UR                  5       (       a=  UR                  5       (       a'  [        R
                  " S5        UR                  5         ggg! [         a#  n[        R
                  " SU 35         SnAgSnAff = f)zIDestroy default torch distributed process group when already initialized.r   NzM[LLM vLLM] Destroying stale default process group before/after vLLM lifecyclez4[LLM vLLM] Failed to clean torch distributed state: )torch.distributeddistributedrh   is_initializedr
   warningdestroy_process_grouprp   )rY   distexcs      r/   rq   +LLMHandler._cleanup_torch_distributed_state   sv    	Y,  ""t':':'<'<no**, (="  	YNNQRUQVWXX	Ys   AA 
B%BBc                     U R                   (       a*  [        R                  R                  U R                   S5      $ SSKJn  [        U" 5       5      $ )z1Get checkpoint directory via the shared resolver.checkpointsr   )get_checkpoints_dir)r7   rJ   pathjoinacestep.model_downloaderr   re   )rY   r   s     r/   _get_checkpoint_dirLLMHandler._get_checkpoint_dir   s8    ''77<< < <mLL@&())r1   c                    U R                  5       n/ n[        R                  R                  U5      (       a  [        R                  " U5       Hq  n[        R                  R                  X5      n[        R                  R                  U5      (       d  MH  UR                  S5      (       d  M`  UR                  U5        Ms     UR                  5         U$ )zIScan and return all model directory names starting with 'acestep-5Hz-lm-'zacestep-5Hz-lm-)
r   rJ   r   existslistdirr   isdirr(   appendsort)rY   checkpoint_dirmodelsitem	item_paths        r/   get_available_5hz_lm_models&LLMHandler.get_available_5hz_lm_models   s    11377>>.))

>2GGLL>	77==++@Q0R0RMM$' 3
 	r1   
model_pathminimal_gpu	min_ratio	max_ratioc                 X    [         R                  " S5      n[         R                  R                  U5      R                  nUS-  nSnU(       a=  [        X5      u  p[        R                  " SU SU
 SU	S SUS	 S
3	5        US:  a  SnX4$ [         R                  R                  U5      nUS-  nX|-
  nXr:  a  SU-  nSnX:  a  [        U[        X2U-  5      5      n	O[        U[        X=S-  U-  5      5      n	X4$ ! [         a#  n[        R                  " SU 35         SnAgSnAff = f)a  
Get GPU memory utilization ratio based on LM model size and available GPU memory.

Args:
    model_path: LM model path (e.g., "acestep-5Hz-lm-0.6B"). Used to determine target memory.
    minimal_gpu: Minimum GPU memory requirement in GB (fallback)
    min_ratio: Minimum memory utilization ratio
    max_ratio: Maximum memory utilization ratio

Returns:
    Tuple of (gpu_memory_utilization_ratio, low_gpu_memory_mode)
zcuda:0   @Fz%Adaptive LM memory allocation: model=z	, target=z
GB, ratio=.3fz, total_gpu=.1fGB   T      ?g?z,Failed to calculate GPU memory utilization: N)?F)rF   rE   r`   get_device_propertiestotal_memoryr   r
   infomemory_reservedminmaxrp   rz   )rY   r   r   r   r   rE   total_gpu_mem_bytes	total_gpulow_gpu_memory_moderatiotarget_memory_gbreserved_mem_bytesreserved_gpuavailable_gpues                  r/   get_gpu_memory_utilization%LLMHandler.get_gpu_memory_utilization   s`   #	\\(+F"'**"B"B6"J"W"W+g5I"' *A**X'CJ<yYiXjjtuz{~t  @L  MV  WZ  L[  []  ^  _ q=*.'11 "'!;!;F!C-7L%4M&!Io&*#+Is9I6M'NOIs9s7Ji6W'XY-- 	NNI!MN	s   B	C< A/C< <
D)D$$D)target_durationgeneration_phasefallback_maxc                    Ubj  US:  ad  [         n [        5       n[        UR                  [         5      n[        [        [        XA5      5      n[        US-  5      nUS:X  a  US-   nO;US-   nO5[         S-  S-   n	Ub  [        X95      nO[        [        U SS5      S-
  U	5      n[        U S5      (       a  [        XR                  S-
  5      nU$ ! [         a     Nf = f)	a  
Compute max_new_tokens based on target duration and generation phase.

In the two-phase architecture:
- CoT phase: generates metadata (~50-200 tokens) + needs buffer for safety.
- Codes phase: CoT is already in the prompt; only audio codes are generated.
  The constrained decoder forces EOS at exactly target_codes, so only a
  small buffer (10 tokens) is needed to avoid a misleading progress bar.

Duration is clamped to ``[DURATION_MIN, max_dur]`` where *max_dur* is the
GPU-config-dependent maximum (from ``get_global_gpu_config()``) capped at
``DURATION_MAX``.  This keeps the progress-bar total aligned with what the
constrained decoder actually enforces.

Args:
    target_duration: Target duration in seconds (5 codes = 1 second).
    generation_phase: "cot" or "codes".
    fallback_max: Fallback value when target_duration is not set.

Returns:
    Computed max_new_tokens value, capped at model's max length.
r      codes
   i  rD   r9   @   )r   r   r   max_duration_with_lmrp   r   r   intr&   rN   rD   )
rY   r   r   r   gpu_max_durgpu_cfgeffective_durationtarget_codesmax_new_tokensduration_caps
             r/   _compute_max_new_tokens"LLMHandler._compute_max_new_tokens   s    8 &?Q+> 'K/1!'">">M "%\3{3T!U1A56L7* ".!2 ".!3
 (!+c1L'!$\!@!$D/482= " 4)) 1C1Cb1HIN;  s   $C 
CCnegative_promptc                 h    U=(       a*    UR                  5       =(       a    UR                  5       S:g  $ )z:Check if negative prompt is meaningful (not default/empty)NO USER INPUT)strip)rY   r   s     r/   _has_meaningful_negative_prompt*LLMHandler._has_meaningful_negative_prompt1  s*    i?#8#8#:i?T?T?VZi?iir1   repetition_penaltyc                 V    [        5       nUS:w  a  UR                  [        US95        U$ )z=Build logits processor list with repetition penalty if needed      ?penalty)r   r   r   )rY   r   logits_processors      r/   _build_logits_processor"LLMHandler._build_logits_processor5  s.    .0$##$DM_$`ar1   use_constrained_decodingconstrained_decoding_debuguser_metadatastop_at_reasoningskip_genresskip_captionskip_languageis_batchmetadata_temperaturecodes_temperaturec                    U
(       + =(       a    USL=(       d    USLnU(       d  U(       d  gU R                   R                  5         XR                   l        X R                   l        U(       a!  XR                   l        XR                   l        O"SU R                   l        SU R                   l        U R                   R                  U5        U
(       a  U R                   R                  S5        U R                   R                  S5        U R                   R                  S5        U R                   R                  S5        U R                   R                  S5        OU R                   R                  U5        U R                   R                  U5        U R                   R                  U5        U R                   R                  U5        U R                   R                  U5        U R                   R                  U	5        U R                   $ )z8Setup and configure constrained processor for generationNFT)rR   ro   enableddebugr   r   set_target_durationset_user_metadataset_stop_at_reasoningset_skip_genresset_skip_captionset_skip_languageset_generation_phase)rY   r   r   r   r   r   r   r   r   r   r   r   r   use_phase_temperaturess                 r/   _setup_constrained_processor'LLMHandler._setup_constrained_processor<  s     &.!u3Gt3S3tWhptWt'0F 	""((* .F""*+E""( ">R&&;;L&&8>BD&&;;?D&&8""66G &&88>&&<<UC&&66t<&&77=&&88> &&88G&&<<=NO&&66{C&&77E&&88G 	""778HI)))r1   captionlyricscot_textc           
          U(       d  US:X  a  U R                  XUSUS9nOU R                  XSSUS9n[        R                  " SU SU SU< S	U 35        U$ )
zKBuild unconditional prompt for CFG based on generation phase and batch moder   T)is_negative_promptr   cot)r   r   r   z CFG unconditional prompt (phase=z, is_batch=z, negative_prompt=z):
)build_formatted_prompt_with_cotbuild_formatted_promptr
   r   )rY   r   r   r   r   r   r   prompts           r/   _build_unconditional_prompt&LLMHandler._build_unconditional_promptv  s     '7299dTc : F 00D5bq 1 F 	./?.@H: V.1fX?	
 r1   rE   c                 T    [         R                  " USS9U l        U R                  (       d:  U R                  R	                  U5      R	                  U R
                  5      U l        O9U R                  R	                  S5      R	                  U R
                  5      U l        U R                  R                  5         SU l        SU l        [        R                  " SU 35        SU SU 3nSU4$ ! [         a0  nSS	[        U5       S
[        R                  " 5        34s SnA$ SnAff = f)zALoad PyTorch model from path and return (success, status_message)T)trust_remote_coder:   ptz95Hz LM initialized successfully using PyTorch backend on +   ✅ 5Hz LM initialized successfully
Model: z
Backend: PyTorch
Device: F   ❌ Error initializing 5Hz LM: 

Traceback:
N)r   from_pretrainedr@   rI   torH   evalrC   rB   r
   r   rp   re   	traceback
format_exc)rY   r   rE   
status_msgr   s        r/   _load_pytorch_modelLLMHandler._load_pytorch_model  s    	m+;;JZ^_DH&&88;;v.11$**=88;;u-00<HHMMO#D#'D KKSTZS[\]G
|SopvowxJ## 	m;CF8CST]ThThTjSklll	ms   C*C- -
D'7%D"D'"D'logitstop_kc                 p    Ub2  US:  a,  U[         R                  " X5      S   S   :  n[        S5      X'   U$ )zApply top-k filtering to logitsr   ).N-inf)rF   topkfloat)rY   r   r  indices_to_removes       r/   _apply_top_k_filterLLMHandler._apply_top_k_filter  s=     &F)B1)Em)T T(-fF%r1   top_pc                 T   Ub  SUs=:  a  S:  a  O  U$ [         R                  " USS9u  p4[         R                  " [         R                  " UR	                  5       SS9SS9nXR:  nUSSS24   R                  5       USS	S24'   S
US'   UR                  S	XF5      n[	        S5      X'   U$ )z)Apply top-p (nucleus) filtering to logitsN        r   T)
descendingr  dim.   r   ).r   r  )rF   r   cumsumsoftmaxr  clonescatter)rY   r   r
  sorted_logitssorted_indicescumulative_probssorted_indices_to_remover  s           r/   _apply_top_p_filterLLMHandler._apply_top_p_filter  s    u!2s!2  -2JJv$,O)M$||EMM-:M:M:OUW,X^`a'7'?$0Hcrc0R0X0X0Z$S!"W-/0$V, 8 @ @N m(-fF%r1   temperaturec                     US:  aL  UR                  5       U-  n[        R                  " USS9n[        R                  " USS9R	                  S5      $ [        R
                  " USS9$ )zSample tokens from logits with temperature.

Upcasts to float32 for numerical stability (float16 logits can overflow
during softmax, especially after CFG scaling).
r   r  r  r  )num_samples)r  rF   r  multinomialsqueezeargmax)rY   r   r  probss       r/   _sample_tokensLLMHandler._sample_tokens  sZ     ?\\^k1FMM&b1E$$U:BB1EE<<B//r1   tokenseos_token_idpad_token_idc                     [         R                  " X:H  5      (       a  gUb#  X2:w  a  [         R                  " X:H  5      (       a  gg)z3Check if any token in the batch is EOS or pad tokenTF)rF   any)rY   r$  r%  r&  s       r/   _check_eos_tokenLLMHandler._check_eos_token  s:    99V+,,#(Dyy/00r1   rR   c                     UbA  [        UR                  S   5       H$  nUR                  X#   R                  5       5        M&     gg)z8Update constrained processor state with generated tokensNr   )rangeshapeupdate_stater   )rY   rR   r$  bs       r/   #_update_constrained_processor_state.LLMHandler._update_constrained_processor_state  s;     ,6<<?+%2269>>3CD , -r1   modelgenerated_idsmodel_kwargspast_key_values	use_cachec                 \    Uc  U" SSU0UDSU0D6nU$ U" SUSS2SS24   US.UDSU0D6nU$ )z*Perform forward pass with KV cache supportN	input_idsr6  r  )r8  r5   r9  )rY   r2  r3  r4  r5  r6  outputss          r/   _forward_passLLMHandler._forward_pass  sr     " ' $G   '23/ /  $	G r1   formatted_promptsc                 @    [        U[        5      nU(       a  X4$ U/U4$ )zPNormalize batch input: convert single string to list and return (list, is_batch))
isinstancelist)rY   r=  r   s      r/   _normalize_batch_input!LLMHandler._normalize_batch_input  s)    /6$..%&00r1   r   lm_model_pathbackendrI   rH   c           	        ^   US:X  a  [         R                  R                  5       (       a  SnGO|[        [         R                  S5      (       a1  [         R                  R
                  R                  5       (       a  SnGO,[        [         S5      (       a'  [         R                  R                  5       (       a  SnGOSnGOUS:X  a  [         R                  R                  5       (       d  [        [         R                  S5      (       aG  [         R                  R
                  R                  5       (       a  [        R                  " S5        SnGO][        [         S5      (       a=  [         R                  R                  5       (       a  [        R                  " S5        SnGO[        R                  " S5        SnGOUS:X  a  [        [         R                  S5      (       a-  [         R                  R
                  R                  5       (       d  [         R                  R                  5       (       a  [        R                  " S	5        SnGOb[        [         S5      (       a=  [         R                  R                  5       (       a  [        R                  " S
5        SnGO[        R                  " S5        SnOUS:X  a  [        [         S5      (       a#  [         R                  R                  5       (       d  [         R                  R                  5       (       a  [        R                  " S5        SnO}[        [         R                  S5      (       aF  [         R                  R
                  R                  5       (       a  [        R                  " S5        SnO[        R                  " S5        SnX@l	        XPl
        Uc2  US;   a  [         R                  U l        Oy[         R                  U l        OcX`l        US:X  aW  U R                  [         R                  :w  a9  [        R                  " SU R                   S35        [         R                  U l        Uc  Sn[        R                  " SU 35        [        R                   R#                  X5      n[        R                   R%                  U5      (       d  SU 3S4$ Xpl        UUUUUU R                  S.U l        US:X  at  [         R                  R                  5       (       aQ  [*        R,                  " 5         [         R                  R/                  5         [         R                  R1                  5         [        R                  " S5        [2        R2                  " 5       n[4        R6                  " USS9n	[        R                  " S[2        R2                  " 5       U-
  S S35        Xl        [        R                  " S5        [2        R2                  " 5       n
[;        5       nUR<                  n[        R                  " SU S UR>                   S!35        [A        U R8                  SSUS"9U l!        [        R                  " S#[2        R2                  " 5       U
-
  S S35        [        [         RD                  S$5      =(       a    [         RD                  RF                  SLnSnUS:X  a  [         R                  R                  5       (       ad   [         R                  RI                  S%5      RK                  5       m [M        U 4S& jS' 5       5      nU(       a  [        R                  " S(T  S)35        Sn S%SK(nURR                  RU                  S*5      SLnU(       d  [        R                  " S+5        Sn S%SK+nSnU(       d  [        R                  " S,5        [[        U=(       d    U=(       d    U(       + =(       d    U(       + 5      nUS-:X  d  US.:X  a  US:X  a  U R]                  5       (       a  [        R                  " S/5        U R_                  U5      u  nnU(       a  US4$ [        R                  " S0U 35        US-:X  a?  [        R                  " S15        U Ra                  Xt5      u  nnU(       d  US4$ S2U S33nUS4$ OEUS-:X  a?  [        R                  " S45        U Ra                  Xt5      u  nnU(       d  US4$ S5U S33nUS4$ US.:X  a"  US:w  a  [        R                  " S6U S735        S8nSnUS.:X  a'  [c        US99nUb  [        R                  " S:U 35        S8nSnUS.:X  Gah  [e        5         US:X  a
  [g        5       OS;nS;nUS:X  a  [         R                  R                  5       (       a   [        [         R                  S<5      (       a'  [         R                  Ri                  5       u  nnUS=-  nOO[         R                  Rk                  S%5      Rl                  nU[         R                  Ro                  S%5      -
  S=-  n US:X  aW  U[p        :  aM  [        R                  " S>US S?US S@[p         SA35        U Ra                  Xt5      u  nnU(       d  US4$ SBU S33nGO^U Rs                  UUUSC9n[        R                  " SDU 35        URu                  SE5      (       a  [        R                  " SFU 35        URw                  5       S%   nU Rx                  (       d  US:X  ad  U R]                  5       (       aO  [        R                  " SG5        U R_                  U5      u  nnU(       a  US4$ [        R                  " SHU SI35        [        R                  " SJ5        U Ra                  Xt5      u  nnU(       d  US4$ SBU S33nUb  USKU 3-  nO0US-:w  a*  U Ra                  Xt5      u  nnU(       d  US4$ Ub  USKU 3-  nWS4$ ! [N         a     GNf = f! [N         a     GNf = f! [X         a     GNxf = f! [N         a    S;n GNf = f! [N         a0  nSL[{        U5       SM[|        R~                  " 5        3S4s SnA$ SnAff = f)Na  
Initialize 5Hz LM model

Args:
    checkpoint_dir: Checkpoint directory path
    lm_model_path: LM model path (relative to checkpoint_dir)
    backend: Backend type ("vllm" or "pt")
    device: Device type ("auto", "cuda", "mps", "xpu", or "cpu")
    offload_to_cpu: Whether to offload to CPU
    dtype: Data type (if None, auto-detect based on device)

Returns:
    (status_message, success)
autor`   rb   ra   r:   zA[initialize] CUDA requested but unavailable. Falling back to MPS.zA[initialize] CUDA requested but unavailable. Falling back to XPU.zA[initialize] CUDA requested but unavailable. Falling back to CPU.zA[initialize] MPS requested but unavailable. Falling back to CUDA.z@[initialize] MPS requested but unavailable. Falling back to XPU.z@[initialize] MPS requested but unavailable. Falling back to CPU.zA[initialize] XPU requested but unavailable. Falling back to CUDA.z@[initialize] XPU requested but unavailable. Falling back to MPS.z@[initialize] XPU requested but unavailable. Falling back to CPU.N)r`   ra   z([initialize] Overriding requested dtype z to float32 for LM on MPS.zacestep-5Hz-lm-1.7Bz3[initialize] lm_model_path is None, using default: u   ❌ 5Hz LM model not found at F)r   rC  rD  rE   rI   rH   z.loading 5Hz LM tokenizer... it may take 80~90sT)use_fastz(5Hz LM tokenizer loaded successfully in .2f secondsz.Initializing constrained decoding processor...z-Setting constrained decoding max_duration to zs based on GPU config (tier: ))	tokenizerr   r   max_durationz%Constrained processor initialized in hipr   c              3   ,   >#    U  H	  oT;   v   M     g 7fNr9  ).0kdev_names     r/   	<genexpr>(LLMHandler.initialize.<locals>.<genexpr>  s     #W;VaM;Vs   )orinxaviertegrazJetson GPU detected (z-): disabling CUDA graph capture for nano-vllm
flash_attnzflash_attn not installed: disabling CUDA graph capture for nano-vllm (SDPA fallback uses .item() calls in paged-cache decode that are incompatible with CUDA graph capture)z|Triton not available: disabling CUDA graph capture for nano-vllm (CUDA graphs require torch.compile which depends on Triton)mlxrn   z8Attempting MLX backend for Apple Silicon acceleration...zMLX backend failed: zDMLX explicitly requested but failed, falling back to PyTorch backendu:   ✅ 5Hz LM initialized (PyTorch fallback from MLX)
Model: z
Backend: PyTorchz;MLX not available (requires Apple Silicon + mlx-lm package)uD   ✅ 5Hz LM initialized (PyTorch fallback, MLX not available)
Model: zJ[initialize] vllm backend requires CUDA, using PyTorch backend for device=.r   )rE   z[initialize] r  mem_get_infor   z3vLLM disabled due to insufficient free VRAM (total=z	GB, free=z
GB, need>=u,   GB free) — falling back to PyTorch backendu>   ✅ 5Hz LM initialized successfully (PyTorch fallback)
Model: )enforce_eager
has_tritonz5Hz LM status message: u   ❌z4vLLM initialization failed before PyTorch fallback: z)vllm failed on MPS, trying MLX backend...zMLX also failed: z, falling back to PyTorchzFalling back to PyTorch backendz
Note: r   r   )@rF   r`   rh   rN   ri   rb   ra   r
   rz   rE   rI   bfloat16rH   rG   r   rJ   r   r   r   rT   rU   rr   rs   rd   rc   timer   r   rA   r   r   tierr   rR   r+   rM  get_device_namerM   r(  rp   importlib.utilutil	find_spectritonImportErrorbool_is_mlx_available_load_mlx_modelr   r   r0   r   r[  r   r   r   VRAM_SAFE_FREE_GB_initialize_5hz_lm_vllmr(   
splitlinesrB   re   r   r   )!rY   r   rC  rD  rE   rI   rH   full_lm_model_path
start_timerA   processor_start
gpu_configmax_duration_for_constraintis_rocm	is_jetson_has_flash_attn	importlib_has_tritonre  enforce_eager_for_vllmmlx_success
mlx_statussuccessr   vllm_preflight_warningvllm_fallback_notetotal_gbfree_gb
free_bytes_total_bytesr   rR  s!                                   @r/   
initializeLLMHandler.initialize  s
   .	m::**,,#FU^^U338J8J8W8W8Y8Y"FUE**uyy/E/E/G/G"F"F6!%***A*A*C*C5>>511enn6H6H6U6U6W6WNN#fg"FUE**uyy/E/E/G/GNN#fg"FNN#fg"F5'%..%*H*HU^^M_M_MlMlMnMn::**,,NN#fg#FUE**uyy/E/E/G/GNN#ef"FNN#ef"F5'%*?*?EIIDZDZD\D\::**,,NN#fg#FU^^U338J8J8W8W8Y8YNN#ef"FNN#ef"F K"0 }_,!&DJ!&DJ"
U?tzzU]]'BNNB4::,Nhi "'DJ $ 5QR_Q`ab!#n!L77>>"45578J7KLeSS'9$"0!." "0,D( EJJ$;$;$=$=



&&(

&&(KKHIJ)99:LW[\MKKB499;Q[C[\_B``hij!. KKHI"iikO.0J*4*I*I'KKGHcGd  eB  CM  CR  CR  BS  ST  U  V)K,,8	*D& KK?		o@]^a?bbjkl emmU3U8I8IQU8UGIEJJ$;$;$=$=$zz99!<BBDH ##W;V#W WI &;H:Er$st $O%"+..":":<"HPT"T #<
  K" R &*'*hY*hoBU*h]hYh%i" %Gv$5&E/))++KK Z[.2.B.BCU.V+K")4//)=j\'JK"e+"NN+qr262J2JK]2f/GZ#*'15'8 8+fgyfz  {M  *NJ#-t#33 , %NN#`a*.*B*BCU*^'GZ")500#hi{h|  }O  "PJ%t++& Vv%5`ag`hhij %)"& )C6)R&)5NN]3I2J#KL"G!% & *,28F2B,.V#

(?(?(A(A&"5::~>>,1JJ,C,C,EMJ&0G&<G*/***J*J1*M*Z*ZK'2UZZ5O5OPQ5R'RW^&_G V#2C(CNNMhWZ^[delmpdqq{  }N  |O  O{  | +/*B*BCU*^'GZ")500#bcubv  wI  "JJ!%!=!=*&<#. "> "J
 KK"9* FG!,,U33)]^h]i'jk-7-B-B-DQ-G*#33%43I3I3K3K &/Z [:>:N:NOa:b 7Z#.+5t+;$; &1B:,Ng/h i"NN+LM262J2JK]2f/GZ#*'15'8 8+jk}j~  Q  *RJ1= *9K8L.M M
E!&*&>&>?Q&Z#%u,,)5H-C,D"EEJt##y !     B % &"%&V  	m4SVH<LYMaMaMcLdeglll	ms   R4p  8H+p  $A#o p  
!o+ +p  o< B(p  :Ap  	p  ;p  	p  B'p  Ap p  Ap Ap  0Cp  Ap  6p  p  
o($p  'o((p  +
o95p  8o99p  <
p
p  	p

p  pp  pp   
q*%qqqr\  r]  c                 0   [         R                  R                  5       (       d  SU l        [        R
                  " S5        g SSKJnJn   [         R                  R                  5       n[         R                  R                  U5      n[        R                  " 5         [         R                  R                  5         U R                  5         U R!                  USS	S
S9u  pU	(       a  SU l        OSU l        [        R$                  " SU SU SU R"                   SUS 35        Sn
U(       dk  SSKJn  SSKnUR-                  S5      nUR.                  R0                  nUR2                  nSUR.                  l        UR5                  UR6                  5        Sn
 [8        R8                  " 5       nU" UUSU R"                  UU R:                  S9U l        [        R$                  " S[8        R8                  " 5       U-
  S S35        SU l        SU l        SU SU SUS SU	 3U
(       a#  WWR.                  l        WR5                  W5        $ $ ! [         a     SU l        [        R
                  " S5         gf = f! U
(       a#  WWR.                  l        WR5                  W5        f f = f! [@         af  nSU l        S [C        U5      ;   a"  S!n[D        RF                  S":X  a  US#-  nUs SnA$ S$[C        U5       S%[H        RJ                  " 5        3s SnA$ SnAff = f)&a  Initialize 5Hz LM model using vllm backend.

Args:
    model_path: Path to the 5Hz LM model checkpoint.
    enforce_eager: Disable CUDA graph capture.  Set to ``True`` when
        Triton is unavailable so vLLM does not attempt graph capture
        that depends on compiled kernels.
    has_triton: Whether the Triton compiler is available.  When
        ``False``, ``torch._dynamo`` diagnostics are temporarily
        suppressed during initialization to avoid verbose fallback
        warnings, then restored afterwards.
Fz8CUDA/ROCm is not available. Please check your GPU setup.u<   ❌ CUDA/ROCm is not available. Please check your GPU setup.r   )LLMSamplingParamszgnano-vllm is not installed. Please install it using 'cd acestep/third_parts/nano-vllm && pip install .'uk   ❌ nano-vllm is not installed. Please install it using 'cd acestep/third_parts/nano-vllm && pip install .'   皙?r   )r   r   r   r      r9   z Initializing 5Hz LM with model: z, enforce_eager: z*, tensor_parallel_size: 1, max_model_len: z, gpu_memory_utilization: r   Nztorch._dynamoTr  )r2  r\  tensor_parallel_sizerD   gpu_memory_utilizationrK  z#5Hz LM initialized successfully in rH  rI  rn   r   z	
Device: z
GPU Memory Utilization: z
Low GPU Memory Mode: z)Cannot find a working triton installationu8   ❌ vLLM backend requires a working Triton installation.win32z[ Falling back to PyTorch is recommended on Windows. Use --backend pt to avoid this warning.r   r   )&rF   r`   rh   rB   r
   errornanovllmr  r  rf  current_devicera  rr   rs   rd   rq   r   rD   r   torch._dynamo_dynamologging	getLoggerconfigsuppress_errorslevelsetLevelERRORr_  rA   r@   rC   rp   re   r$   r'   r   r   )rY   r   r\  r]  r  r  r  device_namer  r   _dynamo_state_savedr  _logging_dynamo_logger_prev_suppress_prev_log_levelrn  r   r   s                      r/   rk  "LLMHandler._initialize_5hz_lm_vllm  s1    zz&&((#(D LLSTQ	A4E	f"ZZ668N**44^DKJJLJJ""$113 ;?:Y:Y%	 ;Z ;7" #%)"%)"KK::,FWXeWf  gQ  RV  Rd  Rd  Qe  e  @V  WZ  [  \  ] #(/*!)!3!3O!D!(!?!?"0"6"615.''7&*#=!YY[
$"/)*"&"4"4+A"00 A$))+PZBZ[^A__ghi'+$#) Ej\Q[\g[h  iC  DZ  [^  C_  _v  wJ  vK  L&5CGNN2"++O< '{  	A#(D LL  C  D A	Az '5CGNN2"++O< '  
	f#(D :c!fDW
<<7*BJ "!4SVH<LYMaMaMcLdee
	fsV   I	 EJ% BI6 )J% 	'I32I36,J""J% %
L/2L!L'#L
LL	cfg_scaleseedsc                    SSK Jn  U R                  U5      u  nn[        U5      nU(       + =(       a    U
SL=(       d    USLnU(       a  SOUnU R	                  U=(       d    UU	UUUUUUUUU
US9nU R                  UUU R                  S-
  S9nU" UUUUUUUU(       a  UR                  OSS9nUS:  a6  U R                  UUUUUUS	9n U /U-  n!U R                  R                  UUU!S
9n"OU R                  R                  UU5      n"/ n#U" H  n$[        U$S5      (       aC  [        U$R                  5      S:  a*  U#R                  U$R                  S   R                  5        MW  [        U$S5      (       a  U#R                  U$R                  5        M  [        U$[         5      (       a  SU$;   a  U#R                  U$S   5        M  U#R                  [#        U$5      5        M     U(       d  U#S   $ U#$ )z
Unified vllm generation function supporting both single and batch modes.
Accepts either a single formatted prompt (str) or a list of formatted prompts (List[str]).
Returns a single string for single mode, or a list of strings for batch mode.
r   )r  Nr   )r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   )
max_tokensr  r  r  r
  r   r   logits_processor_update_stater   r   r   r   r   r   )unconditional_promptsr:  text)r  r  rA  lenr   r   rD   r.  r   r@   generaterN   r:  r   r  r?  dictre   )%rY   r=  r  r  r   r  r
  r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  formatted_prompt_listr   
batch_sizer   effective_sampler_temprR   r  sampling_paramsformatted_unconditional_promptr  r:  output_textsoutputs%                                        r/   	_run_vllmLLMHandler._run_vllmj  s'   < 	, +/*E*EFW*X'x./

 &.!u3Gt3S3tWhptWt(>K !% A A%=%WAW'A+'/#%'-!5/ !B !
  11+-++b0 2 

 )!.12Pe*?*L*Lko	
 s?-1-M-M! /!1! .N .* &D$Dz$Q!hh''%&; ( G hh''(=OG Fvy))c&...AA.E##FNN1$5$:$:;((##FKK0FD))f.>##F6N3##CK0  '/|A@L@r1   formatted_promptc                    U R                  USSSS9nU R                  UU	U
UUUUUUSS9
nU R                  5          UR                  5        VVs0 s H"  u  nnUUR	                  U R
                  5      _M$     nnnU R                  U
U[        U R                  R                  SS5      S9nU R                  U5      nUS	:  Ga	  U R                  UUUUUSS
9nUU/nU R                   R                  nSU R                   l        U R                  USSSS9nUU R                   l        UR                  5        VVs0 s H"  u  nnUUR	                  U R
                  5      _M$     nnnUS   nUR                  SS5      nU R                  UUUUUUUUU R                   R                  =(       d    U R                   R                   SUS9n U SS n GOU(       a\  U R#                  US   UR                  S5      UUUUUU R                   R                  =(       d    U R                   R                   SUS9
n O[$        R&                  " 5          U R                  R(                  " S0 UDUUS:  a  UOS	US:  a  SOSUb  US:  a  UOSUb  SUs=:  a  S	:  a  O  OUOS[+        U5      S:  a  UOSU R                   R                  =(       d    U R                   R                   SS.D6n SSS5        SSS5        [-        W [$        R.                  5      (       a  U R1                  5       S:X  a  U S   n!OU n!OU S   n!US	:  a  WS   R2                  S   n"OUS   R2                  S   n"U!U"S n!U!R
                  R4                  S:w  a  U!R7                  5       n!U R                   R9                  U!SS9n#U#$ s  snnf s  snnf ! , (       d  f       N= f! , (       d  f       N= f)z<Internal helper function for single-item PyTorch generation.r   FTreturn_tensorspadding
truncation
r   r   r   r   r   r   r   r   r   r   r   r9   r  r   r  leftr8  attention_maskN)batch_input_idsbatch_attention_maskr   r  r  r  r
  r   r&  streamerrR   r   r  )
r8  r  r   r  r  r
  r   r&  r  rR   r  )r   r  	do_sampler  r
  r   r&  r  r"   r:   skip_special_tokensr9  )rA   r   _load_model_contextitemsr   rE   r   r&   r@   r  r   r   padding_siderL   _generate_with_cfg_customr&  r%  #_generate_with_constrained_decodingrF   inference_moder  r  r?  Tensorr  r-  typer:   decode)$rY   r  r  r  r   r  r
  r   r   r   r   r   r   r   r   r   r   r   r   r   inputsrR   rQ  r.   r   r   r  batch_textsoriginal_padding_sidebatch_inputs_tokenizedr  r  r:  r3  input_lengthoutput_texts$                                       r/   _run_pt_singleLLMHandler._run_pt_single  s    . ##	 $ 
 !% A A%='A+'/#%'- !B !
 %%'7=||~F~tq!adkk**~FF "99 /!1$TXX__6FM : N  $;;<NO3151Q1Q#!%$3%5" 2R 2.  01OP(,(:(:(G(G%28""/)-););#' #	 *< *& 3H""/KaKgKgKi)jKi41a!QTT$++->*>Ki&)j #9"E'='A'ABRTX'Y$ 88$3)=#1 +''9!%!3!3!@!@!cDDVDVDcDc!*? 9  "!A,)BB$[1#)::.>#?#1 +'9!%!3!3!@!@!cDDVDVDcDc!*? C  ))+"hh// 
 
'53>?K*5/$u','8UQYeD','8S5=N3=NeTX=@AQ=RUV=V)9\`%)%7%7%D%D%gHZHZHgHg!%
G ,W (t gu||,,{{}! '
 '#AJM s? 2+>DDQGL!+.44Q7L%lm4 $$-)--/M((//SX/Yc GF *kN ,+W ('sD   O)N%8C O8)N+!C#OBN1O%O1
N?	;O
Oc                 <   U R                  U5      u  nnU(       GaI  / nU R                  5          [        U5       GH  u  nnU(       a  U[        U5      :  a  [        R
                  " UU   5        [        R                  R                  5       (       a#  [        R                  R                  UU   5        On[        [        R                  S5      (       aO  [        R                  R                  R                  5       (       a"  [        R                  R                  UU   5        U R                  UUUUUUUUU	U
SSSSSUUUUS9nUR                  U5        GM     SSS5        U$ US   nU R                  UUUUUUUUU	U
UUUUUUUUUS9$ ! , (       d  f       U$ = f)a\  
Unified PyTorch generation function supporting both single and batch modes.
Accepts either a single formatted prompt (str) or a list of formatted prompts (List[str]).
Returns a single string for single mode, or a list of strings for batch mode.
Note: PyTorch backend processes batch items sequentially (doesn't support true batching efficiently).
rb   NFTr  r  r  r   r  r
  r   r   r   r   r   r   r   r   r   r   r   r   r   r   )rA  r  	enumerater  rF   manual_seedr`   rh   manual_seed_allrN   ri   rb   r  r   )rY   r=  r  r  r   r  r
  r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r   r  ir  r  s                              r/   _run_ptLLMHandler._run_pty  s   < +/*E*EFW*X'x
 L))++45J+K'A'SZ))%(3 ::2244!JJ66uQx@$U^^U;;@R@R@_@_@a@a!II11%(; #'"5"5)9$/"+(7##+=1I3M(7&**/$(%)&*)9 '%!)' #6 #K, !''4A ,L ,F   13""-#+1%='A+'/#%'-' # 
 	
Q ,+F  s   D-F
Fc                 >    Uc  gSU;   a  SU;   a  SU;   a  SU;   a  gg)z+Check if all required metadata are present.FbpmkeyscaletimesignaturedurationTr9  )rY   r   s     r/   has_all_metasLLMHandler.has_all_metas  s9     M!jM&AoYfFfku  zG  lGr1   metadatac                    0 nS H~  nX1;   d  M
  X   c  M  X   nUS:X  a*  UR                  S5      (       a  UR                  S5      S   n[        U[        5      (       a   UR	                  5       (       a  [        U5      nXBU'   M     [        U5      S:  a%  [        R                  " USSS9R                  5       nOSnS	U S
3$ )a+  
        Format parsed metadata as CoT text using YAML format (matching training format).

        Args:
            metadata: Dictionary with keys: bpm, caption, duration, keyscale, language, timesignature

        Returns:
            Formatted CoT text: "<think>
{yaml_content}
</think>"
        )r  r   r  r  languager  r  z/4/r   T)allow_unicode	sort_keysr!   z<think>
z	
</think>)
endswithr,   r?  re   isdigitr   r  yamldumpr   )rY   r  	cot_itemskeyvaluecot_yamls         r/   _format_metadata_as_cot"LLMHandler._format_metadata_as_cot  s     	ZC8=#< /)ennT.B.B!KK,Q/EeS))emmooJE!&# [ y>Ayy$$OUUWHH8*J//r1   
infer_typeuse_cot_metasuse_cot_captionuse_cot_languager  c                 0   Uc  S nU=(       d    SR                  5       R                  5       nUS;  a/  SU< S3nU(       a  US:  a  / O0 U(       a  US:  a  / OSSUS	0 0S
.$ U=(       a    US:  nU(       a  UOSn0 nSnU R                  U5      nSnSnU(       a  Uc1  [        U5       Vs/ s H  n[        R
                  " SS5      PM     nnO^[        U5      U:  aJ  [        U5      [        U[        U5      -
  5       Vs/ s H  n[        R
                  " SS5      PM     sn-   nOUSU nU" SS5        U(       Gdk  U(       Gac  U(       a  [        R                  " S5        O[        R                  " S5        [        R                  " 5       nU R                  XSS9n[        R                  " SU 35        U R                  UUSUUUU	SUU(       + U(       + SSUUS.U
USS9u  nn [        R                  " 5       U-
  nU(       d  U(       a  / O0 U(       a  / OSSU S	SU00S
.$ U R                  U5      u  nnU(       a5  [        R                  " SUS S[        UR                  5       5       35        O[        R                  " SUS S[        UR                  5       5       35        O_U(       a  [        R                  " S5        O[        R                  " S5        UR                  5        V!V"s0 s H  u  n!n"U"c  M  U!U"_M     nn!n"Ub  US::  aG  UR!                  S 5      (       a1   [#        US    5      n#U#S:  a  U#n[        R                  " S!U# S"35        US#:X  aN  U(       a:  [        U5       Vs/ s H  nUR)                  5       PM     n$nU$S/U-  SSS	UUS$.0S
.$ USSSS	UUS$.0S
.$ U(       a  [        R                  " S%U S&35        O[        R                  " S'5        [        R                  " 5       n%U R+                  U5      n&U R-                  XU&5      n'[        R                  " S(U' 35        U" S)S*U S&35        U(       Gak  U'/U-  n( U R.                  S+:X  a  U R1                  U(UUUUUU	U
UUS,UUU&US-9n)OLU R.                  S.:X  a  U R3                  U(UUUUUU	U
UUS,UUU&US-9n)OU R5                  U(UUUUUU	U
UUS,UUU&US-9n) U R=                  5         / n+/ n$U) HG  n,U R                  U,5      u  nn-U+R?                  U-5        U$R?                  UR)                  5       5        MI     [        R                  " 5       U%-
  nU+ V.s/ s H)  n.U.(       a  [        U.RA                  S15      5      S-
  OSPM+     n/n.[        R                  " S2US S3U/ 35        UU-   n0U$U+SSUUU0S0.U/[C        U/5      S4.S
.$ U R                  U'UUUUUU	USSSS,UUU&S5.U
USS9u  n1n U1(       d  UU-   n0USSU S	UUU0S0.0S
.$ [        R                  " 5       U%-
  nU R                  U15      u  nnU(       a  [        URA                  S15      5      S-
  OSn2[        R                  " S6US S7U2 S835        UU-   n0UUSSUUU0S0.U2S9.S
.$ s  snf s  snf s  sn"n!f ! [$        [&        4 a     GNCf = fs  snf ! [6         aL  n*S/[9        U*5       3n[        R:                  " U5        / / SUS	USUS0.0S
.s Sn*A*U R=                  5         $ Sn*A*ff = f! U R=                  5         f = fs  sn.f ):aM  Two-phase LM generation: CoT generation followed by audio codes generation.

- infer_type='dit': Phase 1 only - generate CoT and return metas (no audio codes)
- infer_type='llm_dit': Phase 1 + Phase 2 - generate CoT then audio codes

Args:
    target_duration: Target duration in seconds for codes generation constraint.
                    5 codes = 1 second. If specified, blocks EOS until target reached.
    user_metadata: User-provided metadata fields (e.g. bpm/duration/keyscale/timesignature).
                   If specified, constrained decoding will inject these values directly.
    use_cot_caption: Whether to generate caption in CoT (default True).
    use_cot_language: Whether to generate language in CoT (default True).
    batch_size: Optional batch size for batch generation. If None or 1, returns single result.
               If > 1, returns batch results (lists).
    seeds: Optional list of seeds for batch generation (for reproducibility).
          Only used when batch_size > 1. TODO: not used yet

Returns:
    Dictionary containing:
        - metadata: Dict or List[Dict] - Generated metadata
        - audio_codes: str or List[str] - Generated audio codes
        - success: bool - Whether generation succeeded
        - error: Optional[str] - Error message if failed
        - extra_outputs: Dict with time_costs and other info
Nc                      g rO  r9  )argskwargss     r/   progress9LLMHandler.generate_with_stop_condition.<locals>.progress2  s    r1   r!   >   ditllm_ditzinvalid infer_type: z (expected 'dit' or 'llm_dit')r  F
time_costs)r  audio_codesrz  r  extra_outputsr  r   l    r  z8Phase 1: Generating CoT metadata (once for all items)...z>Batch Phase 1: Generating CoT metadata (once for all items)...z#Phase 1: Generating CoT metadata...r   )r   z/generate_with_stop_condition: formatted_prompt=r   T)r  r  r   r  r
  r   r   r   r   r   r   r   r   r   r  cfgr   r   r   phase1_timezBatch Phase 1 completed in rH  zs. Generated metadata: zPhase 1 completed in zABatch Phase 1: Using user-provided metadata (skipping generation)z;Phase 1: Using user-provided metadata (skipping generation)r  zUsing CoT-generated duration (z7s) as Phase 2 target_duration (original was None/unset)r  )r  
total_timez*Batch Phase 2: Generating audio codes for z	 items...z"Phase 2: Generating audio codes...z8generate_with_stop_condition: formatted_prompt_with_cot=r   z$Phase 2: Generating audio codes for rn   r   )r=  r  r  r   r  r
  r   r   r   r   r   r   r   r   r  rY  z!Error in batch codes generation: )r  phase2_timer  <|audio_code_zBatch Phase 2 completed in zs. Generated codes: )r   codes_countstotal_codes)r  r  r   r  r
  r   r   r   r   r   r   r   r   r   zPhase 2 completed in zs. Generated z audio codes)r   codes_count)"r   rM   r  r,  randomrandintr  r@  r
   r   r_  r   generate_from_formatted_promptparse_lm_outputkeysr  rL   r  
ValueErrorrf   copyr  r   rC   r  _run_mlxr  rp   re   r  rk   r   r,   sum)3rY   r   r   r  r  r  r   r  r
  r   r   r   r   r   r  r  r  r  r  r  	error_msgr   actual_batch_sizer  r  r  r  r  r  phase1_startr  cot_output_textstatusrQ  r.   cot_durationmetadata_listphase2_startr   formatted_prompt_with_cotr=  codes_outputsr   audio_codes_listr  audio_codes_itemr   r	  r  codes_output_textr  s3                                                      r/   generate_with_stop_condition'LLMHandler.generate_with_stop_condition  sf   ^  !&B--/557
//.zn<Z[I#-*q.Br&0Z!^r" "".!3  0*q.*2J **=9 }?DEV?WX?W!95?WXU//UUSdgjkpgqSqMr&sMrv~~a'CMr&ss001 	PR\]AB99;L  $::7]b:cKKIJZI[\]&*&I&I!1#. "%'6""*<'+%2(7$7)9%9#'(-&$%( *B+E"&1 'J '#OV6 ))+4K"&.B)12r$#&2]K4P%Q  ..?KHa9+c9JJabfgogtgtgvbwaxyz3K3DD[\`aiananap\q[rst _`YZ)6)<)<)>P)>A!1)>HP #!';jAYAY	$Xj%9:!#&2OKK8 GL M :?@Q:R S:RQ:R S -$&4*;#;#!$+6*5'&  !)#%#!$+6*5'&  KKDEVDWW`abKK<=yy{ //9 %)$H$HZb$c!NOhNijk<=N<OyYZ!: ;>O OH0##v-$(NN*;$/"+(7##+=1I3M(7)0 '%!)# %3 %M" %%.$(MM*;$/"+(7##+=1I3M(7)0 '%!)# %2 %M$ %)LL*;$/"+(7##+=1I3M(7)0 '%!)# %1 %MD --/  "M,&*&:&:;&G## ''(89$$X]]_5  -
 ))+4K `pp_oV[UCO <=APQQ_oLpKK5k#5FFZ[gZhij${2J)/ (3'2&0#
 %1#&|#4" " )-(K(K!:#.!*'6""*<'6%)$(%)(/&$ (" *B+E"'+ )L )%v0 %(;6
 (#%$#$+6+6*4'&  ))+4K "112CDNA{IT#k//@AAEZ[KKK/C/@k]Zfgh${2J$* (3'2&0#
 $/" O	 Y&sJ Q  	*  !TL  ?AxH	Y' "#%$&$+6+.*5'&  --/#" --/ qs   ,!Y9!Y>1
Z?Z)0Z	 3Z -Z% ?[>  -Z% -[> .Z% [> 	0\	ZZ%
[;/1[6 [;![> 6[;;[> >\r   c                    U R                   c  [        S5      eU(       a2  U R                  U5      nUS:X  a  U(       a
  SU SU S3nOSU S3nOUnO	SU SU S3nU R                   R                  SS[         S	3S
.SUS
./SSS9$ )a  
Build the chat-formatted prompt for 5Hz LM from caption/lyrics.
Raises a ValueError if the tokenizer is not initialized.

Args:
    caption: Caption text
    lyrics: Lyrics text
    is_negative_prompt: If True, builds unconditional prompt for CFG
    generation_phase: "cot" or "codes" - affects unconditional prompt format
    negative_prompt: Negative prompt for CFG (used when is_negative_prompt=True)

Example:
    prompt = handler.build_formatted_prompt("calm piano", "hello world")
:LLM tokenizer is not initialized. Call initialize() first.r   
# Caption



# Lyric

z# Lyric
system# Instruction


rolecontentuserFTtokenizeadd_generation_prompt)rA   r  r   apply_chat_templater   )rY   r   r   r   r   r   has_negative_promptr   s           r/   r   !LLMHandler.build_formatted_prompt  s     %YZZ #'"F"F"W5(&*?*;=PRSF  )3F ! #7)=CF!!55!@V?WW[.\]F3 "& 6 
 	
r1   c                    U R                   c  [        S5      eU R                  (       ag  U(       a  U R                  U5      nSnU(       a  UOUnOUnUnSU SU S3n	U R                   R	                  SS[
         S3S	.S
U	S	./SSS9n
XS-   -  n
U
$ U(       a  U R                  U5      nSnU(       a  UOSn	OUnSU SU S3n	U R                   R	                  SS[
         S3S	.S
U	S	./SSS9n
XS-   -  n
U
$ )a>  
Build the chat-formatted prompt for codes generation phase with pre-generated CoT.

Args:
    caption: Caption text
    lyrics: Lyrics text
    cot_text: Pre-generated CoT text (e.g., "<think>\nbpm: 120\n...\n</think>")
    is_negative_prompt: If True, uses empty CoT for CFG unconditional prompt
    negative_prompt: Negative prompt for CFG (used when is_negative_prompt=True)

Returns:
    Formatted prompt string

Example:
    cot = "<think>\nbpm: 120\ncaption: calm piano\n...\n</think>"
    prompt = handler.build_formatted_prompt_with_cot("calm piano", "hello", cot)
r%  z<think>

</think>r&  r'  r(  r)  r*  r+  r,  r/  FTr0  r   )rA   r  rX   r   r3  r   )rY   r   r   r   r   r   r4  cot_for_promptcaption_for_promptuser_prompt	formatteds              r/   r   *LLMHandler.build_formatted_prompt_with_cot  s^   $ %YZZ%% "&*&J&J?&[#!68K_QX"!)%,"'(:';=PRSK**>>%ODZC[[_2`a#< &* ? I &00I #'"F"F"W2N-@/oK%N'yfXRHK &&::!@V?WW[.\]K8 "& ; 
	 	f,,	r1   r  c                     U R                   c  [        S5      eU(       a!  U(       a  UR                  5       (       a  UOSnOUnU R                   R                  SS[         S3S.SUS./SS	S
9$ )a;  
Build the chat-formatted prompt for audio understanding from codes.

This is the reverse of generation: given audio codes, generate metadata and lyrics.

Args:
    audio_codes: Audio code string (e.g., "<|audio_code_123|><|audio_code_456|>...")
    is_negative_prompt: If True, builds unconditional prompt for CFG
    negative_prompt: Negative prompt for CFG (used when is_negative_prompt=True)

Returns:
    Formatted prompt string

Example:
    codes = "<|audio_code_18953|><|audio_code_13833|>..."
    prompt = handler.build_formatted_prompt_for_understanding(codes)
r%  r!   r)  r*  r+  r,  r/  FTr0  )rA   r  r   r3  r   )rY   r  r   r   user_contents        r/   (build_formatted_prompt_for_understanding3LLMHandler.build_formatted_prompt_for_understanding
  s    . %YZZ .=/BWBWBYBY?_aL&L!!55 %!01R0SSWX
 #+	 "& 6 
 	
r1   c                    [        U SS5      (       d  0 S4$ U(       a  UR                  5       (       d  0 S4$ [        R                  " S[	        U5       S35        U R                  U5      n[        SU 35        U R                  UUUUUSSSSSS	S
S
S.UUSS9u  pU	(       d  0 U
4$ U R                  U	5      u  pU R                  U	5      nU(       a  XS'   [        R                  " S[	        U5       S35        U(       aM  [        R                  " S[        UR                  5       5       35        [        R                  " SU	SS  S35        SSR                  UR                  5       5       3nX4$ )a!  
Understand audio codes and generate metadata + lyrics.

This is the reverse of the normal generation flow:
- Input: Audio codes
- Output: Metadata (bpm, caption, duration, etc.) + Lyrics

Note: cfg_scale and negative_prompt are not supported in understand mode.

Args:
    audio_codes: String of audio code tokens (e.g., "<|audio_code_123|><|audio_code_456|>...")
    temperature: Sampling temperature for generation
    top_k: Top-K sampling (None = disabled)
    top_p: Top-P (nucleus) sampling (None = disabled)
    repetition_penalty: Repetition penalty (1.0 = no penalty)
    use_constrained_decoding: Whether to use FSM-based constrained decoding for metadata
    constrained_decoding_debug: Whether to enable debug logging for constrained decoding

Returns:
    Tuple of (metadata_dict, status_message)
    metadata_dict contains:
        - bpm: int or str
        - caption: str
        - duration: int or str
        - keyscale: str
        - language: str
        - timesignature: str
        - lyrics: str (extracted from output after </think>)

Example:
    codes = "<|audio_code_18953|><|audio_code_13833|>..."
    metadata, status = handler.understand_audio_from_codes(codes)
    print(metadata['caption'])  # "A cinematic orchestral piece..."
    print(metadata['lyrics'])   # "[Intro: ...]\n..."
rB   F7   ❌ 5Hz LM not initialized. Please initialize it first.u<   ❌ No audio codes provided. Please paste audio codes first.z#Understanding audio codes (length: z chars)zformatted_prompt: N
understandr!   r  r  r
  r   r   r   r   r   r   r   r   r   r  r   z#Understanding completed. Generated z metadata fieldsGenerated metadata: Output text preview:    ...u;   ✅ Understanding completed successfully
Generated fields: , )r&   r   r
   r   r  r>  printr  r  _extract_lyrics_from_outputr   r@  r  r   )rY   r  r  r  r
  r   r   r   r  r  r  r  r  r   r   s                  r/   understand_audio_from_codes&LLMHandler.understand_audio_from_codes:  s   Z t.66PPP+"3"3"5"5UUU9#k:J9K7ST  HHU"#3"456 #AA-*&8#'!% %!&$$0 &>'A#' B 
, v: **;7 11+>!'X9#h-HXYZ%LL/X]]_0E/FGHLL0Tc1B0C3GHSTXT]T]^f^k^k^mTnSop
##r1   r  c                    SSK nSnUR                  X15      nU(       d  gXR                  5       S R                  5       nU(       d  gSnUR	                  USXRR
                  S9nUR	                  SSU5      nUR                  5       $ )a  
Extract lyrics section from LLM output.

The lyrics appear after the </think> tag and typically start with "# Lyric"
or directly with lyric content.

Args:
    output_text: Full LLM output text

Returns:
    Extracted lyrics string, or empty string if no lyrics found
r   Nr5   r!   z^#\s*Lyri[c|cs]?\s*\n)flagsz<\|im_end\|>\s*$)researchendr   sub
IGNORECASE)rY   r  rO  think_end_patternmatchafter_thinklyric_header_patterns          r/   rJ  &LLMHandler._extract_lyrics_from_output  s     	 (		+9 "))+,/557  8ff12{--fX ff0"kB  ""r1   queryinstrumentalc                     U R                   c  [        S5      eU(       a  SOSnU(       a!  U(       a  UR                  5       (       a  UOSnOU SU 3nU R                   R                  SS[         S3S	.S
US	./SSS9$ )a  
Build the chat-formatted prompt for inspiration/simple mode.

This generates a complete sample (caption, lyrics, metadata) from a user's
natural language music description query.

Args:
    query: User's natural language music description
    instrumental: Whether to generate instrumental music (no vocals)
    is_negative_prompt: If True, builds unconditional prompt for CFG
    negative_prompt: Negative prompt for CFG (used when is_negative_prompt=True)

Returns:
    Formatted prompt string

Example:
    query = "a soft Bengali love song for a quiet evening"
    prompt = handler.build_formatted_prompt_for_inspiration(query, instrumental=False)
r%  r=   falser!   z

instrumental: r)  r*  r+  r,  r/  FTr0  )rA   r  r   r3  r   )rY   rY  rZ  r   r   instrumental_strr=  s          r/   &build_formatted_prompt_for_inspiration1LLMHandler.build_formatted_prompt_for_inspiration  s    4 %YZZ &26w.=/BWBWBYBY?_aL $W$67G6HIL!!55 %!01P0QQUV
 #+	 "& 6 
 	
r1   vocal_languagec
                    [        U SS5      (       d  0 S4$ U(       a  UR                  5       (       d  Sn[        R                  " SUSS  SU S	U S
35        U R	                  UUS9n
[        R
                  " SU
 35        SnSnU(       ap  UR                  5       (       a[  UR                  5       R                  5       S:w  a9  SUR                  5       0n[        R                  " SUR                  5        35        U R                  U
UUUUSUSSSSSSS.UU	SS9u  pU(       d  0 U4$ U R                  U5      u  nnU R                  U5      nU(       a  UUS'   OU(       a  SUS'   X/S'   [        R                  " SU S35        U	(       aM  [        R
                  " S[        UR                  5       5       35        [        R
                  " SUSS  S35        SU 3nUU4$ )a  
Create a complete music sample from a user's natural language query.

This is the "Simple Mode" / "Inspiration Mode" feature that generates:
- Metadata (bpm, caption, duration, keyscale, language, timesignature)
- Lyrics (unless instrumental=True)

Args:
    query: User's natural language music description
    instrumental: Whether to generate instrumental music (no vocals)
    vocal_language: Allowed vocal language for constrained decoding (e.g., "en", "zh").
                   If provided and not "unknown", it will be used.
    temperature: Sampling temperature for generation (0.0-2.0)
    top_k: Top-K sampling (None = disabled)
    top_p: Top-P (nucleus) sampling (None = disabled)
    repetition_penalty: Repetition penalty (1.0 = no penalty)
    use_constrained_decoding: Whether to use FSM-based constrained decoding
    constrained_decoding_debug: Whether to enable debug logging

Returns:
    Tuple of (metadata_dict, status_message)
    metadata_dict contains:
        - bpm: int or str
        - caption: str
        - duration: int or str
        - keyscale: str
        - language: str
        - timesignature: str
        - lyrics: str (extracted from output after </think>)
        - instrumental: bool (echoed back)

Example:
    query = "a soft Bengali love song for a quiet evening"
    metadata, status = handler.create_sample_from_query(query, instrumental=False, vocal_language="bn")
    print(metadata['caption'])  # "A gentle romantic acoustic pop ballad..."
    print(metadata['lyrics'])   # "[Intro: ...]\n..."
rB   FrA  r   zCreating sample from query: Nd   z... (instrumental=z, vocal_language=rJ  )rY  rZ  z"Formatted prompt for inspiration: unknownr  zUsing user-specified language: rB  r!   rC  r  r   [Instrumental]rZ  z'Sample created successfully. Generated  fieldsrD  rE  ,  rG  u2   ✅ Sample created successfully
Generated fields: )r&   r   r
   r   r^  r   rM   r  r  rJ  r@  r  )rY   rY  rZ  r`  r  r  r
  r   r   r   r  r   r   r  r  r  r  r   r   s                      r/   create_sample_from_query#LLMHandler.create_sample_from_query  s*   b t.66PPPEKKMM#E25#;-?QR^Q__pq  qA  AB  C  	D  FF% G 
 	9:J9KLM n22449M9M9O9U9U9W[d9d')=)=)?@MKK9.:N:N:P9QRS
 #AA-*&8#'!. %!&$$0 &>'A#% B 
* v: **;7! 11+>!'HX!1HX $0 =hZwOP%LL/X]]_0E/FGHLL0Tc1B0C3GHJ8*U
##r1   c                     U R                   c  [        S5      eU(       a!  U(       a  UR                  5       (       a  UOSnOSU SU 3nU R                   R                  SS[         S3S.S	US./S
SS9$ )ap  
Build the chat-formatted prompt for format/rewrite mode.

This formats user-provided caption and lyrics into a more detailed and specific
musical description with metadata.

Args:
    caption: User's caption/description of the music
    lyrics: User's lyrics
    is_negative_prompt: If True, builds unconditional prompt for CFG
    negative_prompt: Negative prompt for CFG (used when is_negative_prompt=True)

Returns:
    Formatted prompt string

Example:
    caption = "Latin pop, reggaeton, flamenco-pop"
    lyrics = "[Verse 1]\nTengo un nudo..."
    prompt = handler.build_formatted_prompt_for_format(caption, lyrics)
r%  r!   r&  r'  r)  r*  r+  r,  r/  FTr0  )rA   r  r   r3  r   )rY   r   r   r   r   r=  s         r/   !build_formatted_prompt_for_format,LLMHandler.build_formatted_prompt_for_formatt  s    6 %YZZ.=/BWBWBYBY?_aL )	vhGL!!55 %!01O0PPTU
 #+	 "& 6 
 	
r1   c
                    [        U SS5      (       d  0 S4$ U(       a  UR                  5       (       d  SnU(       a  UR                  5       (       d  Sn[        R                  " SUSS  S	[	        U5       35        U R                  UUS
9n
[        R                  " SU
 35        SnU(       a  0 nUR                  S5      b   [        US   5      nUS:  a  XS'   UR                  S5      b   [        US   5      nUS:  a  XS'   UR                  S5      (       a  US   US'   UR                  S5      (       a  US   US'   UR                  S5      (       a  US   US'   U(       d  SnO[        R                  " SU 35        U R                  U
UUUUSUSU(       a  UR                  S5      SLOSSSSSS.UU	SS9u  pU(       d  0 U4$ U R                  U5      u  nnU R                  U5      nU(       a  UUS'   OUUS'   [        R                  " SU S35        U	(       aM  [        R                  " S[        UR                  5       5       35        [        R                  " SUSS  S35        SSR!                  UR                  5       5       3nUU4$ ! [        [        4 a     GNf = f! [        [        4 a     GNf = f) ac  
Format user-provided caption and lyrics into structured music metadata.

This is the "Format" feature that takes user input and generates:
- Enhanced caption with detailed music description
- Metadata (bpm, duration, keyscale, language, timesignature)
- Formatted lyrics (preserved from input)

Note: cfg_scale and negative_prompt are not supported in format mode.

Args:
    caption: User's caption/description (e.g., "Latin pop, reggaeton")
    lyrics: User's lyrics with structure tags
    user_metadata: Optional dict with user-provided metadata to constrain decoding.
                  Supported keys: bpm, duration, keyscale, timesignature, language
    temperature: Sampling temperature for generation (0.0-2.0)
    top_k: Top-K sampling (None = disabled)
    top_p: Top-P (nucleus) sampling (None = disabled)
    repetition_penalty: Repetition penalty (1.0 = no penalty)
    use_constrained_decoding: Whether to use FSM-based constrained decoding
    constrained_decoding_debug: Whether to enable debug logging

Returns:
    Tuple of (metadata_dict, status_message)
    metadata_dict contains:
        - bpm: int or str
        - caption: str (enhanced)
        - duration: int or str
        - keyscale: str
        - language: str
        - timesignature: str
        - lyrics: str (from input, possibly formatted)

Example:
    caption = "Latin pop, reggaeton, flamenco-pop"
    lyrics = "[Verse 1]\nTengo un nudo en la garganta..."
    metadata, status = handler.format_sample_from_input(caption, lyrics)
    print(metadata['caption'])  # "A dramatic and powerful Latin pop track..."
    print(metadata['bpm'])      # 100
rB   FrA  r   rd  z&Formatting sample from input: caption=N2   z..., lyrics length=)r   r   zFormatted prompt for format: r  r   r  r  r  r  z*Using user-provided metadata constraints: rB  r!   rC  r  r   z)Format completed successfully. Generated re  rD  rE  rf  rG  u4   ✅ Format completed successfully
Generated fields: rH  )r&   r   r
   r   r  rj  r   rL   r   r  rf   r  r  rJ  r@  r  r   )rY   r   r   r   r  r  r
  r   r   r   r  constrained_metadatabpm_valdur_valr  r  r  r  formatted_lyricsr   s                       r/   format_sample_from_input#LLMHandler.format_sample_from_input  s   h t.66PPPgmmoo%GV\\^^%F<WSb\NJ]^abh^i]jkl  AA B 
 	45E4FGH  $#%   '3!-"67G{6=U3   ,8!-
";<G{;BZ8   ,,3@3L$Z0  118Eo8V$_5  ,,3@3L$Z0 ('+$HI]H^_`
 #AA-*&8#'!5 %Ui!5!9!9*!ET!Qot$$0 &>'A#% B 
* v: **;7!  ;;KH!1HX "(HX?zQR%LL/X]]_0E/FGHLL0Tc1B0C3GHLTYYW_WdWdWfMgLhi
##E #I.  #I. s$   J -J+ J('J(+J?>J?r  c                 
   [        U SS5      (       d  gU R                  S:X  a  U R                  b  U R                  c  gOU R                  b  U R                  c  gU=(       d    0 nUR                  SS	5      nUR                  S
S5      nUR                  SS5      nUR                  S5      n	UR                  S5      n
UR                  SS5      nUR                  S5      nUR                  S5      nUR                  SS5      nUR                  SS5      nUR                  SS5      nUR                  SS5      nUR                  SS5      nUR                  SS5      nUR                  SS5      n U R                  S:X  aA  U R                  UUUUU	U
UUUUUUUUUUUUUS9nU R                  5         US[        U5       34$ U R                  S:X  aA  U R                  UUUUU	U
UUUUUUUUUUUUUS9nU R                  5         US[        U5       34$ U R                  UUUUU	U
UUUUUUUUUUUUUS9nU R                  5         US [        U5       34$ ! [         Ga#  nS!SKnUR                  " 5       n[        R                  " S"[!        U5      R"                   S#U S$U 35        U R                  S:X  af   S!S%KJn  U" 5         O! [(         a     Of = f [+        U R                  S&5      (       a  U R                  R-                  5         O! [         a     Of = f[.        R0                  " 5         U R                  5         SS'[!        U5      R"                   S#U=(       d    UR3                  5       S(    34s SnA$ SnAff = f))a  
Generate raw LM text output from a pre-built formatted prompt.

Args:
    formatted_prompt: Prompt that is already formatted by `build_formatted_prompt`.
    cfg: Optional dict supporting keys:
        - temperature (float)
        - cfg_scale (float)
        - negative_prompt (str) used when cfg_scale > 1
        - top_k (int), top_p (float), repetition_penalty (float)
        - target_duration (float): Target duration in seconds for codes generation
        - generation_phase (str): "cot" or "codes" for phase-aware CFG
    use_constrained_decoding: Whether to use FSM-based constrained decoding
    constrained_decoding_debug: Whether to enable debug logging for constrained decoding
    stop_at_reasoning: If True, stop generation immediately after </think> tag (no audio codes)

Returns:
    (output_text, status_message)

Example:
    prompt = handler.build_formatted_prompt(caption, lyric)
    text, status = handler.generate_from_formatted_prompt(prompt, {"temperature": 0.7})
rB   F)r!   rA  rY  N)r!   u-   ❌ 5Hz LM is missing MLX model or tokenizer.)r!   u)   ❌ 5Hz LM is missing model or tokenizer.r  g333333?r  r   r   r   r  r
  r   r   r   r   r   r   r   r   r   r!   r   r   rn   )r=  r  r  r   r  r
  r   r   r   r   r   r   r   r   r   r   r   r   r   u+   ✅ Generated successfully (vllm) | length=u*   ✅ Generated successfully (mlx) | length=u)   ✅ Generated successfully (pt) | length=r   z)Error in generate_from_formatted_prompt: : r(  )reset_contextro   u,   ❌ Error generating from formatted prompt: r  )r&   rC   rV   rA   r@   rL   r  rk   r  r  r  rp   r   r   r
   r  r  __name__nanovllm.utils.contextrv  rf  rN   ro   rr   rs   rl  )rY   r  r  r   r   r   r  r  r   r  r
  r   r   r   r   r   r   r   r   r   r   r  r   r   error_detailrv  s                             r/   r  )LLMHandler.generate_from_formatted_prompt:	  s   > t.66Pu$&$*<*<*DJ +EXX!3!3!;BiRggmS1GGK-	''"3_E   WW%93?''"340ww~u57ggmU377#5u='')R(2&77:r*d	6)"nn&6 +'$3'9-E/I$3"/&7 +!-"/%5#!%' - * --/"&QRUVaRbQc$ddd!!U*"mm&6 +'$3'9-E/I$3"/&7 +!-"/%5#!%' , * --/"&PQTU`QaPb$ccc ,,"2'# /#5)A+E /+"3')+!1!' ' K* ))+"KCP[L\K] ^^^ 	$//1LLLDT!WEUEUDVVXYZX[[]^j]klm 6)D!O" txx11(   JJL))+Ed1gFVFVEWWYZ[Z|_k_v_v_xy{_|Y}~~~/	sw   1AI AI A I NAM=7KM=
KM=KM=5LM=
LM=LAM=7N=Nr8  r  r   r  c                    U R                   nU R                  nUR                  5       nUb  UR                  5       nO[        R                  " U5      nSU0nSn[        US5      =(       a    [        UR                  SS5      nU R                  R                  nUc  UnU R                  U5      n[        R                  " 5          [        [        U5      SSU R                  S9 GHW  nU R                  XUUU5      nUR                   SS2S	SS24   nU
b	  U
" UU5      nU H  nU" UU5      nM     U R#                  UU5      nU R%                  UU5      nU R'                  UU5      nU R)                  U
U5        U R+                  UUU5      nUR-                  S
5      n[        R.                  " UU/S
S9n[        R.                  " U[        R0                  " UR2                  S   S
4XR4                  S9/S
S9nXS'   U(       a  [        US5      (       a  UR6                  nU	b  U	R9                  U5        U(       d  GMX    O   SSS5        U	b  U	R;                  5         AU$ ! , (       d  f       N$= f)z
Custom generation loop with constrained decoding support (non-CFG).
This allows us to call update_state() after each token generation.
Nr  generation_configr6  TzLLM Constrained Decodingtokendescunitdisabler  r  r  r   rE   rH   r5  )r@   rE   r  rF   	ones_likerN   r&   r|  rA   r%  r   r  r   r,  rP   r;  r   r  r  r"  r0  r)  	unsqueezecatonesr-  rH   r5  putrQ  )rY   r8  r  r   r  r  r
  r   r&  r  rR   r2  rE   r3  	attn_maskr4  r5  r6  r%  r   stepr:  next_token_logits	processornext_tokensshould_stopnext_tokens_unsqueezeds                              r/   r  .LLMHandler._generate_with_constrained_decoding	  s   "  ")%&,,.I	2I ))4 E#67oGED[D[]hjn<o	 ))66'L  778JK!!#U>29SZakok|k|},,U<Q`bkl %,NN1b!8$<! )4(=mM^(_% "2I(1-AR(S% "2 %)$<$<=NPU$V!$($<$<=NPU$V! #112C[Q 889NP[\ #33K|\ *5)>)>q)A& %		=:P*QWX Y!IIy%**iooa>PRS=T]ckzkz2{&|  CD  E	1:-. 2C!D!D&-&=&=O 'LL!78;W ~ $\ LLN i $#s   E3I<I
I,r  r  c                 z	   SSK Jn  U R                  nU R                  nUR                  S   S-  nSnUnUR                  5       nUb  UR                  5       nO[        R                  " U5      n0 nUb  UUS'   Sn[        US5      =(       a    [        UR                  SS5      nU R                  R                  nUc  U	nU R                  U5      n[        R                  " U[        R                  US	9n[        R                   " 5          [#        [%        U5      S
SU R&                  S9 GH_  nU R)                  UUUUU5      nUR*                  SS2SSS24   nUUUU-    nUUUU-    nUGb&  UR,                  UR.                  :X  Ga  UR0                  b  UR0                  nUR                  U:w  d  UR2                  [        R4                  :w  a  UR7                  U[        R4                  S9nUS   S:H  n U R9                  SS9R;                  S5      n!USS2U!4   R=                  5       n"USS2U!4   R=                  5       n#U#UU"U#-
  -  -   n$[        R>                  " UUR                  S   4[=        S5      U[        R4                  S9n%U$U%SS2U!4'   OSUR=                  5       UUR=                  5       UR=                  5       -
  -  -   n%[        R@                  " U%[=        S5      S9n%Ub  UUUU-    n&U" U&U%5      n%UUUU-    n&U H  n'U'" U&U%5      n%M     U RC                  U%U5      n%U RE                  U%U5      n%URG                  5       (       a7  [%        U5       H(  n(UU(   (       d  M  [=        S5      U%U(SS24'   SU%U(U4'   M*     U RI                  U%U5      n)U RK                  UU)5        U)U:H  n*U	b  U	U:w  a  U*U)U	:H  -  n*UU*-  nU)RM                  S5      n+[        RN                  " UU+RQ                  SS5      /SS9n[        RN                  " U[        RR                  " US-  S4UUR2                  S9/SS9nUUS'   U(       a  [        US5      (       a  URT                  nU
b  U
RW                  U+5        URY                  5       (       d  GM`    O   SSS5        U
b  U
R[                  5         AU$ ! , (       d  f       N$= f)a  
Custom CFG generation loop that:
1. Processes both conditional and unconditional sequences in parallel
2. Applies CFG formula to logits, restricted to valid tokens when in CODES_GENERATION
3. Samples tokens only for conditional sequences
4. Applies the same sampled tokens to both conditional and unconditional sequences
5. Optionally applies constrained decoding via FSM-based logits processor
6. Tracks per-sequence EOS state; stops only when all sequences have finished

Batch format: [cond_0..cond_n, uncond_0..uncond_n]
r   FSMStater"   Nr  r|  r6  T)rH   rE   zLLM CFG Generationr}  r~  r  r  F)as_tupler  r  )nanr  r  r5  ).$acestep.constrained_logits_processorr  r@   rE   r-  r  rF   r  rN   r&   r|  rA   r%  r   zerosrg  r  r   r,  rP   r;  r   stateCODES_GENERATIONnon_audio_code_maskrH   rG   r   nonzeror  r  full
nan_to_numr  r  r(  r"  r0  r  r  repeatr  r5  r  allrQ  ),rY   r  r  r   r  r  r  r
  r   r&  r  rR   r  r2  rE   r  cond_start_idxuncond_start_idxr3  r  r4  r5  r6  r%  r   seq_finishedr  r:  r  cond_logitsuncond_logitsnon_audio_mask
valid_maskvalid_indices
cond_validuncond_valid	cfg_valid
cfg_logitscurrent_input_idsr  r/  r  is_eosr  s,                                               r/   r  $LLMHandler._generate_with_cfg_custom:
  s   2 	B$**1-2
% (--/+1779N"___=N +-;L)* E#67oGED[D[]hjn<o	 ))66'L  778JK {{:UZZO!!#U>29MT[eievevw,,UM<Q`bkl %,NN1b!8$<! 0~j?XY 12BCST^C^ _ *5-33x7P7PP-AAM%:%N%NN%,,6.:N:NRWR_R_:_)7):):&PUP]P]):)^"0"3q"8J$.$6$6$6$F$N$Nq$QM "-Q-=!>!D!D!FJ#0M1A#B#H#H#JL ,yJ<U/V VI!&#[%6%6q%9:f%#mm	"J 4=Jq-/0 "/!4!4!6kFWFWFY\i\o\o\qFq9r!rJ
 "'!1!1*%-!PJ )4(5n^T^E^(_%!67H*!UJ %2.PZAZ$[!!1I!*+<j!IJ "2 "55j%H
!55j%H
  ##%%":.'??/4V}Jq!t,:=Jq,7 / #11*kJ 889NP[\ %4+0L#{l'BCF+f4 *5)>)>q)A& %		=:P:W:WXY[\:]*^de f!&NEJJ
STVWGXago}  pD  pD  =E  ,F  LM  "N1?-. 2C!D!D&-&=&=O 'LL!78  ##%%K x $P LLN  a $#s   
IR,'DR,
R,,
R:c                 f  ^^^ UR                  S5      S   n[        R                  " SU 35        0 mSnSSKnSnUR	                  XQ5      nU(       a  SR                  U5      n/ SQnSnU HG  n	UR                  XUR                  5      n
U
(       d  M(  U
R                  S5      R                  5       n  O   U(       d,  S	U;   a  UR                  S	5      S   OUnUR                  5       nU(       Ga=  UR                  S
5      nSm/ mUUU4S jnU GH  nUR                  5       R                  S5      (       a  M*  U(       a  US   R                  5       (       d  SU;   az  U" 5         UR                  SS5      n[        U5      S:X  aP  US   R                  5       R                  5       mUS   nUR                  5       (       a  TR                  U5        M  M  M  UR                  S5      (       d  UR                  S5      (       d  M  T(       d  GM  TR                  U5        GM     U" 5         TU4$ )a9  
Parse LM output to extract metadata and audio codes.

Expected format:
<think>
bpm: 73
caption: A calm piano melody
duration: 273
genres: Chinese folk
keyscale: G major
language: en
timesignature: 4
</think>

<|audio_code_56535|><|audio_code_62918|>...

Returns:
    Tuple of (metadata_dict, audio_codes_string)
r5   r   zDebug output text: r!   Nz<\|audio_code_\d+\|>)<think>(.*?)</think>r  z<reasoning>(.*?)</reasoning>r  r  r(  c                  R  > T(       a  T(       a  SR                  T5      n TS:X  a   [        U R                  5       5      TS'   OTS:X  a  [        R                  " U 5      TS'   OTS:X  a   [        U R                  5       5      TS'   OgTS:X  a  U R                  5       TS'   OMTS:X  a  U R                  5       TS'   O3TS:X  a  U R                  5       TS'   OTS:X  a  U R                  5       TS'   S	m/ mg	!   U R                  5       TS'    N= f!   U R                  5       TS'    N6= f)
z Save the accumulated field valuer(  r  r   r  genresr  r  r  N)r   r   r   r   postprocess_caption)r  current_keycurrent_value_linesr  s    r/   save_current_field6LLMHandler.parse_lm_output.<locals>.save_current_field$  s    #6 II&9:E"e+<.1%++-.@HUO %	1.P.d.dej.k+$
2A36u{{}3EHZ0 %0-2[[]*$
2/4{{},$
2/4{{},$749KKM1"&(#)<.3kkmHUOA38;;=HZ0s   C5 ,D 5DD&<r^   r"    	)r,   r
   r   rO  findallr   rP  DOTALLgroupr   r(   isspacer  rM   r   )rY   r  debug_output_textr  rO  code_patterncode_matchesreasoning_patternsreasoning_textpatternrU  lines_before_codeslinesr  linepartsfirst_valuer  r  r  s                    @@@r/   r  LLMHandler.parse_lm_output
  s   ( (--j9!<*+<*=>? /zz,<'',/K
 )GIIgBII>Eu!&Q!5!5!7	 * JY]hJh!2!2?!CA!Fny/557N "((.EK"$)@ ::<**3// Q 1 1cTk&( !JJsA.E5zQ&+Ahnn&6&<&<&>&+Ah&,,../66{C /	 ' __S))T__T-B-B"{+2248+ 0  $$r1   c                  T     SSK Jn   U " 5       (       d  gSSKng! [         a     gf = f)zCheck if MLX framework is available (Apple Silicon).

Delegates to the cached ``mlx_available()`` helper to avoid
re-importing ``mlx.core`` when the native extension failed on
first load (which causes a fatal nanobind duplicate-enum crash).
r   )mlx_availableFNT)acestep.models.mlxr  mlx_lmrp   )r  r  s     r/   rh  LLMHandler._is_mlx_availabled  s,    	8 ?? 		s     
''c                     SSK Jn  SSKJn  [        R
                  " SU 35        [        R                  " 5       n U" U5      u  U l        nUR9                  U R                  R;                  5       5        Xl        [        R                  " 5       U-
  n[        R
                  " SUS S35        SU l        SU l         SU S3nSU4$ ! [         Ga  n[        R
                  " SU S35        SSK	nSSK
Jn  SSKJn	Jn
JnJn  U" U5      nU
" U5      nUR                  [!        US	-  5      5      nU(       d  [#        S
U 35      Ue0 nU H#  nUR%                  UR                  U5      5        M%     ['        [)        U5      5      nUR+                  S5      (       dF  [        R
                  " S5        UR-                  5        VVs0 s H  u  nnSU 3U_M     Os  snnf nnnU" US9u  nnUR/                  U5      nU" U5      n[1        US5      (       a  UR3                  U5      nUR5                  [7        UR-                  5       5      SS9  UR9                  UR;                  5       5        UR9                  5         UU l         SnAGN:SnAff = f! [         aK  nSSK!nURD                  " 5       n[        RF                  " SU SU 35        SS[!        U5       34s SnA$ SnAff = f)z
Load the 5Hz LM model using mlx-lm for native Apple Silicon acceleration.

Args:
    model_path: Path to the HuggingFace model directory

Returns:
    Tuple of (success, status_message)
r   N)loadzLoading MLX model from zStandard MLX load failed (z-), retrying with 'model.' prefix remapping...)Path)
load_modelload_configload_tokenizer_get_classeszmodel*.safetensorszNo safetensors found in zmodel.z;Adding 'model.' prefix to weight keys for MLX compatibility)r  sanitizeT)strictz!MLX model loaded successfully in rH  srY  r   z>
Backend: MLX (Apple Silicon native)
Device: Apple Silicon GPUzFailed to load MLX model: r(  Fu   ❌ MLX load failed: )$mlx.corecoremlx_lm.utilsr  r
   r   r_  rV   rp   globpathlibr  r  r  r  r  re   FileNotFoundErrorupdatenextiterr(   r  	from_dictrN   r  load_weightsr@  r   
parametersrW   rC   rB   r   r   rz   )rY   r   mxmlx_loadrn  r  	first_err_globr  r  r  r  r  _model_pathr  weight_filesweightswf
sample_keyrQ  r.   model_classmodel_args_class
model_argsr2  	load_timer   r   r   ry  s                                 r/   ri  LLMHandler._load_mlx_modelu  s   L	;!5KK1*>?J-(%-j%9"\ GGDOO..01#- 		j0IKK;Ic?!LM$D#'D $ &,-  ##y  +( 0 <A A %(^^":.$[1  %zz#k<P.P*QR#+.Fzl,STZcc&BNN2772;/ ' "$w-0
!,,X66KK ]^;B==?K?41as|Q?KGK 1=F0K---77?
#J/5*--#nnW5G""4#8"F((*+

"'W+(|  	;$//1LNN7s"\NKL1#a&:::		;sV   :J C A9J JC1JGB+JJ JJ 
K$A KK$K$c                     SSK Jn   SSKJn  U" U R                  5      $ ! [
        [        4 a7     U R                  R                  5       s $ ! [         a    [        S5      ef = ff = f)z$Create a KV cache for the MLX model.r   Nmake_prompt_cachez;Cannot create MLX KV cache. Ensure mlx-lm version >= 0.20.0)	r  r  mlx_lm.models.cacher  rV   rf  rg   
make_cacheRuntimeError)rY   r  r  s      r/   _make_mlx_cacheLLMHandler._make_mlx_cache  sg    
	=$T__55^, 	1133! "Q 		s      A'A
A'A##A'c                 x  ^]^^ SSK Jm^  SSKnSSKJnJm]  SSKJn  U R                  USSSS9nUS	   nUR                  S
   nT^R                  US   5      nU R                  USS9nU R                  R                  nU R                  R                  =(       d    UnU" US:  a  UOSUb  SUs=:  a  S:  a  O  OUOSUb  US:  a  UOSS9nUS:g  n[        U5      nUS:  nU(       a  SOSnSnSSKJn   Sn!Sn"Sn#U R#                  U	U
USSSSSSSS9
n$U$b  [%        U$S5      (       aD  U$R&                  b7  T^R                  U$R&                  R                  5       R                  5       5      n![%        U$S5      (       a"  U$R                  b  [)        U$R                  5      n"[%        U$S5      (       a  U$R*                  n#U$R,                  U R.                  :X  a  SU;   a  U R0                  U$l        SU$l        [4        R4                  " 5       n%[6        R8                  " SU S35        U]U^4S jn&U(       Ga  U R;                  XUUSSS9n'U R                  U'SSSS9n(T^R                  U(S	   S   5      n)[=        U)5      n*U" U R>                  5      n+U" U R>                  5      n,Un-[=        U-5      S
:  a  [A        U[=        U-5      S
-
  5      n.U R?                  U-SU. S   U+S9  T^RC                  U+ V/s/ s H  n/U/R,                  PM     sn/5        U-U.S n-T^RE                  5         [=        U-5      S
:  a  M  U)n0[=        U05      S
:  a  [A        U[=        U05      S
-
  5      n.U R?                  U0SU. S   U,S9  T^RC                  U, V/s/ s H  n/U/R,                  PM     sn/5        U0U.S n0T^RE                  5         [=        U05      S
:  a  M  U R?                  U-S   U+S9n1U R?                  U0S   U,S9n2T^RC                  U1U25        U+/n3U,/n4[G        S
U5       H1  n5U3RI                  U&" U+5      5        U4RI                  U&" U,5      5        M3     [G        S
U5       H{  n5T^RB                  " U3U5    V/s/ s H  n/U/RJ                  c  M  U/RJ                  PM      sn/6   T^RB                  " U4U5    V/s/ s H  n/U/RJ                  c  M  U/RJ                  PM      sn/6   M}     U1SS2SS2SS24   /U-  n6U2SS2SS2SS24   /U-  n7[4        R4                  " 5       U%-
  n8UU*-   n9U8S:  a  U9U8-  OSn:[6        R8                  " SU9 S U S!U* S"U8S# S$U:S% S&U S'US
-
  U9-   S(35        GOU" U R>                  5      n;Un<[=        U<5      S
:  a  [A        U[=        U<5      S
-
  5      n.U R?                  U<SU. S   U;S9  T^RC                  U; V/s/ s H  n/U/R,                  PM     sn/5        U<U.S n<T^RE                  5         [=        U<5      S
:  a  M  U R?                  U<S   U;S9n=T^RC                  U=5        U;/n>[G        S
U5       H  n5U>RI                  U&" U;5      5        M     [G        S
U5       H?  n5T^RB                  " U>U5    V/s/ s H  n/U/RJ                  c  M  U/RJ                  PM      sn/6   MA     U=SS2SS2SS24   /U-  n?[4        R4                  " 5       U%-
  n8U8S:  a  UU8-  OSn:[6        R8                  " SU S)U8S# S$U:S% S&U S*3	5        [M        US   5      n@[G        U5       VAs/ s H  nA[M        W@5      PM     nBnA[G        U5       VAs/ s H  nA/ PM     nCnAS/U-  nDS/U-  nE/ nF[G        U5       HF  n5U(       a%  U5[=        U5      :  a  WFRI                  UU5   5        M/  WFRI                  S+U5S,-  -   5        MH     [4        R4                  " 5       nG[O        US-U S.U S/3S0S19nH[G        U5       GH  nI[Q        WE5      (       a    GO[G        U5       GH  n5WEU5   (       a  M  T^RR                  RU                  WFU5   WIS,-  -   5        U(       a  W7U5   UW6U5   U7U5   -
  -  -   nJOW?U5   nJWJRW                  S
S5      nJU(       aT  [=        WBU5   5      S:  aB  T^R                  WBU5   5      nKWJSS2UK4   nLT^RY                  ULS:  ULU-  ULU-  5      nMUMUJSS2UK4'   U!b  WJU!-   nJU#b  U"b  WDU5   U#:  aC  T^R[                  WJSS2SU"24   T^R                  [        S25      //5      UJSS2U"S
-   S24   /S
S39nJO[WJSS2U"U"S
-   24   nNT^R]                  UJR                  [        S25      5      nJT^R[                  UJSS2SU"24   UNUJSS2U"S
-   S24   /S
S39nJWJT^R_                  UJSS49-
  nOU" UO5      nPT^RC                  UP5        UPRa                  5       nQWCU5   RI                  UQ5        WBU5   RI                  UQ5        WDU5==   S
-  ss'   UQU:X  a  SWEU5'   GM  Ub  UU:w  a  WQU:X  a  SWEU5'   GM  T^R                  WQ//5      nRU(       aK  U R?                  WRW3U5   S9nSU R?                  URW4U5   S9nTUSSS2SS2SS24   W6U5'   UTSS2SS2SS24   W7U5'   GMr  U R?                  WRW>U5   S9nUUUSS2SS2SS24   W?U5'   GM     WHRc                  S
5        WIS5-  S:X  d  GM  WIS:  d  GM  T^RE                  5         GM     WHRe                  5         [4        R4                  " 5       WG-
  nV[g        S6 WC 5       5      nWUS:  a  WWU-  OSnXWVS:  a  WWWV-  OSnYU8WV-   nZ[6        R8                  " S7U S8WW S9WXS: S;UVS# S$UYS% S<U8S# S=UVS# S>UZS# S?35        / n[[G        U5       H1  n5U R                  Ri                  WCU5   SS@9n\W[RI                  U\5        M3     W[$ s  sn/f s  sn/f s  sn/f s  sn/f s  sn/f s  sn/f s  snAf s  snAf )AaB  
Optimized native MLX batch generation for codes phase.

Strategy: shared prefill + clone cache + interleaved B=1 decode.

On Apple Silicon, LLM decode is memory-bandwidth-bound. Batching the
forward pass (B>1) doubles the KV cache reads per step and actually
*slows down* throughput for 1.7B-class models. Instead, we:

1. Prefill ONCE with B=1, then clone the KV caches for each item.
   This saves ~50% of prefill time vs sequential generation.
2. Interleave B=1 forward passes across items within each step.
   Each item gets its own cache, constrained state, and seed.

This achieves ~1.25x speedup over fully sequential generation while
maintaining the full ~44 tok/s per-item decode speed.

Only used for codes generation phase where all prompts are identical.
Raises on failure so the caller can fall back to sequential mode.
r   N)r  KVCachemake_samplernpFTr  r8  r  r   r   r   r  r   tempr
  r  CFG r!   r  r  r  r  r%  r   r5   z&MLX batch native: prefilling once for z items (shared prompt)c                 
  > / nU  Hy  nT" 5       nUR                   bQ  TR                  UR                   5      Ul         TR                  UR                  5      Ul        UR                  Ul        UR	                  U5        M{     U$ )zNDeep-copy a list of KVCache objects so each batch item gets independent state.)r  arrayvaluesoffsetr   )
cache_listclonedcnew_cr  r  s       r/   _clone_cache_list;LLMHandler._run_mlx_batch_native.<locals>._clone_cache_listR  si    F	66%!#!&&!1EJ#%88AHH#5EL#$88ELe$   Mr1   r  cacher  zMLX batch native prefill:  tokens (cond=	, uncond=) in rH  s (r   z tok/s) [shared across z items, saved z redundant tokens] tokens in z items]*   iCB MLX zBatch Gen (native, n=rJ  toktotalr  r  r  axiskeepdims   c              3   8   #    U  H  n[        U5      v   M     g 7frO  )r  )rP  ts     r/   rS  3LLMHandler._run_mlx_batch_native.<locals>.<genexpr>3  s     ;?a3q66?s   z&MLX batch native generation complete: z items, z total tokens (z.0fz	 avg) in  tok/s) | prefill s + decode s = s totalr  )5r  r  numpyr  r  r  mlx_lm.sample_utilsr  rA   r-  r  r   r%  r&  r  r  r  r   rN   r  r   r   r  	THINK_TAGr  r  r_  r
   r   r   r  rV   r   r   clear_cacher,  r   r  r@  r   r  r  seedreshapewhereconcatenater  	logsumexpr   r  closer  r  )_rY   r  r  r  r  r   r  r
  r   r   r   r   r   r   r   r  r  r  r  r  input_ids_npprompt_lengthr   r   r%  r&  sampleruse_rep_penaltyrep_penalty_valuse_cfg	cfg_labelprefill_step_sizer  _mlx_non_audio_mask_mlx_eos_id_target_codesrR   prefill_startr  uncond_textuncond_inputsuncond_promptuncond_lengthbase_cond_cachebase_uncond_cachecond_remaining
chunk_sizer
  uncond_remainingbase_cond_logitsbase_uncond_logitsitem_cond_cachesitem_uncond_cachesr  item_last_conditem_last_uncondprefill_timetotal_prefill_tokensprefill_tps
base_cache	remainingbase_logitsitem_cachesitem_last_logitsbase_token_idsr  item_all_token_idsitem_new_tokensitem_codes_countitem_finisheditem_seed_basesdecode_startpbarr  step_logitstoken_indicesselectedmodifiedeos_vallogprobs	token_arrtoken_id
next_inputr  r  
logits_outdecode_timetotal_tokens
avg_tokens
decode_tpsr  r  r  r  r  s_                                                                                                @@r/   _run_mlx_batch_native LLMHandler._run_mlx_batch_native  s   L 	B4 ##	 $ 
 k*$**1-,q/* 55+$ 6 
 ))66))66F,  +aS ,u1Bs1B% ,%
 -3 23c/%F2	  	B" !% A A%='A+#$ !B !
 !,,.CDDI^IrIrI~&(hh/D/X/X/^/^/`/f/f/h&i#,n==BWBdBdBp!"7"D"DE,n== 5 B B %**h.@.@@!112:2K2K)/89)5 		<ZLH^_`	 :: /'TX ; K !..D%D / M HH];%?%BCM.M 0@O 1$// B $Nn%) !2C4G!4KL
{
 ;D AY/:/Q/:;!/
!<  n%)  -&'!+ !2C8H4IA4MN
 0* =d CK\]*;<*;Q*;<=#3JK#@   &'!+  $~d/C?[!%1A$1GO`!aGG$&89 !00"3!41j) ''(9/(JK"))*;<M*NO * 1j)*:1*=T*=Q&!&&*=TU*<Q*?V*?Q166&!&&*?VW *
 /q"#qy9:ZGN 21bc19 =>K99;6L#0=#@ AMPQAQ.=WXKKK,-A,B C&y @"3's;s*; <"",^Z\K_<_;``rt +4??;JIi.1$ !2C	NQ4FG
	+: 6t <JO*5*Q*56%jk2	  i.1$ //)D//LKGGK %,K1j)""#4Z#@A *1j)+a.O.QAFF&!&&.OP * !,ArsAI 67*D99;6L:F:J-,6PQKKK,]O <"3's;s*; <"",W6 l1o.<A*<MN<Mqd>2<MN',Z'89'8!2'893+*, z"ASZ&&uQx0&&rAK'78	 # yy{.i[@UV`Uaab/cjop.)D=!! :& # 		q1D7NBC "21"5	^TUEVYijkYlEl8m"mK"21"5K)11!R8 #s+=a+@'AA'E$&HH-?-B$CM*1m+;<H!xx 1 ?2 ?2 H
 5=K= 01 '2"-0C"CK ,1H'*]:&(nn'<K<8HHuV}o%67';?+;(;<6 !"	 '5 '# #.a[1_1L.L"M&(ggk.?.?v&O&(nn'<K<8#';?+;(;<6 !"	 '5 '# 'kD)QQ#H-		"$>>+"))(3"1%,,X6 !#q(# |+'+M!$+0LQY]iQi'+M!$  XXzl3
"&//*DTUVDW/"XK$(OOJFXYZF[O$\M(3ArsAI(>N1%*723	*B$Q'!%;q>!RJ*4QQY*?$Q'W 'Z KKN czQ4!8 o *r 	

 iikL0;?;;2<q.\J.a
3>?\K/
!K/
4ZLnOJs+;9[QTDU V31,s1C;{[^N__cdnorcssz|	
 z"A,,33OA4F\a3bK, # _ ; =" UV, 6 P, O9sB   'n8nn
1n
n#
-n#
)n(n-
4n-
n2'n7c                     SSK Jn  SSKnSSKJn  SSKJn  U R                  USSSS9nUS	   nUR                  S
   nUR                  US   5      nU R                  UU	U
UUUUUUSS9
nU R                  U
US9nU R                  R                  nU R                  R                  =(       d    UnU" US:  a  UOSUb  SUs=:  a  S:  a  O  OUOSUb  US:  a  UOSS9n US:g  n![        U5      n"US:  n#U#(       a  SOSn$SU$ S3n%Sn&SSKJn'  Sn(Sn)Sn*Sn+Ub  [#        US5      (       aD  UR$                  b7  UR                  UR$                  R                  5       R                  5       5      n([#        US5      (       a"  UR                  b  ['        UR                  5      n)[#        US5      (       a  UR(                  n*US:X  aP  UR*                  U'R,                  :X  a6  SU;   a0  U'R.                  Ul        SUl        Sn+[2        R4                  " S5        [6        R6                  " 5       n,U#(       Ga6  U R9                  UUUUUSS9n-U R                  U-SSSS9n.UR                  U.S	   S   5      n/[;        U/5      n0U" U R<                  5      n1U" U R<                  5      n2Un3[;        U35      S
:  a  [?        U&[;        U35      S
-
  5      n4U R=                  U3SU4 S   U1S9  URA                  U1 V5s/ s H  n5U5R*                  PM     sn55        U3U4S n3URC                  5         [;        U35      S
:  a  M  U/n6[;        U65      S
:  a  [?        U&[;        U65      S
-
  5      n4U R=                  U6SU4 S   U2S9  URA                  U2 V5s/ s H  n5U5R*                  PM     sn55        U6U4S n6URC                  5         [;        U65      S
:  a  M  U R=                  U3S   U1S9n7U R=                  U6S   U2S9n8URA                  U7U85        U7SS2SS2SS24   n9U8SS2SS2SS24   n:[6        R6                  " 5       U,-
  n;UU0-   n<U;S:  a  U<U;-  OSn=[2        R4                  " SU< S U S!U0 S"U;S# S$U=S% S&35        GOU" U R<                  5      n>Un?[;        U?5      S
:  a  [?        U&[;        U?5      S
-
  5      n4U R=                  U?SU4 S   U>S9  URA                  U> V5s/ s H  n5U5R*                  PM     sn55        U?U4S n?URC                  5         [;        U?5      S
:  a  M  U R=                  U?S   U>S9n@URA                  U@5        U@SS2SS2SS24   nA[6        R6                  " 5       U,-
  n;U;S:  a  UU;-  OSn=[2        R4                  " SU S'U;S# S$U=S% S&35        [E        US   5      nB/ nC[6        R6                  " 5       nD[G        UU%S(S)9nE[I        U5       GH1  nFU#(       a  W:UW9U:-
  -  -   nGOWAnGWGRK                  S
S5      nGU!(       aN  [;        WB5      S:  a?  UR                  WB5      nHWGSS2UH4   nIURM                  UIS:  UIU"-  UIU"-  5      nJUJUGSS2UH4'   UGbw  UR*                  nKUKU'R.                  :X  a  U(b  WGU(-   nGU*b  U)b  UR0                  U*:  aC  URO                  WGSS2SU)24   UR                  [        S*5      //5      UGSS2U)S
-   S24   /S
S+9nGOWGSS2U)U)S
-   24   nLURQ                  UGR                  [        S*5      5      nGURO                  UGSS2SU)24   ULUGSS2U)S
-   S24   /S
S+9nGOWKU'RR                  :X  a  OWGRU                  URV                  5      nMUR                  UMSS,9nN[X        RZ                  " UN5      nO[X        R\                  " WB/[X        R^                  S-9nPU" UPUO5      nOUR                  UOR                  5       5      nGWGURa                  UGSS.9-
  nQU " UQ5      nRURA                  UR5        URRc                  5       nSWCRe                  US5        WBRe                  US5        WERg                  S
5        Ub  URi                  WS5        WSU:X  a    OUb  UU:w  a  WSU:X  a    OUR                  WS//5      nTU#(       a=  U R=                  WTW1S9n7U R=                  UTW2S9n8U7SS2SS2SS24   n9U8SS2SS2SS24   n:OU R=                  WTW>S9n@U@SS2SS2SS24   nAWFS/-  S:X  d  GM  WFS:  d  GM!  URC                  5         GM4     WERk                  5         [6        R6                  " 5       WD-
  nU[;        WC5      nVUUS:  a  WVWU-  OSnWU;WU-   nX[2        R4                  " S0WV S'UUS# S$UWS% S1U;S# S2UUS# S3UXS# S435        U R                  Rm                  WCSS59nYUY$ s  sn5f s  sn5f s  sn5f )6aN  
Optimized native MLX generation using mlx-lm infrastructure.

Key improvements over the hybrid approach:
1. Native MLX sampling (temperature, top-k, top-p) via mlx-lm make_sampler
   - Eliminates numpy/PyTorch round-trip for EVERY generated token
2. Native MLX repetition penalty (no per-step PyTorch conversion)
3. Chunked prefill for memory-efficient long prompt processing
4. Periodic memory cleanup (mx.clear_cache) matching mlx-lm patterns
5. Bridges to PyTorch ONLY for constrained decoding FSM when active

Raises on failure so the caller can fall back to the legacy hybrid method.
r   Nr  r  r  FTr  r8  r  r  r   r  r   r  r  r!   r  zGen (native)r  r  r  r%  r   r   r5   zGMLX native: pre-transitioned FSM to CODES_GENERATION (native fast path)r  r  r  zMLX native prefill: r  r  r  rH  r  r    tok/s)r  r  r  r  r  r  rH   r  r  z MLX native generation complete: r"  r#  r$  r%  r  )7r  r  r&  r  r  r'  r  rA   r-  r  r   r   r%  r&  r  r  r  rN   r  r   r   r  r(  r  r  r
   r   r_  r   r  rV   r   r   r)  r@  r   r,  r+  r,  r-  r  	COMPLETEDastyperG   rF   
from_numpytensorlongr.  r   r   r  r.  r/  r  )ZrY   r  r  r  r   r  r
  r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r  r  r0  r1  r   rR   r   r%  r&  r2  r3  r4  r5  r6  	tqdm_descr7  r  r8  r9  r:  _use_native_codes_pathr;  r<  r=  r>  r?  
cond_cacheuncond_cacherB  rC  r
  rD  r  r  	last_condlast_uncondrK  rL  rM  r  rO  rd  last_logitsall_token_ids
new_tokensrY  rZ  r  r[  r\  r]  r^  	_cp_stater_  step_logits_f32	np_logitst_logitst_idsr`  ra  rb  rc  re  num_generatedrh  r  r  sZ                                                                                             r/   _run_mlx_single_native!LLMHandler._run_mlx_single_nativeE  s}
   F 	94 ##	 $ 
 k*$**1-,q/* !% A A%='A+'/#%'- !B !
 55+- 6 
 ))66))66F,  +aS ,u1Bs1B% ,%
 -3 23c/%F2	9+\2	 
 	B"!& ,,.CDDI^IrIrI~&(hh/D/X/X/^/^/`/f/f/h&i#,n==BWBdBdBp!"7"D"DE,n== 5 B B
  7*/D/J/JhN`N`/`!112:2K2K)/89)5-1*KK ij 		::! /!1 ; K !..#	 / M HH];%?%BCM.M +4??;J,T__=L $Nn%) !2C4G!4KL
{
 ;D AT*5*Q*56!/
!<  n%)  -&'!+ !2C8H4IA4MN
 0* =d C<X,7,Q,78#3JK#@   &'!+ //.*>j/QK OO,<T,B,OWMGGK/#ArsAI.I'23	2K99;6L#0=#@ AMPQAQ.=WXKKK&';&< =&y @"3's;s*;7D &doo6E Ii.1$ !2C	NQ4FG
	+: 6t <EJ%0%Q%01%jk2	  i.1$ 4FJGGJ$QQY/K99;6L:F:J-,6PQKKK&}o 6"3's;s*;7D \!_-
yy{.yuE.)D)I[9P,QQ)%--a4K 3}#5#9 " 7&q-'7888qL..
 19A},- %0177	 9 99 +6&14G&G$0[5L0<<}L*,.. +A||O < "5=/): ; +A{Q/?,? @: %&	 +9 +'K '2![q5P2P&QG*,''+2C2CU6]*SK*,.. +A||O < ' +A{Q/?,? @: %&	 +9 +'K ("4"44 '2&8&8&DO "t DI$//	:H!LL-

KE4UHEH"$((8>>+;"<K #R\\+\%MMH)IGGI ~~'Hh'  *KKN %0%228< <''LL,HXYeMe
 H:,/J"ooj
oK $
, O'23	2	+ArsAI6!__Zu_E
(BC3 czQ4!8 A *D 	

 iikL0J4?!O][0
!K/
.}o[UXHY Z31,s1C;{[^N__cdnorcssz|	
 ((//
PU/VW 6 8: 1s   )f:ffc                 "    U R                  UUUUUUUUU	U
UUUUUUUUUS9$ ! [         a:  n[        R                  " S[	        U5      R
                   SU S35         SnAOSnAff = fSSKJn  SSKnU R                  USSS	S
9nUS   nUR                  S   nUR                  U5      nU R                  UU	U
UUUUUUSS9
nU R                  U
US9nU R                  R                  nU R                  R                  =(       d    UnUS:  nU(       a  SOSn SU  S3n![         R                   " 5       n"U(       Ga
  U R#                  UUUUUSS9n#U R                  U#SSS	S
9n$UR                  U$S   5      n%U%R                  S   n&U R%                  5       n'U R%                  5       n(U R'                  UU'S9n)U R'                  U%U(S9n*UR)                  U)U*5        U)SS2SS2SS24   n+U*SS2SS2SS24   n,[         R                   " 5       U"-
  n-UU&-   n.U-S:  a  U.U--  OSn/[        R*                  " SU. SU SU& SU-S SU/S S35        OU R%                  5       n0U R'                  UU0S9n1UR)                  U15        U1SS2SS2SS24   n2[         R                   " 5       U"-
  n-U-S:  a  UU--  OSn/[        R*                  " SU SU-S SU/S S35        [-        US   5      n3/ n4[         R                   " 5       n5[/        UU!S S!9n6[1        U5       GH  n7U(       a  W,UW+U,-
  -  -   n8OW2n8U8R3                  SS5      n8U8R5                  UR6                  5      n9UR                  U9S	S"9n:[8        R:                  " U:5      n;[8        R<                  " U3/[8        R>                  S#9n<Ub	  U" U<U;5      n;US:w  a  SS$K J!n=  U=" US%9n>U>" U<U;5      n;U RE                  U;U5      n;U RG                  U;U5      n;U RI                  U;U5      n?U?RK                  5       n@U4RM                  U@5        U3RM                  U@5        U6RO                  S5        Ub  URQ                  W@5        W@U:X  a    OUb  UU:w  a  W@U:X  a    OUR                  W@//5      nAU(       aQ  U R'                  WAW'S9n)U R'                  UAW(S9n*UR)                  U)U*5        U)SS2SS2SS24   n+U*SS2SS2SS24   n,GM  U R'                  WAW0S9n1UR)                  U15        U1SS2SS2SS24   n2GM     U6RS                  5         [         R                   " 5       U5-
  nB[U        U45      nCUBS:  a  WCWB-  OSnDU-WB-   nE[        R*                  " S&WC SUBS SUDS S'U-S S(UBS S)UES S*35        U R                  RW                  U4SS+9nFUF$ ),z
MLX-accelerated single-item generation.

Tries optimized native MLX generation first (using mlx-lm infrastructure
for sampling, repetition penalty, and chunked prefill). Falls back to
hybrid MLX/PyTorch approach if native generation fails.
r  zNative MLX generation failed (ru  z), falling back to hybrid modeNr   r  FTr  r8  r  r  r   r   r  r!   r  
Generationr  r  r  zMLX prefill: r  r  r  rH  r  r   rl  r  r  r  rm  rn  )r   r   zMLX generation complete: r"  r#  r$  r%  r  ),r  rp   r
   rz   r  rw  r  r  r&  rA   r-  r  r   r   r%  r&  r_  r   r  rV   r   r   r@  r   r,  r+  rp  rG   rF   rq  rr  rs  &transformers.generation.logits_processr   r  r  r"  r   r   r  r.  r/  r  r  )GrY   r  r  r  r   r  r
  r   r   r   r   r   r   r   r   r   r   r   r   r   _native_errr  r  r  r0  r1  r   rR   r   r%  r&  r5  r6  rt  r;  r<  r=  r>  r?  rv  rw  r  r  rx  ry  rK  rL  rM  r  rd  rz  r{  r|  rY  rZ  r  r[  r~  r  r  r  r   rep_proct_tokenrb  rc  re  r  rh  r  r  sG                                                                          r/   _run_mlx_singleLLMHandler._run_mlx_single  s   <	..!1'# /#5)A+E /+"3')+!1!' /  *  	NN0k1B1K1K0LB{m \. / 	 	 ##	 $ 
 k*$**1-,' !% A A%='A+'/#%'- !B !
 55+- 6 
 ))66))66F,c/%F2	9+Z0	 		::! /!1 ; K !..#	 / M HH];%?@M)//2M --/J//1L //&
/CK OOMONMGGK/#ArsAI.I'23	2K99;6L#0=#@ AMPQAQ.=WXKKK 45 6&y @"3's;s*;7D ((*Eu=JGGJ$QQY/K99;6L:F:J-,6PQKKK /"3's;s*;7D \!_-
yy{.yuE.)D)I[9P,QQ)%--a4K
 *00<Ot<I''	2HLL-

CE %00A "S(c;DVW#E84 //%@H//%@H ))(K@G||~Hh'  *KKN %0%228< <''LL,HXYeMe H:,/J"ooj
oK $
, O]3'23	2	+ArsAI6!__Zu_E

#(BC3y *| 	

 iikL0J4?!O][0
!K/
'k+cAR S31,s1C;{[^N__cdnorcssz|	
 ((//
PU/Vs    # 
A'0A""A'c                    SSK Jn  U R                  U5      u  nnU(       Ga?  [        U5      n[        [	        U5      5      S:H  nUS:H  =(       a6    U=(       a-    US:  =(       a!    [        U S5      =(       a    U R                  SLnU(       a;   [        R                  " SU S35        U R                  US   UUUUUUUUU	U
UUUUS9$ [        R                  " SU S35        / n[        U5       Hl  u  nnU(       a-  U[        U5      :  a  UR                  R!                  UU   5        U R#                  UUUUUUUUU	U
SSSSSUUUUS9nUR%                  U5        Mn     U$ US   nU R#                  UUUUUUUUU	U
UUUUUUUUUS9$ ! [         a:  n[        R                  " S	[        U5      R                   S
U S35         SnANSnAff = f)a  
Unified MLX generation function supporting both single and batch modes.

For batch mode in codes generation phase, uses optimized batch native path
that shares prefill across all items (saving ~50% prefill time).
Falls back to sequential processing if batch native fails.
r   Nr  r   rV   z9MLX batch: using optimized batch native path (batch_size=z, shared prefill))r  r  r  r  r   r  r
  r   r   r   r   r   r   r   r  zMLX batch native failed (ru  z"), falling back to sequential modez-MLX batch: using sequential mode (batch_size=rJ  FTr  )r  r  rA  r  setrN   rV   r
   r   ri  rp   rz   r  rw  r  r  r*  r  r   ) rY   r=  r  r  r   r  r
  r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r   r  all_prompts_identicalcan_use_batch_nativer   r  r  r  r  s                                    r/   r  LLMHandler._run_mlxx  sa   < 	 +/*E*EFW*X'x23J %(,A(B$Cq$H! G+ 0)0N0 D,/0 OO4/ ! $KK''1l2CE  55)>q)A#-$/"+(7##+=1I3M(7 '%!)# 6  0 KKG
|STUVL'01F'G##QU^IINN58,"22%5 +'$3'9-E/I$3"&&+ $!%"&%5#!%' 3 * ##K05 (H6   13##-#+1%='A+'/#%'-' $ 
 	
Q ! NN3DG4D4D3ERs K: ; s   9F 
G0GGc              #   ,
  #    U R                   (       d  Sv   gU R                  S;   a  Sv   gU R                  nUc  Sv   g [        UR	                  5       5      R
                  R                  n[        U R
                  5      R                  S5      S   nX#:X  a  Sv   g[        R                  " SU R
                   35        [        R                  " 5       n[        US5      (       a4  UR                  U R
                  5      R                  U R                  5        [        R                  " 5       U-
  n[        R                  " SU R
                   SUS	 S
35         Sv   [        R                  " S5        [        R                  " 5       n[        US5      (       a  UR                  S5        [         R"                  " 5         [$        R&                  R)                  5       (       a  [$        R&                  R+                  5         O[        [$        S5      (       aB  [$        R,                  R)                  5       (       a  [$        R,                  R+                  5         O[        [$        R.                  S5      (       a  [$        R.                  R0                  R)                  5       (       aR  [        [$        S5      (       a=  [        [$        R0                  S5      (       a  [$        R0                  R+                  5         [        R                  " 5       U-
  n[        R                  " SUS	 S
35        g! [         a    Sn GNf = f! [        R                  " S5        [        R                  " 5       n[        US5      (       a  UR                  S5        [         R"                  " 5         [$        R&                  R)                  5       (       a  [$        R&                  R+                  5         O[        [$        S5      (       aB  [$        R,                  R)                  5       (       a  [$        R,                  R+                  5         O[        [$        R.                  S5      (       a  [$        R.                  R0                  R)                  5       (       aR  [        [$        S5      (       a=  [        [$        R0                  S5      (       a  [$        R0                  R+                  5         [        R                  " 5       U-
  n[        R                  " SUS	 S
35        f = f7f)z
Context manager to load a model to GPU and offload it back to CPU after use.
Only used for PyTorch backend when offload_to_cpu is True.
N)rn   rY  r^   r   zLoading LLM to r   zLoaded LLM to z in z.4fr  zOffloading LLM to CPUr:   ra   rb   rd   zOffloaded LLM to CPU in )rI   rC   r@   r  r  rE   r  StopIterationre   r,   r
   r   r_  rN   r   rH   rr   rs   rF   r`   rh   rd   ra   ri   rb   )rY   r2  r  target_devicern  r  offload_times          r/   r  LLMHandler._load_model_context  s     "" .=
	"!%"2"2"45<<AAN DKK(..s3A6* 	odkk]34YY[
5$HHT[[!$$TZZ0IIK*,	nT[[Mi_AFG	H KK/1Jud##JJLzz&&((

&&(&&599+A+A+C+C		%%'//ENN4F4F4S4S4U4UZabginZoZot{  }B  }F  }F  HU  uV  uV		%%'99;3LKK2<2DAFGA  	"!N	"& KK/1Jud##JJLzz&&((

&&(&&599+A+A+C+C		%%'//ENN4F4F4S4S4U4UZabginZoZot{  }B  }F  }F  HU  uV  uV		%%'99;3LKK2<2DAFGsE   A T-L0 0C.TM #GT0M <T?M  TGTTc                 x   U R                   S:X  a  U R                  $ U R                   S:X  Ga  U R                  Gc  [        R                  " S5        [        U R                  SS5      nUb  UR                  R                  nOU R                  nUc  [        S5      eSSK
nUR                  " 5       n[        R                  " USU R                  S	9U l        UR                  " 5       U-
  n[        R                  " S
US S35        U R                  (       a<  U R                  R                  5         [        R                  " S5        U R                  $ Ub.  [!        UR                  R#                  5       5      R$                  nOU R$                  nU R                  R'                  U5      U l        U R                  R                  5         [        R                  " SU 35        U R                  $ U R                   S:X  Ga  U R                  Gc  [        R                  " S5        [        U SS5      nUc  [        S5      eSSK
nUR                  " 5       n[        R                  " USU R                  S	9U l        UR                  " 5       U-
  n[        R                  " S
US S35        U R                  (       a<  U R                  R                  5         [        R                  " S5        U R                  $ [)        [*        R,                  S5      (       a/  [*        R,                  R.                  R1                  5       (       a  SOSnU R                  R'                  U5      U l        U R                  R                  5         [        R                  " SU 35        U R                  $ [        SU R                    35      e)a?  
Get HuggingFace model for perplexity scoring.

For vllm backend, loads HuggingFace model from disk (weights are cached by transformers).
For pt backend, returns the existing model.
For mlx backend, loads HuggingFace model from disk (MLX model can't be used for torch scoring).

Returns:
    HuggingFace model instance
r   rn   Nz7Loading HuggingFace model for scoring (from checkpoint)model_runnerz-vLLM model path is not available for scoring.r   T)r   torch_dtypezHuggingFace model loaded in rH  r  z?HuggingFace model for scoring kept on CPU (offload_to_cpu=True)z'HuggingFace model for scoring ready on rY  zGLoading HuggingFace model for scoring (MLX backend, need PyTorch model)rW   zEMLX model path not stored. Cannot load HuggingFace model for scoring.rb   r:   zUnknown backend: )rC   r@   rS   r
   r   r&   r  r2  rT   r  r_  r   r   rH   rI   r   r  r  rE   r   rN   rF   ri   rb   rh   )rY   r  r   r_  rn  r  rE   s          r/   get_hf_model_for_scoring#LLMHandler.get_hf_model_for_scoring=  s    t#88O' ))1UV
  'txxF+!-!4!4!:!:J!%!9!9J%$%TUU !YY[
-A-Q-Q&* $

.*
 !IIK*4	:9S/KL &&..335KK ab --- $/!%l&8&8&C&C&E!F!M!M!%151K1K1N1Nv1VD...335KK"I& RS---&))1ef %T+<dC
%$%lmm!YY[
-A-Q-Q&* $

.*
 !IIK*4	:9S/KL &&..335KK ab --- '.enne&D&DI[I[IhIhIjIjUpuF151K1K1N1Nv1VD...335KK"I& RS--- 01A1A0BCDDr1   )rS   rU   rT   rV   rW   rR   rE   rP   rH   r@   rC   rB   rA   rD   rI   r7   rX   rO  )r\   N)Nr   g?r   )FNN)F)rn   rF  FN)FT)TFNNNNFTFFr   r!   r!   r!   N)TFNNFTFFr   r!   r!   r!   N)333333?r   r   NNr   TFNNTTTNNN)r!   Fr   r   )Fr   )g333333?NNr   TF)FFr   )FNr  NNr   TF)Nr  NNr   TF)NTFF)Orw  
__module____qualname____firstlineno____doc__STOP_REASONING_TAGrJ   rK   rL   rQ   r   re   rZ   rk   rt   rq   r   r   r   r  r   rg  r   r   r   r   r   r   r   r   r   r   r   rF   r  r  r  r"  r)  r0  r   r;  r   rA  rH   r  rk  r  r  r  r  r  r"  r   r   r>  rK  rJ  r^  rg  rj  rr  r  r   r  r  r  staticmethodrh  ri  r  ri  r  r  r  r	   r  r  __static_attributes__r9  r1   r/   r3   r3   0   sV   2# ::>>*5TA!+ !+F (D@Y*S *T#Y 0S 0e 0di 0  }B 0  MR  SX  Z^  S^  M_ 0l '+	A!%A A sm	A
 
AFjs jt j %  DW  $ 04-18*"&8* %)8* "%	8*
  S(3-%7 898*  8* 8* 8* 8* 8* 8* 'uo8* $E?8* 
4	58*B   	
    
6mc m3 m5sCS m"%,, x} QVQ]Q] %,, x SXS_S_ 0U\\ 0 0%,, 0u|| 3 V^_bVc hl ERtIu E  @E  @L  @L E || 38n	
 "#  
01c49n8M 1RWX\]`XacgXgRh 1 $'+VmVm Vm 	Vm
 Vm Vm $Vm 
sDy	Vmp]f# ]fd ]f`d ]fps ]fP *.+004-1+/<@"' "# %%)/mA d3i0mA mA 	mA
 mA }mA mA "mA #'mA %)mA 'uomA $E?mA "%mA  S(3-%7 89mA  mA  !mA" #mA$ %mA& 'mA( )mA* +mA, -mA. S	"/mA0 
sDI~	1mA^^^ ^ 	^
 ^ }^ ^ "^ #'^ %)^ "%^  S(3-%7 89^  ^ ^ ^  !^" #^$ %^& '^( )^* 
+^R *.+0+/<@"' "# %%)+b
 d3i0b
 b
 	b

 b
 }b
 b
 "b
 #'b
 %)b
 "%b
  S(3-%7 89b
  b
 b
 b
  !b
" #b
$ %b
& 'b
( )b
* S	"+b
, 
sDI~	-b
H8Dhsm9K4L+M RV 0S#X 03 0D ".#!%$')-+0+/<@" $!%$(%))@@ @ 	@
 @ @ @ }@ @ "@ #'@ %)@ "%@  S(3-%7 89@ @  !@" #@$ SM%@& S	"'@* 
c3h+@D.
c .
3 .
Y] .
y| .
  X[ .
  ru .
`Ts TC TSV Tlp T  LO T  fi Tr $).	.
.
 !.
 	.

 
.
f !#!%$')-+0b$b$ b$ }	b$
 b$ "b$ #'b$ %)b$ 
tCH~s"	#b$H$#s $#s $#R ##(.4
4
 4
 !	4

 4
 
4
r #(,!#!%$')-+0x$x$ x$ !	x$
 x$ }x$ x$ "x$ #'x$ %)x$ 
tCH~s"	#x$| $).2
2
 2
 !	2

 2
 
2
p 37!#!%$')-+0P$P$ P$  S#X/	P$
 P$ }P$ P$ "P$ #'P$ %)P$ 
tCH~s"	#P$j )-)-+0"'^^ d38n%^ #'	^
 %)^  ^ 
sCx^V OS^<<^ !.^ 	^
 ^ }^ ^ "^ ^ <(^  ((JK^ 
^X OSll 'u||4l 	l
 l l }l l "l l <(l  ((JKl 
l\v%3 v%5c3h9L3M v%x t   V;# V;%c	2B V;p> &*!gg g 	g
 g g }g g "g #'g %)g "%g g g g  S	"!g" 
c#gRAA A 	A
 A }A A "A #'A %)A "%A  S(3-%7 89A  A A A  !A" #A$ %A& 'A( )A* 
+AF
nn n 	n
 n }n n "n #'n %)n "%n  S(3-%7 89n  n n n  !n" #n$ %n& 'n( )n* 
+nr *.+0+/<@"' "# %%)+D
 d3i0D
 D
 	D

 D
 }D
 D
 "D
 #'D
 %)D
 "%D
  S(3-%7 89D
  D
 D
 D
  !D
" #D
$ %D
& 'D
( )D
* S	"+D
, 
sDI~	-D
T 8H 8Ht`Er1   r3   )1r  rr   rJ   r$   r   r_  r  r)   typingr   r   r   r   r   r   
contextlibr	   r  rF   logurur
   r   transformersr   r   !transformers.generation.streamersr   r  r   r   acestep.llm_backend_compatr   r  r   acestep.constantsr   r   r   r   r   r   acestep.gpu_configr   r   r   r   rj  r0   r3   r9  r1   r/   <module>r     sy    
 	 
     : : %     < : B S u  u s s
  	
mAE mAEr1   