nexaai 1.0.4rc14__cp310-cp310-macosx_14_0_universal2.whl → 1.0.4rc16__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.

Files changed (39) hide show
  1. nexaai/__init__.py +6 -1
  2. nexaai/_stub.cpython-310-darwin.so +0 -0
  3. nexaai/_version.py +1 -1
  4. nexaai/asr.py +7 -3
  5. nexaai/asr_impl/mlx_asr_impl.py +3 -2
  6. nexaai/asr_impl/pybind_asr_impl.py +3 -2
  7. nexaai/binds/libcrypto.dylib +0 -0
  8. nexaai/binds/libnexa_bridge.dylib +0 -0
  9. nexaai/binds/libssl.dylib +0 -0
  10. nexaai/binds/nexa_llama_cpp/libggml-base.dylib +0 -0
  11. nexaai/binds/nexa_llama_cpp/libnexa_plugin.dylib +0 -0
  12. nexaai/binds/nexa_mlx/libnexa_plugin.dylib +0 -0
  13. nexaai/common.py +7 -0
  14. nexaai/cv.py +8 -3
  15. nexaai/cv_impl/mlx_cv_impl.py +3 -2
  16. nexaai/cv_impl/pybind_cv_impl.py +3 -2
  17. nexaai/embedder.py +7 -3
  18. nexaai/embedder_impl/mlx_embedder_impl.py +3 -2
  19. nexaai/embedder_impl/pybind_embedder_impl.py +6 -3
  20. nexaai/image_gen.py +6 -2
  21. nexaai/image_gen_impl/mlx_image_gen_impl.py +3 -2
  22. nexaai/image_gen_impl/pybind_image_gen_impl.py +3 -2
  23. nexaai/llm.py +8 -5
  24. nexaai/llm_impl/mlx_llm_impl.py +19 -6
  25. nexaai/llm_impl/pybind_llm_impl.py +7 -5
  26. nexaai/mlx_backend/llm/interface.py +2 -2
  27. nexaai/rerank.py +7 -3
  28. nexaai/rerank_impl/mlx_rerank_impl.py +3 -2
  29. nexaai/rerank_impl/pybind_rerank_impl.py +3 -2
  30. nexaai/tts.py +7 -3
  31. nexaai/tts_impl/mlx_tts_impl.py +3 -2
  32. nexaai/tts_impl/pybind_tts_impl.py +3 -2
  33. nexaai/vlm.py +6 -3
  34. nexaai/vlm_impl/mlx_vlm_impl.py +85 -41
  35. nexaai/vlm_impl/pybind_vlm_impl.py +5 -3
  36. {nexaai-1.0.4rc14.dist-info → nexaai-1.0.4rc16.dist-info}/METADATA +9 -8
  37. {nexaai-1.0.4rc14.dist-info → nexaai-1.0.4rc16.dist-info}/RECORD +39 -37
  38. {nexaai-1.0.4rc14.dist-info → nexaai-1.0.4rc16.dist-info}/WHEEL +0 -0
  39. {nexaai-1.0.4rc14.dist-info → nexaai-1.0.4rc16.dist-info}/top_level.txt +0 -0
nexaai/__init__.py CHANGED
@@ -19,7 +19,10 @@ except ImportError:
19
19
  __version__ = "0.0.1"
20
20
 
21
21
  # Import common configuration classes first (no external dependencies)
22
- from .common import ModelConfig, GenerationConfig, ChatMessage, SamplerConfig
22
+ from .common import ModelConfig, GenerationConfig, ChatMessage, SamplerConfig, PluginID
23
+
24
+ # Create alias for PluginID to be accessible as plugin_id
25
+ plugin_id = PluginID
23
26
 
24
27
  # Import new feature classes (no external dependencies in base classes)
25
28
  from .llm import LLM
@@ -40,6 +43,8 @@ __all__ = [
40
43
  "ChatMessage",
41
44
  "SamplerConfig",
42
45
  "EmbeddingConfig",
46
+ "PluginID",
47
+ "plugin_id",
43
48
 
44
49
  "LLM",
45
50
  "Embedder",
Binary file
nexaai/_version.py CHANGED
@@ -1,4 +1,4 @@
1
1
  # This file is generated by CMake from _version.py.in
2
2
  # Do not modify this file manually - it will be overwritten
3
3
 
4
- __version__ = "1.0.4-rc14"
4
+ __version__ = "1.0.4-rc16"
nexaai/asr.py CHANGED
@@ -1,8 +1,9 @@
1
- from typing import List, Optional, Sequence, Tuple
1
+ from typing import List, Optional, Sequence, Tuple, Union
2
2
  from abc import abstractmethod
3
3
  from dataclasses import dataclass
4
4
 
5
5
  from nexaai.base import BaseModel
6
+ from nexaai.common import PluginID
6
7
 
7
8
 
8
9
  @dataclass
@@ -33,11 +34,14 @@ class ASR(BaseModel):
33
34
  model_path: str,
34
35
  tokenizer_path: Optional[str] = None,
35
36
  language: Optional[str] = None,
36
- plugin_id: str = "llama_cpp",
37
+ plugin_id: Union[PluginID, str] = PluginID.LLAMA_CPP,
37
38
  device_id: Optional[str] = None
38
39
  ) -> 'ASR':
39
40
  """Load ASR model from local path, routing to appropriate implementation."""
40
- if plugin_id == "mlx":
41
+ # Check plugin_id value for routing - handle both enum and string
42
+ plugin_value = plugin_id.value if isinstance(plugin_id, PluginID) else plugin_id
43
+
44
+ if plugin_value == "mlx":
41
45
  from nexaai.asr_impl.mlx_asr_impl import MLXASRImpl
42
46
  return MLXASRImpl._load_from(model_path, tokenizer_path, language, plugin_id, device_id)
43
47
  else:
@@ -1,7 +1,8 @@
1
1
  # Note: This code is generated by Cursor, not tested yet.
2
2
 
3
- from typing import List, Optional
3
+ from typing import List, Optional, Union
4
4
 
5
+ from nexaai.common import PluginID
5
6
  from nexaai.asr import ASR, ASRConfig, ASRResult
6
7
  from nexaai.mlx_backend.asr.interface import MlxAsr as MLXASRInterface
7
8
  from nexaai.mlx_backend.ml import ModelConfig as MLXModelConfig, SamplerConfig as MLXSamplerConfig, GenerationConfig as MLXGenerationConfig, EmbeddingConfig
@@ -18,7 +19,7 @@ class MLXASRImpl(ASR):
18
19
  model_path: str,
19
20
  tokenizer_path: Optional[str] = None,
20
21
  language: Optional[str] = None,
21
- plugin_id: str = "mlx",
22
+ plugin_id: Union[PluginID, str] = PluginID.MLX,
22
23
  device_id: Optional[str] = None
23
24
  ) -> 'MLXASRImpl':
24
25
  """Load ASR model from local path using MLX backend."""
@@ -1,5 +1,6 @@
1
- from typing import List, Optional
1
+ from typing import List, Optional, Union
2
2
 
3
+ from nexaai.common import PluginID
3
4
  from nexaai.asr import ASR, ASRConfig, ASRResult
4
5
 
5
6
 
@@ -14,7 +15,7 @@ class PyBindASRImpl(ASR):
14
15
  model_path: str,
15
16
  tokenizer_path: Optional[str] = None,
16
17
  language: Optional[str] = None,
17
- plugin_id: str = "llama_cpp",
18
+ plugin_id: Union[PluginID, str] = PluginID.LLAMA_CPP,
18
19
  device_id: Optional[str] = None
19
20
  ) -> 'PyBindASRImpl':
20
21
  """Load ASR model from local path using PyBind backend."""
Binary file
Binary file
Binary file
Binary file
nexaai/common.py CHANGED
@@ -1,5 +1,12 @@
1
1
  from dataclasses import dataclass
2
2
  from typing import TypedDict, Literal, Optional, List
3
+ from enum import Enum
4
+
5
+
6
+ class PluginID(str, Enum):
7
+ """Enum for plugin identifiers."""
8
+ MLX = "mlx"
9
+ LLAMA_CPP = "llama_cpp"
3
10
 
4
11
 
5
12
  class ChatMessage(TypedDict):
