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,531 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Manifest and metadata utilities for handling nexa.manifest files and model metadata.
|
|
3
|
+
|
|
4
|
+
This module provides utilities to:
|
|
5
|
+
- Load and save nexa.manifest files
|
|
6
|
+
- Create GGUF and MLX manifests
|
|
7
|
+
- Process manifest metadata (handle null fields, fetch avatars, etc.)
|
|
8
|
+
- Manage backward compatibility with old download_metadata.json files
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import os
|
|
12
|
+
import json
|
|
13
|
+
from datetime import datetime
|
|
14
|
+
from typing import Dict, Any, List, Optional, Union
|
|
15
|
+
|
|
16
|
+
from .quantization_utils import (
|
|
17
|
+
extract_quantization_from_filename,
|
|
18
|
+
detect_quantization_for_mlx
|
|
19
|
+
)
|
|
20
|
+
from .model_types import (
|
|
21
|
+
PIPELINE_TO_MODEL_TYPE,
|
|
22
|
+
MODEL_TYPE_TO_PIPELINE
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
MODEL_FILE_TYPE_TO_PLUGIN_ID_MAPPING = {
|
|
26
|
+
'npu': 'npu',
|
|
27
|
+
'mlx': 'mlx',
|
|
28
|
+
'gguf': 'llama_cpp'
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
def process_manifest_metadata(manifest: Dict[str, Any], repo_id: str) -> Dict[str, Any]:
|
|
32
|
+
"""Process manifest metadata to handle null/missing fields."""
|
|
33
|
+
# Handle pipeline_tag
|
|
34
|
+
pipeline_tag = manifest.get('pipeline_tag')
|
|
35
|
+
if not pipeline_tag:
|
|
36
|
+
# Reverse map from ModelType if available
|
|
37
|
+
model_type = manifest.get('ModelType')
|
|
38
|
+
pipeline_tag = MODEL_TYPE_TO_PIPELINE.get(model_type) if model_type else None
|
|
39
|
+
|
|
40
|
+
# Handle download_time - keep as null if missing
|
|
41
|
+
download_time = manifest.get('download_time')
|
|
42
|
+
|
|
43
|
+
# Handle avatar_url - leave it null if missing/null
|
|
44
|
+
avatar_url = manifest.get('avatar_url')
|
|
45
|
+
|
|
46
|
+
# Return processed metadata
|
|
47
|
+
processed_manifest = manifest.copy()
|
|
48
|
+
processed_manifest.update({
|
|
49
|
+
'pipeline_tag': pipeline_tag,
|
|
50
|
+
'download_time': download_time,
|
|
51
|
+
'avatar_url': avatar_url
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
return processed_manifest
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def load_nexa_manifest(directory_path: str) -> Dict[str, Any]:
|
|
58
|
+
"""Load manifest from nexa.manifest if it exists."""
|
|
59
|
+
manifest_path = os.path.join(directory_path, 'nexa.manifest')
|
|
60
|
+
if os.path.exists(manifest_path):
|
|
61
|
+
try:
|
|
62
|
+
with open(manifest_path, 'r', encoding='utf-8') as f:
|
|
63
|
+
return json.load(f)
|
|
64
|
+
except (json.JSONDecodeError, IOError):
|
|
65
|
+
pass
|
|
66
|
+
return {}
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def load_download_metadata(directory_path: str, repo_id: Optional[str] = None) -> Dict[str, Any]:
|
|
70
|
+
"""Load download metadata from nexa.manifest if it exists, fallback to old format."""
|
|
71
|
+
# First try to load from new manifest format
|
|
72
|
+
manifest = load_nexa_manifest(directory_path)
|
|
73
|
+
if manifest and repo_id:
|
|
74
|
+
# Process the manifest to handle null/missing fields
|
|
75
|
+
return process_manifest_metadata(manifest, repo_id)
|
|
76
|
+
elif manifest:
|
|
77
|
+
# Return manifest as-is if no repo_id provided (for backward compatibility)
|
|
78
|
+
return manifest
|
|
79
|
+
|
|
80
|
+
# Fallback to old format for backward compatibility
|
|
81
|
+
old_metadata_path = os.path.join(directory_path, 'download_metadata.json')
|
|
82
|
+
if os.path.exists(old_metadata_path):
|
|
83
|
+
try:
|
|
84
|
+
with open(old_metadata_path, 'r', encoding='utf-8') as f:
|
|
85
|
+
return json.load(f)
|
|
86
|
+
except (json.JSONDecodeError, IOError):
|
|
87
|
+
pass
|
|
88
|
+
return {}
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def save_download_metadata(directory_path: str, metadata: Dict[str, Any]) -> None:
|
|
92
|
+
"""Save download metadata to nexa.manifest in the new format."""
|
|
93
|
+
manifest_path = os.path.join(directory_path, 'nexa.manifest')
|
|
94
|
+
try:
|
|
95
|
+
with open(manifest_path, 'w', encoding='utf-8') as f:
|
|
96
|
+
json.dump(metadata, f, indent=2)
|
|
97
|
+
except IOError:
|
|
98
|
+
# If we can't save metadata, don't fail the download
|
|
99
|
+
pass
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def _get_plugin_id_from_model_file_type(model_file_type: Optional[str], default: str = "llama_cpp") -> str:
|
|
103
|
+
"""Map model file type to PluginId."""
|
|
104
|
+
return MODEL_FILE_TYPE_TO_PLUGIN_ID_MAPPING.get(model_file_type, default)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def create_gguf_manifest(repo_id: str, files: List[str], directory_path: str, old_metadata: Dict[str, Any], is_mmproj: bool = False, file_name: Optional[Union[str, List[str]]] = None, **kwargs) -> Dict[str, Any]:
|
|
108
|
+
"""Create GGUF format manifest."""
|
|
109
|
+
|
|
110
|
+
# Load existing manifest to merge GGUF files if it exists
|
|
111
|
+
existing_manifest = load_nexa_manifest(directory_path)
|
|
112
|
+
|
|
113
|
+
# Check if there's a downloaded nexa.manifest from the repo
|
|
114
|
+
downloaded_manifest = old_metadata.get('downloaded_manifest', {})
|
|
115
|
+
|
|
116
|
+
model_files = {}
|
|
117
|
+
if existing_manifest and "ModelFile" in existing_manifest:
|
|
118
|
+
model_files = existing_manifest["ModelFile"].copy()
|
|
119
|
+
|
|
120
|
+
# Initialize MMProjFile from existing manifest or empty
|
|
121
|
+
mmproj_file = {
|
|
122
|
+
"Name": "",
|
|
123
|
+
"Downloaded": False,
|
|
124
|
+
"Size": 0
|
|
125
|
+
}
|
|
126
|
+
if existing_manifest and "MMProjFile" in existing_manifest:
|
|
127
|
+
mmproj_file = existing_manifest["MMProjFile"].copy()
|
|
128
|
+
|
|
129
|
+
# Process GGUF files
|
|
130
|
+
for current_file_name in files:
|
|
131
|
+
if current_file_name.endswith('.gguf'):
|
|
132
|
+
# Check if this file is an mmproj file
|
|
133
|
+
is_current_mmproj = 'mmproj' in current_file_name.lower()
|
|
134
|
+
|
|
135
|
+
# If we're downloading specific files and this is marked as mmproj, respect that
|
|
136
|
+
if is_mmproj and file_name is not None:
|
|
137
|
+
filenames_to_check = file_name if isinstance(file_name, list) else [file_name]
|
|
138
|
+
is_current_mmproj = current_file_name in filenames_to_check
|
|
139
|
+
|
|
140
|
+
file_path = os.path.join(directory_path, current_file_name)
|
|
141
|
+
file_size = 0
|
|
142
|
+
if os.path.exists(file_path):
|
|
143
|
+
try:
|
|
144
|
+
file_size = os.path.getsize(file_path)
|
|
145
|
+
except (OSError, IOError):
|
|
146
|
+
pass
|
|
147
|
+
|
|
148
|
+
if is_current_mmproj:
|
|
149
|
+
# This is an mmproj file, put it in MMProjFile
|
|
150
|
+
mmproj_file = {
|
|
151
|
+
"Name": current_file_name,
|
|
152
|
+
"Downloaded": True,
|
|
153
|
+
"Size": file_size
|
|
154
|
+
}
|
|
155
|
+
else:
|
|
156
|
+
# Regular model file, put in ModelFile
|
|
157
|
+
# Use the new enum-based quantization extraction
|
|
158
|
+
quantization_type = extract_quantization_from_filename(current_file_name)
|
|
159
|
+
quant_level = quantization_type.value if quantization_type else "UNKNOWN"
|
|
160
|
+
|
|
161
|
+
# FIXME: hardcode to handle the multiple mmproj files problem
|
|
162
|
+
if quant_level == "UNKNOWN" and "mmproj" in current_file_name.lower():
|
|
163
|
+
pass
|
|
164
|
+
else:
|
|
165
|
+
model_files[quant_level] = {
|
|
166
|
+
"Name": current_file_name,
|
|
167
|
+
"Downloaded": True,
|
|
168
|
+
"Size": file_size
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
# Determine PluginId with priority: kwargs > downloaded_manifest > model_file_type > default
|
|
172
|
+
plugin_id = kwargs.get('plugin_id')
|
|
173
|
+
if not plugin_id:
|
|
174
|
+
model_file_type = old_metadata.get('model_file_type')
|
|
175
|
+
if downloaded_manifest.get('PluginId'):
|
|
176
|
+
plugin_id = downloaded_manifest.get('PluginId')
|
|
177
|
+
elif model_file_type:
|
|
178
|
+
plugin_id = _get_plugin_id_from_model_file_type(model_file_type)
|
|
179
|
+
else:
|
|
180
|
+
plugin_id = "llama_cpp"
|
|
181
|
+
|
|
182
|
+
# Determine ModelType with priority: kwargs > downloaded_manifest > pipeline_tag mapping
|
|
183
|
+
model_type = kwargs.get('model_type')
|
|
184
|
+
if not model_type:
|
|
185
|
+
if downloaded_manifest.get('ModelType'):
|
|
186
|
+
model_type = downloaded_manifest.get('ModelType')
|
|
187
|
+
else:
|
|
188
|
+
model_type = PIPELINE_TO_MODEL_TYPE.get(old_metadata.get('pipeline_tag'), "other")
|
|
189
|
+
|
|
190
|
+
# Determine ModelName with priority: kwargs > downloaded_manifest > empty string
|
|
191
|
+
model_name = kwargs.get('model_name')
|
|
192
|
+
if not model_name:
|
|
193
|
+
model_name = downloaded_manifest.get('ModelName', '')
|
|
194
|
+
|
|
195
|
+
# Get DeviceId and MinSDKVersion from kwargs or default to empty string
|
|
196
|
+
device_id = kwargs.get('device_id', '')
|
|
197
|
+
min_sdk_version = kwargs.get('min_sdk_version', '')
|
|
198
|
+
|
|
199
|
+
manifest = {
|
|
200
|
+
"Name": repo_id,
|
|
201
|
+
"ModelName": model_name,
|
|
202
|
+
"ModelType": model_type,
|
|
203
|
+
"PluginId": plugin_id,
|
|
204
|
+
"DeviceId": device_id,
|
|
205
|
+
"MinSDKVersion": min_sdk_version,
|
|
206
|
+
"ModelFile": model_files,
|
|
207
|
+
"MMProjFile": mmproj_file,
|
|
208
|
+
"TokenizerFile": {
|
|
209
|
+
"Name": "",
|
|
210
|
+
"Downloaded": False,
|
|
211
|
+
"Size": 0
|
|
212
|
+
},
|
|
213
|
+
"ExtraFiles": None,
|
|
214
|
+
# Preserve old metadata fields
|
|
215
|
+
"pipeline_tag": old_metadata.get('pipeline_tag') if old_metadata.get('pipeline_tag') else existing_manifest.get('pipeline_tag'),
|
|
216
|
+
"download_time": old_metadata.get('download_time') if old_metadata.get('download_time') else existing_manifest.get('download_time'),
|
|
217
|
+
"avatar_url": old_metadata.get('avatar_url') if old_metadata.get('avatar_url') else existing_manifest.get('avatar_url')
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return manifest
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def create_mlx_manifest(repo_id: str, files: List[str], directory_path: str, old_metadata: Dict[str, Any], is_mmproj: bool = False, file_name: Optional[Union[str, List[str]]] = None, **kwargs) -> Dict[str, Any]:
|
|
224
|
+
"""Create MLX format manifest."""
|
|
225
|
+
|
|
226
|
+
# Load existing manifest to merge MLX files if it exists
|
|
227
|
+
existing_manifest = load_nexa_manifest(directory_path)
|
|
228
|
+
|
|
229
|
+
# Check if there's a downloaded nexa.manifest from the repo
|
|
230
|
+
downloaded_manifest = old_metadata.get('downloaded_manifest', {})
|
|
231
|
+
|
|
232
|
+
model_files = {}
|
|
233
|
+
extra_files = []
|
|
234
|
+
|
|
235
|
+
# Initialize MMProjFile
|
|
236
|
+
mmproj_file = {
|
|
237
|
+
"Name": "",
|
|
238
|
+
"Downloaded": False,
|
|
239
|
+
"Size": 0
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
# Try different methods to extract quantization for MLX models
|
|
243
|
+
quantization_type = detect_quantization_for_mlx(repo_id, directory_path)
|
|
244
|
+
|
|
245
|
+
# Use the detected quantization or default to "DEFAULT"
|
|
246
|
+
quant_level = quantization_type.value if quantization_type else "DEFAULT"
|
|
247
|
+
|
|
248
|
+
for current_file_name in files:
|
|
249
|
+
file_path = os.path.join(directory_path, current_file_name)
|
|
250
|
+
file_size = 0
|
|
251
|
+
if os.path.exists(file_path):
|
|
252
|
+
try:
|
|
253
|
+
file_size = os.path.getsize(file_path)
|
|
254
|
+
except (OSError, IOError):
|
|
255
|
+
pass
|
|
256
|
+
|
|
257
|
+
# Check if this file is an mmproj file
|
|
258
|
+
is_current_mmproj = 'mmproj' in current_file_name.lower()
|
|
259
|
+
|
|
260
|
+
# If we're downloading specific files and this is marked as mmproj, respect that
|
|
261
|
+
if is_mmproj and file_name is not None:
|
|
262
|
+
filenames_to_check = file_name if isinstance(file_name, list) else [file_name]
|
|
263
|
+
is_current_mmproj = current_file_name in filenames_to_check
|
|
264
|
+
|
|
265
|
+
if is_current_mmproj:
|
|
266
|
+
# This is an mmproj file, put it in MMProjFile
|
|
267
|
+
mmproj_file = {
|
|
268
|
+
"Name": current_file_name,
|
|
269
|
+
"Downloaded": True,
|
|
270
|
+
"Size": file_size
|
|
271
|
+
}
|
|
272
|
+
# Check if this is a main model file (safetensors but not index files)
|
|
273
|
+
elif (current_file_name.endswith('.safetensors') and not current_file_name.endswith('.index.json')):
|
|
274
|
+
model_files[quant_level] = {
|
|
275
|
+
"Name": current_file_name,
|
|
276
|
+
"Downloaded": True,
|
|
277
|
+
"Size": file_size
|
|
278
|
+
}
|
|
279
|
+
else:
|
|
280
|
+
# Add to extra files
|
|
281
|
+
extra_files.append({
|
|
282
|
+
"Name": current_file_name,
|
|
283
|
+
"Downloaded": True,
|
|
284
|
+
"Size": file_size
|
|
285
|
+
})
|
|
286
|
+
|
|
287
|
+
# Determine PluginId with priority: kwargs > downloaded_manifest > model_file_type > default
|
|
288
|
+
plugin_id = kwargs.get('plugin_id')
|
|
289
|
+
if not plugin_id:
|
|
290
|
+
model_file_type = old_metadata.get('model_file_type')
|
|
291
|
+
if downloaded_manifest.get('PluginId'):
|
|
292
|
+
plugin_id = downloaded_manifest.get('PluginId')
|
|
293
|
+
elif model_file_type:
|
|
294
|
+
plugin_id = _get_plugin_id_from_model_file_type(model_file_type)
|
|
295
|
+
else:
|
|
296
|
+
plugin_id = "mlx"
|
|
297
|
+
|
|
298
|
+
# Determine ModelType with priority: kwargs > downloaded_manifest > pipeline_tag mapping
|
|
299
|
+
model_type = kwargs.get('model_type')
|
|
300
|
+
if not model_type:
|
|
301
|
+
if downloaded_manifest.get('ModelType'):
|
|
302
|
+
model_type = downloaded_manifest.get('ModelType')
|
|
303
|
+
else:
|
|
304
|
+
model_type = PIPELINE_TO_MODEL_TYPE.get(old_metadata.get('pipeline_tag'), "other")
|
|
305
|
+
|
|
306
|
+
# Determine ModelName with priority: kwargs > downloaded_manifest > empty string
|
|
307
|
+
model_name = kwargs.get('model_name')
|
|
308
|
+
if not model_name:
|
|
309
|
+
model_name = downloaded_manifest.get('ModelName', '')
|
|
310
|
+
|
|
311
|
+
# Get DeviceId and MinSDKVersion from kwargs or default to empty string
|
|
312
|
+
device_id = kwargs.get('device_id', '')
|
|
313
|
+
min_sdk_version = kwargs.get('min_sdk_version', '')
|
|
314
|
+
|
|
315
|
+
manifest = {
|
|
316
|
+
"Name": repo_id,
|
|
317
|
+
"ModelName": model_name,
|
|
318
|
+
"ModelType": model_type,
|
|
319
|
+
"PluginId": plugin_id,
|
|
320
|
+
"DeviceId": device_id,
|
|
321
|
+
"MinSDKVersion": min_sdk_version,
|
|
322
|
+
"ModelFile": model_files,
|
|
323
|
+
"MMProjFile": mmproj_file,
|
|
324
|
+
"TokenizerFile": {
|
|
325
|
+
"Name": "",
|
|
326
|
+
"Downloaded": False,
|
|
327
|
+
"Size": 0
|
|
328
|
+
},
|
|
329
|
+
"ExtraFiles": extra_files if extra_files else None,
|
|
330
|
+
# Preserve old metadata fields
|
|
331
|
+
"pipeline_tag": old_metadata.get('pipeline_tag') if old_metadata.get('pipeline_tag') else existing_manifest.get('pipeline_tag'),
|
|
332
|
+
"download_time": old_metadata.get('download_time') if old_metadata.get('download_time') else existing_manifest.get('download_time'),
|
|
333
|
+
"avatar_url": old_metadata.get('avatar_url') if old_metadata.get('avatar_url') else existing_manifest.get('avatar_url')
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
return manifest
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
def create_npu_manifest(repo_id: str, files: List[str], directory_path: str, old_metadata: Dict[str, Any], is_mmproj: bool = False, file_name: Optional[Union[str, List[str]]] = None, **kwargs) -> Dict[str, Any]:
|
|
340
|
+
"""Create NPU format manifest."""
|
|
341
|
+
|
|
342
|
+
# Load existing manifest to merge NPU files if it exists
|
|
343
|
+
existing_manifest = load_nexa_manifest(directory_path)
|
|
344
|
+
|
|
345
|
+
# Check if there's a downloaded nexa.manifest from the repo
|
|
346
|
+
downloaded_manifest = old_metadata.get('downloaded_manifest', {})
|
|
347
|
+
|
|
348
|
+
model_files = {}
|
|
349
|
+
extra_files = []
|
|
350
|
+
|
|
351
|
+
# Initialize MMProjFile
|
|
352
|
+
mmproj_file = {
|
|
353
|
+
"Name": "",
|
|
354
|
+
"Downloaded": False,
|
|
355
|
+
"Size": 0
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
for current_file_name in files:
|
|
359
|
+
file_path = os.path.join(directory_path, current_file_name)
|
|
360
|
+
file_size = 0
|
|
361
|
+
if os.path.exists(file_path):
|
|
362
|
+
try:
|
|
363
|
+
file_size = os.path.getsize(file_path)
|
|
364
|
+
except (OSError, IOError):
|
|
365
|
+
pass
|
|
366
|
+
|
|
367
|
+
# Check if this file is an mmproj file
|
|
368
|
+
is_current_mmproj = 'mmproj' in current_file_name.lower()
|
|
369
|
+
|
|
370
|
+
# If we're downloading specific files and this is marked as mmproj, respect that
|
|
371
|
+
if is_mmproj and file_name is not None:
|
|
372
|
+
filenames_to_check = file_name if isinstance(file_name, list) else [file_name]
|
|
373
|
+
is_current_mmproj = current_file_name in filenames_to_check
|
|
374
|
+
|
|
375
|
+
if is_current_mmproj:
|
|
376
|
+
# This is an mmproj file, put it in MMProjFile
|
|
377
|
+
mmproj_file = {
|
|
378
|
+
"Name": current_file_name,
|
|
379
|
+
"Downloaded": True,
|
|
380
|
+
"Size": file_size
|
|
381
|
+
}
|
|
382
|
+
else:
|
|
383
|
+
# For NPU, all non-mmproj files go to extra_files
|
|
384
|
+
extra_files.append({
|
|
385
|
+
"Name": current_file_name,
|
|
386
|
+
"Downloaded": True,
|
|
387
|
+
"Size": file_size
|
|
388
|
+
})
|
|
389
|
+
|
|
390
|
+
# Pick the first file from extra_files and add it to ModelFile with key "N/A"
|
|
391
|
+
if extra_files:
|
|
392
|
+
first_file = extra_files[0]
|
|
393
|
+
model_files["N/A"] = {
|
|
394
|
+
"Name": first_file["Name"],
|
|
395
|
+
"Downloaded": first_file["Downloaded"],
|
|
396
|
+
"Size": first_file["Size"]
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
# Determine PluginId with priority: kwargs > downloaded_manifest > model_file_type > default
|
|
400
|
+
plugin_id = kwargs.get('plugin_id')
|
|
401
|
+
if not plugin_id:
|
|
402
|
+
model_file_type = old_metadata.get('model_file_type')
|
|
403
|
+
if downloaded_manifest.get('PluginId'):
|
|
404
|
+
plugin_id = downloaded_manifest.get('PluginId')
|
|
405
|
+
elif model_file_type:
|
|
406
|
+
plugin_id = _get_plugin_id_from_model_file_type(model_file_type)
|
|
407
|
+
else:
|
|
408
|
+
plugin_id = "npu"
|
|
409
|
+
|
|
410
|
+
# Determine ModelType with priority: kwargs > downloaded_manifest > pipeline_tag mapping
|
|
411
|
+
model_type = kwargs.get('model_type')
|
|
412
|
+
if not model_type:
|
|
413
|
+
if downloaded_manifest.get('ModelType'):
|
|
414
|
+
model_type = downloaded_manifest.get('ModelType')
|
|
415
|
+
else:
|
|
416
|
+
model_type = PIPELINE_TO_MODEL_TYPE.get(old_metadata.get('pipeline_tag'), "other")
|
|
417
|
+
|
|
418
|
+
# Determine ModelName with priority: kwargs > downloaded_manifest > empty string
|
|
419
|
+
model_name = kwargs.get('model_name')
|
|
420
|
+
if not model_name:
|
|
421
|
+
model_name = downloaded_manifest.get('ModelName', '')
|
|
422
|
+
|
|
423
|
+
# Get DeviceId and MinSDKVersion from kwargs or default to empty string
|
|
424
|
+
device_id = kwargs.get('device_id', '')
|
|
425
|
+
min_sdk_version = kwargs.get('min_sdk_version', '')
|
|
426
|
+
|
|
427
|
+
manifest = {
|
|
428
|
+
"Name": repo_id,
|
|
429
|
+
"ModelName": model_name,
|
|
430
|
+
"ModelType": model_type,
|
|
431
|
+
"PluginId": plugin_id,
|
|
432
|
+
"DeviceId": device_id,
|
|
433
|
+
"MinSDKVersion": min_sdk_version,
|
|
434
|
+
"ModelFile": model_files,
|
|
435
|
+
"MMProjFile": mmproj_file,
|
|
436
|
+
"TokenizerFile": {
|
|
437
|
+
"Name": "",
|
|
438
|
+
"Downloaded": False,
|
|
439
|
+
"Size": 0
|
|
440
|
+
},
|
|
441
|
+
"ExtraFiles": extra_files if extra_files else None,
|
|
442
|
+
# Preserve old metadata fields
|
|
443
|
+
"pipeline_tag": old_metadata.get('pipeline_tag') if old_metadata.get('pipeline_tag') else existing_manifest.get('pipeline_tag'),
|
|
444
|
+
"download_time": old_metadata.get('download_time') if old_metadata.get('download_time') else existing_manifest.get('download_time'),
|
|
445
|
+
"avatar_url": old_metadata.get('avatar_url') if old_metadata.get('avatar_url') else existing_manifest.get('avatar_url')
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
return manifest
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
def detect_model_type(files: List[str], old_metadata: Dict[str, Any] = None) -> str:
|
|
452
|
+
"""Detect if this is a GGUF, MLX, or NPU model based on file extensions and metadata.
|
|
453
|
+
|
|
454
|
+
Args:
|
|
455
|
+
files: List of files in the model directory
|
|
456
|
+
old_metadata: Metadata dict that may contain 'model_file_type'
|
|
457
|
+
|
|
458
|
+
Returns:
|
|
459
|
+
Model type string: 'gguf', 'mlx', or 'npu'
|
|
460
|
+
"""
|
|
461
|
+
# Check if model_file_type is explicitly set to NPU
|
|
462
|
+
if old_metadata and old_metadata.get('model_file_type') == 'npu':
|
|
463
|
+
return "npu"
|
|
464
|
+
|
|
465
|
+
# Otherwise, detect based on file extensions
|
|
466
|
+
has_gguf = any(f.endswith('.gguf') for f in files)
|
|
467
|
+
has_safetensors = any(f.endswith('.safetensors') or 'safetensors' in f for f in files)
|
|
468
|
+
|
|
469
|
+
if has_gguf:
|
|
470
|
+
return "gguf"
|
|
471
|
+
elif has_safetensors:
|
|
472
|
+
return "mlx"
|
|
473
|
+
else:
|
|
474
|
+
# Default to mlx for other types
|
|
475
|
+
return "mlx"
|
|
476
|
+
|
|
477
|
+
|
|
478
|
+
def create_manifest_from_files(repo_id: str, files: List[str], directory_path: str, old_metadata: Dict[str, Any], is_mmproj: bool = False, file_name: Optional[Union[str, List[str]]] = None, **kwargs) -> Dict[str, Any]:
|
|
479
|
+
"""
|
|
480
|
+
Create appropriate manifest format based on detected model type.
|
|
481
|
+
|
|
482
|
+
Args:
|
|
483
|
+
repo_id: Repository ID
|
|
484
|
+
files: List of files in the model directory
|
|
485
|
+
directory_path: Path to the model directory
|
|
486
|
+
old_metadata: Existing metadata (pipeline_tag, download_time, avatar_url, model_file_type)
|
|
487
|
+
is_mmproj: Whether the downloaded file is an mmproj file
|
|
488
|
+
file_name: The specific file(s) that were downloaded (None if entire repo was downloaded)
|
|
489
|
+
**kwargs: Additional metadata including plugin_id, model_name, model_type, device_id, min_sdk_version
|
|
490
|
+
|
|
491
|
+
Returns:
|
|
492
|
+
Dict containing the appropriate manifest format
|
|
493
|
+
"""
|
|
494
|
+
model_type = detect_model_type(files, old_metadata)
|
|
495
|
+
|
|
496
|
+
if model_type == "gguf":
|
|
497
|
+
return create_gguf_manifest(repo_id, files, directory_path, old_metadata, is_mmproj, file_name, **kwargs)
|
|
498
|
+
elif model_type == "npu":
|
|
499
|
+
return create_npu_manifest(repo_id, files, directory_path, old_metadata, is_mmproj, file_name, **kwargs)
|
|
500
|
+
else: # mlx or other
|
|
501
|
+
return create_mlx_manifest(repo_id, files, directory_path, old_metadata, is_mmproj, file_name, **kwargs)
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
def save_manifest_with_files_metadata(repo_id: str, local_dir: str, old_metadata: Dict[str, Any], is_mmproj: bool = False, file_name: Optional[Union[str, List[str]]] = None, **kwargs) -> None:
|
|
505
|
+
"""
|
|
506
|
+
Create and save manifest based on files found in the directory.
|
|
507
|
+
|
|
508
|
+
Args:
|
|
509
|
+
repo_id: Repository ID
|
|
510
|
+
local_dir: Local directory containing the model files
|
|
511
|
+
old_metadata: Existing metadata to preserve
|
|
512
|
+
is_mmproj: Whether the downloaded file is an mmproj file
|
|
513
|
+
file_name: The specific file(s) that were downloaded (None if entire repo was downloaded)
|
|
514
|
+
**kwargs: Additional metadata including plugin_id, model_name, model_type, device_id, min_sdk_version
|
|
515
|
+
"""
|
|
516
|
+
# Get list of files in the directory
|
|
517
|
+
files = []
|
|
518
|
+
try:
|
|
519
|
+
for root, dirs, filenames in os.walk(local_dir):
|
|
520
|
+
for filename in filenames:
|
|
521
|
+
# Store relative path from the directory
|
|
522
|
+
rel_path = os.path.relpath(os.path.join(root, filename), local_dir)
|
|
523
|
+
files.append(rel_path)
|
|
524
|
+
except (OSError, IOError):
|
|
525
|
+
pass
|
|
526
|
+
|
|
527
|
+
# Create appropriate manifest
|
|
528
|
+
manifest = create_manifest_from_files(repo_id, files, local_dir, old_metadata, is_mmproj, file_name, **kwargs)
|
|
529
|
+
|
|
530
|
+
# Save manifest
|
|
531
|
+
save_download_metadata(local_dir, manifest)
|