ó
    ‡Ž¡j\  ã            
       ó–  • S r SSKrSSKrSSKrSSK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  SS	KJr  SS
KJr  SSKJrJrJr  SSKJrJr  SSKJr  SSK J!r!J"r"  \" 5       (       a  SSK#J$r$  \RJ                  " \&5      r'S\(\RR                  -  S\(S-  S\(S-  4S jr*S\(\RR                  -  S\(S\(S-  4S jr+ S,S\(\RR                  -  S\,S-  S\-\,\(S-  4   4S jjr.SSSSS.r/S\0S\-\1\(   \24   4S  jr3 " S! S"5      r4S#\S\(4S$ jr5S#\S%\(SS4S& jr6S#\S'\(\RR                  -  S\-\(S(4   4S) jr7 S,S*\(S\(S-  S\4S+ jjr8g)-zOConversion between Mistral tekken tokenizers and HuggingFace tokenizer formats.é    N)Ú	lru_cache)ÚPath)Úcopyfile)Ú
AddedTokenÚRegexÚ	TokenizerÚdecodersÚpre_tokenizersÚ
processors)ÚBPEé   )Úbytes_to_unicode)ÚTokenizersBackend)Úcached_fileÚloggingÚrequires_backends)ÚCHAT_TEMPLATE_FILEÚ#LEGACY_PROCESSOR_CHAT_TEMPLATE_FILE)Úis_mistral_common_availableé   )ÚTEKKEN_VOCAB_FILEÚis_tekken_vocab_filename)Ú
TekkenizerÚtekken_fileÚchat_templateÚreturnc                 óö  • Ub  U$ [        U 5      R                  nU[        -  nUR                  5       (       a  UR	                  SS9$ U[
        -  nUR                  5       (       a.  [        USS9 n[        R                  " U5      nSSS5        US   $ [        5       (       a   SSK
Jn  U" U 5      $ g! , (       d  f       WS   $ = f! [         a&  n[        R                  SU  SU S	35         SnAgSnAff = f)
uL  Resolve the chat template to attach during tekken to HF conversion.

Applies a fixed precedence order:

1. `chat_template` argument (if not `None`) â€” returned unchanged.
2. Sibling `chat_template.jinja` file in the same directory as *tekken_file*.
3. Sibling `chat_template.json` file â€” value of its `"chat_template"` key.
4. Automatic generation via `mistral_common.integrations.chat_templates` (lazy import).
5. `None` if none of the above succeed.

Args:
    tekken_file (`str` or `os.PathLike`): Path to the `tekken.json` file.
    chat_template (`str` or `None`): Explicit chat template string. Only `None`
        triggers the lookup cascade; an empty string is returned as-is.

Returns:
    Resolved chat template string, or `None`.

Raises:
    KeyError: If `chat_template.json` exists but does not contain a `"chat_template"` key.
Núutf-8©Úencodingr   r   )Ú"convert_tokenizer_to_chat_templatez'Failed to generate chat template from 'z': z#. Falling back to no chat template.)r   Úparentr   Úis_fileÚ	read_textr   ÚopenÚjsonÚloadr   Ú9mistral_common.integrations.chat_templates.chat_templatesr!   Ú	ExceptionÚloggerÚwarning_once)	r   r   r"   Ú
jinja_pathÚ	json_pathÚfÚdatar!   Úexcs	            Ú¹C:\Users\johnn\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.13_qbz5n2kfra8p0\LocalCache\local-packages\Python313\site-packages\transformers/integrations/mistral/tokenizer.pyÚ_resolve_chat_templater2   *   s  € ð. Ñ ØÐä�+Ó×%Ñ%€Fð Ô,Ñ,€JØ×Ñ×ÑØ×#Ñ#¨WÐ#Ð5Ð5ð Ô<Ñ<€IØ×Ñ×ÑÜ�) gÒ.°!Ü—9’9˜Q“<ˆD÷ /à�OÑ$Ð$ô #×$Ñ$ð
	õñ 6°kÓBÐBð ÷' /Ô.à�OÑ$Ð$ûô ó 	Ü×ÑØ9¸+¸ÀcÈ#ÈÐNqÐrôô ûð		ús$   Á0B3Â$C Â3
CÃ
C8ÃC3Ã3C8Úpretrained_model_name_or_pathÚfilenamec                 ó"   • [        U U4SSS.UD6$ )a  Return the resolved path for *filename* inside *pretrained_model_name_or_path*, or `None`.

Exceptions for missing entries and connection errors are suppressed so that
callers can treat a `None` return as "file not found / not reachable".

Args:
    pretrained_model_name_or_path (`str` or `os.PathLike`): Model id or local directory.
    filename (`str`): File name to look up inside the checkpoint.
    **cache_kwargs: Forwarded to [`~utils.cached_file`].

Returns:
    Resolved local path string, or `None` if the file could not be found.
F)Ú%_raise_exceptions_for_missing_entriesÚ'_raise_exceptions_for_connection_errors)r   )r3   r4   Úcache_kwargss      r1   Ú_probe_filer9   d   s.   € ô$ Ø%Øðð /4Ø05ñ	ð
 ñð ó    Úmistral_formatc                 ó>  • USL a  gUR                  SS5        UR                  SS5        USL aH  [        5       (       d  [        S5      e[        U [        40 UD6nUc  [        S[         S	U  S
35      eSU4$ [        5       (       d  g[        U [        40 UD6nUSLU4$ )uh  Resolve whether to use `MistralCommonBackend` for tokenization.

Probes for `tekken.json` in the checkpoint directory and checks whether
`mistral-common` is installed to determine the appropriate tokenizer backend.

Args:
    pretrained_model_name_or_path (`str` or `os.PathLike`):
        This can be either:

        - a string, the *model id* of a pretrained model hosted on huggingface.co.
        - a path to a *directory* containing model files.
    mistral_format (`bool`, *optional*):
        Tri-state control for tokenizer backend selection:

        - `True` â€” force `MistralCommonBackend` (raises `ImportError` if `mistral-common`
          is not installed, raises `OSError` if `tekken.json` is not found).
        - `False` â€” force standard HuggingFace tokenizer.
        - `None` â€” auto-detect: selects native (`MistralCommonBackend`) when
          `mistral-common` is installed and a `tekken.json` is found, regardless of
          whether HF-format files are also present. Otherwise falls back to the
          standard HuggingFace tokenizer.
    **cache_kwargs:
        Forwarded to [`~utils.cached_file`] (e.g. `cache_dir`, `force_download`,
        `local_files_only`, `revision`, `token`).

Returns:
    `tuple[bool, str | None]`: A tuple of `(use_mistral_format, tekken_file_path)` where
    `use_mistral_format` indicates whether `MistralCommonBackend` should be used, and
    `tekken_file_path` is the resolved path to `tekken.json` (or `None`).

Raises:
    ImportError: If `mistral_format=True` and `mistral-common` is not installed.
    OSError: If `mistral_format=True` and `tekken.json` cannot be found.
F)FNr6   Nr7   TzZmistral_format=True requires `mistral-common`. Install it with: pip install mistral-commonzCannot find 'z' at 'zH'. Set `mistral_format=False` to use standard HuggingFace files instead.)Úpopr   ÚImportErrorr9   r   ÚOSError)r3   r;   r8   r   s       r1   Úresolve_mistral_formatr@      sÛ   € ðN ˜ÒØð ×ÑÐ<¸dÔCØ×ÑÐ>ÀÔEà˜ÒÜ*×,Ñ,ÜØlóð ô
 "Ð"?ÔARÑcÐVbÑcˆØÑÜØÔ 1Ð2°&Ð9VÐ8Wð XXð Xóð ð �kÐ"Ð"ô '×(Ñ(ØäÐ;Ô=NÑ_ÐR^Ñ_€KØ˜tÐ# [Ð1Ð1r:   z<s>z</s>z<pad>z<unk>)Ú	bos_tokenÚ	eos_tokenÚ	pad_tokenÚ	unk_tokenÚrawc                 ó>  • U S   nSnU R                  S5      nUc;  [        [        S/5        [        [        SU5      n[        [        R                  5      n[        S U 5       5      nU[        [        [        U5      5      5      :w  a  [        SU 35      e[        S U 5       5       VVs/ s H  u  pVUPM	     nnnUR                  S	5      nUc  [        U5      n[        [        U5      U5       V	s/ s H  o’R                  U	S
9PM     n
n	Xz-   U4$ s  snnf s  sn	f )a  Derive the expected special-token strings and special-token count from a parsed tekken.json.

Single source of truth for the special-token layout, shared by
`MistralConverter._parse_tekken_file` (to build the vocab) and
`_check_tekken_vocab_unchanged` (to compare against a live tokenizer), so the two cannot
silently drift apart.

Args:
    raw (`dict`): A parsed tekken.json, i.e. the result of `json.load` on the file.

Returns:
    `tuple[list[str], int]`: The special-token strings, ordered by rank (the real entries
    from *raw* followed by any `<SPECIAL_i>` filler needed to reach `num_special_tokens`),
    and the resolved `num_special_tokens`.

Raises:
    ImportError: If *raw* has no top-level `"special_tokens"` key (old tekken format) and
        `mistral-common` is not installed.
Úconfigz<SPECIAL_{id}>Úspecial_tokenszmistral-commonÚSPECIAL_TOKEN_TEMPLATEc              3   ó*   #   • U  H	  oS    v •  M     g7f)ÚrankN© ©Ú.0Úentrys     r1   Ú	<genexpr>Ú*_derive_tekken_specials.<locals>.<genexpr>í   s   é € ÐLÒ7K¨e &žMÒ7Kùs   ‚zGtekken.json special_tokens ranks must be contiguous starting at 0, got c           
   3   ód   #   • U  H&  nUS    [        [        US   SUS   5      5      4v •  M(     g7f)rK   Ú	token_strÚvalueN)ÚstrÚgetattrrM   s     r1   rP   rQ   ó   s8   é € ð #
â-�ð �6‰]œC¤¨¨kÑ(:¸GÀUÈ;ÑEWÓ XÓYÕZÚ-ùs   ‚.0Údefault_num_special_tokens)Úid)Úgetr   ÚMistralConverterrV   r   ÚlistÚDEPRECATED_SPECIAL_TOKENSÚsortedÚrangeÚlenÚ
ValueErrorÚformat)rE   rG   Úfiller_templateÚspecial_tokens_dictsÚdeclared_ranksÚ_rS   Úspecial_stringsÚnum_special_tokensÚiÚfiller_stringss              r1   Ú_derive_tekken_specialsrj   Í   s<  € ð( �‰]€FØ&€OàŸ7™7Ð#3Ó4ÐØÑ#äÔ*Ð-=Ð,>Ô?Ü!¤*Ð.FÈÓXˆÜ#¤J×$HÑ$HÓIÐô ÑLÑ7KÓLÓL€NØœœe¤C¨Ó$7Ó8Ó9Ó9ÜÐbÐcqÐbrÐsÓtÐtô #ñ #
á-ó#
ô 
ôò
‰LˆAó 	ñ
ð ñ ð  Ÿ™Ð$@ÓAÐØÑ!Ü  Ó1Ðä<AÄ#ÀoÓBVÐXjÔ<kÓlÒ<k°q×,Ñ,°Ð,Ó2Ñ<k€NÐlØÑ+Ð-?Ð?Ð?ùóùò ms   Â-DÃ4Dc            
       óª   • \ rS rSrSrSS\S\4S jjrS\S\SS4S jr\	S	\
\\4   S\\
\\4   \\\\4      4   4S
 j5       rS\4S jrS\4S jrSrg)rZ   i  zPConverter from Mistral tekken BPE vocab to a HuggingFace `tokenizers.Tokenizer`.Ú
vocab_fileÚadd_prefix_spacec                 ó&   • U R                  X5        g)a!  Parse a raw `tekken.json` file into a ready-to-use converter.

Matches `mistral_common`'s `Tekkenizer.from_file` vocab and special-token layout.

Args:
    vocab_file (`str`): Path to a `tekken.json` file.
    add_prefix_space (`bool`): Whether to add a leading space during tokenization.
N)Ú_parse_tekken_file)Úselfrl   rm   Úkwargss       r1   Ú__init__ÚMistralConverter.__init__  s   € ð 	×Ñ 
Õ=r:   r   Nc                 óÎ  • [        USS9 n[        R                  " U5      nSSS5        WS   nUS   nUR                  S5      n[	        U5      u  p‰U V
s/ s H  n
[        U
SS9PM     nn
US	   nUb	  Xy-
  nUSU nU Vs/ s H  n[        R                  " US
   5      PM     nn[        U5       VVs0 s H	  u  nnUU_M     nnnU R                  U5      u  nnUR                  5        VVs0 s H  u  nnUUU	-   _M     nnn[        U5       H  u  nn
UUU
'   M     X`l        X l        X°l        UU l        UU l        g! , (       d  f       GN$= fs  sn
f s  snf s  snnf s  snnf )zÊParse a tekken.json file and set all instance attributes.

Args:
    vocab_file (`str`): Path to a `tekken.json` file.
    add_prefix_space (`bool`): Whether to add a leading space during tokenization.
r   r   NrG   ÚpatternÚdefault_vocab_sizeT)ÚspecialÚvocabÚtoken_bytes)r%   r&   r'   rY   rj   r   Úbase64Ú	b64decodeÚ	enumerateÚ_extract_mergesÚitemsru   rm   Úadditional_special_tokensÚ_precomputed_vocabÚ_precomputed_merges)rp   rl   rm   r.   ÚuntypedrG   ru   Ú
vocab_sizeÚspecial_token_stringsrg   rS   r   Úbpe_ranks_rawÚinner_vocab_sizeÚkÚ	bpe_ranksrK   ÚtokenÚbpe_ranks_dictrx   ÚmergesÚvs                         r1   ro   Ú#MistralConverter._parse_tekken_file  s  € ô �* wÒ/°1Ü—i’i “lˆG÷ 0ð ˜Ñ"ˆØ˜Ñ#ˆØ—Z‘ZÐ 4Ó5ˆ
ä4KÈGÓ4TÑ1ÐáZoÓ$pÒZoÈY¤Z°	À4Ô%HÑZoÐ!Ð$pð   Ñ(ˆØÑ!Ø)Ñ>ÐØ)Ð*;Ð+;Ð<ˆMáANÓOÂ¸A”V×%Ò% a¨Ñ&6Ö7Áˆ	ÐOÜ9BÀ9Ô9MÔNÒ9M©+¨$°˜% š+Ñ9MˆÑNà×,Ñ,¨^Ó<‰ˆˆvà7<·{±{´}ÔE²}©t¨q°!��AÐ*Ñ*Ò*±}ˆÑEÜ(Ð)>Ö?‰OˆD�)Ø#ˆE�)Óñ  @ð ŒØ 0ÔØ)BÔ&Ø"'ˆÔØ#)ˆÕ ÷= 0Ö/üò %qùò PùÛNùó Fs#   ‹D?ÁEÂ#EÂ4EÃ.E!Ä?
Erˆ   c                 ó  ^ ^• [        5       m[        S[        S[        4U4S jj5       n0 n/ nT R	                  5        H’  u  pEXRU" U5      '   [        U5      S:X  a  M   / n[        S[        U5      5       H8  nUSU XGS p˜UT ;   d  M  U	T ;   d  M  X‰-   T ;   d  M%  UR                  X‰U45        M:     [        UU 4S jS9nUR                  U5        M”     [        US S9nU V
s/ s H  o¡" U
S	   5      U" U
S   5      4PM     nn
X+4$ s  sn
f )
zMExtract a unicode vocab and ordered BPE merge list from byte-level BPE ranks.Úbr   c           	      óˆ   >• SR                  U R                  S5       Vs/ s H  nT[        U5         PM     sn5      $ s  snf )NÚ zlatin-1)ÚjoinÚdecodeÚord)r�   ÚcharÚbyte_encoders     €r1   Útoken_bytes_to_stringÚ?MistralConverter._extract_merges.<locals>.token_bytes_to_string;  s8   ø€ à—7‘7ÀÇÁÈÔ@SÓTÒ@S¸˜L¬¨T«Ô3Ñ@SÑTÓUÐUùÒTs    ?r   Nc                 ó$   >• TU S      TU S      4$ )Nr   r   rL   )Úxrˆ   s    €r1   Ú<lambda>Ú2MistralConverter._extract_merges.<locals>.<lambda>K  s   ø€ °¸1¸Q¹4±À)ÈAÈaÉDÁ/Ñ0Rr:   )Úkeyc                 ó   • U S   $ )Né   rL   )Úvals    r1   r›   rœ   N  s   € ¸¸Aºr:   r   )
r   r   ÚbytesrU   r~   r_   r^   Úappendr]   Úextend)rˆ   r—   rx   Ú
all_mergesr‰   rK   ÚlocalÚindexÚpiece_lÚpiece_rr    r‹   r–   s   `           @r1   r}   Ú MistralConverter._extract_merges6  s,  ù€ ô (Ó)ˆä	ð	V¤Uð 	V¬sö 	Vó 
ð	Vð !#ˆØ57ˆ
à$Ÿ?™?Ö,‰KˆEØ26Ñ'¨Ó.Ñ/Ü�5‹z˜Q‹ÙØˆEÜ˜q¤# e£*Ö-�Ø#(¨¨% =°%¸°-˜Ø˜iÕ'¨G°yÕ,@ÀgÑFWÐ\eÕEeØ—L‘L '°DÐ!9Ö:ñ .ô ˜5Ô&RÑSˆEØ×Ñ˜eÖ$ñ -ô ˜JÑ,>Ñ?ˆ
Ù\fÓgÒ\fÐUXÐ(¨¨Q©Ó0Ñ2GÈÈAÉÓ2OÓPÑ\fˆÐgØˆ}Ðùò hs   Ã#Dc                 ó®   • [        [        U R                  U R                  SS95      n[	        UR
                  S5      (       a  SUR
                  l        U$ )zKBuild a raw `tokenizers.Tokenizer` with BPE model (no pre/post-processing).F)Úfuse_unkÚignore_mergesT)r   r   r€   r�   ÚhasattrÚmodelr¬   ©rp   Ú	tokenizers     r1   r°   ÚMistralConverter.tokenizerR  sE   € äœc $×"9Ñ"9¸4×;SÑ;SÐ^cÑdÓeˆ	Ü�9—?‘? O×4Ñ4Ø,0ˆI�O‰OÔ)ØÐr:   c                 ó„  • U R                  5       n[        R                  " [        R                  " [	        U R
                  5      SSS9[        R                  " U R                  SS9/5      Ul        [        R                  " 5       Ul
        UR                  U R                  5        [        R                  " SS9Ul        U$ )zOBuild a fully configured `tokenizers.Tokenizer` with pre-tokenizer and decoder.ÚisolatedF)ÚbehaviorÚinvert)rm   Ú	use_regex)Útrim_offsets)r°   r
   ÚSequenceÚSplitr   ru   Ú	ByteLevelrm   Úpre_tokenizerr	   ÚdecoderÚadd_special_tokensr   r   Úpost_processorr¯   s     r1   Ú	convertedÚMistralConverter.convertedY  s™   € à—N‘NÓ$ˆ	Ü"0×"9Ò"9ä×$Ò$¤U¨4¯<©<Ó%8À:ÐV[Ñ\Ü×(Ò(¸$×:OÑ:OÐ[`Ñaðó#