nexaai/cv.py CHANGED
@@ -1,8 +1,9 @@
1
- from typing import List, Optional
1
+ from typing import List, Optional, Union
2
2
  from abc import abstractmethod
3
3
  from dataclasses import dataclass
4
4
 
5
5
  from nexaai.base import BaseModel
6
+ from nexaai.common import PluginID
6
7
 
7
8
 
8
9
  @dataclass
@@ -69,12 +70,16 @@ class CVModel(BaseModel):
69
70
 
70
71
  @classmethod
71
72
  def _load_from(cls,
73
+ _: str, # TODO: remove this argument, this is a hack to make api design happy
72
74
  config: CVModelConfig,
73
- plugin_id: str = "llama_cpp",
75
+ plugin_id: Union[PluginID, str] = PluginID.LLAMA_CPP,
74
76
  device_id: Optional[str] = None
75
77
  ) -> 'CVModel':
76
78
  """Load CV model from configuration, routing to appropriate implementation."""
77
- if plugin_id == "mlx":
79
+ # Check plugin_id value for routing - handle both enum and string
80
+ plugin_value = plugin_id.value if isinstance(plugin_id, PluginID) else plugin_id
81
+
82
+ if plugin_value == "mlx":
78
83
  from nexaai.cv_impl.mlx_cv_impl import MLXCVImpl
79
84
  return MLXCVImpl._load_from(config, plugin_id, device_id)
80
85
  else:
@@ -1,8 +1,9 @@
1
1
  # Note: This code is generated by Cursor, not tested yet.
2
2
 
3
- from typing import Optional
3
+ from typing import Optional, Union
4
4
  import os
5
5
 
6
+ from nexaai.common import PluginID
6
7
  from nexaai.cv import CVModel, CVModelConfig, CVResults
7
8
  from nexaai.mlx_backend.cv.interface import CVModel as MLXCVInterface, create_cv_model
8
9
 
@@ -16,7 +17,7 @@ class MLXCVImpl(CVModel):
16
17
  @classmethod
17
18
  def _load_from(cls,
18
19
  config: CVModelConfig,
19
- plugin_id: str = "mlx",
20
+ plugin_id: Union[PluginID, str] = PluginID.MLX,
20
21
  device_id: Optional[str] = None
21
22
  ) -> 'MLXCVImpl':
22
23
  """Load CV model from configuration using MLX backend."""
@@ -1,5 +1,6 @@
1
- from typing import Optional
1
+ from typing import Optional, Union
2
2
 
3
+ from nexaai.common import PluginID
3
4
  from nexaai.cv import CVModel, CVModelConfig, CVResults
4
5
 
5
6
 
@@ -12,7 +13,7 @@ class PyBindCVImpl(CVModel):
12
13
  @classmethod
13
14
  def _load_from(cls,
14
15
  config: CVModelConfig,
15
- plugin_id: str = "llama_cpp",
16
+ plugin_id: Union[PluginID, str] = PluginID.LLAMA_CPP,
16
17
  device_id: Optional[str] = None
17
18
  ) -> 'PyBindCVImpl':
18
19
  """Load CV model from configuration using PyBind backend."""
nexaai/embedder.py CHANGED
@@ -4,6 +4,7 @@ from abc import abstractmethod
4
4
  import numpy as np
5
5
 
6
6
  from nexaai.base import BaseModel
7
+ from nexaai.common import PluginID
7
8
 
8
9
 
9
10
  @dataclass
@@ -21,19 +22,22 @@ class Embedder(BaseModel):
21
22
  pass
22
23
 
23
24
  @classmethod
24
- def _load_from(cls, model_path: str, tokenizer_file: str = "tokenizer.json", plugin_id: str = "llama_cpp"):
25
+ def _load_from(cls, model_path: str, tokenizer_file: str = "tokenizer.json", plugin_id: Union[PluginID, str] = PluginID.LLAMA_CPP):
25
26
  """
26
27
  Load an embedder from model files, routing to appropriate implementation.
27
28
 
28
29
  Args:
29
30
  model_path: Path to the model file
30
31
  tokenizer_file: Path to the tokenizer file (default: "tokenizer.json")
31
- plugin_id: Plugin ID to use for the model (default: "llama_cpp")
32
+ plugin_id: Plugin ID to use for the model (default: PluginID.LLAMA_CPP)
32
33
 
33
34
  Returns:
34
35
  Embedder instance
35
36
  """
36
- if plugin_id == "mlx":
37
+ # Check plugin_id value for routing - handle both enum and string
38
+ plugin_value = plugin_id.value if isinstance(plugin_id, PluginID) else plugin_id
39
+
40
+ if plugin_value == "mlx":
37
41
  from nexaai.embedder_impl.mlx_embedder_impl import MLXEmbedderImpl
38
42
  return MLXEmbedderImpl._load_from(model_path, tokenizer_file, plugin_id)
39
43
  else:
@@ -1,6 +1,7 @@
1
1
  from typing import List, Union
2
2
  import numpy as np
3
3
 
4
+ from nexaai.common import PluginID
4
5
  from nexaai.embedder import Embedder, EmbeddingConfig
5
6
  from nexaai.mlx_backend.embedding.interface import Embedder as MLXEmbedderInterface
6
7
  from nexaai.mlx_backend.ml import ModelConfig as MLXModelConfig, SamplerConfig as MLXSamplerConfig, GenerationConfig as MLXGenerationConfig, EmbeddingConfig
@@ -13,14 +14,14 @@ class MLXEmbedderImpl(Embedder):
13
14
  self._mlx_embedder = None
14
15
 
15
16
  @classmethod
16
- def _load_from(cls, model_path: str, tokenizer_file: str = "tokenizer.json", plugin_id: str = "mlx"):
17
+ def _load_from(cls, model_path: str, tokenizer_file: str = "tokenizer.json", plugin_id: Union[PluginID, str] = PluginID.MLX):
17
18
  """
18
19
  Load an embedder from model files using MLX backend.
19
20
 
20
21
  Args:
21
22
  model_path: Path to the model file
22
23
  tokenizer_file: Path to the tokenizer file (default: "tokenizer.json")
23
- plugin_id: Plugin ID to use for the model (default: "mlx")
24
+ plugin_id: Plugin ID to use for the model (default: PluginID.MLX)
24
25
 
25
26
  Returns:
26
27
  MLXEmbedderImpl instance
@@ -1,6 +1,7 @@
1
1
  from typing import List, Union
2
2
  import numpy as np
3
3
 
4
+ from nexaai.common import PluginID
4
5
  from nexaai.embedder import Embedder, EmbeddingConfig
5
6
  from nexaai.binds import embedder_bind
6
7
  from nexaai.runtime import _ensure_runtime
@@ -15,20 +16,22 @@ class PyBindEmbedderImpl(Embedder):
15
16
  self._handle = _handle_ptr
16
17
 
17
18
  @classmethod
18
- def _load_from(cls, model_path: str, tokenizer_file: str = "tokenizer.json", plugin_id: str = "llama_cpp"):
19
+ def _load_from(cls, model_path: str, tokenizer_file: str = "tokenizer.json", plugin_id: Union[PluginID, str] = PluginID.LLAMA_CPP):
19
20
  """
20
21
  Load an embedder from model files
21
22
 
22
23
  Args:
23
24
  model_path: Path to the model file
24
25
  tokenizer_file: Path to the tokenizer file (default: "tokenizer.json")
25
- plugin_id: Plugin ID to use for the model (default: "llama_cpp")
26
+ plugin_id: Plugin ID to use for the model (default: PluginID.LLAMA_CPP)
26
27
 
27
28
  Returns:
28
29
  PyBindEmbedderImpl instance
