
    i&                     6   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
mZ d dlmZ d dlmZ d dlmZ d dlmZmZmZmZ i ddddd	d	d
dddddddddddddddddddddddddddZdZg dZd Zdedee   fd Z	 d7d!ed"ed#ed$ej>                  fd%Z 	 d7d!eeef   d"ed#ed$ej>                  fd&Z!	 d8d!ed"ed$e
ej>                  e"f   fd'Z#d(ed)ed*efd+Z$	 	 	 	 	 	 	 	 	 	 	 d9d*ed,ed-ed.e	e%   d/e	e%   d0ed)ed1e	e   d2ed3ed4e	e   d5efd6Z&y):    N)Path)dedent)ListOptionalTupleUnion)tree_flatten)base_load_modelget_model_classget_model_pathload_config	qwen3_ttsoutettssparkmarvissesamecsmvoxcpmz	voxcpm1.5vibevoice_streaming	vibevoicechatterbox_turbosoprano	bailingmmkitten
kitten_ttsecho_ttsfish_qwen3_omniirodori_ttsvoxtral_tts
kugelaudio   )float16bfloat16float32c                  <   t        t              j                  dz  } g }| j                         rm| j	                         r]| j                         D ]J  }|j	                         s|j                  j                  d      r0|j                  |j                         L |S )z
    Get a list of all available TTS model types by scanning the models directory.

    Returns:
        List[str]: A list of available model type names
    models__)	r   __file__parentexistsis_diriterdirname
startswithappend)
models_diravailable_modelsitems      h/Volumes/fast/ai/experiments/voice-extract-mac/.venv/lib/python3.12/site-packages/mlx_audio/tts/utils.pyget_available_modelsr4   +   s|     h&&1Jz002&&(D{{}TYY%9%9$%? ''		2 )     
model_type
model_namec                 (    t        | |dt              S )a  
    Retrieve the model architecture module based on the model type and name.

    This function attempts to find the appropriate model architecture by:
    1. Checking if the model_type is directly in the MODEL_REMAPPING dictionary
    2. Looking for partial matches in segments of the model_name

    Args:
        model_type (str): The type of model to load (e.g., "outetts").
        model_name (List[str]): List of model name components that might contain
                               remapping information.

    Returns:
        Tuple[module, str]: A tuple containing:
            - The imported architecture module
            - The resolved model_type string after remapping

    Raises:
        ValueError: If the model type is not supported (module import fails).
    tts)r6   r7   categorymodel_remapping)r   MODEL_REMAPPING)r6   r7   s     r3   get_model_and_argsr=   =   s    * '	 r5   
model_pathlazystrictreturnc           	      ,    t        d| dt        ||d|S )aC  
    Load and initialize the model from a given path.

    Args:
        model_path (Path): The path to load the model from.
        lazy (bool): If False eval the model parameters to make sure they are
            loaded in memory before returning, otherwise they will be loaded
            when needed. Default: ``False``

    Returns:
        nn.Module: The loaded and initialized model.

    Raises:
        FileNotFoundError: If the weight files (.safetensors) are not found.
        ValueError: If the model class or args class are not found or cannot be instantiated.
    r9   )r>   r:   r;   r?   r@    )r
   r<   r>   r?   r@   kwargss       r3   
load_modelrF   Z   s/    &  '  r5   c                      t        | f||d|S )aa  
    Load a text-to-speech model from a local path or HuggingFace repository.

    This is the main entry point for loading TTS models. It automatically
    detects the model type and initializes the appropriate model class.

    Args:
        model_path: The local path or HuggingFace repo ID to load from.
        lazy: If False, evaluate model parameters immediately.
        strict: If True, raise an error if any weights are missing.
        **kwargs: Additional keyword arguments:
            - revision (str): HuggingFace revision/branch to use
            - force_download (bool): Force re-download of model files

    Returns:
        nn.Module: The loaded and initialized model.

    Example:
        >>> from mlx_audio.tts import load
        >>> model = load("mlx-community/outetts-0.3-500M-bf16")
        >>> audio = model.generate("Hello world!")
    )r?   r@   )rF   rD   s       r3   loadrH   w   s    2 jEtFEfEEr5   c                 <    t        | |fi |}t        | fi |}||fS N)rF   r   )r>   r?   rE   modelconfigs        r3   fetch_from_hubrM      s.     z4262E.v.F&=r5   pathupload_repohf_pathc                 
   ddl }ddlm}m}m} ddlm} |j                  |      }|j                  j                  dgn|j                  j                  dgz   |j                  _	        t        d| d| d	| d