ˆ	Ôô %×.Ò.Ó0ˆ	ÔØ×$Ñ$ T×%CÑ%CÔDä#-×#7Ò#7ÀUÑ#Kˆ	Ô àÐr:   )r�   r€   rm   r   ru   )F)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__rU   Úboolrr   ro   ÚstaticmethodÚdictr¡   ÚintÚtupler[   r}   r   r°   r¿   Ú__static_attributes__rL   r:   r1   rZ   rZ     sš   † ÙZñ	> 3ð 	>¸$õ 	>ð%*¨Sð %*ÀDð %*ÈTô %*ðN ð 4¨¨s¨
Ñ#3ð ¸¸dÀ3ÈÀ8¹nÈdÐSXÐY\Ð^aÐYaÑSbÑNcÐ>cÑ8dó ó ðð6˜9ô ð˜9÷ r:   rZ   r°   c                 ó  • U R                   R                  S5      =(       d    [        U SS5      n[        U[        5      (       a4  [        U5      (       a$  [        R                  R                  U5      (       d  [        S5      eU$ )aû  Locate the on-disk `tekken.json` a tokenizer was built from.

Called once by `save_tekken_format`, which passes the resolved path on to
`_check_tekken_vocab_unchanged` to know what to diff against.

Args:
    tokenizer (`TokenizersBackend`): The tokenizer to resolve a source file for. Must
        have been loaded or converted from a native Mistral tekken vocabulary file,
        i.e. its `vocab_file` must still point at an existing file whose name identifies
        it as tekken (see `is_tekken_vocab_filename`).