29
30
  """
30
31
  _ensure_runtime()
31
- handle = embedder_bind.ml_embedder_create(model_path, tokenizer_file, plugin_id)
32
+ # Convert enum to string for C++ binding
33
+ plugin_id_str = plugin_id.value if isinstance(plugin_id, PluginID) else plugin_id
34
+ handle = embedder_bind.ml_embedder_create(model_path, tokenizer_file, plugin_id_str)
32
35
  return cls(handle)
33
36
 
34
37
  def eject(self):
nexaai/image_gen.py CHANGED
@@ -3,6 +3,7 @@ from abc import abstractmethod
3
3
  from dataclasses import dataclass
4
4
 
5
5
  from nexaai.base import BaseModel
6
+ from nexaai.common import PluginID
6
7
 
7
8
 
8
9
  @dataclass
@@ -67,13 +68,16 @@ class ImageGen(BaseModel):
67
68
  def _load_from(cls,
68
69
  model_path: str,
69
70
  scheduler_config_path: str = "",
70
- plugin_id: str = "llama_cpp",
71
+ plugin_id: Union[PluginID, str] = PluginID.LLAMA_CPP,
71
72
  device_id: Optional[str] = None,
72
73
  float16: bool = True,
73
74
  quantize: bool = False
74
75
  ) -> 'ImageGen':
75
76
  """Load image generation model from local path, routing to appropriate implementation."""
76
- if plugin_id == "mlx":
77
+ # Check plugin_id value for routing - handle both enum and string
78
+ plugin_value = plugin_id.value if isinstance(plugin_id, PluginID) else plugin_id
79
+
80
+ if plugin_value == "mlx":
77
81
  from nexaai.image_gen_impl.mlx_image_gen_impl import MLXImageGenImpl
78
82
  return MLXImageGenImpl._load_from(model_path, scheduler_config_path, plugin_id, device_id, float16, quantize)
79
83
  else:
@@ -1,8 +1,9 @@
1
1
  # Note: This code is generated by Cursor, not tested yet.
2
2
 
3
- from typing import List, Optional
3
+ from typing import List, Optional, Union
4
4
  import os
5
5
 
6
+ from nexaai.common import PluginID
6
7
  from nexaai.image_gen import ImageGen, ImageGenerationConfig, ImageSamplerConfig, SchedulerConfig, Image
7
8
  from nexaai.mlx_backend.sd.interface import ImageGen as MLXImageGenInterface
8
9
 
@@ -17,7 +18,7 @@ class MLXImageGenImpl(ImageGen):
17
18
  def _load_from(cls,
18
19
  model_path: str,
19
20
  scheduler_config_path: str = "",
20
- plugin_id: str = "mlx",
21
+ plugin_id: Union[PluginID, str] = PluginID.MLX,
21
22
  device_id: Optional[str] = None,
22
23
  float16: bool = True,
23
24
  quantize: bool = False
@@ -1,5 +1,6 @@
1
- from typing import List, Optional
1
+ from typing import List, Optional, Union
2
2
 
3
+ from nexaai.common import PluginID
3
4
  from nexaai.image_gen import ImageGen, ImageGenerationConfig, ImageSamplerConfig, SchedulerConfig, Image
4
5
 
5
6
 
@@ -13,7 +14,7 @@ class PyBindImageGenImpl(ImageGen):
13
14
  def _load_from(cls,
14
15
  model_path: str,
15
16
  scheduler_config_path: str = "",
16
- plugin_id: str = "llama_cpp",
17
+ plugin_id: Union[PluginID, str] = PluginID.LLAMA_CPP,
17
18
  device_id: Optional[str] = None,
18
19
  float16: bool = True,
19
20
  quantize: bool = False
nexaai/llm.py CHANGED
@@ -1,9 +1,9 @@
1
- from typing import Generator, Optional
1
+ from typing import Generator, Optional, Union
2
2
  from abc import abstractmethod
3
3
  import queue
4
4
  import threading
5
5
 
6
- from nexaai.common import ModelConfig, GenerationConfig, ChatMessage
6
+ from nexaai.common import ModelConfig, GenerationConfig, ChatMessage, PluginID
7
7
  from nexaai.base import BaseModel
8
8
 
9
9
  class LLM(BaseModel):
@@ -17,11 +17,14 @@ class LLM(BaseModel):
17
17
  local_path: str,
18
18
  tokenizer_path: Optional[str] = None,
19
19
  m_cfg: ModelConfig = ModelConfig(),
20
- plugin_id: str = "llama_cpp",
20
+ plugin_id: Union[PluginID, str] = PluginID.LLAMA_CPP,
21
21
  device_id: Optional[str] = None
22
22
  ) -> 'LLM':
23
23
  """Load model from local path, routing to appropriate implementation."""
24
- if plugin_id == "mlx":
24
+ # Check plugin_id value for routing - handle both enum and string
25
+ plugin_value = plugin_id.value if isinstance(plugin_id, PluginID) else plugin_id
26
+
27
+ if plugin_value == "mlx":
25
28
  from nexaai.llm_impl.mlx_llm_impl import MLXLLMImpl
26
29
  return MLXLLMImpl._load_from(local_path, tokenizer_path, m_cfg, plugin_id, device_id)
27
30
  else:
@@ -37,7 +40,7 @@ class LLM(BaseModel):
37
40
  self._cancel_event.clear()
38
41
 
39
42
  @abstractmethod
40
- def apply_chat_template(self, messages: list[ChatMessage]) -> str:
43
+ def apply_chat_template(self, messages: list[ChatMessage], tools: Optional[str] = None, enable_thinking: bool = True, add_generation_prompt: bool = True) -> str:
41
44
  """Apply the chat template to messages."""
42
45
  pass
43
46
 
@@ -1,6 +1,6 @@
1
- from typing import Generator, Optional, Any
1
+ from typing import Generator, Optional, Any, Sequence, Union
2
2
 
3
- from nexaai.common import ModelConfig, GenerationConfig, ChatMessage
3
+ from nexaai.common import ModelConfig, GenerationConfig, ChatMessage, PluginID
4
4
  from nexaai.llm import LLM
5
5
  from nexaai.mlx_backend.llm.interface import LLM as MLXLLMInterface
6
6
  from nexaai.mlx_backend.ml import ModelConfig as MLXModelConfig, SamplerConfig as MLXSamplerConfig, GenerationConfig as MLXGenerationConfig, EmbeddingConfig
@@ -17,7 +17,7 @@ class MLXLLMImpl(LLM):
17
17
  local_path: str,
18
18
  tokenizer_path: Optional[str] = None,
19
19
  m_cfg: ModelConfig = ModelConfig(),
20
- plugin_id: str = "mlx",
20
+ plugin_id: Union[PluginID, str] = PluginID.MLX,
21
21
  device_id: Optional[str] = None
22
22
  ) -> 'MLXLLMImpl':
23
23
  """Load model from local path using MLX backend."""
@@ -54,7 +54,13 @@ class MLXLLMImpl(LLM):
54
54
  self._mlx_llm.destroy()
55
55
  self._mlx_llm = None
56
56
 
57
- def apply_chat_template(self, messages: list[ChatMessage]) -> str:
57
+ def apply_chat_template(
58
+ self,
59
+ messages: Sequence[ChatMessage],
60
+ tools: Optional[str] = None,
61
+ enable_thinking: bool = True,
62
+ add_generation_prompt: bool = True
63
+ ) -> str:
58
64
  """Apply the chat template to messages."""
59
65
  if not self._mlx_llm:
60
66
  raise RuntimeError("MLX LLM not loaded")
@@ -68,9 +74,16 @@ class MLXLLMImpl(LLM):
68
74
  def __init__(self, role, content):
69
75
  self.role = role
70
76
  self.content = content
71
- mlx_messages.append(MLXChatMessage(msg["role"], msg["content"]))
77
+
78
+ # Handle both dict-style and attribute-style access
79
+ if hasattr(msg, 'role') and hasattr(msg, 'content'):
80
+ # Message is already an object with attributes
81
+ mlx_messages.append(MLXChatMessage(msg.role, msg.content))
82
+ else:
83
+ # Message is a dict
84
+ mlx_messages.append(MLXChatMessage(msg["role"], msg["content"]))
72
85
 
73
- return self._mlx_llm.apply_chat_template(mlx_messages)
86
+ return self._mlx_llm.apply_chat_template(mlx_messages, tools=tools, enable_thinking=enable_thinking, add_generation_prompt=add_generation_prompt)
74
87
  except Exception as e:
75
88
  raise RuntimeError(f"Failed to apply chat template: {str(e)}")
76
89
 
@@ -1,8 +1,8 @@
1
- from typing import Generator, Optional
1
+ from typing import Generator, Optional, Union
2
2
  import queue
3
3
  import threading
4
4
 
5
- from nexaai.common import ModelConfig, GenerationConfig, ChatMessage
5
+ from nexaai.common import ModelConfig, GenerationConfig, ChatMessage, PluginID
6
6
  from nexaai.binds import llm_bind, common_bind
7
7
  from nexaai.runtime import _ensure_runtime
8
8
  from nexaai.llm import LLM
@@ -19,7 +19,7 @@ class PyBindLLMImpl(LLM):
19
19
  local_path: str,
20
20
  tokenizer_path: Optional[str] = None,
21
21
  m_cfg: ModelConfig = ModelConfig(),
22
- plugin_id: str = "llama_cpp",
22
+ plugin_id: Union[PluginID, str] = PluginID.LLAMA_CPP,
23
23
  device_id: Optional[str] = None
24
24
  ) -> 'PyBindLLMImpl':
25
25
  """Load model from local path."""
@@ -49,11 +49,13 @@ class PyBindLLMImpl(LLM):
49
49
  config.chat_template_content = m_cfg.chat_template_content
50
50
 
51
51
  # Create handle : returns py::capsule with automatic cleanup
52
+ # Convert enum to string for C++ binding
53
+ plugin_id_str = plugin_id.value if isinstance(plugin_id, PluginID) else plugin_id
52
54
  handle = llm_bind.ml_llm_create(
53
55
  model_path=local_path,
54
56
  tokenizer_path=tokenizer_path,
55
57
  model_config=config,
56
- plugin_id=plugin_id,
58
+ plugin_id=plugin_id_str,
57
59
  device_id=device_id
58
60
  )
59
61
  return cls(handle, m_cfg)
@@ -64,7 +66,7 @@ class PyBindLLMImpl(LLM):
64
66
  del self._handle
65
67
  self._handle = None
66
68
 
67
- def apply_chat_template(self, messages: list[ChatMessage]) -> str:
69
+ def apply_chat_template(self, messages: list[ChatMessage], tools: Optional[str] = None, enable_thinking: bool = True, add_generation_prompt: bool = True) -> str:
68
70
  """Apply the chat template to messages."""
69
71
  # Convert TypedDict to list of dicts for binding
70
72
  message_dicts = [
@@ -467,7 +467,7 @@ class LLM(BaseLLM, ProfilingMixin):
467
467
  # We'll ignore the argument for now.
468
468
  return self.tokenizer.chat_template
469
469
 
470
- def apply_chat_template(self, messages: Sequence[ChatMessage], tools: Optional[str] = None, enable_thinking: bool = True) -> str:
470
+ def apply_chat_template(self, messages: Sequence[ChatMessage], tools: Optional[str] = None, enable_thinking: bool = True, add_generation_prompt: bool = True) -> str:
471
471
  """