| d| d| d      |_        |j                  |j                  j                  | d              |j                           |       }	|	j!                  |d       |	j#                  | |d       t%        d| d       y)z
    Uploads the model to Hugging Face hub.

    Args:
        path (str): Local path to the model.
        upload_repo (str): Name of the HF repo to upload to.
        hf_path (str): Path to the original Hugging Face model.
    r   N)HfApi	ModelCardlogging   )__version__mlxz
        # z7
        This model was converted to MLX format from [`z`](https://huggingface.co/z) using mlx-audio version **zF**.
        Refer to the [original model card](https://huggingface.co/z) for more details on the model.
        ## Use with mlx

        ```bash
        pip install -U mlx-audio
        ```

        ```bash
        python -m mlx_audio.tts.generate --model z3 --text "Describe this image."
        ```
        z	README.mdT)repo_idexist_okrK   )folder_pathrX   	repo_typez0Upload successful, go to https://huggingface.co/z for details.)oshuggingface_hubrR   rS   rT   versionrV   rH   datatagsr   textsaverN   joinset_verbosity_infocreate_repoupload_folderprint)
rN   rO   rP   r\   rR   rS   rT   rV   cardapis
             r3   upload_to_hubrj      s    99%>>'"D $		 6eWDIINNeW<TDIIN- 77>i?YZaYbb~  @K  L LCCJ) L2 3> ?		DI  	IIbggll4-.G 
'COOK$O7  
 
<[M
WXr5   mlx_pathquantizeq_group_sizeq_bitsdtyperevision
dequantizetrust_remote_codequant_predicateq_modec                 b   ddl m} ddlm}m}m}m} t        d       t        | |      }t        |d|	      \  }}t        |
t              r	 ||
|      }
t        |dd	       fd
|
}
n|
fd}
t        t        |j                                     }||j!                  dd       }|t"        v rNt        d|       t        t$        |      }|j'                         D ci c]  \  }}||j)                  |       }}}|r|rt+        d      |rDt        d       |j-                  t/        |j'                                       |||||||
      \  }}|r5t        d        ||      }t        t        |j                                     }t        |t              rt1        |      }|j3                  dd       dD ]  }t5        j4                  t        ||z              }|D ]  }t7        j8                  ||        t5        j4                  t        |dz  |z        d      }|D ]T  }t1        |      j;                  |      }||j<                  z  }|j3                  dd       t7        j8                  ||       V   |||d        |||dz         |t?        |||        y y c c}}w )Nr   )mixed_quant_predicate_builder)dequantize_modelquantize_modelsave_config
save_modelz[INFO] Loading)rp   T)r?   rr   model_quant_predicatec                      y)NTrC   )pms     r3   <lambda>zconvert.<locals>.<lambda>   s    QUr5   c                     t        |d      xr8 |j                  j                  d   dz  dk(  xr t        |d      xr	  | |      S )Nweight@   r   to_quantized)hasattrr   shape)r}   r~   r{   s     r3   base_quant_requirementsz(convert.<locals>.base_quant_requirements   sQ    Ax  ,r"R'1,,>*, &a+		
r5   c                 ,     | |      xr	  | |      S rJ   rC   )r}   r~   r   original_predicates     r3   r   zconvert.<locals>.<lambda>   s    #Aq)F.@A.FFr5   torch_dtypez[INFO] Using dtype:z/Choose either quantize or dequantize, not both.z[INFO] Quantizing)moders   z[INFO] Dequantizing)parentsrY   )z*.pyz*.jsonz*.wavz*.ptz*.safetensorsz*.yamlz*.txtz**)	recursive)donate_modelzconfig.json)config_path) mlx_lm.convertrv   mlx_lm.utilsrw   rx   ry   rz   rg   r   rM   
isinstancestrgetattrdictr	   
parametersgetMODEL_CONVERSION_DTYPESmxitemsastype
ValueErrorload_weightslistr   mkdirglobshutilcopyrelative_tor)   rj   ) rP   rk   rl   rm   rn   ro   rO   rp   rq   rr   rs   rt   rv   rw   rx   ry   rz   r>   rK   rL   weightskvpatternfilesfilesubdir_filesrel_pathdest_dirr   r{   r   s                                 @@@r3   convertr      s    =VV	
(;J"1BME6 /3'7O $E+BDUV
 1,
 < 0 0 234G}

=$/''#U+E"29--/B/$!Q1ahhuo%/BJJKK!"401(+
 #$ '|E$4$4$678(C > NN4$N/ 		#j7234DKKh'  yyZ$%6%@!ATR DDz--j9H(//1HNN4$N7KKh' !, xT2H}$<=hW5 o Cs   %J+)FT)F)	mlx_modelFNNNNNFTNaffine)'r   rT   r   pathlibr   textwrapr   typingr   r   r   r   mlx.corecorer   mlx.nnnn	mlx.utilsr	   mlx_audio.utilsr
   r   r   r   r<   MAX_FILE_SIZE_GBr   r4   r   r=   boolModulerF   rH   r   rM   rj   intr   rC   r5   r3   <module>r      s        / /   " y W h	
 
8 h  ; * y  l 
 ( =  =!" ,#&  < $3 DI < :> 26YY< FJFc4i F(,F>BFYYF: $) 
299d?,Y ,Y# ,Y ,Yb  "& ""%)n6n6n6 n6 3-	n6
 SMn6 n6 n6 smn6 n6 n6 c]n6 n6r5   