Returns:
    `str`: The validated path to the tokenizer's source tekken vocabulary file.

Raises:
    OSError: If the tokenizer's `vocab_file` does not resolve to an existing file
        identified as tekken (see `is_tekken_vocab_filename`).
rl   Nz½Cannot save in 'mistral' format: the original tekken.json is not available. Load a native checkpoint (that still contains tekken.json) or install mistral-common to use MistralCommonBackend.)
Úinit_kwargsrY   rV   Ú
isinstancerU   r   ÚosÚpathÚisfiler?   )r°   rl   s     r1   Ú_resolve_tekken_sourcerÒ   j  ss   € ð& ×&Ñ&×*Ñ*¨<Ó8×b¼GÀIÈ|Ð]aÓ<b€JÜ�z¤3×'Ñ'Ô,DÀZ×,PÑ,PÔUW×U\ÑU\×UcÑUcÐdn×UoÑUoÜð:ó
ð 	
ð
 Ðr:   rl   c                 ó  • [        USS9 n[        R                  " U5      nSSS5        WS   n[        U5      u  pV[	        U5      nUR                  S5      nUc  [        US   5      U-   n[        U 5      n	U R                  R                  5        V
s1 s H  oªR                  iM     nn
[        X·-
  5      n[        X{-
  5      nX˜:g  nU(       d  U(       a‚  S/nU(       a  UR                  SU 35        U(       a  UR                  S	U 35        U(       a  UR                  S
U	 SU 35        UR                  S5        [        SR                  U5      5      eU(       a  [        SU	 SU S35      eg! , (       d  f       GNW= fs  sn
f )a÷  Compare *tokenizer*'s vocab against the `tekken.json` it was converted from.

`save_format="mistral"` writes a native `tekken.json` by copying the source file
directly, so any in-session mutation (`add_tokens`, `add_special_tokens`) would be
silently dropped, and `tekken.json` cannot represent arbitrary added tokens anyway.
This guard is called only from `save_tekken_format`, right before that lossy copy, to
turn a silent drop into a raised error.

Only two things are compared: the total vocab size, and the *set* of added-token
content strings (via `tokenizer.added_tokens_decoder`). This does not check token ids
or other `AddedToken` attributes (e.g. `lstrip`, `rstrip`, `normalized`).

Args:
    tokenizer (`TokenizersBackend`): The tokenizer to check. Never mutated.
    vocab_file (`str`): Path to the source `tekken.json` to compare against.

Raises:
    ValueError: If the vocab size or the added-token set diverges from the source
        `tekken.json`.
    OSError: If `vocab_file` cannot be opened.
r   r   NrG   rv   rx   z“Cannot save in 'mistral' format: the tokenizer vocab state has diverged from its source tekken.json, which cannot represent arbitrary added tokens.zUnexpected added tokens: z!Missing expected special tokens: zVocab size: observed=z, expected=z7Use save_format='hf' instead to preserve these changes.Ú
zGCannot save in 'mistral' format: the tokenizer reports a vocab size of z&, but its source tekken.json declares a   (via default_vocab_size/default_num_special_tokens). Either the vocab was resized in this session, in which case use save_format='hf' to preserve the change, or the source tekken.json is itself inconsistent and should be regenerated with matching vocab and config sizes.)r%   r&   r'   rj   ÚsetrY   r_   Úadded_tokens_decoderÚvaluesÚcontentr]   r¢   r`   r’   )r°   rl   r.   rE   rG   Úexpected_special_tokens_listrg   Úexpected_special_tokensÚexpected_vocab_sizeÚobserved_vocab_sizer‰   Úobserved_added_tokensÚunexpected_tokensÚmissing_tokensÚsize_divergesÚliness                   r1   Ú_check_tekken_vocab_unchangedrâ   ‡  s‘  € ô, 
ˆj 7Ò	+¨qÜ�iŠi˜‹lˆ÷ 
,ð �‰]€FÜ7NÈsÓ7SÑ4Ð Ü!Ð">Ó?Ðà Ÿ*™*Ð%9Ó:ÐØÑ"Ü! # g¡,Ó/Ð2DÑDÐä˜i›.ÐØ8A×8VÑ8V×8]Ñ8]Ô8_Ó`Ò8_¨uŸ]œ]Ñ8_ÐÐ`äÐ4ÑNÓOÐÜÐ3ÑKÓL€NØ'Ñ>€MæžNðJð
ˆö Ø�L‰LÐ4Ð5FÐ4GÐHÔIÞØ�L‰LÐ<¸^Ð<LÐMÔNÞØ�L‰LÐ0Ð1DÐ0EÀ[ÐQdÐPeÐfÔgØ�‰ÐNÔOÜ˜Ÿ™ 5Ó)Ó*Ð*æÜØUØ"Ð#Ð#IÐJ]ÐI^ð _&ð&ó
ð 	
ð ÷A 
,Ö	+üò as   ‹E2ÂFÅ2
FÚsave_directory.c                 óL  • [        U 5      n[        X5        [        R                  " USS9  [        R                  R                  U[        5      n[        R                  R                  U5      (       a$  [        R                  R                  X#5      (       d  [        X#5        U4$ )aÓ  Write a tokenizer back out in native Mistral format by copying its source tekken file.

Used by `TokenizersBackend.save_pretrained` for `save_format="mistral"`. The tokenizer's
original tekken vocabulary file (resolved via `vocab_file`) is copied byte-for-byte into
*save_directory* as `tekken.json`, regardless of the source's own basename (e.g. a source
named `tekken_240911.json` is normalized to `tekken.json` on save, so the output directory
stays discoverable by both `resolve_mistral_format` and mistral-common.

Resaving into the same directory the tokenizer was loaded from is a no-op copy: the
source and destination are the same file, so the copy is skipped instead of raising
`shutil.SameFileError`. The divergence guard still runs first, so an in-place resave of
a mutated tokenizer is still rejected.

Args:
    tokenizer (`TokenizersBackend`): The tokenizer to save. Must have been loaded or
        converted from a native Mistral tekken vocabulary file, i.e. its `vocab_file`
        must still point at an existing file identified as tekken (see
        `is_tekken_vocab_filename`), and it must not have diverged from that source
        file (see `_check_tekken_vocab_unchanged`).
    save_directory (`str` or `os.PathLike`): The path to a directory where the tekken
        vocabulary file will be written.

Returns:
    `tuple[str, ...]`: A 1-tuple containing the path of the saved tekken vocabulary file.

Raises:
    OSError: If the tokenizer's `vocab_file` does not resolve to an existing file
        identified as tekken (see `is_tekken_vocab_filename`).
    ValueError: If the tokenizer has diverged from its source tekken vocabulary file
        (added tokens, changed vocab size). See `_check_tekken_vocab_unchanged`.
T)Úexist_ok)
rÒ   râ   rÏ   ÚmakedirsrÐ   r’   r   ÚexistsÚsamefiler   )r°   rã   rl   Údests       r1   Úsave_tekken_formatrê   È  sr   € ô@ (¨	Ó2€JÜ! )Ô8ä‡K‚K�¨Ò.ô �7‰7�<‰<˜Ô(9Ó:€DÜ�G‰G�N‰N˜4× Ñ ¤R§W¡W×%5Ñ%5°j×%GÑ%GÜ�Ô"Øˆ7€Nr:   Útokenizer_filec                 ór   • [        X5      n[        U SS9n[        SUR                  5       U US.[        D6nU$ )u  Build a `TokenizersBackend` from a Mistral `tekken.json` file.

The chat template is resolved via a fixed precedence order (see
`_resolve_chat_template`): explicit `chat_template` argument â†’ sibling
`chat_template.jinja` â†’ sibling `chat_template.json` â†’ auto-generation via
`mistral-common` â†’ `None`.

Args:
    tokenizer_file (`str`): Path to the `tekken.json` vocabulary file.
    chat_template (`str`, *optional*): Explicit Jinja2 chat template string.
        When not provided (`None`), the template is resolved automatically
        from sibling files or generated via `mistral-common` if available.

Returns:
    Configured `TokenizersBackend` with BPE model, special token mappings, and
    an attached chat template (or `None` when none could be resolved).
F)rl   rm   )Útokenizer_objectrl   r   rL   )r2   rZ   r   r¿   Ú_MAP_SPECIALS)rë   r   ÚresolvedÚ	converterÚfasts        r1   Úconvert_tekken_tokenizerrò   õ  sL   € ô* & nÓD€HÜ ¨NÈUÑS€IÜð Ø"×,Ñ,Ó.Ø!Øñô ñ	€Dð €Kr:   )N)9rÅ   rz   r&   rÏ   Ú	functoolsr   Úpathlibr   Úshutilr   Ú
tokenizersr   r   r   r	   r
   r   Útokenizers.modelsr   Úconvert_slow_tokenizerr   Útokenization_utils_tokenizersr   Úutilsr   r   r   Ú	utils.hubr   r   Úutils.import_utilsr   Ú	constantsr   r   Ú'mistral_common.tokens.tokenizers.tekkenr   Ú
get_loggerrÁ   r*   rU   ÚPathLiker2   r9   rÆ   rÊ   r@   rî   rÈ   r[   rÉ   rj   rZ   rÒ   râ   rê   rò   rL   r:   r1   Ú<module>r     sÌ  ðñ Vã Û Û 	Ý Ý Ý ç Y× YÝ !å 6Ý >ß <Ñ <ß PÝ =ß Bñ × Ñ ÝBð 
×	Ò	˜HÓ	%€ð7¨¨b¯k©kÑ(9ð 7È#ÐPTÉ*ð 7ÐY\Ð_cÑYcô 7ðtØ#&¨¯©Ñ#4ðàðð 	ˆ4�Zô	ð: #'ñC2Ø#&¨¯©Ñ#4ðC2à˜4‘KðC2ð ˆ4��t‘ÐÑõ	C2ðN ØØØñ	€ð1@ ð 1@¨%°°S±	¸3°Ñ*?ô 1@÷hfñ fðRÐ&7ð ¸Cô ð:>
Ð->ð >
ÈCð >
ÐTXô >
ðB*Ð"3ð *ÀSÈ2Ï;É;ÑEVð *Ð[`ÐadÐfiÐaiÑ[jô *ð^ !%ñØðà˜‘:ðð ör:   