472
472
  Apply chat template to messages with incremental prompt support and optional tools.
473
473
 
@@ -526,7 +526,7 @@ class LLM(BaseLLM, ProfilingMixin):
526
526
  incremental_messages,
527
527
  tokenize=False,
528
528
  enable_thinking=enable_thinking,
529
- add_generation_prompt=True,
529
+ add_generation_prompt=add_generation_prompt,
530
530
  tools=parsed_tools
531
531
  )
532
532
  except Exception as e:
nexaai/rerank.py CHANGED
@@ -1,8 +1,9 @@
1
- from typing import List, Optional, Sequence
1
+ from typing import List, Optional, Sequence, Union
2
2
  from abc import abstractmethod
3
3
  from dataclasses import dataclass
4
4
 
5
5
  from nexaai.base import BaseModel
6
+ from nexaai.common import PluginID
6
7
 
7
8
 
8
9
  @dataclass
@@ -24,11 +25,14 @@ class Reranker(BaseModel):
24
25
  def _load_from(cls,
25
26
  model_path: str,
26
27
  tokenizer_file: str = "tokenizer.json",
27
- plugin_id: str = "llama_cpp",
28
+ plugin_id: Union[PluginID, str] = PluginID.LLAMA_CPP,
28
29
  device_id: Optional[str] = None
29
30
  ) -> 'Reranker':
30
31
  """Load reranker model from local path, routing to appropriate implementation."""
31
- if plugin_id == "mlx":
32
+ # Check plugin_id value for routing - handle both enum and string
33
+ plugin_value = plugin_id.value if isinstance(plugin_id, PluginID) else plugin_id
34
+
35
+ if plugin_value == "mlx":
32
36
  from nexaai.rerank_impl.mlx_rerank_impl import MLXRerankImpl
33
37
  return MLXRerankImpl._load_from(model_path, tokenizer_file, plugin_id, device_id)
34
38
  else:
@@ -1,8 +1,9 @@
1
1
  # Note: This code is generated by Cursor, not tested yet.
2
2
 
3
- from typing import List, Optional, Sequence
3
+ from typing import List, Optional, Sequence, Union
4
4
  import os
5
5
 
6
+ from nexaai.common import PluginID
6
7
  from nexaai.rerank import Reranker, RerankConfig
7
8
  from nexaai.mlx_backend.rerank.interface import Reranker as MLXRerankInterface, create_reranker
8
9
 
@@ -17,7 +18,7 @@ class MLXRerankImpl(Reranker):
17
18
  def _load_from(cls,
18
19
  model_path: str,
19
20
  tokenizer_file: str = "tokenizer.json",
20
- plugin_id: str = "mlx",
21
+ plugin_id: Union[PluginID, str] = PluginID.MLX,
21
22
  device_id: Optional[str] = None
22
23
  ) -> 'MLXRerankImpl':
23
24
  """Load reranker model from local path using MLX backend."""
@@ -1,5 +1,6 @@
1
- from typing import List, Optional, Sequence
1
+ from typing import List, Optional, Sequence, Union
2
2
 
3
+ from nexaai.common import PluginID
3
4
  from nexaai.rerank import Reranker, RerankConfig
4
5
 
5
6
 
@@ -13,7 +14,7 @@ class PyBindRerankImpl(Reranker):
13
14
  def _load_from(cls,
14
15
  model_path: str,
15
16
  tokenizer_file: str = "tokenizer.json",
16
- plugin_id: str = "llama_cpp",
17
+ plugin_id: Union[PluginID, str] = PluginID.LLAMA_CPP,
17
18
  device_id: Optional[str] = None
18
19
  ) -> 'PyBindRerankImpl':
19
20
  """Load reranker model from local path using PyBind backend."""
nexaai/tts.py CHANGED
@@ -1,8 +1,9 @@
1
- from typing import List, Optional
1
+ from typing import List, Optional, Union
2
2
  from abc import abstractmethod
3
3
  from dataclasses import dataclass
4
4
 
5
5
  from nexaai.base import BaseModel
6
+ from nexaai.common import PluginID
6
7
 
7
8
 
8
9
  @dataclass
@@ -43,11 +44,14 @@ class TTS(BaseModel):
43
44
  def _load_from(cls,
44
45
  model_path: str,
45
46
  vocoder_path: str,
46
- plugin_id: str = "llama_cpp",
47
+ plugin_id: Union[PluginID, str] = PluginID.LLAMA_CPP,
47
48
  device_id: Optional[str] = None
48
49
  ) -> 'TTS':
49
50
  """Load TTS model from local path, routing to appropriate implementation."""
50
- if plugin_id == "mlx":
51
+ # Check plugin_id value for routing - handle both enum and string
52
+ plugin_value = plugin_id.value if isinstance(plugin_id, PluginID) else plugin_id
53
+
54
+ if plugin_value == "mlx":
51
55
  from nexaai.tts_impl.mlx_tts_impl import MLXTTSImpl
52
56
  return MLXTTSImpl._load_from(model_path, vocoder_path, plugin_id, device_id)
53
57
  else:
@@ -1,8 +1,9 @@
1
1
  # Note: This code is generated by Cursor, not tested yet.
2
2
 
3
- from typing import List, Optional
3
+ from typing import List, Optional, Union
4
4
  import os
5
5
 
6
+ from nexaai.common import PluginID
6
7
  from nexaai.tts import TTS, TTSConfig, TTSResult
7
8
  from nexaai.mlx_backend.tts.interface import MlxTts as MLXTTSInterface
8
9
 
@@ -17,7 +18,7 @@ class MLXTTSImpl(TTS):
17
18
  def _load_from(cls,
18
19
  model_path: str,
19
20
  vocoder_path: str,
20
- plugin_id: str = "mlx",
21
+ plugin_id: Union[PluginID, str] = PluginID.MLX,
21
22
  device_id: Optional[str] = None
22
23
  ) -> 'MLXTTSImpl':
