nexaai 1.0.18__cp310-cp310-macosx_14_0_universal2.whl → 1.0.19__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.
Potentially problematic release.
This version of nexaai might be problematic. Click here for more details.
- nexaai/_stub.cpython-310-darwin.so +0 -0
- nexaai/_version.py +1 -1
- nexaai/asr.py +2 -1
- nexaai/binds/{nexa_llama_cpp → cpu_gpu}/libggml-base.dylib +0 -0
- nexaai/binds/{nexa_llama_cpp → cpu_gpu}/libmtmd.dylib +0 -0
- nexaai/binds/{nexa_llama_cpp/libllama.dylib → cpu_gpu/libnexa_cpu_gpu.dylib} +0 -0
- nexaai/binds/{nexa_llama_cpp → cpu_gpu}/libnexa_plugin.dylib +0 -0
- nexaai/binds/libnexa_bridge.dylib +0 -0
- nexaai/binds/llm_bind.cpython-310-darwin.so +0 -0
- nexaai/binds/{nexa_mlx → metal}/libnexa_plugin.dylib +0 -0
- nexaai/binds/{nexa_nexaml → nexaml}/libggml-base.dylib +0 -0
- nexaai/binds/{nexa_nexaml → nexaml}/libnexa-mm-process.dylib +0 -0
- nexaai/binds/{nexa_nexaml → nexaml}/libnexa-sampling.dylib +0 -0
- nexaai/binds/nexaml/libnexa_plugin.dylib +0 -0
- nexaai/binds/nexaml/libnexaproc.dylib +0 -0
- nexaai/binds/{nexa_nexaml → nexaml}/libomp.dylib +0 -0
- nexaai/binds/nexaml/libqwen3-vl.dylib +0 -0
- nexaai/binds/nexaml/libqwen3vl-vision.dylib +0 -0
- nexaai/cv.py +2 -1
- nexaai/embedder.py +1 -1
- nexaai/image_gen.py +2 -1
- nexaai/llm.py +5 -3
- nexaai/llm_impl/mlx_llm_impl.py +2 -0
- nexaai/llm_impl/pybind_llm_impl.py +2 -0
- nexaai/mlx_backend/vlm/generate_qwen3_vl.py +176 -96
- nexaai/mlx_backend/vlm/generate_qwen3_vl_moe.py +259 -0
- nexaai/mlx_backend/vlm/interface.py +99 -30
- nexaai/mlx_backend/vlm/main.py +58 -9
- nexaai/mlx_backend/vlm/modeling/models/qwen3_vl/qwen3vl.py +338 -299
- 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/rerank.py +2 -1
- nexaai/tts.py +2 -1
- nexaai/utils/manifest_utils.py +222 -15
- nexaai/utils/model_manager.py +120 -14
- nexaai/utils/model_types.py +2 -0
- nexaai/vlm.py +2 -1
- {nexaai-1.0.18.dist-info → nexaai-1.0.19.dist-info}/METADATA +1 -2
- {nexaai-1.0.18.dist-info → nexaai-1.0.19.dist-info}/RECORD +211 -200
- nexaai/binds/nexa_nexaml/libnexa_plugin.dylib +0 -0
- nexaai/binds/nexa_nexaml/libnexaproc.dylib +0 -0
- nexaai/binds/nexa_nexaml/libqwen3-vl.dylib +0 -0
- nexaai/binds/nexa_nexaml/libqwen3vl-vision.dylib +0 -0
- /nexaai/binds/{nexa_llama_cpp → cpu_gpu}/libggml-cpu.so +0 -0
- /nexaai/binds/{nexa_llama_cpp → cpu_gpu}/libggml-metal.so +0 -0
- /nexaai/binds/{nexa_llama_cpp → cpu_gpu}/libggml.dylib +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/ml.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/__init__.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/__init__.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/models/__init__.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/models/bigvgan/__init__.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/models/bigvgan/activation.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/models/bigvgan/amp.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/models/bigvgan/bigvgan.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/models/bigvgan/conv.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/models/bigvgan/resample.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/models/descript/__init__.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/models/descript/base.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/models/descript/dac.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/models/descript/nn/__init__.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/models/descript/nn/layers.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/models/descript/nn/quantize.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/models/encodec/__init__.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/models/encodec/encodec.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/models/mimi/__init__.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/models/mimi/mimi.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/models/mimi/modules/__init__.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/models/mimi/modules/conv.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/models/mimi/modules/kv_cache.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/models/mimi/modules/quantization.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/models/mimi/modules/seanet.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/models/mimi/modules/transformer.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/models/s3/__init__.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/models/s3/model.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/models/s3/model_v2.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/models/s3/utils.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/models/snac/__init__.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/models/snac/attention.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/models/snac/layers.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/models/snac/snac.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/models/snac/vq.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/models/vocos/__init__.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/models/vocos/mel.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/models/vocos/vocos.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/tests/__init__.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/tests/test_bigvgan.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/tests/test_descript.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/tests/test_encodec.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/tests/test_mimi.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/tests/test_s3.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/tests/test_snac.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/codec/tests/test_vocos.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/server.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/sts/__init__.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/sts/tests/test_voice_pipeline.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/sts/voice_pipeline.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/stt/__init__.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/stt/generate.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/stt/models/__init__.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/stt/models/parakeet/__init__.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/stt/models/parakeet/alignment.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/stt/models/parakeet/attention.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/stt/models/parakeet/audio.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/stt/models/parakeet/conformer.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/stt/models/parakeet/ctc.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/stt/models/parakeet/parakeet.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/stt/models/parakeet/rnnt.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/stt/models/parakeet/tokenizer.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/stt/models/wav2vec/feature_extractor.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/stt/models/wav2vec/wav2vec.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/stt/models/whisper/__init__.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/stt/models/whisper/audio.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/stt/models/whisper/decoding.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/stt/models/whisper/timing.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/stt/models/whisper/tokenizer.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/stt/models/whisper/whisper.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/stt/models/whisper/writers.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/stt/tests/test_models.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/stt/utils.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/__init__.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/audio_player.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/convert.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/generate.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/__init__.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/bark/__init__.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/bark/bark.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/bark/isftnet.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/bark/pipeline.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/base.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/dia/__init__.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/dia/audio.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/dia/config.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/dia/dia.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/dia/layers.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/indextts/__init__.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/indextts/attention.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/indextts/bigvgan.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/indextts/conformer.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/indextts/ecapa_tdnn/__init__.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/indextts/ecapa_tdnn/asp.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/indextts/ecapa_tdnn/ecapa_tdnn.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/indextts/ecapa_tdnn/se_res2net.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/indextts/ecapa_tdnn/tdnn.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/indextts/gpt2.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/indextts/indextts.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/indextts/mel.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/indextts/normalize.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/indextts/perceiver.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/interpolate.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/kokoro/__init__.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/kokoro/istftnet.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/kokoro/kokoro.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/kokoro/modules.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/kokoro/pipeline.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/kokoro/voice.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/llama/__init__.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/llama/llama.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/outetts/__init__.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/outetts/audio_processor.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/outetts/dac_interface.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/outetts/outetts.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/outetts/prompt_processor.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/outetts/tokens.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/sesame/__init__.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/sesame/attention.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/sesame/sesame.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/sesame/watermarking.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/spark/__init__.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/spark/audio_tokenizer.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/spark/bicodec.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/spark/modules/__init__.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/spark/modules/blocks/__init__.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/spark/modules/blocks/sampler.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/spark/modules/encoder_decoder/__init__.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/spark/modules/encoder_decoder/feat_decoder.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/spark/modules/encoder_decoder/feat_encoder.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/spark/modules/encoder_decoder/wave_generator.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/spark/modules/finite_scalar_quantization.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/spark/modules/residual.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/spark/modules/residual_fsq.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/spark/modules/speaker/__init__.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/spark/modules/speaker/ecapa_tdnn.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/spark/modules/speaker/perceiver_encoder.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/spark/modules/speaker/pooling_layers.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/spark/modules/speaker/speaker_encoder.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/spark/spark.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/spark/utils/audio.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/spark/utils/file.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/models/spark/utils/token_parser.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/tests/__init__.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/tests/test_base.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/tests/test_convert.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/tests/test_interpolate.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/tests/test_models.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/tts/utils.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/utils.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/mlx_audio/version.py +0 -0
- /nexaai/binds/{nexa_mlx → metal}/py-lib/profiling.py +0 -0
- /nexaai/binds/{nexa_nexaml → nexaml}/libfftw3.3.dylib +0 -0
- /nexaai/binds/{nexa_nexaml → nexaml}/libfftw3f.3.dylib +0 -0
- /nexaai/binds/{nexa_nexaml → nexaml}/libggml-cpu.so +0 -0
- /nexaai/binds/{nexa_nexaml → nexaml}/libggml-metal.so +0 -0
- /nexaai/binds/{nexa_nexaml → nexaml}/libggml.dylib +0 -0
- /nexaai/binds/{nexa_nexaml → nexaml}/libmp3lame.0.dylib +0 -0
- /nexaai/binds/{nexa_nexaml → nexaml}/libmpg123.0.dylib +0 -0
- {nexaai-1.0.18.dist-info → nexaai-1.0.19.dist-info}/WHEEL +0 -0
- {nexaai-1.0.18.dist-info → nexaai-1.0.19.dist-info}/top_level.txt +0 -0
nexaai/utils/model_manager.py
CHANGED
|
@@ -595,6 +595,7 @@ class HuggingFaceDownloader:
|
|
|
595
595
|
self.enable_transfer = enable_transfer
|
|
596
596
|
self.original_hf_transfer = None
|
|
597
597
|
self.endpoint = endpoint # Store endpoint for avatar fetching
|
|
598
|
+
self._model_info_cache: Dict[str, Any] = {} # Cache for model_info results
|
|
598
599
|
|
|
599
600
|
def _create_repo_directory(self, local_dir: str, repo_id: str) -> str:
|
|
600
601
|
"""Create a directory structure for the repository following HF convention."""
|
|
@@ -618,6 +619,32 @@ class HuggingFaceDownloader:
|
|
|
618
619
|
os.makedirs(local_dir, exist_ok=True)
|
|
619
620
|
return local_dir
|
|
620
621
|
|
|
622
|
+
def _get_model_info_cached(self, repo_id: str, files_metadata: bool = False):
|
|
623
|
+
"""Get model info with caching to avoid rate limiting.
|
|
624
|
+
|
|
625
|
+
Args:
|
|
626
|
+
repo_id: Repository ID
|
|
627
|
+
files_metadata: Whether to include files metadata
|
|
628
|
+
|
|
629
|
+
Returns:
|
|
630
|
+
Model info object from HuggingFace API
|
|
631
|
+
"""
|
|
632
|
+
# Create cache key based on repo_id and files_metadata flag
|
|
633
|
+
cache_key = f"{repo_id}:files={files_metadata}"
|
|
634
|
+
|
|
635
|
+
# Return cached result if available
|
|
636
|
+
if cache_key in self._model_info_cache:
|
|
637
|
+
return self._model_info_cache[cache_key]
|
|
638
|
+
|
|
639
|
+
# Fetch from API and cache the result
|
|
640
|
+
try:
|
|
641
|
+
info = self.api.model_info(repo_id, files_metadata=files_metadata, token=self.token)
|
|
642
|
+
self._model_info_cache[cache_key] = info
|
|
643
|
+
return info
|
|
644
|
+
except Exception:
|
|
645
|
+
# Don't cache errors, re-raise
|
|
646
|
+
raise
|
|
647
|
+
|
|
621
648
|
def _get_repo_info_for_progress(
|
|
622
649
|
self,
|
|
623
650
|
repo_id: str,
|
|
@@ -625,7 +652,7 @@ class HuggingFaceDownloader:
|
|
|
625
652
|
) -> tuple[int, int]:
|
|
626
653
|
"""Get total repository size and file count for progress tracking."""
|
|
627
654
|
try:
|
|
628
|
-
info = self.
|
|
655
|
+
info = self._get_model_info_cached(repo_id, files_metadata=True)
|
|
629
656
|
|
|
630
657
|
total_size = 0
|
|
631
658
|
file_count = 0
|
|
@@ -720,7 +747,7 @@ class HuggingFaceDownloader:
|
|
|
720
747
|
):
|
|
721
748
|
"""Validate repository exists and get info."""
|
|
722
749
|
try:
|
|
723
|
-
info = self.
|
|
750
|
+
info = self._get_model_info_cached(repo_id, files_metadata=False)
|
|
724
751
|
return info
|
|
725
752
|
except RepositoryNotFoundError:
|
|
726
753
|
error_msg = f"Repository '{repo_id}' not found. Please check the repository ID."
|
|
@@ -789,6 +816,36 @@ class HuggingFaceDownloader:
|
|
|
789
816
|
# If no expected size, just check that file is not empty
|
|
790
817
|
return os.path.getsize(file_path) > 0
|
|
791
818
|
|
|
819
|
+
def _extract_model_file_type_from_tags(self, repo_id: str) -> Optional[str]:
|
|
820
|
+
"""Extract model file type from repo tags with priority: NPU > MLX > GGUF."""
|
|
821
|
+
try:
|
|
822
|
+
info = self._get_model_info_cached(repo_id, files_metadata=False)
|
|
823
|
+
if hasattr(info, 'tags') and info.tags:
|
|
824
|
+
# Convert tags to lowercase for case-insensitive matching
|
|
825
|
+
tags_lower = [tag.lower() for tag in info.tags]
|
|
826
|
+
|
|
827
|
+
# Check with priority: NPU > MLX > GGUF
|
|
828
|
+
if 'npu' in tags_lower:
|
|
829
|
+
return 'npu'
|
|
830
|
+
elif 'mlx' in tags_lower:
|
|
831
|
+
return 'mlx'
|
|
832
|
+
elif 'gguf' in tags_lower:
|
|
833
|
+
return 'gguf'
|
|
834
|
+
except Exception:
|
|
835
|
+
pass
|
|
836
|
+
return None
|
|
837
|
+
|
|
838
|
+
def _load_downloaded_manifest(self, local_dir: str) -> Dict[str, Any]:
|
|
839
|
+
"""Load nexa.manifest from the downloaded repository if it exists."""
|
|
840
|
+
manifest_path = os.path.join(local_dir, 'nexa.manifest')
|
|
841
|
+
if os.path.exists(manifest_path):
|
|
842
|
+
try:
|
|
843
|
+
with open(manifest_path, 'r', encoding='utf-8') as f:
|
|
844
|
+
return json.load(f)
|
|
845
|
+
except (json.JSONDecodeError, IOError):
|
|
846
|
+
pass
|
|
847
|
+
return {}
|
|
848
|
+
|
|
792
849
|
def _fetch_and_save_metadata(self, repo_id: str, local_dir: str, is_mmproj: bool = False, file_name: Optional[Union[str, List[str]]] = None, **kwargs) -> None:
|
|
793
850
|
"""Fetch model info and save metadata after successful download."""
|
|
794
851
|
# Initialize metadata with defaults to ensure manifest is always created
|
|
@@ -800,8 +857,8 @@ class HuggingFaceDownloader:
|
|
|
800
857
|
|
|
801
858
|
# Try to fetch additional metadata, but don't let failures prevent manifest creation
|
|
802
859
|
try:
|
|
803
|
-
# Fetch model info to get pipeline_tag
|
|
804
|
-
info = self.
|
|
860
|
+
# Fetch model info to get pipeline_tag (using cache)
|
|
861
|
+
info = self._get_model_info_cached(repo_id, files_metadata=False)
|
|
805
862
|
if hasattr(info, 'pipeline_tag') and info.pipeline_tag:
|
|
806
863
|
old_metadata['pipeline_tag'] = info.pipeline_tag
|
|
807
864
|
except Exception as e:
|
|
@@ -810,11 +867,21 @@ class HuggingFaceDownloader:
|
|
|
810
867
|
|
|
811
868
|
# Use input avater url if provided
|
|
812
869
|
old_metadata['avatar_url'] = kwargs.get('avatar_url')
|
|
870
|
+
|
|
871
|
+
# Extract model file type from tags
|
|
872
|
+
model_file_type = self._extract_model_file_type_from_tags(repo_id)
|
|
873
|
+
if model_file_type:
|
|
874
|
+
old_metadata['model_file_type'] = model_file_type
|
|
875
|
+
|
|
876
|
+
# Load existing nexa.manifest from downloaded repo (if exists)
|
|
877
|
+
downloaded_manifest = self._load_downloaded_manifest(local_dir)
|
|
878
|
+
if downloaded_manifest:
|
|
879
|
+
old_metadata['downloaded_manifest'] = downloaded_manifest
|
|
813
880
|
|
|
814
881
|
|
|
815
882
|
# CRITICAL: Always create the manifest file, regardless of metadata fetch failures
|
|
816
883
|
try:
|
|
817
|
-
save_manifest_with_files_metadata(repo_id, local_dir, old_metadata, is_mmproj, file_name)
|
|
884
|
+
save_manifest_with_files_metadata(repo_id, local_dir, old_metadata, is_mmproj, file_name, **kwargs)
|
|
818
885
|
print(f"[OK] Successfully created nexa.manifest for {repo_id}")
|
|
819
886
|
except Exception as e:
|
|
820
887
|
# This is critical - if manifest creation fails, we should know about it
|
|
@@ -823,8 +890,11 @@ class HuggingFaceDownloader:
|
|
|
823
890
|
try:
|
|
824
891
|
minimal_manifest = {
|
|
825
892
|
"Name": repo_id,
|
|
826
|
-
"
|
|
827
|
-
"
|
|
893
|
+
"ModelName": kwargs.get('model_name', ''),
|
|
894
|
+
"ModelType": kwargs.get('model_type', 'other'),
|
|
895
|
+
"PluginId": kwargs.get('plugin_id', 'unknown'),
|
|
896
|
+
"DeviceId": kwargs.get('device_id', ''),
|
|
897
|
+
"MinSDKVersion": kwargs.get('min_sdk_version', ''),
|
|
828
898
|
"ModelFile": {},
|
|
829
899
|
"MMProjFile": {"Name": "", "Downloaded": False, "Size": 0},
|
|
830
900
|
"TokenizerFile": {"Name": "", "Downloaded": False, "Size": 0},
|
|
@@ -1136,6 +1206,12 @@ def download_from_huggingface(
|
|
|
1136
1206
|
is_mmproj (bool, optional): Whether the file being downloaded is an mmproj file. Only used when
|
|
1137
1207
|
file_name is not None. If None, defaults to True if 'mmproj' is in
|
|
1138
1208
|
the filename, False otherwise.
|
|
1209
|
+
**kwargs: Additional parameters including:
|
|
1210
|
+
- plugin_id (str): Override PluginId in nexa.manifest (highest priority)
|
|
1211
|
+
- model_name (str): Override ModelName in nexa.manifest (highest priority)
|
|
1212
|
+
- model_type (str): Override ModelType in nexa.manifest (highest priority)
|
|
1213
|
+
- device_id (str): Set DeviceId in nexa.manifest (highest priority)
|
|
1214
|
+
- min_sdk_version (str): Set MinSDKVersion in nexa.manifest (highest priority)
|
|
1139
1215
|
|
|
1140
1216
|
Returns:
|
|
1141
1217
|
str: Path to the downloaded file or directory
|
|
@@ -1213,7 +1289,7 @@ def _download_model_if_needed(
|
|
|
1213
1289
|
token: Union[bool, str, None] = None,
|
|
1214
1290
|
is_mmproj: bool = False,
|
|
1215
1291
|
**kwargs
|
|
1216
|
-
) -> str:
|
|
1292
|
+
) -> tuple[str, Optional[str]]:
|
|
1217
1293
|
"""
|
|
1218
1294
|
Helper function to download a model from HuggingFace if it doesn't exist locally.
|
|
1219
1295
|
|
|
@@ -1224,15 +1300,38 @@ def _download_model_if_needed(
|
|
|
1224
1300
|
token: HuggingFace authentication token for private repositories
|
|
1225
1301
|
|
|
1226
1302
|
Returns:
|
|
1227
|
-
str:
|
|
1303
|
+
tuple[str, Optional[str]]: Tuple of (local_path, model_name)
|
|
1304
|
+
- local_path: Local path to the model (either existing or downloaded)
|
|
1305
|
+
- model_name: ModelName from nexa.manifest if available, None otherwise
|
|
1228
1306
|
|
|
1229
1307
|
Raises:
|
|
1230
1308
|
RuntimeError: If download fails
|
|
1231
1309
|
"""
|
|
1310
|
+
# Helper function to extract model_name from manifest
|
|
1311
|
+
def _extract_model_name_from_manifest(path: str) -> Optional[str]:
|
|
1312
|
+
"""Extract ModelName from nexa.manifest if it exists."""
|
|
1313
|
+
# If path is a file, check its parent directory for manifest
|
|
1314
|
+
if os.path.isfile(path):
|
|
1315
|
+
manifest_dir = os.path.dirname(path)
|
|
1316
|
+
else:
|
|
1317
|
+
manifest_dir = path
|
|
1318
|
+
|
|
1319
|
+
manifest_path = os.path.join(manifest_dir, 'nexa.manifest')
|
|
1320
|
+
if not os.path.exists(manifest_path):
|
|
1321
|
+
return None
|
|
1322
|
+
|
|
1323
|
+
try:
|
|
1324
|
+
with open(manifest_path, 'r', encoding='utf-8') as f:
|
|
1325
|
+
manifest = json.load(f)
|
|
1326
|
+
return manifest.get('ModelName')
|
|
1327
|
+
except (json.JSONDecodeError, IOError):
|
|
1328
|
+
return None
|
|
1329
|
+
|
|
1232
1330
|
# Check if model_path exists locally (file or directory)
|
|
1233
1331
|
if os.path.exists(model_path):
|
|
1234
|
-
# Local path exists,
|
|
1235
|
-
|
|
1332
|
+
# Local path exists, try to extract model_name
|
|
1333
|
+
model_name = _extract_model_name_from_manifest(model_path)
|
|
1334
|
+
return model_path, model_name
|
|
1236
1335
|
|
|
1237
1336
|
# Model path doesn't exist locally, try to download from HuggingFace
|
|
1238
1337
|
try:
|
|
@@ -1252,7 +1351,10 @@ def _download_model_if_needed(
|
|
|
1252
1351
|
**kwargs
|
|
1253
1352
|
)
|
|
1254
1353
|
|
|
1255
|
-
|
|
1354
|
+
# Extract model_name from the downloaded manifest
|
|
1355
|
+
model_name = _extract_model_name_from_manifest(downloaded_path)
|
|
1356
|
+
|
|
1357
|
+
return downloaded_path, model_name
|
|
1256
1358
|
|
|
1257
1359
|
except Exception as e:
|
|
1258
1360
|
# Only handle download-related errors
|
|
@@ -1321,7 +1423,7 @@ def auto_download_model(func: Callable) -> Callable:
|
|
|
1321
1423
|
# Download name_or_path if needed
|
|
1322
1424
|
if name_or_path is not None:
|
|
1323
1425
|
try:
|
|
1324
|
-
downloaded_name_path = _download_model_if_needed(
|
|
1426
|
+
downloaded_name_path, model_name = _download_model_if_needed(
|
|
1325
1427
|
name_or_path, 'name_or_path', progress_callback, token, **kwargs
|
|
1326
1428
|
)
|
|
1327
1429
|
|
|
@@ -1332,6 +1434,10 @@ def auto_download_model(func: Callable) -> Callable:
|
|
|
1332
1434
|
args = tuple(args_list)
|
|
1333
1435
|
else:
|
|
1334
1436
|
kwargs['name_or_path'] = downloaded_name_path
|
|
1437
|
+
|
|
1438
|
+
# Add model_name to kwargs if it exists and not already set
|
|
1439
|
+
if model_name is not None and 'model_name' not in kwargs:
|
|
1440
|
+
kwargs['model_name'] = model_name
|
|
1335
1441
|
|
|
1336
1442
|
except Exception as e:
|
|
1337
1443
|
raise e # Re-raise the error from _download_model_if_needed
|
|
@@ -1339,7 +1445,7 @@ def auto_download_model(func: Callable) -> Callable:
|
|
|
1339
1445
|
# Download mmproj_path if needed
|
|
1340
1446
|
if mmproj_path is not None:
|
|
1341
1447
|
try:
|
|
1342
|
-
downloaded_mmproj_path = _download_model_if_needed(
|
|
1448
|
+
downloaded_mmproj_path, _ = _download_model_if_needed(
|
|
1343
1449
|
mmproj_path, 'mmproj_path', progress_callback, token, is_mmproj=True, **kwargs
|
|
1344
1450
|
)
|
|
1345
1451
|
|
nexaai/utils/model_types.py
CHANGED
|
@@ -13,6 +13,8 @@ class ModelTypeMapping(Enum):
|
|
|
13
13
|
"""Enum for mapping HuggingFace pipeline_tag to our ModelType."""
|
|
14
14
|
TEXT_GENERATION = ("text-generation", "llm")
|
|
15
15
|
IMAGE_TEXT_TO_TEXT = ("image-text-to-text", "vlm")
|
|
16
|
+
ANY_TO_ANY = ("any-to-any", "ata")
|
|
17
|
+
AUTOMATIC_SPEECH_RECOGNITION = ("automatic-speech-recognition", "asr")
|
|
16
18
|
|
|
17
19
|
def __init__(self, pipeline_tag: str, model_type: str):
|
|
18
20
|
self.pipeline_tag = pipeline_tag
|
nexaai/vlm.py
CHANGED
|
@@ -22,7 +22,8 @@ class VLM(BaseModel):
|
|
|
22
22
|
model_name: Optional[str] = None,
|
|
23
23
|
m_cfg: ModelConfig = ModelConfig(),
|
|
24
24
|
plugin_id: Union[PluginID, str] = PluginID.LLAMA_CPP,
|
|
25
|
-
device_id: Optional[str] = None
|
|
25
|
+
device_id: Optional[str] = None,
|
|
26
|
+
**kwargs
|
|
26
27
|
) -> 'VLM':
|
|
27
28
|
"""Load VLM model from local path, routing to appropriate implementation.
|
|
28
29
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nexaai
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.19
|
|
4
4
|
Summary: Python bindings for NexaSDK C-lib backend
|
|
5
5
|
Author-email: "Nexa AI, Inc." <dev@nexa.ai>
|
|
6
6
|
Project-URL: Homepage, https://github.com/NexaAI/nexasdk-bridge
|
|
@@ -14,7 +14,6 @@ Requires-Python: >=3.7
|
|
|
14
14
|
Description-Content-Type: text/markdown
|
|
15
15
|
Requires-Dist: huggingface_hub
|
|
16
16
|
Requires-Dist: tqdm
|
|
17
|
-
Requires-Dist: hf_xet
|
|
18
17
|
Requires-Dist: numpy
|
|
19
18
|
Requires-Dist: httpx
|
|
20
19
|
Provides-Extra: mlx
|