
    (HJjL                     .   d Z ddlZddlZddlZddlZddlZddlZddlmZ ddl	m
Z
 ddlmZmZmZ ddlZddlmZ ddlmZ ddlZddlmZ ddlmZ ddlmZ d	d
lmZ d	dlmZ d	dl m!Z! d	dl"m#Z# dZ$d Z%d Z&d Z'd Z( ed       G d de             Z)d Z*y)z9
Adapted from a PyTorch implementation by David Grangier
    N)version)Path)AnyCallableOptional)LM)register_model)tqdm   )batch_generate)make_prompt_cache)make_sampler)loadi    c                     t        |       }|D cg c]  }| j                  |       }}|D cg c]  }|dk  r|n| }}| dt        |       S c c}w c c}w )zFLimit a string <s> to the first occurrence of any substring in untils.r   N)lenfindmin)suntilslufxs         Y/Users/ahmed/devFolder/claude-voice/.venv/lib/python3.12/site-packages/mlx_lm/evaluate.py_rstrip_untilr   !   s^    AA"#FqFA#$%&Aqa!e	AA&Xs1v; 	$&s
   AAc                 T    | j                  |      x}dk7  r| |t        |      z   d S | S )zHTruncate the prefix of the string after the first occurrence of pattern.N)r   r   )r   patternidxs      r   _lstripr    )   s3    vvg2%s7|#%&&H    c                 p   t        j                  | D cg c]  }t        |       c}      }|j                         }t        j                  | D cg c]&  }t        j
                  |d|t        |      z
  f      ( c}d      }t        j                  |      t        j                  |      fS c c}w c c}w )Nr   axis)nparrayr   maxstackpadmx)inputsr   lengthsmaxlenpaddeds        r   _pad_inputsr/   0   s    hh/1A/0G[[]FXX289&QAvA'	(&9F 88FRXXg... 0 	:s   B.+B3c                  "     ddt         f fd}|S )Nreturnc                 H     | j                   j                  |fd|| dS )NF)tokenizeadd_generation_promptcontinue_final_message)	tokenizerapply_chat_template)selfchat_historyr4   extra_kwargss      r   r7   z-chat_template_fn.<locals>.apply_chat_template;   s:    1t~~11
"7'<#<	

 
 	
r!   )T)str)r:   r7   s   ` r   chat_template_fnr<   :   s    
s 
 r!   mlxlmc                       e Zd Z e       Z	 	 	 	 	 ddedee   dedee   dedee	e
j                  ge
j                  f      ddf fd	Zdd
efdZddee   d
efdZd Zedefd       Zdeeeef      fdZdee   fdZdee   fdZ xZS )MLXLMNpath_or_hf_repo
max_tokens
batch_sizeuse_chat_templatetrust_remote_codesamplerr1   c                     t         |           d|rdnd i}t        ||      \  | _        | _        || _        || _        || _        || j                  j                  d u| _        || _	        y )NrD   T)tokenizer_config)
super__init__r   _modelr6   _max_tokens_batch_sizerC   chat_template_sampler)	r8   r@   rA   rB   rC   rD   rE   rG   	__class__s	           r   rI   zMLXLM.__init__L   sx     	/9JPTU&*.>'
#T^ &%!2$%)^^%A%A%MD"r!   	step_sizec                    t        j                  |      d    }t        | j                        }t	        d|j
                  d   |      D ]b  }| j                  |d d |||z   f   |      }t        j                  |D cg c]  }|j                   c}       t        j                          d t        j                  d d dd d f   j                  t         j                              }||fS c c}w )Nr   r   cacher   )r*   r&   r   rJ   rangeshapeevalstateclear_cachennlog_softmaxastypefloat32)r8   promptrP   rS   ilogitsclogprobss           r   _process_promptzMLXLM._process_prompta   s    &!$'!$++.q&,,q/95A[[1q9}+<(<!=U[KFGGe,eQWWe,-NN 6 >>&B"2"9"9"**"EF -s   =C-
rS   c           	         t        |      \  }}|dd df   |ddd f   }}|xs t        | j                        }d}g g }}t        d|j                  d   |      D ]J  }	|d d |	|	|z   f   }
|
j                  d   }| j                  |
|      }t        j                  |j                  t        j                              }t        j                  ||d d |	|	|z   t        j                  f   d      d   }|d d |	|	|z   f   t        j                  |d      k(  }t        j                  t        j                  |||z         |d d d f   k  |d      }t        j                  ||       t        j                           |j#                  |       |j#                  |       ||z  }M t        j$                  |d      }t        j$                  |d      }|||fS )	N.r   r   r   rR   r#   ).r   F)r/   r   rJ   rT   rU   rY   rZ   r[   r*   r\   take_along_axisnewaxisargmaxwherearangerV   rX   appendconcatenate)r8   r+   rS   rP   r,   targetsoffsetscores	is_greedyr^   inpTr_   	log_probsscoreigs                   r   	_score_fnzMLXLM._score_fnk   s   %f- crc*F37O7*4;;7	q&,,q/95AAI--.C		!A[[E[2Fv}}RZZ'@AI&&71a!i-&7#CD2E AI--."))F2LLB"))FAJ7'!T':JJBPUVBGGE2NNR MM% aKF' 6* Q/NN915	w	))r!   c           	          |D cg c]3  }t        | j                  j                  || j                               5 c}S c c}w )Nadd_special_tokens)tupler6   encoderC   )r8   textsts      r   	_tokenizezMLXLM._tokenize   sR    
 	
  %%a@V@V<V%W 	
 	
 
s   8A c                 N    | j                   j                  j                  dd      S )N/__)r6   name_or_pathreplace)r8   s    r   tokenizer_namezMLXLM.tokenizer_name   s    ~~**223==r!   c                    t        j                  dt        |      z         t        j                  j                         }t        j                  t              }t        |      D ]5  \  }}||j                  d      j                  ||j                  d   f       7 t        |j                               }g }g }|j                         D ]/  }	t        |	 \  }}
|j                  |       |j                  |
       1 ||j                         d|j!                            }||j                         d|j!                            }d}g g }}t#        t        ||      t        |            D ]<  \  }}| j%                  |g      d   }| j%                  |D cg c]  }||z   	 c}      }t'        d |D              }| j(                  xs t*        }t'        d||z
  dz
        }t        |      }t'        t        |      |z
  d      }|t        |      |z
  d }|dk(  rU|dz  }t,        j/                  t1        d       gt        |      z         t2        j/                  dgt        |      z         | j5                  |      \  }}t        j6                  |      j9                         }|D ]  }|t        |      d }|j                  |d|d   f   j9                                |j                  |d   |k(         t        |      dk(  r^| j;                  t        j<                  |      dddf   t?        j@                  |      	      \  }}}|d
xx   t        jB                  |      j9                         z  cc<   |d
xx   t        jD                  |      j9                         z  cc<    ? |dkD  rt        j                  d| ddz          t        |      } t        j                  jG                  t        |      t        jH                        j9                         }!|dg|!t        |      z
  z  z   }|dg|!t        |      z
  z  z   }t        j<                  |      }t        j<                  |      }t        j                  jK                  |t        jH                        }t        j                  jK                  |t        jH                        }t        jL                  ||       g }"tO        |j!                               D ]T  }#||#d|j!                            D $cg c]  }$|$D ]  }|  }%}$}|%| g|!t        |%      z
  z  z  }%|"j/                  |%       V t        jP                  t        j<                  |"            }&|d|  |&   }|d|  |&   }t        t        |jS                         |jS                                     S c c}w c c}}$w )a  Compute log-likelihood of generating a continuation from a context.
        Downstream tasks should attempt to use loglikelihood instead of other
        LM calls whenever possible.
        :param requests: list[Instance]
            A list of Instance objects, with property `args` which returns a tuple (context, continuation).
            `context: str`
                Context string. Implementations of LM must be able to handle an
                empty context string.
            `continuation: str`
                The continuation over which log likelihood will be calculated. If
                there is a word boundary, the space should be in the continuation.
                For example, context="hello" continuation=" world" is correct.
        :return: list[tuple[float, bool]]
            A list of pairs (logprob, isgreedy)
            `logprob: float`
                The log probability of `continuation`.
            `isgreedy`:
                Whether `continuation` would be generated by greedy sampling from `context`.
        z&Estimating loglikelihood for %d pairs.r   r   N)totalc              3   2   K   | ]  }t        |        y wNr   ).0r   s     r   	<genexpr>z&MLXLM.loglikelihood.<locals>.<genexpr>   s     !A.Q#a&.   infFrR   r   zPrefix eliminated for z requests with zcompletion longer than context.stream)*logginginfor   r*   distributedinitcollectionsdefaultdictlist	enumerateargsri   keysvalueszipranksizer
   r|   r'   rK   DEFAULT_MAX_TOKENS
all_scoresextendfloatall_is_greedyrb   rf   itemrt   r&   copydeepcopysumallall_maxcpu
all_gatherrV   rT   argsorttolist)'r8   requestsgroup
group_reqsr   req	questions	responsesindicesvresplong_completionsrm   rn   qrsprefixrfull_sequencesmax_completed_lrA   
truncationorig_prefix_lprefix_lra   rS   max_idxr   r+   rr   _rs   num_results	per_groupall_indicesr   questionrank_indicesinv_sorts'                                          r   loglikelihoodzMLXLM.loglikelihood   s   ( 	=HMN##% !,,T2
!(+HCsxx{#**C!+=> ,*+		""$AQICNN3T" % ejjl:ejjl:;	ejjl:ejjl:;		#i33y>JJEAr^^QC(+F!^^B,?BqQUB,?@N!!A.!AAO ))?-?JQ* <q @AJKM3v;3Q7HCK(245F 1} A% !!E%L=/CG";<$$eWs2w%67 #226:OHeii)..0G#3v;=) hq&)|499;<  &)w"68v;!##~~HHV$T1W-T]]55I  .  q" r
bffUm0022
"!22 $/ KL aLL()9(:/J34 (mNN**3v;rvv*FKKM	1#S[!8999s9~+E FF	&!HHY'	**6"&&*ANN--i-G	
	" %**,'D$+D,@EJJL,@$A$AXcX$A   [MY\9J-JKKL|, ( ::bhh{34%h/l{+H5	C)9)9);<==E -@rs   V>
Wc                    t        j                  dt        |      z         | j                  |D cg c]  }|j                  d    c}      }g }t        t        dt        |      | j                              D ]  }|||| j                  z    }| j                  |      \  }}}	t        j                  |j                  d         |dddf   k  }
|j                  |
|z  j                  d      j                                 |S c c}w )a  Compute full log-likelihood of a string, with no truncation, for perplexity computation
        - We will use the full max context length of the model.
        - For inputs that exceed the max context length, we divide the tokenized string into chunks of up to
        the max context length.
        - IMPORTANT: Each document's loglikelihood/perplexity is computed *separately*, unlike other implementations
          which may simply concatenate multiple documents together.
        - IMPORTANT: We maximize the amount of context for each prediction. Specifically, for inputs that we break into
          multiple chunks, the last input will still a full-sized context.
          Example:
            Input tokens: [ 0 1 2 3 4 5 6 7 8 9 ]
            Prefix: EOT
            Max context length: 4
            Resulting input/prediction pairs:
                INPUT:  EOT   0   1   2
                PRED:     0   1   2   3
                INPUT:    3   4   5   6
                PRED:     4   5   6   7
                INPUT:    5   6   7   8
                PRED:             8   9
          Observe that:
            1. Each token is predicted exactly once
            2. For the last pair, we provide the full context, but only score the last two tokens
        :param requests: list[Instance]
            A list of Instance objects with property `args` which returns a tuple (context,).
            string: str
                String for which we are computing overall loglikelihood
        :return: list[tuple[float]]
            A list of tuples (logprob,)
            logprob: float
                The log probability of `context` conditioned on the EOT token.
        z2Estimating loglikelihood rolling for %d sequences.r   r   Nr#   )r   r   r   r|   r   r
   rT   rL   rt   r*   rh   rU   r   r   r   )r8   r   r   r+   r   r^   batchrm   r,   r   masks              r   loglikelihood_rollingzMLXLM.loglikelihood_rolling  s    @ 	@3x=P	
  A! AB
eAs6{D,<,<=>A1q4#3#334E!%!6FGQ99V\\"-.D1AADtf}11r1:AACD	 ?  !Bs   Dc                 J   t         j                  j                         }t        |      }||j	                         d|j                            }t        j                  dt        |      z         t        |D cg c]  }|j                   c} \  }}|D cg c]*  }| j                  j                  || j                         , }}|D cg c]&  }| j                  xs |j                  dt              ( }	}t!        | j"                  | j                  ||	d| j$                        j&                  }
t)        t        |
|            D ]T  \  }\  }}t+        ||d         |
|<   | j                  j,                  s2t/        || j                  j0                        |
|<   V |j                         dkD  rAt        j2                  t         j4                        5  ||j                         z   dz
  |j                         z  }|t        |
      z
  }|
D cg c]  }t7        |j                  d	             }
}t        j8                  t;        d
 |
D                    }t         j                  j=                  |      j?                         }t        j8                  |
D cg c]  }t        |       c}dg|z  z         }t        j8                  |
D cg c]  }|dg|t        |      z
  z  z    c}dg|z  g|z  z   t         j@                        }
t         j                  jC                  |
d         jE                  dd      jG                  dd      jI                         }
t         j                  jC                  |d         jE                  dd      jG                  dd      jI                         }|
d| }
|d| }t        |
|      D cg c]!  \  }}tK        |d|       jM                         # }
}}ddd       |
S |
S c c}w c c}w c c}w c c}w c c}w c c}w c c}}w # 1 sw Y   |
S xY w)aC  Generate greedily until a stopping sequence
        :param requests: list[Instance]
            A list of Instance objects with property `args` which returns a tuple (context, until).
            context: str
                Context string
            until: [str]
                The string sequences to generate until. These string sequences
                may each span across multiple tokens, or may be part of one token.
        :return: list[str]
            A list of strings continuation
            continuation: str
                The generated continuation.
        Nz)Generating continuation for %d sequences.rv   max_gen_tokensT)modelr6   promptsrA   verboserE   untilr   zutf-8c              3   2   K   | ]  }t        |        y wr   r   )r   r`   s     r   r   z'MLXLM.generate_until.<locals>.<genexpr>p  s     &C{!s1v{r   r   )'r*   r   r   r   r   r   r   r   r   r   r6   ry   rC   rK   getr   r   rJ   rN   rz   r   r   has_thinkingr    	think_endr   r   r   r&   r'   r   r   uint8r   swapaxesflattenr   	bytearraydecode)r8   r   r   total_requestsr   contextsoptionscontextoptrA   completionsetextpad_tor)   r`   max_lenr,   r   s                      r   generate_untilzMLXLM.generate_until5  s    ##% XEJJL8EJJL89@3x=PQh!?hs#((h!?@' $	
 $ NN!!0F0F,F "  $	 	 
 
 M(8:L MM 	 

 %++nn!MM
 % 	 (K(ABNA{c*4W>KN~~**!(t~~/G/G!HA C ::<!266"(5::<7!;

Ls;//@KL1tAHHW$56L((3&C{&C#CD..009>>@((K#@KqCFK#@A39#LM hh;FG;aQ!#a& 011;GsW}o+,HH NN--k$.?@Xa^WQ]VX	  NN--gdm<Xa^WQ]VX	  */>:!/>2:=k7:S:S$!QIae$++-:S  5 #< {A "@


0 M $AG$5 #< sV   8O4/O9+O>:P!P/A'PP
(!P	P
%CP?&P%PPP")N   NFN)   )Nr   )__name__
__module____qualname__r<   r7   r;   r   intboolr   r*   r&   rI   rb   r   rt   r|   propertyr   r   rx   r   r   r   r   __classcell__)rO   s   @r   r?   r?   G   s    +,
 %),0"'<@   SM  	 
 $D>     (BHH:rxx#789  
 * *x} * *B
 > > >n>eE4K.@)A n>`+e +ZU$s) Ur!   r?   c                  d	   t        j                  d      } | j                  ddd       | j                  ddd       | j                  d	d
d       | j                  dt        dd       | j                  dt        d d       | j                  dt        dd        | j                  dd dt               | j                  dt        dd       | j                  dddd        | j                  d!t         j                  d"d         | j                  d#t
        j                  d$d%       | j                  d&dd'd        | j                  d(dd)*       | j                  d+t        d,d-       | j                  d.t        d/d0       | j                  d1t        d2d3       | j                         }t        |j                        }|j                  dd4       d5t        j                  d6<   t        j                  j!                  |j                          t        j"                  j%                         }t        j&                  t        j"                  j)                  d7t        j*                  8             |j-                         d7kD  r0|j/                         d2k(  rt1        d9|j-                          d:       t3        |j4                  |j6                  |j8                  ;      }t;        |j<                  |j>                  |j@                  |jB                  |jD                  |<      }tG        dGi |jH                  t:        _!        tK        jL                  ||jN                  |jP                  |jR                  |jT                  |jV                  |j                   |j                   |j                   |j                   |jX                  =      }d>|j<                  j[                  d?d@      t]        dA      g}|jT                  ||jT                  dBgz  }||jN                  z  }d@j_                  |      }|j/                         d2k(  rr||z  }	|	ja                  t        jb                  |dC   dDE             t1        dF       |dC   je                         D ]"  }
t1        t        jb                  |
dDE             $ y y )HNz2Evaluate an MLX model using lm-evaluation-harness.z--modelzModel to evaluateT)helprequiredz--tasks+)nargsr   z--output-dir.z"Output directory for result files.)defaultr   z--batch-size   z
Batch size)typer   r   z--num-shotszNumber of shotsz--max-tokenszhMaximum number of tokens to generate. When set, this value takes precedence over task specific defaults.)r   r   r   z--limitz&Limit the number of examples per task.)r   r   r   z--seed{   zRandom seed.z--fewshot-as-multiturn
store_truezZWhether to provide the fewshot examples as a multiturn conversation or a single user turn.F)actionr   r   z--apply-chat-templatezSpecifies whether to apply a chat template to the prompt. If the model has a chat template, this defaults to `True`, otherwise `False`.z--chat-template-argszvA JSON formatted string of arguments for the tokenizer's
        apply_chat_template, e.g. '{"enable_thinking":false}'z{}z--confirm-run-unsafe-codez?Confirm that you want to run tasks that execute untrusted code.z--trust-remote-codez)Enable trusting remote code for tokenizer)r   r   z--tempg        zSampling temperaturez--top-pg      ?zSampling top-pz--top-kr   zSampling top-k)parentsexist_okfalseTOKENIZERS_PARALLELISMr   r   zEvaluating with z nodes)temptop_ptop_k)rA   rB   rC   rD   rE   )r   tasksfewshot_as_multiturnr7   num_fewshotlimitrandom_seednumpy_random_seedtorch_random_seedfewshot_random_seedconfirm_run_unsafe_coderV   r~   r   lm_eval02dresults   )indentzResults: )3argparseArgumentParseradd_argumentr   BooleanOptionalActionjsonloadsr   
parse_argsr   
output_dirmkdirosenvironr*   randomseedr   r   rV   all_sumr   r   r   printr   r   r   r   r?   r   rA   rB   r7   rD   r<   chat_template_argsr
  simple_evaluater  r  rC   	num_shotsr  r	  r   r   join
write_textdumpsr   )parserr   r  worldrE   lmr  	file_keysfilenameoutput_pathresults              r   mainr,    s?   $$<F 	(;dK
	t<
*N   S"<P
CDUV
3   5	   sCnM
 .   --    ZZA   #N	   8  
 uc@VW
	sAQR
	Q=MNDdoo&JTD1 ,3BJJ'(IINN499 NN!EGGBNN""1RVV"45zz|aEJJLA- f56YYjjjjG
 


????2200
B !1 K43J3J KE%%jj!6600NNjjII)))) II $ < <G ++C5wy7IJI~~!,..	Ixx	"Hzz|q 8+tzz')*<QGHji(//1F$**VA./ 2	 r!   )+__doc__r  r   r   r  r   r  importlib.metadatar   pathlibr   typingr   r   r   r
  mlx.corecorer*   mlx.nnrY   numpyr%   lm_eval.api.modelr   lm_eval.api.registryr	   r
   generater   models.cacher   sample_utilsr   utilsr   r   r   r    r/   r<   r?   r,  r  r!   r   <module>r;     s         	 &  * *       /  $ + &  /
 BB B BJ
t0r!   