23
24
  """Load TTS model from local path using MLX backend."""
@@ -1,5 +1,6 @@
1
- from typing import List, Optional
1
+ from typing import List, Optional, Union
2
2
 
3
+ from nexaai.common import PluginID
3
4
  from nexaai.tts import TTS, TTSConfig, TTSResult
4
5
 
5
6
 
@@ -13,7 +14,7 @@ class PyBindTTSImpl(TTS):
13
14
  def _load_from(cls,
14
15
  model_path: str,
15
16
  vocoder_path: str,
16
- plugin_id: str = "llama_cpp",
17
+ plugin_id: Union[PluginID, str] = PluginID.LLAMA_CPP,
17
18
  device_id: Optional[str] = None
18
19
  ) -> 'PyBindTTSImpl':
19
20
  """Load TTS model from local path using PyBind backend."""
nexaai/vlm.py CHANGED
@@ -5,7 +5,7 @@ import threading
5
5
  import base64
6
6
  from pathlib import Path
7
7
 
8
- from nexaai.common import ModelConfig, GenerationConfig, MultiModalMessage
8
+ from nexaai.common import ModelConfig, GenerationConfig, MultiModalMessage, PluginID
9
9
  from nexaai.base import BaseModel
10
10
 
11
11
 
@@ -20,7 +20,7 @@ class VLM(BaseModel):
20
20
  local_path: str,
21
21
  mmproj_path: str,
22
22
  m_cfg: ModelConfig = ModelConfig(),
23
- plugin_id: str = "llama_cpp",
23
+ plugin_id: Union[PluginID, str] = PluginID.LLAMA_CPP,
24
24
  device_id: Optional[str] = None
25
25
  ) -> 'VLM':
26
26
  """Load VLM model from local path, routing to appropriate implementation.
@@ -35,7 +35,10 @@ class VLM(BaseModel):
35
35
  Returns:
36
36
  VLM instance
37
37
  """
38
- if plugin_id == "mlx":
38
+ # Check plugin_id value for routing - handle both enum and string
39
+ plugin_value = plugin_id.value if isinstance(plugin_id, PluginID) else plugin_id
40
+
41
+ if plugin_value == "mlx":
39
42
  from nexaai.vlm_impl.mlx_vlm_impl import MlxVlmImpl
40
43
  return MlxVlmImpl._load_from(local_path, mmproj_path, m_cfg, plugin_id, device_id)
41
44
  else:
@@ -1,6 +1,6 @@
1
- from typing import Generator, Optional, List, Dict, Any
1
+ from typing import Generator, Optional, List, Dict, Any, Union
2
2
 
3
- from nexaai.common import ModelConfig, GenerationConfig, MultiModalMessage
3
+ from nexaai.common import ModelConfig, GenerationConfig, MultiModalMessage, PluginID
4
4
  from nexaai.vlm import VLM
5
5
  from nexaai.mlx_backend.vlm.interface import VLM as MLXVLMInterface
6
6
  from nexaai.mlx_backend.ml import ModelConfig as MLXModelConfig, SamplerConfig as MLXSamplerConfig, GenerationConfig as MLXGenerationConfig, EmbeddingConfig
@@ -17,7 +17,7 @@ class MlxVlmImpl(VLM):
17
17
  local_path: str,
18
18
  mmproj_path: str,
19
19
  m_cfg: ModelConfig = ModelConfig(),
20
- plugin_id: str = "mlx",
20
+ plugin_id: Union[PluginID, str] = PluginID.MLX,
21
21
  device_id: Optional[str] = None
22
22
  ) -> 'MlxVlmImpl':
23
23
  """Load VLM model from local path using MLX backend.
@@ -76,8 +76,10 @@ class MlxVlmImpl(VLM):
76
76
  raise RuntimeError("MLX VLM not loaded")
77
77
 
78
78
  try:
79
- # Convert MultiModalMessage to MLX format
80
79
  mlx_messages = []
80
+ total_images = 0
81
+ total_audios = 0
82
+
81
83
  for msg in messages:
82
84
  # Create a simple object with role and content attributes
83
85
  class MLXChatMessage:
@@ -85,19 +87,38 @@ class MlxVlmImpl(VLM):
85
87
  self.role = role
86
88
  self.content = content
87
89
 
88
- # For MLX VLM, we need to extract text content from multimodal messages
89
- # This is a simplified approach - the actual implementation may need
90
- # more sophisticated handling of different content types
90
+ # Extract text content and count media files
91
91
  text_content = ""
92
+ first_content = True
93
+
92
94
  for content_item in msg["content"]:
93
- if content_item["type"] == "text":
95
+ content_type = content_item.get("type", "")
96
+
97
+ if content_type == "text":
98
+ if not first_content:
99
+ text_content += " "
94
100
  text_content += content_item.get("text", "")
95
- # Note: image/audio/video content is typically handled separately
96
- # in the generation phase, not in the chat template
101
+ first_content = False
102
+ elif content_type == "image":
103
+ total_images += 1
104
+ elif content_type == "audio":
105
+ total_audios += 1
97
106
 
98
107
  mlx_messages.append(MLXChatMessage(msg["role"], text_content))
99
108
 
100
- return self._mlx_vlm.apply_chat_template(mlx_messages)
109
+ if total_images > 0 or total_audios > 0:
110
+ # Use apply_chat_template_with_media when media is present
111
+ return self._mlx_vlm.apply_chat_template_with_media(
112
+ mlx_messages,
113
+ num_images=total_images,
114
+ num_audios=total_audios,
115
+ tools=tools,
116
+ enable_thinking=False # Default to False, could be made configurable
117
+ )
118
+ else:
119
+ # Use regular apply_chat_template for text-only messages
120
+ return self._mlx_vlm.apply_chat_template(mlx_messages)
121
+
101
122
  except Exception as e:
102
123
  raise RuntimeError(f"Failed to apply chat template: {str(e)}")
103
124
 
@@ -107,9 +128,6 @@ class MlxVlmImpl(VLM):
107
128
  raise RuntimeError("MLX VLM not loaded")
108
129
 
109
130
  try:
110
- # Get MLX config classes
111
- _, MLXSamplerConfig, MLXGenerationConfig, _ = get_mlx_configs()
112
-
113
131
  # Convert GenerationConfig to MLX format
114
132
  mlx_gen_config = MLXGenerationConfig()
115
133
  mlx_gen_config.max_tokens = g_cfg.max_tokens
@@ -130,25 +148,57 @@ class MlxVlmImpl(VLM):
130
148
  mlx_sampler_config.grammar_string = g_cfg.sampler_config.grammar_string
131
149
  mlx_gen_config.sampler_config = mlx_sampler_config
132
150
 
133
- # Create a token callback for streaming
134
- def token_callback(token: str) -> bool:
135
- # Check if generation should be cancelled
136
- return not self._cancel_event.is_set()
151
+ import queue
152
+ import threading
153
+
154
+ # Create a queue for streaming tokens
155
+ token_queue = queue.Queue()
156
+ exception_container = [None]
157
+ self.reset_cancel() # Reset cancel flag before generation
137
158
 
138
- # Use MLX VLM streaming generation
139
- result = self._mlx_vlm.generate_stream(prompt, mlx_gen_config, token_callback)
159
+ def token_callback(token: str, user_data: Any = None) -> bool:
160
+ if self._cancel_event.is_set():
161
+ token_queue.put(('end', None))
162
+ return False
163
+ try:
164
+ token_queue.put(('token', token))
165
+ return True
166
+ except Exception as e:
167
+ exception_container[0] = e
168
+ return False
140
169
 
141
- # MLX VLM interface returns a GenerationResult, extract the text
142
- if hasattr(result, 'text') and result.text:
143
- # Split the result into words and yield them
144
- words = result.text.split()
145
- for i, word in enumerate(words):
146
- if self._cancel_event.is_set():
170
+ # Run generation in a separate thread
171
+ def generate():
172
+ try:
173
+ self._mlx_vlm.generate_stream(prompt, mlx_gen_config, token_callback)
174
+ except Exception as e:
175
+ exception_container[0] = e
176
+ finally:
177
+ token_queue.put(('end', None))
178
+
179
+ thread = threading.Thread(target=generate)
180
+ thread.start()
181
+
182
+ # Yield tokens as they come from the queue
183
+ while True:
184
+ if exception_container[0]:
185
+ raise exception_container[0]
186
+
187
+ try:
188
+ msg_type, token = token_queue.get(timeout=0.1)
189
+ if msg_type == 'end':
147
190
  break
148
- if i == 0:
149
- yield word
150
- else:
151
- yield " " + word
191
+ elif msg_type == 'token':
192
+ yield token
193
+ except queue.Empty:
194
+ if not thread.is_alive():
195
+ break
196
+ continue
197
+
198
+ thread.join()
199
+
200
+ if exception_container[0]:
201
+ raise exception_container[0]
152
202
 
153
203
  except Exception as e:
154
204
  raise RuntimeError(f"Failed to generate streaming text: {str(e)}")
@@ -168,9 +218,6 @@ class MlxVlmImpl(VLM):
168
218
  raise RuntimeError("MLX VLM not loaded")
169
219
 
170
220
  try:
171
- # Get MLX config classes
172
- _, MLXSamplerConfig, MLXGenerationConfig, _ = get_mlx_configs()
173
-
174
221
  # Convert GenerationConfig to MLX format
175
222
  mlx_gen_config = MLXGenerationConfig()
176
223
  mlx_gen_config.max_tokens = g_cfg.max_tokens
@@ -191,15 +238,12 @@ class MlxVlmImpl(VLM):
191
238
  mlx_sampler_config.grammar_string = g_cfg.sampler_config.grammar_string
192
239
  mlx_gen_config.sampler_config = mlx_sampler_config
193
240
 
194
- # Use MLX VLM generation
195
- result = self._mlx_vlm.generate(prompt, mlx_gen_config)
241
+ # Simple token callback that just continues
242
+ def token_callback(token: str, user_data: Any = None) -> bool:
243
+ return not self._cancel_event.is_set()
196
244
 
197
- # MLX VLM interface returns a GenerationResult, extract the text
198
- if hasattr(result, 'text'):
199
- return result.text
200
- else:
201
- # Fallback if result is just a string
202
- return str(result)
245
+ # Use MLX streaming generation and return the full result
246
+ return self._mlx_vlm.generate_stream(prompt, mlx_gen_config, token_callback)
203
247
 
204
248
  except Exception as e:
205
249
  raise RuntimeError(f"Failed to generate text: {str(e)}")
@@ -4,7 +4,7 @@ import threading
4
4
  import base64
5
5
  from pathlib import Path
6
6
 
7
- from nexaai.common import ModelConfig, GenerationConfig, MultiModalMessage
7
+ from nexaai.common import ModelConfig, GenerationConfig, MultiModalMessage, PluginID
8
8
  from nexaai.binds import vlm_bind, common_bind
9
9
  from nexaai.runtime import _ensure_runtime
10
10
  from nexaai.vlm import VLM
@@ -21,7 +21,7 @@ class PyBindVLMImpl(VLM):
21
21
  local_path: str,
22
22
  mmproj_path: str,
23
23
  m_cfg: ModelConfig = ModelConfig(),
24
- plugin_id: str = "llama_cpp",
24
+ plugin_id: Union[PluginID, str] = PluginID.LLAMA_CPP,
25
25
  device_id: Optional[str] = None
26
26
  ) -> 'PyBindVLMImpl':
27
27
  """Load VLM model from local path.
