nexaai 1.0.29__cp310-cp310-macosx_14_0_universal2.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nexaai/__init__.py +99 -0
- nexaai/_stub.cpython-310-darwin.so +0 -0
- nexaai/_version.py +4 -0
- nexaai/asr.py +68 -0
- nexaai/asr_impl/__init__.py +0 -0
- nexaai/asr_impl/mlx_asr_impl.py +93 -0
- nexaai/asr_impl/pybind_asr_impl.py +127 -0
- nexaai/base.py +39 -0
- nexaai/binds/__init__.py +7 -0
- nexaai/binds/asr_bind.cpython-310-darwin.so +0 -0
- nexaai/binds/common_bind.cpython-310-darwin.so +0 -0
- nexaai/binds/cpu_gpu/libggml-base.dylib +0 -0
- nexaai/binds/cpu_gpu/libggml-cpu.so +0 -0
- nexaai/binds/cpu_gpu/libggml-metal.so +0 -0
- nexaai/binds/cpu_gpu/libggml.dylib +0 -0
- nexaai/binds/cpu_gpu/libmtmd.dylib +0 -0
- nexaai/binds/cpu_gpu/libnexa_cpu_gpu.dylib +0 -0
- nexaai/binds/cpu_gpu/libnexa_plugin.dylib +0 -0
- nexaai/binds/cv_bind.cpython-310-darwin.so +0 -0
- nexaai/binds/diarize_bind.cpython-310-darwin.so +0 -0
- nexaai/binds/embedder_bind.cpython-310-darwin.so +0 -0
- nexaai/binds/libnexa_bridge.dylib +0 -0
- nexaai/binds/llm_bind.cpython-310-darwin.so +0 -0
- nexaai/binds/metal/libnexa_plugin.dylib +0 -0
- nexaai/binds/metal/py-lib/ml.py +888 -0
- nexaai/binds/metal/py-lib/mlx_audio/__init__.py +0 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/__init__.py +1 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/models/__init__.py +5 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/models/bigvgan/__init__.py +1 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/models/bigvgan/activation.py +51 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/models/bigvgan/amp.py +96 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/models/bigvgan/bigvgan.py +149 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/models/bigvgan/conv.py +114 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/models/bigvgan/resample.py +177 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/models/descript/__init__.py +1 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/models/descript/base.py +228 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/models/descript/dac.py +285 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/models/descript/nn/__init__.py +1 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/models/descript/nn/layers.py +129 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/models/descript/nn/quantize.py +149 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/models/encodec/__init__.py +1 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/models/encodec/encodec.py +777 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/models/mimi/__init__.py +1 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/models/mimi/mimi.py +286 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/models/mimi/modules/__init__.py +20 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/models/mimi/modules/conv.py +398 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/models/mimi/modules/kv_cache.py +199 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/models/mimi/modules/quantization.py +179 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/models/mimi/modules/seanet.py +314 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/models/mimi/modules/transformer.py +256 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/models/s3/__init__.py +1 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/models/s3/model.py +260 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/models/s3/model_v2.py +383 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/models/s3/utils.py +122 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/models/snac/__init__.py +1 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/models/snac/attention.py +97 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/models/snac/layers.py +306 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/models/snac/snac.py +154 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/models/snac/vq.py +135 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/models/vocos/__init__.py +1 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/models/vocos/mel.py +33 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/models/vocos/vocos.py +359 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/tests/__init__.py +0 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/tests/test_bigvgan.py +54 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/tests/test_descript.py +109 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/tests/test_encodec.py +58 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/tests/test_mimi.py +22 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/tests/test_s3.py +25 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/tests/test_snac.py +40 -0
- nexaai/binds/metal/py-lib/mlx_audio/codec/tests/test_vocos.py +93 -0
- nexaai/binds/metal/py-lib/mlx_audio/server.py +525 -0
- nexaai/binds/metal/py-lib/mlx_audio/sts/__init__.py +0 -0
- nexaai/binds/metal/py-lib/mlx_audio/sts/tests/test_voice_pipeline.py +156 -0
- nexaai/binds/metal/py-lib/mlx_audio/sts/voice_pipeline.py +327 -0
- nexaai/binds/metal/py-lib/mlx_audio/stt/__init__.py +0 -0
- nexaai/binds/metal/py-lib/mlx_audio/stt/generate.py +174 -0
- nexaai/binds/metal/py-lib/mlx_audio/stt/models/__init__.py +0 -0
- nexaai/binds/metal/py-lib/mlx_audio/stt/models/parakeet/__init__.py +1 -0
- nexaai/binds/metal/py-lib/mlx_audio/stt/models/parakeet/alignment.py +248 -0
- nexaai/binds/metal/py-lib/mlx_audio/stt/models/parakeet/attention.py +187 -0
- nexaai/binds/metal/py-lib/mlx_audio/stt/models/parakeet/audio.py +76 -0
- nexaai/binds/metal/py-lib/mlx_audio/stt/models/parakeet/conformer.py +331 -0
- nexaai/binds/metal/py-lib/mlx_audio/stt/models/parakeet/ctc.py +34 -0
- nexaai/binds/metal/py-lib/mlx_audio/stt/models/parakeet/parakeet.py +604 -0
- nexaai/binds/metal/py-lib/mlx_audio/stt/models/parakeet/rnnt.py +157 -0
- nexaai/binds/metal/py-lib/mlx_audio/stt/models/parakeet/tokenizer.py +2 -0
- nexaai/binds/metal/py-lib/mlx_audio/stt/models/wav2vec/feature_extractor.py +757 -0
- nexaai/binds/metal/py-lib/mlx_audio/stt/models/wav2vec/wav2vec.py +738 -0
- nexaai/binds/metal/py-lib/mlx_audio/stt/models/whisper/__init__.py +1 -0
- nexaai/binds/metal/py-lib/mlx_audio/stt/models/whisper/audio.py +82 -0
- nexaai/binds/metal/py-lib/mlx_audio/stt/models/whisper/decoding.py +742 -0
- nexaai/binds/metal/py-lib/mlx_audio/stt/models/whisper/timing.py +329 -0
- nexaai/binds/metal/py-lib/mlx_audio/stt/models/whisper/tokenizer.py +398 -0
- nexaai/binds/metal/py-lib/mlx_audio/stt/models/whisper/whisper.py +862 -0
- nexaai/binds/metal/py-lib/mlx_audio/stt/models/whisper/writers.py +268 -0
- nexaai/binds/metal/py-lib/mlx_audio/stt/tests/test_models.py +381 -0
- nexaai/binds/metal/py-lib/mlx_audio/stt/utils.py +195 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/__init__.py +1 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/audio_player.py +120 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/convert.py +71 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/generate.py +449 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/__init__.py +0 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/bark/__init__.py +4 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/bark/bark.py +528 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/bark/isftnet.py +12 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/bark/pipeline.py +442 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/base.py +84 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/dia/__init__.py +1 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/dia/audio.py +287 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/dia/config.py +256 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/dia/dia.py +592 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/dia/layers.py +870 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/indextts/__init__.py +3 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/indextts/attention.py +180 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/indextts/bigvgan.py +124 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/indextts/conformer.py +247 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/indextts/ecapa_tdnn/__init__.py +0 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/indextts/ecapa_tdnn/asp.py +59 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/indextts/ecapa_tdnn/ecapa_tdnn.py +91 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/indextts/ecapa_tdnn/se_res2net.py +132 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/indextts/ecapa_tdnn/tdnn.py +42 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/indextts/gpt2.py +38 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/indextts/indextts.py +412 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/indextts/mel.py +37 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/indextts/normalize.py +294 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/indextts/perceiver.py +62 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/interpolate.py +108 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/kokoro/__init__.py +4 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/kokoro/istftnet.py +979 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/kokoro/kokoro.py +331 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/kokoro/modules.py +659 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/kokoro/pipeline.py +453 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/kokoro/voice.py +113 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/llama/__init__.py +3 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/llama/llama.py +324 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/outetts/__init__.py +1 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/outetts/audio_processor.py +351 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/outetts/dac_interface.py +162 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/outetts/outetts.py +255 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/outetts/prompt_processor.py +181 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/outetts/tokens.py +36 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/sesame/__init__.py +3 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/sesame/attention.py +195 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/sesame/sesame.py +633 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/sesame/watermarking.py +105 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/spark/__init__.py +1 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/spark/audio_tokenizer.py +138 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/spark/bicodec.py +269 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/spark/modules/__init__.py +0 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/spark/modules/blocks/__init__.py +0 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/spark/modules/blocks/sampler.py +111 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/spark/modules/encoder_decoder/__init__.py +0 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/spark/modules/encoder_decoder/feat_decoder.py +120 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/spark/modules/encoder_decoder/feat_encoder.py +136 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/spark/modules/encoder_decoder/wave_generator.py +113 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/spark/modules/finite_scalar_quantization.py +238 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/spark/modules/residual.py +209 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/spark/modules/residual_fsq.py +309 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/spark/modules/speaker/__init__.py +1 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/spark/modules/speaker/ecapa_tdnn.py +283 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/spark/modules/speaker/perceiver_encoder.py +326 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/spark/modules/speaker/pooling_layers.py +297 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/spark/modules/speaker/speaker_encoder.py +155 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/spark/spark.py +382 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/spark/utils/audio.py +220 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/spark/utils/file.py +221 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/models/spark/utils/token_parser.py +181 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/tests/__init__.py +0 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/tests/test_base.py +66 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/tests/test_convert.py +173 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/tests/test_interpolate.py +88 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/tests/test_models.py +974 -0
- nexaai/binds/metal/py-lib/mlx_audio/tts/utils.py +337 -0
- nexaai/binds/metal/py-lib/mlx_audio/utils.py +237 -0
- nexaai/binds/metal/py-lib/mlx_audio/version.py +1 -0
- nexaai/binds/metal/py-lib/profiling.py +239 -0
- nexaai/binds/nexaml/libfftw3.3.dylib +0 -0
- nexaai/binds/nexaml/libfftw3f.3.dylib +0 -0
- nexaai/binds/nexaml/libggml-base.dylib +0 -0
- nexaai/binds/nexaml/libggml-cpu.so +0 -0
- nexaai/binds/nexaml/libggml-metal.so +0 -0
- nexaai/binds/nexaml/libggml.dylib +0 -0
- nexaai/binds/nexaml/libmp3lame.0.dylib +0 -0
- nexaai/binds/nexaml/libmpg123.0.dylib +0 -0
- nexaai/binds/nexaml/libnexa-mm-process.dylib +0 -0
- nexaai/binds/nexaml/libnexa-sampling.dylib +0 -0
- nexaai/binds/nexaml/libnexa_plugin.dylib +0 -0
- nexaai/binds/nexaml/libnexaproc.dylib +0 -0
- nexaai/binds/nexaml/libomp.dylib +0 -0
- nexaai/binds/nexaml/libqwen3-vl.dylib +0 -0
- nexaai/binds/nexaml/libqwen3vl-vision.dylib +0 -0
- nexaai/binds/rerank_bind.cpython-310-darwin.so +0 -0
- nexaai/binds/vlm_bind.cpython-310-darwin.so +0 -0
- nexaai/common.py +106 -0
- nexaai/cv.py +95 -0
- nexaai/cv_impl/__init__.py +0 -0
- nexaai/cv_impl/mlx_cv_impl.py +91 -0
- nexaai/cv_impl/pybind_cv_impl.py +124 -0
- nexaai/diarize.py +80 -0
- nexaai/diarize_impl/__init__.py +1 -0
- nexaai/diarize_impl/pybind_diarize_impl.py +125 -0
- nexaai/embedder.py +73 -0
- nexaai/embedder_impl/__init__.py +0 -0
- nexaai/embedder_impl/mlx_embedder_impl.py +118 -0
- nexaai/embedder_impl/pybind_embedder_impl.py +96 -0
- nexaai/image_gen.py +141 -0
- nexaai/image_gen_impl/__init__.py +0 -0
- nexaai/image_gen_impl/mlx_image_gen_impl.py +292 -0
- nexaai/image_gen_impl/pybind_image_gen_impl.py +85 -0
- nexaai/llm.py +98 -0
- nexaai/llm_impl/__init__.py +0 -0
- nexaai/llm_impl/mlx_llm_impl.py +271 -0
- nexaai/llm_impl/pybind_llm_impl.py +238 -0
- nexaai/log.py +92 -0
- nexaai/mlx_backend/asr/__init__.py +12 -0
- nexaai/mlx_backend/asr/interface.py +122 -0
- nexaai/mlx_backend/common/__init__.py +0 -0
- nexaai/mlx_backend/common/utils.py +25 -0
- nexaai/mlx_backend/cv/__init__.py +0 -0
- nexaai/mlx_backend/cv/generate.py +195 -0
- nexaai/mlx_backend/cv/interface.py +162 -0
- nexaai/mlx_backend/cv/main.py +81 -0
- nexaai/mlx_backend/cv/modeling/pp_ocr_v4.py +1736 -0
- nexaai/mlx_backend/embedding/__init__.py +0 -0
- nexaai/mlx_backend/embedding/generate.py +333 -0
- nexaai/mlx_backend/embedding/interface.py +617 -0
- nexaai/mlx_backend/embedding/main.py +173 -0
- nexaai/mlx_backend/embedding/modeling/__init__.py +0 -0
- nexaai/mlx_backend/embedding/modeling/nexa_jina_v2.py +399 -0
- nexaai/mlx_backend/image_gen/__init__.py +1 -0
- nexaai/mlx_backend/image_gen/generate_sd.py +244 -0
- nexaai/mlx_backend/image_gen/interface.py +82 -0
- nexaai/mlx_backend/image_gen/main.py +281 -0
- nexaai/mlx_backend/image_gen/stable_diffusion/__init__.py +306 -0
- nexaai/mlx_backend/image_gen/stable_diffusion/clip.py +116 -0
- nexaai/mlx_backend/image_gen/stable_diffusion/config.py +65 -0
- nexaai/mlx_backend/image_gen/stable_diffusion/model_io.py +386 -0
- nexaai/mlx_backend/image_gen/stable_diffusion/sampler.py +105 -0
- nexaai/mlx_backend/image_gen/stable_diffusion/tokenizer.py +100 -0
- nexaai/mlx_backend/image_gen/stable_diffusion/unet.py +460 -0
- nexaai/mlx_backend/image_gen/stable_diffusion/vae.py +274 -0
- nexaai/mlx_backend/llm/__init__.py +0 -0
- nexaai/mlx_backend/llm/generate.py +149 -0
- nexaai/mlx_backend/llm/interface.py +764 -0
- nexaai/mlx_backend/llm/main.py +68 -0
- nexaai/mlx_backend/ml.py +888 -0
- nexaai/mlx_backend/mlx_audio/__init__.py +0 -0
- nexaai/mlx_backend/mlx_audio/codec/__init__.py +1 -0
- nexaai/mlx_backend/mlx_audio/codec/models/__init__.py +5 -0
- nexaai/mlx_backend/mlx_audio/codec/models/bigvgan/__init__.py +1 -0
- nexaai/mlx_backend/mlx_audio/codec/models/bigvgan/activation.py +51 -0
- nexaai/mlx_backend/mlx_audio/codec/models/bigvgan/amp.py +96 -0
- nexaai/mlx_backend/mlx_audio/codec/models/bigvgan/bigvgan.py +149 -0
- nexaai/mlx_backend/mlx_audio/codec/models/bigvgan/conv.py +114 -0
- nexaai/mlx_backend/mlx_audio/codec/models/bigvgan/resample.py +177 -0
- nexaai/mlx_backend/mlx_audio/codec/models/descript/__init__.py +1 -0
- nexaai/mlx_backend/mlx_audio/codec/models/descript/base.py +228 -0
- nexaai/mlx_backend/mlx_audio/codec/models/descript/dac.py +285 -0
- nexaai/mlx_backend/mlx_audio/codec/models/descript/nn/__init__.py +1 -0
- nexaai/mlx_backend/mlx_audio/codec/models/descript/nn/layers.py +129 -0
- nexaai/mlx_backend/mlx_audio/codec/models/descript/nn/quantize.py +149 -0
- nexaai/mlx_backend/mlx_audio/codec/models/encodec/__init__.py +1 -0
- nexaai/mlx_backend/mlx_audio/codec/models/encodec/encodec.py +777 -0
- nexaai/mlx_backend/mlx_audio/codec/models/mimi/__init__.py +1 -0
- nexaai/mlx_backend/mlx_audio/codec/models/mimi/mimi.py +286 -0
- nexaai/mlx_backend/mlx_audio/codec/models/mimi/modules/__init__.py +20 -0
- nexaai/mlx_backend/mlx_audio/codec/models/mimi/modules/conv.py +398 -0
- nexaai/mlx_backend/mlx_audio/codec/models/mimi/modules/kv_cache.py +199 -0
- nexaai/mlx_backend/mlx_audio/codec/models/mimi/modules/quantization.py +179 -0
- nexaai/mlx_backend/mlx_audio/codec/models/mimi/modules/seanet.py +314 -0
- nexaai/mlx_backend/mlx_audio/codec/models/mimi/modules/transformer.py +256 -0
- nexaai/mlx_backend/mlx_audio/codec/models/s3/__init__.py +1 -0
- nexaai/mlx_backend/mlx_audio/codec/models/s3/model.py +260 -0
- nexaai/mlx_backend/mlx_audio/codec/models/s3/model_v2.py +383 -0
- nexaai/mlx_backend/mlx_audio/codec/models/s3/utils.py +122 -0
- nexaai/mlx_backend/mlx_audio/codec/models/snac/__init__.py +1 -0
- nexaai/mlx_backend/mlx_audio/codec/models/snac/attention.py +97 -0
- nexaai/mlx_backend/mlx_audio/codec/models/snac/layers.py +306 -0
- nexaai/mlx_backend/mlx_audio/codec/models/snac/snac.py +154 -0
- nexaai/mlx_backend/mlx_audio/codec/models/snac/vq.py +135 -0
- nexaai/mlx_backend/mlx_audio/codec/models/vocos/__init__.py +1 -0
- nexaai/mlx_backend/mlx_audio/codec/models/vocos/mel.py +33 -0
- nexaai/mlx_backend/mlx_audio/codec/models/vocos/vocos.py +359 -0
- nexaai/mlx_backend/mlx_audio/codec/tests/__init__.py +0 -0
- nexaai/mlx_backend/mlx_audio/codec/tests/test_bigvgan.py +54 -0
- nexaai/mlx_backend/mlx_audio/codec/tests/test_descript.py +109 -0
- nexaai/mlx_backend/mlx_audio/codec/tests/test_encodec.py +58 -0
- nexaai/mlx_backend/mlx_audio/codec/tests/test_mimi.py +22 -0
- nexaai/mlx_backend/mlx_audio/codec/tests/test_s3.py +25 -0
- nexaai/mlx_backend/mlx_audio/codec/tests/test_snac.py +40 -0
- nexaai/mlx_backend/mlx_audio/codec/tests/test_vocos.py +93 -0
- nexaai/mlx_backend/mlx_audio/server.py +525 -0
- nexaai/mlx_backend/mlx_audio/sts/__init__.py +0 -0
- nexaai/mlx_backend/mlx_audio/sts/tests/test_voice_pipeline.py +156 -0
- nexaai/mlx_backend/mlx_audio/sts/voice_pipeline.py +327 -0
- nexaai/mlx_backend/mlx_audio/stt/__init__.py +0 -0
- nexaai/mlx_backend/mlx_audio/stt/generate.py +174 -0
- nexaai/mlx_backend/mlx_audio/stt/models/__init__.py +0 -0
- nexaai/mlx_backend/mlx_audio/stt/models/parakeet/__init__.py +1 -0
- nexaai/mlx_backend/mlx_audio/stt/models/parakeet/alignment.py +248 -0
- nexaai/mlx_backend/mlx_audio/stt/models/parakeet/attention.py +187 -0
- nexaai/mlx_backend/mlx_audio/stt/models/parakeet/audio.py +76 -0
- nexaai/mlx_backend/mlx_audio/stt/models/parakeet/conformer.py +331 -0
- nexaai/mlx_backend/mlx_audio/stt/models/parakeet/ctc.py +34 -0
- nexaai/mlx_backend/mlx_audio/stt/models/parakeet/parakeet.py +604 -0
- nexaai/mlx_backend/mlx_audio/stt/models/parakeet/rnnt.py +157 -0
- nexaai/mlx_backend/mlx_audio/stt/models/parakeet/tokenizer.py +2 -0
- nexaai/mlx_backend/mlx_audio/stt/models/wav2vec/feature_extractor.py +757 -0
- nexaai/mlx_backend/mlx_audio/stt/models/wav2vec/wav2vec.py +738 -0
- nexaai/mlx_backend/mlx_audio/stt/models/whisper/__init__.py +1 -0
- nexaai/mlx_backend/mlx_audio/stt/models/whisper/audio.py +82 -0
- nexaai/mlx_backend/mlx_audio/stt/models/whisper/decoding.py +742 -0
- nexaai/mlx_backend/mlx_audio/stt/models/whisper/timing.py +329 -0
- nexaai/mlx_backend/mlx_audio/stt/models/whisper/tokenizer.py +398 -0
- nexaai/mlx_backend/mlx_audio/stt/models/whisper/whisper.py +862 -0
- nexaai/mlx_backend/mlx_audio/stt/models/whisper/writers.py +268 -0
- nexaai/mlx_backend/mlx_audio/stt/tests/test_models.py +381 -0
- nexaai/mlx_backend/mlx_audio/stt/utils.py +195 -0
- nexaai/mlx_backend/mlx_audio/tts/__init__.py +1 -0
- nexaai/mlx_backend/mlx_audio/tts/audio_player.py +120 -0
- nexaai/mlx_backend/mlx_audio/tts/convert.py +71 -0
- nexaai/mlx_backend/mlx_audio/tts/generate.py +449 -0
- nexaai/mlx_backend/mlx_audio/tts/models/__init__.py +0 -0
- nexaai/mlx_backend/mlx_audio/tts/models/bark/__init__.py +4 -0
- nexaai/mlx_backend/mlx_audio/tts/models/bark/bark.py +528 -0
- nexaai/mlx_backend/mlx_audio/tts/models/bark/isftnet.py +12 -0
- nexaai/mlx_backend/mlx_audio/tts/models/bark/pipeline.py +442 -0
- nexaai/mlx_backend/mlx_audio/tts/models/base.py +84 -0
- nexaai/mlx_backend/mlx_audio/tts/models/dia/__init__.py +1 -0
- nexaai/mlx_backend/mlx_audio/tts/models/dia/audio.py +287 -0
- nexaai/mlx_backend/mlx_audio/tts/models/dia/config.py +256 -0
- nexaai/mlx_backend/mlx_audio/tts/models/dia/dia.py +592 -0
- nexaai/mlx_backend/mlx_audio/tts/models/dia/layers.py +870 -0
- nexaai/mlx_backend/mlx_audio/tts/models/indextts/__init__.py +3 -0
- nexaai/mlx_backend/mlx_audio/tts/models/indextts/attention.py +180 -0
- nexaai/mlx_backend/mlx_audio/tts/models/indextts/bigvgan.py +124 -0
- nexaai/mlx_backend/mlx_audio/tts/models/indextts/conformer.py +247 -0
- nexaai/mlx_backend/mlx_audio/tts/models/indextts/ecapa_tdnn/__init__.py +0 -0
- nexaai/mlx_backend/mlx_audio/tts/models/indextts/ecapa_tdnn/asp.py +59 -0
- nexaai/mlx_backend/mlx_audio/tts/models/indextts/ecapa_tdnn/ecapa_tdnn.py +91 -0
- nexaai/mlx_backend/mlx_audio/tts/models/indextts/ecapa_tdnn/se_res2net.py +132 -0
- nexaai/mlx_backend/mlx_audio/tts/models/indextts/ecapa_tdnn/tdnn.py +42 -0
- nexaai/mlx_backend/mlx_audio/tts/models/indextts/gpt2.py +38 -0
- nexaai/mlx_backend/mlx_audio/tts/models/indextts/indextts.py +412 -0
- nexaai/mlx_backend/mlx_audio/tts/models/indextts/mel.py +37 -0
- nexaai/mlx_backend/mlx_audio/tts/models/indextts/normalize.py +294 -0
- nexaai/mlx_backend/mlx_audio/tts/models/indextts/perceiver.py +62 -0
- nexaai/mlx_backend/mlx_audio/tts/models/interpolate.py +108 -0
- nexaai/mlx_backend/mlx_audio/tts/models/kokoro/__init__.py +4 -0
- nexaai/mlx_backend/mlx_audio/tts/models/kokoro/istftnet.py +979 -0
- nexaai/mlx_backend/mlx_audio/tts/models/kokoro/kokoro.py +331 -0
- nexaai/mlx_backend/mlx_audio/tts/models/kokoro/modules.py +659 -0
- nexaai/mlx_backend/mlx_audio/tts/models/kokoro/pipeline.py +453 -0
- nexaai/mlx_backend/mlx_audio/tts/models/kokoro/voice.py +113 -0
- nexaai/mlx_backend/mlx_audio/tts/models/llama/__init__.py +3 -0
- nexaai/mlx_backend/mlx_audio/tts/models/llama/llama.py +324 -0
- nexaai/mlx_backend/mlx_audio/tts/models/outetts/__init__.py +1 -0
- nexaai/mlx_backend/mlx_audio/tts/models/outetts/audio_processor.py +351 -0
- nexaai/mlx_backend/mlx_audio/tts/models/outetts/dac_interface.py +162 -0
- nexaai/mlx_backend/mlx_audio/tts/models/outetts/default_speaker.json +461 -0
- nexaai/mlx_backend/mlx_audio/tts/models/outetts/outetts.py +255 -0
- nexaai/mlx_backend/mlx_audio/tts/models/outetts/prompt_processor.py +181 -0
- nexaai/mlx_backend/mlx_audio/tts/models/outetts/tokens.py +36 -0
- nexaai/mlx_backend/mlx_audio/tts/models/sesame/__init__.py +3 -0
- nexaai/mlx_backend/mlx_audio/tts/models/sesame/attention.py +195 -0
- nexaai/mlx_backend/mlx_audio/tts/models/sesame/sesame.py +633 -0
- nexaai/mlx_backend/mlx_audio/tts/models/sesame/watermarking.py +105 -0
- nexaai/mlx_backend/mlx_audio/tts/models/spark/__init__.py +1 -0
- nexaai/mlx_backend/mlx_audio/tts/models/spark/audio_tokenizer.py +138 -0
- nexaai/mlx_backend/mlx_audio/tts/models/spark/bicodec.py +269 -0
- nexaai/mlx_backend/mlx_audio/tts/models/spark/modules/__init__.py +0 -0
- nexaai/mlx_backend/mlx_audio/tts/models/spark/modules/blocks/__init__.py +0 -0
- nexaai/mlx_backend/mlx_audio/tts/models/spark/modules/blocks/sampler.py +111 -0
- nexaai/mlx_backend/mlx_audio/tts/models/spark/modules/encoder_decoder/__init__.py +0 -0
- nexaai/mlx_backend/mlx_audio/tts/models/spark/modules/encoder_decoder/feat_decoder.py +120 -0
- nexaai/mlx_backend/mlx_audio/tts/models/spark/modules/encoder_decoder/feat_encoder.py +136 -0
- nexaai/mlx_backend/mlx_audio/tts/models/spark/modules/encoder_decoder/wave_generator.py +113 -0
- nexaai/mlx_backend/mlx_audio/tts/models/spark/modules/finite_scalar_quantization.py +238 -0
- nexaai/mlx_backend/mlx_audio/tts/models/spark/modules/residual.py +209 -0
- nexaai/mlx_backend/mlx_audio/tts/models/spark/modules/residual_fsq.py +309 -0
- nexaai/mlx_backend/mlx_audio/tts/models/spark/modules/speaker/__init__.py +1 -0
- nexaai/mlx_backend/mlx_audio/tts/models/spark/modules/speaker/ecapa_tdnn.py +283 -0
- nexaai/mlx_backend/mlx_audio/tts/models/spark/modules/speaker/perceiver_encoder.py +326 -0
- nexaai/mlx_backend/mlx_audio/tts/models/spark/modules/speaker/pooling_layers.py +297 -0
- nexaai/mlx_backend/mlx_audio/tts/models/spark/modules/speaker/speaker_encoder.py +155 -0
- nexaai/mlx_backend/mlx_audio/tts/models/spark/spark.py +382 -0
- nexaai/mlx_backend/mlx_audio/tts/models/spark/utils/audio.py +220 -0
- nexaai/mlx_backend/mlx_audio/tts/models/spark/utils/file.py +221 -0
- nexaai/mlx_backend/mlx_audio/tts/models/spark/utils/token_parser.py +181 -0
- nexaai/mlx_backend/mlx_audio/tts/tests/__init__.py +0 -0
- nexaai/mlx_backend/mlx_audio/tts/tests/test_base.py +66 -0
- nexaai/mlx_backend/mlx_audio/tts/tests/test_convert.py +173 -0
- nexaai/mlx_backend/mlx_audio/tts/tests/test_interpolate.py +88 -0
- nexaai/mlx_backend/mlx_audio/tts/tests/test_models.py +974 -0
- nexaai/mlx_backend/mlx_audio/tts/utils.py +337 -0
- nexaai/mlx_backend/mlx_audio/utils.py +237 -0
- nexaai/mlx_backend/mlx_audio/version.py +1 -0
- nexaai/mlx_backend/profiling.py +239 -0
- nexaai/mlx_backend/rerank/__init__.py +0 -0
- nexaai/mlx_backend/rerank/generate.py +174 -0
- nexaai/mlx_backend/rerank/interface.py +287 -0
- nexaai/mlx_backend/rerank/main.py +127 -0
- nexaai/mlx_backend/rerank/modeling/__init__.py +0 -0
- nexaai/mlx_backend/rerank/modeling/nexa_jina_rerank.py +330 -0
- nexaai/mlx_backend/sd/__init__.py +1 -0
- nexaai/mlx_backend/sd/interface.py +362 -0
- nexaai/mlx_backend/sd/main.py +286 -0
- nexaai/mlx_backend/sd/modeling/__init__.py +306 -0
- nexaai/mlx_backend/sd/modeling/clip.py +116 -0
- nexaai/mlx_backend/sd/modeling/config.py +65 -0
- nexaai/mlx_backend/sd/modeling/model_io.py +385 -0
- nexaai/mlx_backend/sd/modeling/sampler.py +105 -0
- nexaai/mlx_backend/sd/modeling/tokenizer.py +100 -0
- nexaai/mlx_backend/sd/modeling/unet.py +460 -0
- nexaai/mlx_backend/sd/modeling/vae.py +274 -0
- nexaai/mlx_backend/tts/__init__.py +12 -0
- nexaai/mlx_backend/tts/interface.py +276 -0
- nexaai/mlx_backend/vlm/__init__.py +3 -0
- nexaai/mlx_backend/vlm/generate.py +572 -0
- nexaai/mlx_backend/vlm/generate_qwen3_vl.py +374 -0
- nexaai/mlx_backend/vlm/generate_qwen3_vl_moe.py +259 -0
- nexaai/mlx_backend/vlm/interface.py +559 -0
- nexaai/mlx_backend/vlm/main.py +365 -0
- nexaai/mlx_backend/vlm/modeling/__init__.py +0 -0
- nexaai/mlx_backend/vlm/modeling/convert.py +68 -0
- nexaai/mlx_backend/vlm/modeling/models/__init__.py +0 -0
- nexaai/mlx_backend/vlm/modeling/models/aya_vision/__init__.py +8 -0
- nexaai/mlx_backend/vlm/modeling/models/aya_vision/aya_vision.py +193 -0
- nexaai/mlx_backend/vlm/modeling/models/aya_vision/interpolate.py +186 -0
- nexaai/mlx_backend/vlm/modeling/models/aya_vision/language.py +233 -0
- nexaai/mlx_backend/vlm/modeling/models/aya_vision/vision.py +503 -0
- nexaai/mlx_backend/vlm/modeling/models/base.py +202 -0
- nexaai/mlx_backend/vlm/modeling/models/cache.py +230 -0
- nexaai/mlx_backend/vlm/modeling/models/deepseek_vl_v2/__init__.py +10 -0
- nexaai/mlx_backend/vlm/modeling/models/deepseek_vl_v2/conversation.py +264 -0
- nexaai/mlx_backend/vlm/modeling/models/deepseek_vl_v2/deepseek_vl_v2.py +472 -0
- nexaai/mlx_backend/vlm/modeling/models/deepseek_vl_v2/language.py +591 -0
- nexaai/mlx_backend/vlm/modeling/models/deepseek_vl_v2/processing_deepsek_vl_v2.py +526 -0
- nexaai/mlx_backend/vlm/modeling/models/deepseek_vl_v2/vision.py +356 -0
- nexaai/mlx_backend/vlm/modeling/models/florence2/__init__.py +8 -0
- nexaai/mlx_backend/vlm/modeling/models/florence2/florence2.py +366 -0
- nexaai/mlx_backend/vlm/modeling/models/florence2/language.py +488 -0
- nexaai/mlx_backend/vlm/modeling/models/florence2/vision.py +591 -0
- nexaai/mlx_backend/vlm/modeling/models/gemma3/__init__.py +8 -0
- nexaai/mlx_backend/vlm/modeling/models/gemma3/gemma3.py +213 -0
- nexaai/mlx_backend/vlm/modeling/models/gemma3/language.py +315 -0
- nexaai/mlx_backend/vlm/modeling/models/gemma3/vision.py +238 -0
- nexaai/mlx_backend/vlm/modeling/models/gemma3n/__init__.py +2 -0
- nexaai/mlx_backend/vlm/modeling/models/gemma3n/audio.py +1038 -0
- nexaai/mlx_backend/vlm/modeling/models/gemma3n/config.py +139 -0
- nexaai/mlx_backend/vlm/modeling/models/gemma3n/gemma3n.py +322 -0
- nexaai/mlx_backend/vlm/modeling/models/gemma3n/language.py +629 -0
- nexaai/mlx_backend/vlm/modeling/models/gemma3n/vision.py +1022 -0
- nexaai/mlx_backend/vlm/modeling/models/idefics2/__init__.py +9 -0
- nexaai/mlx_backend/vlm/modeling/models/idefics2/idefics2.py +294 -0
- nexaai/mlx_backend/vlm/modeling/models/idefics2/language.py +191 -0
- nexaai/mlx_backend/vlm/modeling/models/idefics2/vision.py +267 -0
- nexaai/mlx_backend/vlm/modeling/models/idefics3/__init__.py +8 -0
- nexaai/mlx_backend/vlm/modeling/models/idefics3/idefics3.py +175 -0
- nexaai/mlx_backend/vlm/modeling/models/idefics3/language.py +192 -0
- nexaai/mlx_backend/vlm/modeling/models/idefics3/vision.py +233 -0
- nexaai/mlx_backend/vlm/modeling/models/internvl_chat/__init__.py +9 -0
- nexaai/mlx_backend/vlm/modeling/models/internvl_chat/internvl_chat.py +140 -0
- nexaai/mlx_backend/vlm/modeling/models/internvl_chat/language.py +220 -0
- nexaai/mlx_backend/vlm/modeling/models/internvl_chat/processor.py +393 -0
- nexaai/mlx_backend/vlm/modeling/models/internvl_chat/vision.py +293 -0
- nexaai/mlx_backend/vlm/modeling/models/kernels.py +307 -0
- nexaai/mlx_backend/vlm/modeling/models/kimi_vl/__init__.py +8 -0
- nexaai/mlx_backend/vlm/modeling/models/kimi_vl/kimi_vl.py +143 -0
- nexaai/mlx_backend/vlm/modeling/models/kimi_vl/language.py +509 -0
- nexaai/mlx_backend/vlm/modeling/models/kimi_vl/vision.py +522 -0
- nexaai/mlx_backend/vlm/modeling/models/llama4/__init__.py +8 -0
- nexaai/mlx_backend/vlm/modeling/models/llama4/language.py +386 -0
- nexaai/mlx_backend/vlm/modeling/models/llama4/llama4.py +138 -0
- nexaai/mlx_backend/vlm/modeling/models/llama4/vision.py +560 -0
- nexaai/mlx_backend/vlm/modeling/models/llava/__init__.py +8 -0
- nexaai/mlx_backend/vlm/modeling/models/llava/language.py +240 -0
- nexaai/mlx_backend/vlm/modeling/models/llava/llava.py +153 -0
- nexaai/mlx_backend/vlm/modeling/models/llava/vision.py +259 -0
- nexaai/mlx_backend/vlm/modeling/models/llava_bunny/__init__.py +9 -0
- nexaai/mlx_backend/vlm/modeling/models/llava_bunny/language.py +236 -0
- nexaai/mlx_backend/vlm/modeling/models/llava_bunny/llava_bunny.py +256 -0
- nexaai/mlx_backend/vlm/modeling/models/llava_bunny/vision.py +303 -0
- nexaai/mlx_backend/vlm/modeling/models/llava_next/__init__.py +8 -0
- nexaai/mlx_backend/vlm/modeling/models/llava_next/language.py +230 -0
- nexaai/mlx_backend/vlm/modeling/models/llava_next/llava_next.py +160 -0
- nexaai/mlx_backend/vlm/modeling/models/llava_next/vision.py +243 -0
- nexaai/mlx_backend/vlm/modeling/models/mistral3/__init__.py +8 -0
- nexaai/mlx_backend/vlm/modeling/models/mistral3/mistral3.py +283 -0
- nexaai/mlx_backend/vlm/modeling/models/mllama/__init__.py +8 -0
- nexaai/mlx_backend/vlm/modeling/models/mllama/language.py +416 -0
- nexaai/mlx_backend/vlm/modeling/models/mllama/mllama.py +172 -0
- nexaai/mlx_backend/vlm/modeling/models/mllama/vision.py +499 -0
- nexaai/mlx_backend/vlm/modeling/models/molmo/__init__.py +8 -0
- nexaai/mlx_backend/vlm/modeling/models/molmo/language.py +243 -0
- nexaai/mlx_backend/vlm/modeling/models/molmo/molmo.py +133 -0
- nexaai/mlx_backend/vlm/modeling/models/molmo/vision.py +465 -0
- nexaai/mlx_backend/vlm/modeling/models/multi_modality/__init__.py +10 -0
- nexaai/mlx_backend/vlm/modeling/models/multi_modality/language.py +230 -0
- nexaai/mlx_backend/vlm/modeling/models/multi_modality/multi_modality.py +385 -0
- nexaai/mlx_backend/vlm/modeling/models/multi_modality/sam.py +557 -0
- nexaai/mlx_backend/vlm/modeling/models/multi_modality/vision.py +526 -0
- nexaai/mlx_backend/vlm/modeling/models/paligemma/__init__.py +8 -0
- nexaai/mlx_backend/vlm/modeling/models/paligemma/language.py +282 -0
- nexaai/mlx_backend/vlm/modeling/models/paligemma/paligemma.py +160 -0
- nexaai/mlx_backend/vlm/modeling/models/paligemma/vision.py +242 -0
- nexaai/mlx_backend/vlm/modeling/models/phi3_v/__init__.py +8 -0
- nexaai/mlx_backend/vlm/modeling/models/phi3_v/language.py +21 -0
- nexaai/mlx_backend/vlm/modeling/models/phi3_v/phi3_v.py +243 -0
- nexaai/mlx_backend/vlm/modeling/models/phi3_v/su_rope.py +71 -0
- nexaai/mlx_backend/vlm/modeling/models/phi3_v/vision.py +324 -0
- nexaai/mlx_backend/vlm/modeling/models/pixtral/__init__.py +8 -0
- nexaai/mlx_backend/vlm/modeling/models/pixtral/language.py +229 -0
- nexaai/mlx_backend/vlm/modeling/models/pixtral/pixtral.py +161 -0
- nexaai/mlx_backend/vlm/modeling/models/pixtral/vision.py +320 -0
- nexaai/mlx_backend/vlm/modeling/models/qwen2_5_vl/__init__.py +2 -0
- nexaai/mlx_backend/vlm/modeling/models/qwen2_5_vl/config.py +108 -0
- nexaai/mlx_backend/vlm/modeling/models/qwen2_5_vl/language.py +490 -0
- nexaai/mlx_backend/vlm/modeling/models/qwen2_5_vl/qwen2_5_vl.py +168 -0
- nexaai/mlx_backend/vlm/modeling/models/qwen2_5_vl/vision.py +414 -0
- nexaai/mlx_backend/vlm/modeling/models/qwen2_vl/__init__.py +2 -0
- nexaai/mlx_backend/vlm/modeling/models/qwen2_vl/config.py +104 -0
- nexaai/mlx_backend/vlm/modeling/models/qwen2_vl/language.py +490 -0
- nexaai/mlx_backend/vlm/modeling/models/qwen2_vl/qwen2_vl.py +167 -0
- nexaai/mlx_backend/vlm/modeling/models/qwen2_vl/vision.py +312 -0
- nexaai/mlx_backend/vlm/modeling/models/qwen3_vl/llm_common/__init__.py +0 -0
- nexaai/mlx_backend/vlm/modeling/models/qwen3_vl/llm_common/base.py +117 -0
- nexaai/mlx_backend/vlm/modeling/models/qwen3_vl/llm_common/cache.py +531 -0
- nexaai/mlx_backend/vlm/modeling/models/qwen3_vl/llm_common/generate.py +701 -0
- nexaai/mlx_backend/vlm/modeling/models/qwen3_vl/llm_common/rope_utils.py +255 -0
- nexaai/mlx_backend/vlm/modeling/models/qwen3_vl/llm_common/sample_utils.py +303 -0
- nexaai/mlx_backend/vlm/modeling/models/qwen3_vl/llm_common/tokenizer_utils.py +407 -0
- nexaai/mlx_backend/vlm/modeling/models/qwen3_vl/processor.py +476 -0
- nexaai/mlx_backend/vlm/modeling/models/qwen3_vl/qwen3vl.py +1262 -0
- nexaai/mlx_backend/vlm/modeling/models/qwen3vl_moe/llm_common/__init__.py +0 -0
- nexaai/mlx_backend/vlm/modeling/models/qwen3vl_moe/llm_common/base.py +117 -0
- nexaai/mlx_backend/vlm/modeling/models/qwen3vl_moe/llm_common/cache.py +531 -0
- nexaai/mlx_backend/vlm/modeling/models/qwen3vl_moe/llm_common/generate.py +701 -0
- nexaai/mlx_backend/vlm/modeling/models/qwen3vl_moe/llm_common/rope_utils.py +255 -0
- nexaai/mlx_backend/vlm/modeling/models/qwen3vl_moe/llm_common/sample_utils.py +303 -0
- nexaai/mlx_backend/vlm/modeling/models/qwen3vl_moe/llm_common/tokenizer_utils.py +407 -0
- nexaai/mlx_backend/vlm/modeling/models/qwen3vl_moe/processor.py +476 -0
- nexaai/mlx_backend/vlm/modeling/models/qwen3vl_moe/qwen3vl_moe.py +1308 -0
- nexaai/mlx_backend/vlm/modeling/models/qwen3vl_moe/switch_layers.py +210 -0
- nexaai/mlx_backend/vlm/modeling/models/smolvlm/__init__.py +8 -0
- nexaai/mlx_backend/vlm/modeling/models/smolvlm/smolvlm.py +62 -0
- nexaai/mlx_backend/vlm/modeling/processing_qwen2_5_vl.py +209 -0
- nexaai/mlx_backend/vlm/modeling/processing_qwen2_vl.py +215 -0
- nexaai/mlx_backend/vlm/modeling/prompt_utils.py +474 -0
- nexaai/mlx_backend/vlm/modeling/sample_utils.py +39 -0
- nexaai/mlx_backend/vlm/modeling/tokenizer_utils.py +344 -0
- nexaai/mlx_backend/vlm/modeling/trainer/__init__.py +9 -0
- nexaai/mlx_backend/vlm/modeling/trainer/lora.py +70 -0
- nexaai/mlx_backend/vlm/modeling/trainer/trainer.py +296 -0
- nexaai/mlx_backend/vlm/modeling/trainer/utils.py +160 -0
- nexaai/mlx_backend/vlm/modeling/utils.py +928 -0
- nexaai/rerank.py +57 -0
- nexaai/rerank_impl/__init__.py +0 -0
- nexaai/rerank_impl/mlx_rerank_impl.py +94 -0
- nexaai/rerank_impl/pybind_rerank_impl.py +136 -0
- nexaai/runtime.py +68 -0
- nexaai/runtime_error.py +24 -0
- nexaai/tts.py +75 -0
- nexaai/tts_impl/__init__.py +0 -0
- nexaai/tts_impl/mlx_tts_impl.py +94 -0
- nexaai/tts_impl/pybind_tts_impl.py +43 -0
- nexaai/utils/decode.py +18 -0
- nexaai/utils/manifest_utils.py +531 -0
- nexaai/utils/model_manager.py +1745 -0
- nexaai/utils/model_types.py +49 -0
- nexaai/utils/progress_tracker.py +389 -0
- nexaai/utils/quantization_utils.py +245 -0
- nexaai/vlm.py +130 -0
- nexaai/vlm_impl/__init__.py +0 -0
- nexaai/vlm_impl/mlx_vlm_impl.py +259 -0
- nexaai/vlm_impl/pybind_vlm_impl.py +275 -0
- nexaai-1.0.29.dist-info/METADATA +35 -0
- nexaai-1.0.29.dist-info/RECORD +580 -0
- nexaai-1.0.29.dist-info/WHEEL +5 -0
- nexaai-1.0.29.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import re
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from numbers import Number
|
|
5
|
+
from typing import Any, Generator, List, Optional, Tuple, Union
|
|
6
|
+
|
|
7
|
+
import mlx.core as mx
|
|
8
|
+
import mlx.nn as nn
|
|
9
|
+
from misaki import en, espeak
|
|
10
|
+
|
|
11
|
+
from .voice import load_voice_tensor
|
|
12
|
+
|
|
13
|
+
ALIASES = {
|
|
14
|
+
"en-us": "a",
|
|
15
|
+
"en-gb": "b",
|
|
16
|
+
"es": "e",
|
|
17
|
+
"fr-fr": "f",
|
|
18
|
+
"hi": "h",
|
|
19
|
+
"it": "i",
|
|
20
|
+
"pt-br": "p",
|
|
21
|
+
"ja": "j",
|
|
22
|
+
"zh": "z",
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
LANG_CODES = dict(
|
|
26
|
+
# pip install misaki[en]
|
|
27
|
+
a="American English",
|
|
28
|
+
b="British English",
|
|
29
|
+
# espeak-ng
|
|
30
|
+
e="es",
|
|
31
|
+
f="fr-fr",
|
|
32
|
+
h="hi",
|
|
33
|
+
i="it",
|
|
34
|
+
p="pt-br",
|
|
35
|
+
# pip install misaki[ja]
|
|
36
|
+
j="Japanese",
|
|
37
|
+
# pip install misaki[zh]
|
|
38
|
+
z="Mandarin Chinese",
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class KokoroPipeline:
|
|
43
|
+
"""
|
|
44
|
+
KokoroPipeline is a language-aware support class with 2 main responsibilities:
|
|
45
|
+
1. Perform language-specific G2P, mapping (and chunking) text -> phonemes
|
|
46
|
+
2. Manage and store voices, lazily downloaded from HF if needed
|
|
47
|
+
|
|
48
|
+
You are expected to have one KokoroPipeline per language. If you have multiple
|
|
49
|
+
KokoroPipeline instances, you should reuse one KokoroModel instance across all of them.
|
|
50
|
+
|
|
51
|
+
KokoroPipeline is designed to work with a KokoroModel, but this is not required.
|
|
52
|
+
There are 2 ways to pass an existing model into a pipeline:
|
|
53
|
+
1. On init: us_pipeline = KokoroPipeline(lang_code='a', model=model)
|
|
54
|
+
2. On call: us_pipeline(text, voice, model=model)
|
|
55
|
+
|
|
56
|
+
By default, KokoroPipeline will automatically initialize its own KokoroModel. To
|
|
57
|
+
suppress this, construct a "quiet" KokoroPipeline with model=False.
|
|
58
|
+
|
|
59
|
+
A "quiet" KokoroPipeline yields (graphemes, phonemes, None) without generating
|
|
60
|
+
any audio. You can use this to phonemize and chunk your text in advance.
|
|
61
|
+
|
|
62
|
+
A "loud" KokoroPipeline _with_ a model yields (graphemes, phonemes, audio).
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
def __init__(
|
|
66
|
+
self,
|
|
67
|
+
lang_code: str,
|
|
68
|
+
model: nn.Module,
|
|
69
|
+
trf: bool = False,
|
|
70
|
+
):
|
|
71
|
+
"""Initialize a KokoroPipeline.
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
lang_code: Language code for G2P processing
|
|
75
|
+
model: KokoroModel instance, True to create new model, False for no model
|
|
76
|
+
trf: Whether to use transformer-based G2P
|
|
77
|
+
"""
|
|
78
|
+
lang_code = lang_code.lower()
|
|
79
|
+
lang_code = ALIASES.get(lang_code, lang_code)
|
|
80
|
+
assert lang_code in LANG_CODES, (lang_code, LANG_CODES)
|
|
81
|
+
self.lang_code = lang_code
|
|
82
|
+
self.model = model
|
|
83
|
+
self.voices = {}
|
|
84
|
+
if lang_code in "ab":
|
|
85
|
+
try:
|
|
86
|
+
fallback = espeak.EspeakFallback(british=lang_code == "b")
|
|
87
|
+
except Exception as e:
|
|
88
|
+
logging.warning("EspeakFallback not Enabled: OOD words will be skipped")
|
|
89
|
+
logging.warning({str(e)})
|
|
90
|
+
fallback = None
|
|
91
|
+
self.g2p = en.G2P(
|
|
92
|
+
trf=trf, british=lang_code == "b", fallback=fallback, unk=""
|
|
93
|
+
)
|
|
94
|
+
elif lang_code == "j":
|
|
95
|
+
try:
|
|
96
|
+
from misaki import ja
|
|
97
|
+
|
|
98
|
+
self.g2p = ja.JAG2P()
|
|
99
|
+
except ImportError:
|
|
100
|
+
logging.error(
|
|
101
|
+
"You need to `pip install misaki[ja]` to use lang_code='j'"
|
|
102
|
+
)
|
|
103
|
+
raise
|
|
104
|
+
elif lang_code == "z":
|
|
105
|
+
try:
|
|
106
|
+
from misaki import zh
|
|
107
|
+
|
|
108
|
+
self.g2p = zh.ZHG2P()
|
|
109
|
+
except ImportError:
|
|
110
|
+
logging.error(
|
|
111
|
+
"You need to `pip install misaki[zh]` to use lang_code='z'"
|
|
112
|
+
)
|
|
113
|
+
raise
|
|
114
|
+
else:
|
|
115
|
+
language = LANG_CODES[lang_code]
|
|
116
|
+
logging.warning(
|
|
117
|
+
f"Using EspeakG2P(language='{language}'). Chunking logic not yet implemented, so long texts may be truncated unless you split them with '\\n'."
|
|
118
|
+
)
|
|
119
|
+
self.g2p = espeak.EspeakG2P(language=language)
|
|
120
|
+
|
|
121
|
+
def load_single_voice(self, voice: str) -> mx.array:
|
|
122
|
+
if voice in self.voices:
|
|
123
|
+
return self.voices[voice]
|
|
124
|
+
if voice.endswith(".pt"):
|
|
125
|
+
f = voice
|
|
126
|
+
else:
|
|
127
|
+
# we may need to adjust the dirname. Maybe sit should be loaded from a dir passed in or some other hardcoded dir.
|
|
128
|
+
f = f"voices/{voice}.pt"
|
|
129
|
+
if not voice.startswith(self.lang_code):
|
|
130
|
+
v = LANG_CODES.get(voice, voice)
|
|
131
|
+
p = LANG_CODES.get(self.lang_code, self.lang_code)
|
|
132
|
+
logging.warning(
|
|
133
|
+
f"Language mismatch, loading {v} voice into {p} pipeline."
|
|
134
|
+
)
|
|
135
|
+
pack = mx.array(load_voice_tensor(f))
|
|
136
|
+
self.voices[voice] = pack
|
|
137
|
+
return pack
|
|
138
|
+
|
|
139
|
+
"""
|
|
140
|
+
load_voice is a helper function that lazily downloads and loads a voice:
|
|
141
|
+
Single voice can be requested (e.g. 'af_bella') or multiple voices (e.g. 'af_bella,af_jessica').
|
|
142
|
+
If multiple voices are requested, they are averaged.
|
|
143
|
+
Delimiter is optional and defaults to ','.
|
|
144
|
+
"""
|
|
145
|
+
|
|
146
|
+
def load_voice(self, voice: str, delimiter: str = ",") -> mx.array:
|
|
147
|
+
if voice in self.voices:
|
|
148
|
+
return self.voices[voice]
|
|
149
|
+
logging.debug(f"Loading voice: {voice}")
|
|
150
|
+
packs = [self.load_single_voice(v) for v in voice.split(delimiter)]
|
|
151
|
+
if len(packs) == 1:
|
|
152
|
+
return packs[0]
|
|
153
|
+
self.voices[voice] = mx.mean(mx.stack(packs), axis=0)
|
|
154
|
+
return self.voices[voice]
|
|
155
|
+
|
|
156
|
+
@classmethod
|
|
157
|
+
def tokens_to_ps(cls, tokens: List[en.MToken]) -> str:
|
|
158
|
+
return "".join(
|
|
159
|
+
t.phonemes + (" " if t.whitespace else "") for t in tokens
|
|
160
|
+
).strip()
|
|
161
|
+
|
|
162
|
+
@classmethod
|
|
163
|
+
def waterfall_last(
|
|
164
|
+
cls,
|
|
165
|
+
tokens: List[en.MToken],
|
|
166
|
+
next_count: int,
|
|
167
|
+
waterfall: List[str] = ["!.?…", ":;", ",—"],
|
|
168
|
+
bumps: List[str] = [")", ""],
|
|
169
|
+
) -> int:
|
|
170
|
+
for w in waterfall:
|
|
171
|
+
z = next(
|
|
172
|
+
(
|
|
173
|
+
i
|
|
174
|
+
for i, t in reversed(list(enumerate(tokens)))
|
|
175
|
+
if t.phonemes in set(w)
|
|
176
|
+
),
|
|
177
|
+
None,
|
|
178
|
+
)
|
|
179
|
+
if z is None:
|
|
180
|
+
continue
|
|
181
|
+
z += 1
|
|
182
|
+
if z < len(tokens) and tokens[z].phonemes in bumps:
|
|
183
|
+
z += 1
|
|
184
|
+
if next_count - len(cls.tokens_to_ps(tokens[:z])) <= 510:
|
|
185
|
+
return z
|
|
186
|
+
return len(tokens)
|
|
187
|
+
|
|
188
|
+
@classmethod
|
|
189
|
+
def tokens_to_text(cls, tokens: List[en.MToken]) -> str:
|
|
190
|
+
return "".join(t.text + t.whitespace for t in tokens).strip()
|
|
191
|
+
|
|
192
|
+
def en_tokenize(
|
|
193
|
+
self, tokens: List[en.MToken]
|
|
194
|
+
) -> Generator[Tuple[str, str, List[en.MToken]], None, None]:
|
|
195
|
+
tks = []
|
|
196
|
+
pcount = 0
|
|
197
|
+
for t in tokens:
|
|
198
|
+
# American English: ɾ => T
|
|
199
|
+
t.phonemes = "" if t.phonemes is None else t.phonemes.replace("ɾ", "T")
|
|
200
|
+
next_ps = t.phonemes + (" " if t.whitespace else "")
|
|
201
|
+
next_pcount = pcount + len(next_ps.rstrip())
|
|
202
|
+
if next_pcount > 510:
|
|
203
|
+
z = KokoroPipeline.waterfall_last(tks, next_pcount)
|
|
204
|
+
text = KokoroPipeline.tokens_to_text(tks[:z])
|
|
205
|
+
logging.debug(
|
|
206
|
+
f"Chunking text at {z}: '{text[:30]}{'...' if len(text) > 30 else ''}'"
|
|
207
|
+
)
|
|
208
|
+
ps = KokoroPipeline.tokens_to_ps(tks[:z])
|
|
209
|
+
yield text, ps, tks[:z]
|
|
210
|
+
tks = tks[z:]
|
|
211
|
+
pcount = len(KokoroPipeline.tokens_to_ps(tks))
|
|
212
|
+
if not tks:
|
|
213
|
+
next_ps = next_ps.lstrip()
|
|
214
|
+
tks.append(t)
|
|
215
|
+
pcount += len(next_ps)
|
|
216
|
+
if tks:
|
|
217
|
+
text = KokoroPipeline.tokens_to_text(tks)
|
|
218
|
+
ps = KokoroPipeline.tokens_to_ps(tks)
|
|
219
|
+
yield "".join(text).strip(), "".join(ps).strip(), tks
|
|
220
|
+
|
|
221
|
+
@classmethod
|
|
222
|
+
def infer(
|
|
223
|
+
cls,
|
|
224
|
+
model: nn.Module,
|
|
225
|
+
ps: str,
|
|
226
|
+
pack: mx.array,
|
|
227
|
+
speed: Number = 1,
|
|
228
|
+
):
|
|
229
|
+
return model(ps, pack[len(ps) - 1], speed, return_output=True)
|
|
230
|
+
|
|
231
|
+
def generate_from_tokens(
|
|
232
|
+
self,
|
|
233
|
+
tokens: Union[str, List[en.MToken]],
|
|
234
|
+
voice: str,
|
|
235
|
+
speed: Number = 1,
|
|
236
|
+
model: Optional[nn.Module] = None,
|
|
237
|
+
) -> Generator["KokoroPipeline.Result", None, None]:
|
|
238
|
+
"""Generate audio from either raw phonemes or pre-processed tokens.
|
|
239
|
+
|
|
240
|
+
Args:
|
|
241
|
+
tokens: Either a phoneme string or list of pre-processed MTokens
|
|
242
|
+
voice: The voice to use for synthesis
|
|
243
|
+
speed: Speech speed modifier (default: 1)
|
|
244
|
+
model: Optional Model instance (uses pipeline's model if not provided)
|
|
245
|
+
|
|
246
|
+
Yields:
|
|
247
|
+
KokoroPipeline.Result containing the input tokens and generated audio
|
|
248
|
+
|
|
249
|
+
Raises:
|
|
250
|
+
ValueError: If no voice is provided or token sequence exceeds model limits
|
|
251
|
+
"""
|
|
252
|
+
model = model or self.model
|
|
253
|
+
if model and voice is None:
|
|
254
|
+
raise ValueError(
|
|
255
|
+
'Specify a voice: pipeline.generate_from_tokens(..., voice="af_heart")'
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
pack = self.load_voice(voice) if model else None
|
|
259
|
+
|
|
260
|
+
# Handle raw phoneme string
|
|
261
|
+
if isinstance(tokens, str):
|
|
262
|
+
logging.debug("Processing phonemes from raw string")
|
|
263
|
+
if len(tokens) > 510:
|
|
264
|
+
raise ValueError(f"Phoneme string too long: {len(tokens)} > 510")
|
|
265
|
+
output = KokoroPipeline.infer(model, tokens, pack, speed) if model else None
|
|
266
|
+
yield self.Result(graphemes="", phonemes=tokens, output=output)
|
|
267
|
+
return
|
|
268
|
+
|
|
269
|
+
logging.debug("Processing MTokens")
|
|
270
|
+
# Handle pre-processed tokens
|
|
271
|
+
for gs, ps, tks in self.en_tokenize(tokens):
|
|
272
|
+
if not ps:
|
|
273
|
+
continue
|
|
274
|
+
elif len(ps) > 510:
|
|
275
|
+
logging.warning(
|
|
276
|
+
f"Unexpected len(ps) == {len(ps)} > 510 and ps == '{ps}'"
|
|
277
|
+
)
|
|
278
|
+
logging.warning("Truncating to 510 characters")
|
|
279
|
+
ps = ps[:510]
|
|
280
|
+
output = KokoroPipeline.infer(model, ps, pack, speed) if model else None
|
|
281
|
+
if output is not None and output.pred_dur is not None:
|
|
282
|
+
KokoroPipeline.join_timestamps(tks, output.pred_dur)
|
|
283
|
+
yield self.Result(graphemes=gs, phonemes=ps, tokens=tks, output=output)
|
|
284
|
+
|
|
285
|
+
@classmethod
|
|
286
|
+
def join_timestamps(cls, tokens: List[en.MToken], pred_dur: mx.array):
|
|
287
|
+
# Multiply by 600 to go from pred_dur frames to sample_rate 24000
|
|
288
|
+
# Equivalent to dividing pred_dur frames by 40 to get timestamp in seconds
|
|
289
|
+
# We will count nice round half-frames, so the divisor is 80
|
|
290
|
+
MAGIC_DIVISOR = 80
|
|
291
|
+
if not tokens or len(pred_dur) < 3:
|
|
292
|
+
# We expect at least 3: <bos>, token, <eos>
|
|
293
|
+
return
|
|
294
|
+
# We track 2 counts, measured in half-frames: (left, right)
|
|
295
|
+
# This way we can cut space characters in half
|
|
296
|
+
# TODO: Is -3 an appropriate offset?
|
|
297
|
+
left = right = 2 * max(0, pred_dur[0].item() - 3)
|
|
298
|
+
# Updates:
|
|
299
|
+
# left = right + (2 * token_dur) + space_dur
|
|
300
|
+
# right = left + space_dur
|
|
301
|
+
i = 1
|
|
302
|
+
for t in tokens:
|
|
303
|
+
if i >= len(pred_dur) - 1:
|
|
304
|
+
break
|
|
305
|
+
if not t.phonemes:
|
|
306
|
+
if t.whitespace:
|
|
307
|
+
i += 1
|
|
308
|
+
left = right + pred_dur[i].item()
|
|
309
|
+
right = left + pred_dur[i].item()
|
|
310
|
+
i += 1
|
|
311
|
+
continue
|
|
312
|
+
j = i + len(t.phonemes)
|
|
313
|
+
if j >= len(pred_dur):
|
|
314
|
+
break
|
|
315
|
+
t.start_ts = left / MAGIC_DIVISOR
|
|
316
|
+
token_dur = pred_dur[i:j].sum().item()
|
|
317
|
+
space_dur = pred_dur[j].item() if t.whitespace else 0
|
|
318
|
+
left = right + (2 * token_dur) + space_dur
|
|
319
|
+
t.end_ts = left / MAGIC_DIVISOR
|
|
320
|
+
right = left + space_dur
|
|
321
|
+
i = j + (1 if t.whitespace else 0)
|
|
322
|
+
|
|
323
|
+
@dataclass
|
|
324
|
+
class Result:
|
|
325
|
+
graphemes: str
|
|
326
|
+
phonemes: str
|
|
327
|
+
tokens: Optional[List[en.MToken]] = None
|
|
328
|
+
output: Optional[Any] = None
|
|
329
|
+
text_index: Optional[int] = None
|
|
330
|
+
|
|
331
|
+
@property
|
|
332
|
+
def audio(self) -> Optional[mx.array]:
|
|
333
|
+
return None if self.output is None else self.output.audio
|
|
334
|
+
|
|
335
|
+
@property
|
|
336
|
+
def pred_dur(self) -> Optional[mx.array]:
|
|
337
|
+
return None if self.output is None else self.output.pred_dur
|
|
338
|
+
|
|
339
|
+
### MARK: BEGIN BACKWARD COMPAT ###
|
|
340
|
+
def __iter__(self):
|
|
341
|
+
yield self.graphemes
|
|
342
|
+
yield self.phonemes
|
|
343
|
+
yield self.audio
|
|
344
|
+
|
|
345
|
+
def __getitem__(self, index):
|
|
346
|
+
return [self.graphemes, self.phonemes, self.audio][index]
|
|
347
|
+
|
|
348
|
+
def __len__(self):
|
|
349
|
+
return 3
|
|
350
|
+
|
|
351
|
+
def __call__(
|
|
352
|
+
self,
|
|
353
|
+
text: Union[str, List[str]],
|
|
354
|
+
voice: Optional[str] = None,
|
|
355
|
+
speed: Number = 1,
|
|
356
|
+
split_pattern: Optional[str] = r"\n+",
|
|
357
|
+
) -> Generator["KokoroPipeline.Result", None, None]:
|
|
358
|
+
if voice is None:
|
|
359
|
+
raise ValueError(
|
|
360
|
+
'Specify a voice: en_us_pipeline(text="Hello world!", voice="af_heart")'
|
|
361
|
+
)
|
|
362
|
+
pack = self.load_voice(voice) if self.model else None
|
|
363
|
+
if isinstance(text, str):
|
|
364
|
+
text = re.split(split_pattern, text.strip()) if split_pattern else [text]
|
|
365
|
+
# Process each segment
|
|
366
|
+
for graphemes_index, graphemes in enumerate(text):
|
|
367
|
+
if not graphemes.strip(): # Skip empty segments
|
|
368
|
+
continue
|
|
369
|
+
|
|
370
|
+
# English processing (unchanged)
|
|
371
|
+
if self.lang_code in "ab":
|
|
372
|
+
# print(f"Processing English text: {graphemes[:50]}{'...' if len(graphemes) > 50 else ''}")
|
|
373
|
+
_, tokens = self.g2p(graphemes)
|
|
374
|
+
for gs, ps, tks in self.en_tokenize(tokens):
|
|
375
|
+
if not ps:
|
|
376
|
+
continue
|
|
377
|
+
elif len(ps) > 510:
|
|
378
|
+
logging.warning(
|
|
379
|
+
f"Unexpected len(ps) == {len(ps)} > 510 and ps == '{ps}'"
|
|
380
|
+
)
|
|
381
|
+
ps = ps[:510]
|
|
382
|
+
output = (
|
|
383
|
+
KokoroPipeline.infer(self.model, ps, pack, speed)
|
|
384
|
+
if self.model
|
|
385
|
+
else None
|
|
386
|
+
)
|
|
387
|
+
if output is not None and output.pred_dur is not None:
|
|
388
|
+
KokoroPipeline.join_timestamps(tks, output.pred_dur)
|
|
389
|
+
yield self.Result(
|
|
390
|
+
graphemes=gs,
|
|
391
|
+
phonemes=ps,
|
|
392
|
+
tokens=tks,
|
|
393
|
+
output=output,
|
|
394
|
+
text_index=graphemes_index,
|
|
395
|
+
)
|
|
396
|
+
|
|
397
|
+
# Non-English processing with chunking
|
|
398
|
+
else:
|
|
399
|
+
# Split long text into smaller chunks (roughly 400 characters each)
|
|
400
|
+
# Using sentence boundaries when possible
|
|
401
|
+
chunk_size = 400
|
|
402
|
+
chunks = []
|
|
403
|
+
|
|
404
|
+
# Try to split on sentence boundaries first
|
|
405
|
+
sentences = re.split(r"([.!?]+)", graphemes)
|
|
406
|
+
current_chunk = ""
|
|
407
|
+
|
|
408
|
+
for i in range(0, len(sentences), 2):
|
|
409
|
+
sentence = sentences[i]
|
|
410
|
+
# Add the punctuation back if it exists
|
|
411
|
+
if i + 1 < len(sentences):
|
|
412
|
+
sentence += sentences[i + 1]
|
|
413
|
+
|
|
414
|
+
if len(current_chunk) + len(sentence) <= chunk_size:
|
|
415
|
+
current_chunk += sentence
|
|
416
|
+
else:
|
|
417
|
+
if current_chunk:
|
|
418
|
+
chunks.append(current_chunk.strip())
|
|
419
|
+
current_chunk = sentence
|
|
420
|
+
|
|
421
|
+
if current_chunk:
|
|
422
|
+
chunks.append(current_chunk.strip())
|
|
423
|
+
|
|
424
|
+
# If no chunks were created (no sentence boundaries), fall back to character-based chunking
|
|
425
|
+
if not chunks:
|
|
426
|
+
chunks = [
|
|
427
|
+
graphemes[i : i + chunk_size]
|
|
428
|
+
for i in range(0, len(graphemes), chunk_size)
|
|
429
|
+
]
|
|
430
|
+
|
|
431
|
+
# Process each chunk
|
|
432
|
+
for chunk in chunks:
|
|
433
|
+
if not chunk.strip():
|
|
434
|
+
continue
|
|
435
|
+
|
|
436
|
+
ps, _ = self.g2p(chunk)
|
|
437
|
+
if not ps:
|
|
438
|
+
continue
|
|
439
|
+
elif len(ps) > 510:
|
|
440
|
+
logging.warning(f"Truncating len(ps) == {len(ps)} > 510")
|
|
441
|
+
ps = ps[:510]
|
|
442
|
+
|
|
443
|
+
output = (
|
|
444
|
+
KokoroPipeline.infer(self.model, ps, pack, speed)
|
|
445
|
+
if self.model
|
|
446
|
+
else None
|
|
447
|
+
)
|
|
448
|
+
yield self.Result(
|
|
449
|
+
graphemes=chunk,
|
|
450
|
+
phonemes=ps,
|
|
451
|
+
output=output,
|
|
452
|
+
text_index=graphemes_index,
|
|
453
|
+
)
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import io
|
|
2
|
+
import pickle
|
|
3
|
+
import sys
|
|
4
|
+
import zipfile
|
|
5
|
+
|
|
6
|
+
import numpy as np
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def load_voice_tensor(path: str) -> np.ndarray:
|
|
10
|
+
"""
|
|
11
|
+
Load a voice pack .pt file into a NumPy array.
|
|
12
|
+
Handles either flat layout or one extra top-level folder.
|
|
13
|
+
Improved version that works without PyTorch installed.
|
|
14
|
+
"""
|
|
15
|
+
# map PyTorch storage names to NumPy dtypes
|
|
16
|
+
_STORAGE_TO_DTYPE = {
|
|
17
|
+
"FloatStorage": np.float32,
|
|
18
|
+
"DoubleStorage": np.float64,
|
|
19
|
+
"HalfStorage": np.float16,
|
|
20
|
+
"IntStorage": np.int32,
|
|
21
|
+
"LongStorage": np.int64,
|
|
22
|
+
"ByteStorage": np.uint8,
|
|
23
|
+
"CharStorage": np.int8,
|
|
24
|
+
"ShortStorage": np.int16,
|
|
25
|
+
"BoolStorage": np.bool_,
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
# Create mock storage classes to handle cases where torch isn't available
|
|
29
|
+
class MockStorage:
|
|
30
|
+
def __init__(self, name):
|
|
31
|
+
self.__name__ = name
|
|
32
|
+
|
|
33
|
+
# Create storage class instances
|
|
34
|
+
_MOCK_STORAGE_CLASSES = {
|
|
35
|
+
name: MockStorage(name) for name in _STORAGE_TO_DTYPE.keys()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
storages: dict[str, np.ndarray] = {}
|
|
39
|
+
|
|
40
|
+
with zipfile.ZipFile(path, "r") as zf:
|
|
41
|
+
names = zf.namelist()
|
|
42
|
+
|
|
43
|
+
# detect optional top-level prefix
|
|
44
|
+
if "byteorder" in names:
|
|
45
|
+
prefix = ""
|
|
46
|
+
else:
|
|
47
|
+
tops = {n.split("/", 1)[0] for n in names if "/" in n}
|
|
48
|
+
prefix = (tops.pop() + "/") if len(tops) == 1 else ""
|
|
49
|
+
|
|
50
|
+
try:
|
|
51
|
+
byteorder = zf.read(f"{prefix}byteorder").decode("ascii").strip()
|
|
52
|
+
except KeyError:
|
|
53
|
+
byteorder = sys.byteorder
|
|
54
|
+
|
|
55
|
+
# build a helper for retrieving raw storage blobs
|
|
56
|
+
def _persistent_load(pid):
|
|
57
|
+
typename, storage_type, root_key, _, numel = pid
|
|
58
|
+
if typename != "storage":
|
|
59
|
+
raise RuntimeError(f"Unknown persistent id: {typename}")
|
|
60
|
+
if root_key not in storages:
|
|
61
|
+
raw = zf.read(f"{prefix}data/{root_key}")
|
|
62
|
+
# Get storage type name more robustly
|
|
63
|
+
if hasattr(storage_type, '__name__'):
|
|
64
|
+
name = storage_type.__name__
|
|
65
|
+
else:
|
|
66
|
+
name = str(storage_type)
|
|
67
|
+
try:
|
|
68
|
+
dtype = _STORAGE_TO_DTYPE[name]
|
|
69
|
+
except KeyError:
|
|
70
|
+
raise RuntimeError(f"Unsupported storage type: {name}")
|
|
71
|
+
if byteorder != sys.byteorder:
|
|
72
|
+
dtype = dtype.newbyteorder()
|
|
73
|
+
storages[root_key] = np.frombuffer(raw, dtype=dtype, count=numel)
|
|
74
|
+
return storages[root_key]
|
|
75
|
+
|
|
76
|
+
# mimic torch._utils._rebuild_tensor_v2
|
|
77
|
+
def _rebuild_tensor_v2(
|
|
78
|
+
storage, storage_offset, size, stride, requires_grad, backward_hooks
|
|
79
|
+
):
|
|
80
|
+
count = 1
|
|
81
|
+
for d in size:
|
|
82
|
+
count *= d
|
|
83
|
+
segment = storage[storage_offset : storage_offset + count]
|
|
84
|
+
return segment.reshape(size)
|
|
85
|
+
|
|
86
|
+
class _NoTorchUnpickler(pickle.Unpickler):
|
|
87
|
+
def persistent_load(self, pid):
|
|
88
|
+
return _persistent_load(pid)
|
|
89
|
+
|
|
90
|
+
def find_class(self, module, name):
|
|
91
|
+
# Handle torch utilities
|
|
92
|
+
if module == "torch._utils" and name == "_rebuild_tensor_v2":
|
|
93
|
+
return _rebuild_tensor_v2
|
|
94
|
+
|
|
95
|
+
# Handle torch storage classes
|
|
96
|
+
if module == "torch" and name in _STORAGE_TO_DTYPE:
|
|
97
|
+
return _MOCK_STORAGE_CLASSES[name]
|
|
98
|
+
|
|
99
|
+
# Handle other torch classes that we don't need
|
|
100
|
+
if module.startswith("torch"):
|
|
101
|
+
# Return a dummy function for unused torch classes
|
|
102
|
+
return lambda *args, **kwargs: None
|
|
103
|
+
|
|
104
|
+
# For everything else, use default behavior
|
|
105
|
+
try:
|
|
106
|
+
return super().find_class(module, name)
|
|
107
|
+
except (ImportError, AttributeError):
|
|
108
|
+
# If we can't find the class, create a mock
|
|
109
|
+
return lambda *args, **kwargs: None
|
|
110
|
+
|
|
111
|
+
data_pkl = zf.read(f"{prefix}data.pkl")
|
|
112
|
+
unpickler = _NoTorchUnpickler(io.BytesIO(data_pkl))
|
|
113
|
+
return unpickler.load()
|