@@ -61,11 +61,13 @@ class PyBindVLMImpl(VLM):
61
61
  config.chat_template_content = m_cfg.chat_template_content
62
62
 
63
63
  # Create handle : returns py::capsule with automatic cleanup
64
+ # Convert enum to string for C++ binding
65
+ plugin_id_str = plugin_id.value if isinstance(plugin_id, PluginID) else plugin_id
64
66
  handle = vlm_bind.create_vlm(
65
67
  model_path=local_path,
66
68
  mmproj_path=mmproj_path,
67
69
  model_config=config,
68
- plugin_id=plugin_id,
70
+ plugin_id=plugin_id_str,
69
71
  device_id=device_id
70
72
  )
71
73
  return cls(handle, m_cfg)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nexaai
3
- Version: 1.0.4rc14
3
+ Version: 1.0.4rc16
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
@@ -17,10 +17,11 @@ Requires-Dist: tqdm
17
17
  Requires-Dist: hf_xet
18
18
  Requires-Dist: numpy
19
19
  Requires-Dist: httpx
20
- Provides-Extra: mlx
21
- Requires-Dist: mlx; extra == "mlx"
22
- Requires-Dist: mlx-lm; extra == "mlx"
23
- Requires-Dist: mlx-vlm; extra == "mlx"
24
- Requires-Dist: tokenizers; extra == "mlx"
25
- Requires-Dist: safetensors; extra == "mlx"
26
- Requires-Dist: Pillow; extra == "mlx"
20
+ Requires-Dist: mlx
21
+ Requires-Dist: mlx-lm
22
+ Requires-Dist: scipy
23
+ Requires-Dist: soundfile
24
+ Requires-Dist: Pillow
25
+ Requires-Dist: opencv-python
26
+ Requires-Dist: shapely
27
+ Requires-Dist: pyclipper
@@ -1,33 +1,35 @@
1
- nexaai/__init__.py,sha256=JTjJWdiBXHZyc_91Oe-GNOcODFp9gbUQM43bzNY7S8Q,1906
2
- nexaai/_stub.cpython-310-darwin.so,sha256=jLqSTNxJs9FVD19-Vwob9M8ciDqSHgKE3KgoF4FDlbI,66768
3
- nexaai/_version.py,sha256=81zx9t__xAdjV8GwoDFsZWlADrXI5VeJD0AkYlQ8P9g,143
4
- nexaai/asr.py,sha256=Yg8Yml_nklzJYl3C_lwvEApTdNjY2czAurDaoEjkiIU,1813
1
+ nexaai/__init__.py,sha256=jXdC4vv6DBK1fVewYTYSUhOOYfvf_Mk81UIeMGGIKUg,2029
2
+ nexaai/_stub.cpython-310-darwin.so,sha256=J8U8gAiGKjmFexJuT4XWOm1k49lmsyJ-WYQJaTi6fyA,66768
3
+ nexaai/_version.py,sha256=NGCgH5JHTkWsbmkVT9FhcM7m4cxgmEZiw51TUG210EA,143
4
+ nexaai/asr.py,sha256=NljMXDErwPNMOPaRkJZMEDka9Nk8xyur7L8i924TStY,2054
5
5
  nexaai/base.py,sha256=N8PRgDFA-XPku2vWnQIofQ7ipz3pPlO6f8YZGnuhquE,982
6
- nexaai/common.py,sha256=VPM7NaUNaLTT7quW-u4D2uOeNrQqPjvfcgJlYGS3Qy8,1525
7
- nexaai/cv.py,sha256=CYfLSDU0_QJkcaIDIJ-a-JjA9FMvIUrSfG71_7-79hI,2934
8
- nexaai/embedder.py,sha256=VheiZEYBuuBjhQcvLawCz26jX0I169Xk4b9VP-ERjqU,2211
9
- nexaai/image_gen.py,sha256=IhLQLpmPkK9KcHteUdaQdxrnTIjk6xdyekRqeJtHfWw,4122
10
- nexaai/llm.py,sha256=egHa6YafNWyZy5qrmZRNZlFHO8LRUejc_gkOpK0nbnw,3105
11
- nexaai/rerank.py,sha256=7EEm96gpvd6kXO_Q8xSrQDlLZdAYTk0MODeNWDq70WA,1631
6
+ nexaai/common.py,sha256=5ElYo4uDP2CT3Kqxoo7XzqcJtDBuwwbIi_Wr14aT9Z4,1659
7
+ nexaai/cv.py,sha256=RHCDo8gvBH8BkGZx7qVyp-OKxqi7E1GG9XzyaXehCNA,3273
8
+ nexaai/embedder.py,sha256=Cw0tSHkPgd-RI62afCqQAcTHMnQhaI2CvfTMO-1JKOg,2452
9
+ nexaai/image_gen.py,sha256=0C_5Tjj4BYmxLbmMmvwajp-yy2mmEEOKwBFnDQNPzx4,4356
10
+ nexaai/llm.py,sha256=QQDRg8zlu-xHmWjtSOsK1vhQBHaqRIdL3T9I4cVX7W4,3416
11
+ nexaai/rerank.py,sha256=vWaBucoQ1wz-2iYnZqyFIcEjm-4Xcs1KDbFN5X8zzDQ,1872
12
12
  nexaai/runtime.py,sha256=mxxHYsb5iBUAm2K_u-XJWr_U-spJ9S4eApc8kf9myjw,1957
13
- nexaai/tts.py,sha256=4EbC0BfFh5TLrm_3Q5vx1sXdug5gvOi-owNeX7ekbdA,1926
14
- nexaai/vlm.py,sha256=g65S8ChMnp_wsz_O4szjR3Z8sD_46NHaxDlfdoZoQ0c,4291
13
+ nexaai/tts.py,sha256=ZnBpWUxIfHhh7KfEjddtH7hHOTa91zg7ogGLakMIALo,2167
14
+ nexaai/vlm.py,sha256=pZcMWkF2Ml9liVNbHxLqBJxwm2bxVNM1dkoelwWMyIE,4500
15
15
  nexaai/asr_impl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
- nexaai/asr_impl/mlx_asr_impl.py,sha256=JuyxFzFbbgclK5_2Rq5pT278h0q8LztJX7Tggz0zkbM,3191
17
- nexaai/asr_impl/pybind_asr_impl.py,sha256=ybvthYgtVbH_JgpSsl0nxjZYvXyk8KGRSKdsJ-hLfZE,1450
16
+ nexaai/asr_impl/mlx_asr_impl.py,sha256=eosd8-TIWAOwV0HltmoFrLwzXHcU4jyxtncvuZE9pgA,3257
17
+ nexaai/asr_impl/pybind_asr_impl.py,sha256=pE9Hb_hMi5yAc4MF83bLVOb8zDtreCkB3_u7XED9YpA,1516
18
18
  nexaai/binds/__init__.py,sha256=T9Ua7SzHNglSeEqXlfH5ymYXRyXhNKkC9z_y_bWCNMo,80
19
19
  nexaai/binds/common_bind.cpython-310-darwin.so,sha256=hVxY76tn7hN6uHDIgM7LWNvgoudHgNZVoaygM9X1RWE,217232
20
20
  nexaai/binds/embedder_bind.cpython-310-darwin.so,sha256=FT8581RNciilskK89PhtnNSjw4Oh0-xk8QdbJVFmOd8,202064
21
- nexaai/binds/libnexa_bridge.dylib,sha256=JfXpiJg-_MpB77NYNUZnvQdOZWYppGHgpUJ83n9cKVg,251256
21
+ nexaai/binds/libcrypto.dylib,sha256=aWif9WhTKVQhmZL3DmtIpMkZY5JSb_Ny6CClmUBKYM4,4710416
22
+ nexaai/binds/libnexa_bridge.dylib,sha256=W2PFrGAVDmalbBvyECD5GTEylLut3gg99p93Fi-QaAM,251480
23
+ nexaai/binds/libssl.dylib,sha256=Q2frAdhR729oKYuCjJOEr1Ott3idFWoFp98fwNqtIaU,881616
22
24
  nexaai/binds/llm_bind.cpython-310-darwin.so,sha256=Bv08rn9OBAHy01eAQeANiJSrCxskn1xSx4Gl1Vcrhm0,166064
23
- nexaai/binds/nexa_llama_cpp/libggml-base.dylib,sha256=D_mlY_PNMIFlm6mHERSLMoA7QfYHwEPVlb0UKMbl2N0,632048
25
+ nexaai/binds/nexa_llama_cpp/libggml-base.dylib,sha256=CzsTec_QHlvbBGzmx4MBQ4LUjG7aIqW1rP5p_A90Vds,632048
24
26
  nexaai/binds/nexa_llama_cpp/libggml-cpu.so,sha256=RiMhOv6IAWY1zkFTp0JCB7CYoPfOv54vBVQHvj1koBM,661120
25
27
  nexaai/binds/nexa_llama_cpp/libggml-metal.so,sha256=L4RQvaD0w4qBjexi4O05RMCH8842fof5QgBEvyx0RcA,673104
26
28
  nexaai/binds/nexa_llama_cpp/libggml.dylib,sha256=aOTj_6RrAMkfDO0ZI28_3nfcC-l4Y3dRCiS3C0d0_eI,58592
27
29
  nexaai/binds/nexa_llama_cpp/libllama.dylib,sha256=fDPnTG6EQ1JN6aRmnIFQzag_kmtyImRxKjMOOtaTY5Q,1746928
28
30
  nexaai/binds/nexa_llama_cpp/libmtmd.dylib,sha256=ccnBRsJNFGTCsjgW03N9PvX26wUirqpxljnxdVPINVc,587008
29
- nexaai/binds/nexa_llama_cpp/libnexa_plugin.dylib,sha256=1kAoSq1w8pPiNmceOdmAZ7ehfENauFoGq8mpIwGl-kk,1806696
30
- nexaai/binds/nexa_mlx/libnexa_plugin.dylib,sha256=aw8if8RwXjb02CehbqGPHOeEKRUcTpzeJZLOkjTBm8A,596328
31
+ nexaai/binds/nexa_llama_cpp/libnexa_plugin.dylib,sha256=d7s5TwlMFTGsrUifN1e6dOWxStsLFpuu6Ko6ImXZ5Sg,2368184
32
+ nexaai/binds/nexa_mlx/libnexa_plugin.dylib,sha256=yjbdy0FpBE_RwgqvwGxd3czIfs3OYVoh--vWpn2H7RQ,1422888
31
33
  nexaai/binds/nexa_mlx/py-lib/ml.py,sha256=LafDM_TeXmuQkld2tdQxUBGgooT0JPMXngLam2TADqU,23179
32
34
  nexaai/binds/nexa_mlx/py-lib/profiling.py,sha256=Dc-mybFwBdCIKFWL7CbSHjkOJGAoYHG7r_e_XPhzwBU,9361
33
35
  nexaai/binds/nexa_mlx/py-lib/mlx_audio/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -181,17 +183,17 @@ nexaai/binds/nexa_mlx/py-lib/mlx_audio/tts/tests/test_convert.py,sha256=79ddUhtT
181
183
  nexaai/binds/nexa_mlx/py-lib/mlx_audio/tts/tests/test_interpolate.py,sha256=9dNmH03C46HtxwesH2DpT2oTNEG1KCZWYEKq6UQ3vfk,3536
182
184
  nexaai/binds/nexa_mlx/py-lib/mlx_audio/tts/tests/test_models.py,sha256=12RiOfPtSZQj5g5JM-yCJk3uGQfM3OdmRiPt5uUDE4E,35096
183
185
  nexaai/cv_impl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
184
- nexaai/cv_impl/mlx_cv_impl.py,sha256=mdK4DEffPe96AgDGDXtQeHlG958hf8FO1fBZ1qjZMEE,3162
185
- nexaai/cv_impl/pybind_cv_impl.py,sha256=yS4JKfRSaIjjVP7hJ-CizG76pIX85bpmGLk9B9cnL24,998
186
+ nexaai/cv_impl/mlx_cv_impl.py,sha256=gKECQOv8iaWwG3bl7xeqVy2NN_9K7tYerIFzfn4eLo4,3228
187
+ nexaai/cv_impl/pybind_cv_impl.py,sha256=uSmwBste4cT7c8DQmXzRLmzwDf773PAbXNYWW1UzVls,1064
186
188
  nexaai/embedder_impl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
187
- nexaai/embedder_impl/mlx_embedder_impl.py,sha256=dTOz34WGDnhsI9L7Ctv6fGPngvMAUc4FwEwRgBp_M9I,4317
188
- nexaai/embedder_impl/pybind_embedder_impl.py,sha256=AGGrOq4z0mDpQZInOvJsOIlQWflByhDjsihMu_Wjtbk,3286
189
+ nexaai/embedder_impl/mlx_embedder_impl.py,sha256=OsDzsc_2wZkSoWu6yCOZadMkaYdBW3uyjF11hDKTaX8,4383
190
+ nexaai/embedder_impl/pybind_embedder_impl.py,sha256=Ga1JYauVkRq6jwAGL7Xx5HDaIx483_v9gZVoTyd3xNU,3495
189
191
  nexaai/image_gen_impl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
190
- nexaai/image_gen_impl/mlx_image_gen_impl.py,sha256=OxSbk9zIDj7tTvsdM8bMJQDBhpn-mygBNktewd_wgtE,11153
191
- nexaai/image_gen_impl/pybind_image_gen_impl.py,sha256=XoSdWG5ID_g93WT9QB0qCP64a4rX-Rva0u4fQ8xpoqg,3626
192
+ nexaai/image_gen_impl/mlx_image_gen_impl.py,sha256=BuDkksvXyb4J02GsdnbGAmYckfUU0Eah6BimoMD3QqY,11219
193
+ nexaai/image_gen_impl/pybind_image_gen_impl.py,sha256=ms34VYoD5AxZFG6cIG0QAJDjCtfphaZ1bHzKzey1xF8,3692
192
194
  nexaai/llm_impl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
193
- nexaai/llm_impl/mlx_llm_impl.py,sha256=HCi1uQBjccDDi64LbAgyH85lWx7qDZIW8i43dojGfF0,10210
194
- nexaai/llm_impl/pybind_llm_impl.py,sha256=8Us4N5KF6oi-0-K_5Dpf2rYe9smd89ZfWFrP_fWBsM4,7374
195
+ nexaai/llm_impl/mlx_llm_impl.py,sha256=2Ifc_mfTHDX64BWVHLjOhFCIMqM_Z-Cn4RfExlMtq0s,10865
196
+ nexaai/llm_impl/pybind_llm_impl.py,sha256=DpO38rlGcvf0Zpe4bPKsbPD3EguBf0dDS9Ve64bgdvo,7653
195
197
  nexaai/mlx_backend/ml.py,sha256=LafDM_TeXmuQkld2tdQxUBGgooT0JPMXngLam2TADqU,23179
196
198
  nexaai/mlx_backend/profiling.py,sha256=Dc-mybFwBdCIKFWL7CbSHjkOJGAoYHG7r_e_XPhzwBU,9361
197
199
  nexaai/mlx_backend/asr/__init__.py,sha256=fuT_9_xpYJ28m4yjly5L2jChUrzlSQz-b_S7nujxkSM,451
@@ -211,7 +213,7 @@ nexaai/mlx_backend/embedding/modeling/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCe
211
213
  nexaai/mlx_backend/embedding/modeling/nexa_jina_v2.py,sha256=F9Z_9r-Dh0wNThiMp5W5hqE2dt5bf4ps5_c6h4BuWGw,15218
212
214
  nexaai/mlx_backend/llm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
213
215
  nexaai/mlx_backend/llm/generate.py,sha256=Phes0tzxbbEWA2hDylQvD0LjorMaPwvcfZq9RKCAOt0,4399
214
- nexaai/mlx_backend/llm/interface.py,sha256=Fx28O2jCDPaEfr0xLffWnqGIU5Gspggxr-o54-fBWj4,29257
216
+ nexaai/mlx_backend/llm/interface.py,sha256=YBLAdz_5gQ1VF9o98Tuj6xB_M2nUB9kX9VkM-Mp6ryc,29310
215
217
  nexaai/mlx_backend/llm/main.py,sha256=gFDE4VZv_CLKMCTn0N521OfCKH_Ys26bHDh6g9VEFNc,1982
216
218
  nexaai/mlx_backend/mlx_audio/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
217
219
  nexaai/mlx_backend/mlx_audio/server.py,sha256=Pqy13Fafq4WX_cTuvRFz1jq89beQm2QQGpXmhK4b9jc,17547
@@ -502,19 +504,19 @@ nexaai/mlx_backend/vlm/modeling/trainer/lora.py,sha256=tGjvenjEQ8_1Az8Nz3smz5Mgv
502
504
  nexaai/mlx_backend/vlm/modeling/trainer/trainer.py,sha256=h16SaHt76JzFruXuidgXDx7_2evx4L0SecvzqLmhyZw,9081
503
505
  nexaai/mlx_backend/vlm/modeling/trainer/utils.py,sha256=29oHf_7946YeJKP_-Dt-NPeN4xJq8Fj7Yv4jZKO9RWA,4909
504
506
  nexaai/rerank_impl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
505
- nexaai/rerank_impl/mlx_rerank_impl.py,sha256=I-jumShLm1jAmKunRcDNUU4yjfWLoWClFMFONd88-Es,3177
506
- nexaai/rerank_impl/pybind_rerank_impl.py,sha256=FIIN96zCxXopqpqZdBd7OjuqqviFBY8HMZek1bCeoJw,1447
507
+ nexaai/rerank_impl/mlx_rerank_impl.py,sha256=h37PKSIRBY8mwzVeLeP4ix9ui3waIsg4gorzelYLJbM,3243
508
+ nexaai/rerank_impl/pybind_rerank_impl.py,sha256=CtwkG7YrW58GPMDERJSnISGTVCXWNju5__R2W837t7c,1513
507
509
  nexaai/tts_impl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
508
- nexaai/tts_impl/mlx_tts_impl.py,sha256=D71IFtIYWzrVdBS2y5vDBWjZ4ZAzRRjFHC0KO0pA5BU,3035
509
- nexaai/tts_impl/pybind_tts_impl.py,sha256=Be5QiXzDz6h1LTIQzUBd0ZyBs7rUpNA-pULCXFtt2Is,1378
510
+ nexaai/tts_impl/mlx_tts_impl.py,sha256=i_uNPdvlXYtL3e01oKjDlP9jgkWCRt1bBHsExaaiJi8,3101
511
+ nexaai/tts_impl/pybind_tts_impl.py,sha256=mpn44r6pfYLIl-NrEy2dXHjGtWtNCmM7HRyxiANxUI4,1444
510
512
  nexaai/utils/avatar_fetcher.py,sha256=bWy8ujgbOiTHFCjFxTwkn3uXbZ84PgEGUkXkR3MH4bI,3821
511
513
  nexaai/utils/decode.py,sha256=61n4Zf6c5QLyqGoctEitlI9BX3tPlP2a5aaKNHbw3T4,404
512
514
  nexaai/utils/model_manager.py,sha256=c07ocxxw1IHCQw6esbmYK0dX2R2OajfEIGsC_2teHXo,48572
513
515
  nexaai/utils/progress_tracker.py,sha256=76HlPkyN41IMHSsH56-qdlN_aY_oBfJz50J16Cx67R0,15102
514
516
  nexaai/vlm_impl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
515
- nexaai/vlm_impl/mlx_vlm_impl.py,sha256=4lFZ8ZQnYZ-Uoh9j2Fh2UzpdpMAy_v1Jz-lrqX33XcI,8947
516
- nexaai/vlm_impl/pybind_vlm_impl.py,sha256=C-3fa0AIypI33OAGuGfVxo1V7zN0wjQMgruKlDIlW4Q,8333
517
- nexaai-1.0.4rc14.dist-info/METADATA,sha256=dsyrftSmP4lR0EolabKfzo8ZRG5CBMHYJKGDRoP0eIM,952
518
- nexaai-1.0.4rc14.dist-info/WHEEL,sha256=T2p57lol9__xkoU6aJTyN1Pm43ZpRU3q6km7mIbrAMs,114
519
- nexaai-1.0.4rc14.dist-info/top_level.txt,sha256=LRE2YERlrZk2vfuygnSzsEeqSknnZbz3Z1MHyNmBU4w,7
520
- nexaai-1.0.4rc14.dist-info/RECORD,,
517
+ nexaai/vlm_impl/mlx_vlm_impl.py,sha256=Dm-N38wqK3Cjdk3n7wfVGKC7hwxHvaM8pz37VzvJC-Y,10443
518
+ nexaai/vlm_impl/pybind_vlm_impl.py,sha256=mvydHMHNWtkmyqouLIj1XSYZgsro3tcp3s_aqkjljE0,8510
519
+ nexaai-1.0.4rc16.dist-info/METADATA,sha256=NuLsDWtJssKVjTNP4oo-tFItIBxIbiq-0hTq1rv706s,883
520
+ nexaai-1.0.4rc16.dist-info/WHEEL,sha256=T2p57lol9__xkoU6aJTyN1Pm43ZpRU3q6km7mIbrAMs,114
521
+ nexaai-1.0.4rc16.dist-info/top_level.txt,sha256=LRE2YERlrZk2vfuygnSzsEeqSknnZbz3Z1MHyNmBU4w,7
522
+ nexaai-1.0.4rc16.dist-info/RECORD,,