nexaai 1.0.4rc13__cp310-cp310-win_amd64.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 (59) hide show
  1. nexaai/__init__.py +71 -0
  2. nexaai/_stub.cp310-win_amd64.pyd +0 -0
  3. nexaai/_version.py +4 -0
  4. nexaai/asr.py +60 -0
  5. nexaai/asr_impl/__init__.py +0 -0
  6. nexaai/asr_impl/mlx_asr_impl.py +91 -0
  7. nexaai/asr_impl/pybind_asr_impl.py +43 -0
  8. nexaai/base.py +39 -0
  9. nexaai/binds/__init__.py +3 -0
  10. nexaai/binds/common_bind.cp310-win_amd64.pyd +0 -0
  11. nexaai/binds/embedder_bind.cp310-win_amd64.pyd +0 -0
  12. nexaai/binds/llm_bind.cp310-win_amd64.pyd +0 -0
  13. nexaai/binds/nexa_bridge.dll +0 -0
  14. nexaai/binds/nexa_llama_cpp/ggml-base.dll +0 -0
  15. nexaai/binds/nexa_llama_cpp/ggml-cpu.dll +0 -0
  16. nexaai/binds/nexa_llama_cpp/ggml-cuda.dll +0 -0
  17. nexaai/binds/nexa_llama_cpp/ggml-vulkan.dll +0 -0
  18. nexaai/binds/nexa_llama_cpp/ggml.dll +0 -0
  19. nexaai/binds/nexa_llama_cpp/llama.dll +0 -0
  20. nexaai/binds/nexa_llama_cpp/mtmd.dll +0 -0
  21. nexaai/binds/nexa_llama_cpp/nexa_plugin.dll +0 -0
  22. nexaai/common.py +61 -0
  23. nexaai/cv.py +87 -0
  24. nexaai/cv_impl/__init__.py +0 -0
  25. nexaai/cv_impl/mlx_cv_impl.py +88 -0
  26. nexaai/cv_impl/pybind_cv_impl.py +31 -0
  27. nexaai/embedder.py +68 -0
  28. nexaai/embedder_impl/__init__.py +0 -0
  29. nexaai/embedder_impl/mlx_embedder_impl.py +114 -0
  30. nexaai/embedder_impl/pybind_embedder_impl.py +91 -0
  31. nexaai/image_gen.py +136 -0
  32. nexaai/image_gen_impl/__init__.py +0 -0
  33. nexaai/image_gen_impl/mlx_image_gen_impl.py +291 -0
  34. nexaai/image_gen_impl/pybind_image_gen_impl.py +84 -0
  35. nexaai/llm.py +89 -0
  36. nexaai/llm_impl/__init__.py +0 -0
  37. nexaai/llm_impl/mlx_llm_impl.py +249 -0
  38. nexaai/llm_impl/pybind_llm_impl.py +207 -0
  39. nexaai/rerank.py +51 -0
  40. nexaai/rerank_impl/__init__.py +0 -0
  41. nexaai/rerank_impl/mlx_rerank_impl.py +91 -0
  42. nexaai/rerank_impl/pybind_rerank_impl.py +42 -0
  43. nexaai/runtime.py +64 -0
  44. nexaai/tts.py +70 -0
  45. nexaai/tts_impl/__init__.py +0 -0
  46. nexaai/tts_impl/mlx_tts_impl.py +93 -0
  47. nexaai/tts_impl/pybind_tts_impl.py +42 -0
  48. nexaai/utils/avatar_fetcher.py +104 -0
  49. nexaai/utils/decode.py +18 -0
  50. nexaai/utils/model_manager.py +1195 -0
  51. nexaai/utils/progress_tracker.py +372 -0
  52. nexaai/vlm.py +120 -0
  53. nexaai/vlm_impl/__init__.py +0 -0
  54. nexaai/vlm_impl/mlx_vlm_impl.py +205 -0
  55. nexaai/vlm_impl/pybind_vlm_impl.py +228 -0
  56. nexaai-1.0.4rc13.dist-info/METADATA +26 -0
  57. nexaai-1.0.4rc13.dist-info/RECORD +59 -0
  58. nexaai-1.0.4rc13.dist-info/WHEEL +5 -0
  59. nexaai-1.0.4rc13.dist-info/top_level.txt +1 -0
@@ -0,0 +1,291 @@
1
+ # Note: This code is generated by Cursor, not tested yet.
2
+
3
+ from typing import List, Optional
4
+ import os
5
+
6
+ from nexaai.image_gen import ImageGen, ImageGenerationConfig, ImageSamplerConfig, SchedulerConfig, Image
7
+ from nexaai.mlx_backend.sd.interface import ImageGen as MLXImageGenInterface
8
+
9
+
10
+ class MLXImageGenImpl(ImageGen):
11
+ def __init__(self):
12
+ """Initialize MLX Image Generation implementation."""
13
+ super().__init__()
14
+ self._mlx_image_gen = None
15
+
16
+ @classmethod
17
+ def _load_from(cls,
18
+ model_path: str,
19
+ scheduler_config_path: str = "",
20
+ plugin_id: str = "mlx",
21
+ device_id: Optional[str] = None,
22
+ float16: bool = True,
23
+ quantize: bool = False
24
+ ) -> 'MLXImageGenImpl':
25
+ """Load image generation model from local path using MLX backend."""
26
+ try:
27
+ # MLX Image Generation interface is already imported
28
+
29
+ # Create instance and load MLX image generation model
30
+ instance = cls()
31
+ instance._mlx_image_gen = MLXImageGenInterface(
32
+ model_path=model_path,
33
+ scheduler_config_path=scheduler_config_path,
34
+ device=device_id,
35
+ float16=float16,
36
+ quantize=quantize
37
+ )
38
+
39
+ return instance
40
+ except Exception as e:
41
+ raise RuntimeError(f"Failed to load MLX Image Generation: {str(e)}")
42
+
43
+ def eject(self):
44
+ """Destroy the model and free resources."""
45
+ if self._mlx_image_gen:
46
+ self._mlx_image_gen.destroy()
47
+ self._mlx_image_gen = None
48
+
49
+ def load_model(self, model_path: str, extra_data: Optional[str] = None) -> bool:
50
+ """Load model from path."""
51
+ if not self._mlx_image_gen:
52
+ raise RuntimeError("MLX Image Generator not initialized")
53
+
54
+ try:
55
+ return self._mlx_image_gen.load_model(model_path, extra_data)
56
+ except Exception as e:
57
+ raise RuntimeError(f"Failed to load image generation model: {str(e)}")
58
+
59
+ def set_scheduler(self, config: SchedulerConfig) -> None:
60
+ """Set scheduler configuration."""
61
+ if not self._mlx_image_gen:
62
+ raise RuntimeError("MLX Image Generator not loaded")
63
+
64
+ try:
65
+ # Convert our config to MLX format
66
+ import sys
67
+ mlx_path = self._get_mlx_path()
68
+ if mlx_path not in sys.path:
69
+ sys.path.insert(0, mlx_path)
70
+
71
+ # MLX ImageGen uses a simpler interface, we'll store the config for use in generation
72
+ self._scheduler_config = config
73
+ self._mlx_image_gen.set_scheduler(config)
74
+ except Exception as e:
75
+ raise RuntimeError(f"Failed to set scheduler: {str(e)}")
76
+
77
+ def set_sampler(self, config: ImageSamplerConfig) -> None:
78
+ """Set sampler configuration."""
79
+ if not self._mlx_image_gen:
80
+ raise RuntimeError("MLX Image Generator not loaded")
81
+
82
+ try:
83
+ # Convert our config to MLX format
84
+ import sys
85
+ mlx_path = self._get_mlx_path()
86
+ if mlx_path not in sys.path:
87
+ sys.path.insert(0, mlx_path)
88
+ from sd.interface import ImageSamplerConfig as MLXImageSamplerConfig
89
+
90
+ mlx_config = MLXImageSamplerConfig(
91
+ method=config.method,
92
+ steps=config.steps,
93
+ guidance_scale=config.guidance_scale,
94
+ eta=config.eta,
95
+ seed=config.seed
96
+ )
97
+
98
+ self._mlx_image_gen.set_sampler(mlx_config)
99
+ except Exception as e:
100
+ raise RuntimeError(f"Failed to set sampler: {str(e)}")
101
+
102
+ def reset_sampler(self) -> None:
103
+ """Reset sampler to default configuration."""
104
+ if not self._mlx_image_gen:
105
+ raise RuntimeError("MLX Image Generator not loaded")
106
+
107
+ try:
108
+ self._mlx_image_gen.reset_sampler()
109
+ except Exception as e:
110
+ raise RuntimeError(f"Failed to reset sampler: {str(e)}")
111
+
112
+ def txt2img(self, prompt: str, config: ImageGenerationConfig) -> Image:
113
+ """Generate image from text prompt."""
114
+ if not self._mlx_image_gen:
115
+ raise RuntimeError("MLX Image Generator not loaded")
116
+
117
+ try:
118
+ # Convert our config to MLX format
119
+ import sys
120
+ mlx_path = self._get_mlx_path()
121
+ if mlx_path not in sys.path:
122
+ sys.path.insert(0, mlx_path)
123
+ from sd.interface import ImageGenerationConfig as MLXImageGenerationConfig
124
+
125
+ mlx_config = self._convert_generation_config(config)
126
+
127
+ # Use MLX text-to-image generation
128
+ result = self._mlx_image_gen.txt2img(prompt, mlx_config)
129
+
130
+ # Convert MLX result to our format
131
+ return self._convert_image_result(result)
132
+
133
+ except Exception as e:
134
+ raise RuntimeError(f"Failed to generate image from text: {str(e)}")
135
+
136
+ def img2img(self, init_image: Image, prompt: str, config: ImageGenerationConfig) -> Image:
137
+ """Generate image from initial image and text prompt."""
138
+ if not self._mlx_image_gen:
139
+ raise RuntimeError("MLX Image Generator not loaded")
140
+
141
+ try:
142
+ # Convert our config to MLX format
143
+ mlx_config = self._convert_generation_config(config)
144
+
145
+ # Convert our image to MLX format
146
+ import sys
147
+ mlx_path = self._get_mlx_path()
148
+ if mlx_path not in sys.path:
149
+ sys.path.insert(0, mlx_path)
150
+ from sd.interface import Image as MLXImage
151
+
152
+ mlx_init_image = MLXImage(
153
+ data=init_image.data,
154
+ width=init_image.width,
155
+ height=init_image.height,
156
+ channels=init_image.channels
157
+ )
158
+
159
+ # Use MLX image-to-image generation
160
+ result = self._mlx_image_gen.img2img(mlx_init_image, prompt, mlx_config)
161
+
162
+ # Convert MLX result to our format
163
+ return self._convert_image_result(result)
164
+
165
+ except Exception as e:
166
+ raise RuntimeError(f"Failed to generate image from image: {str(e)}")
167
+
168
+ def generate(self, config: ImageGenerationConfig) -> Image:
169
+ """Generate image from configuration."""
170
+ if not self._mlx_image_gen:
171
+ raise RuntimeError("MLX Image Generator not loaded")
172
+
173
+ try:
174
+ # Convert our config to MLX format
175
+ mlx_config = self._convert_generation_config(config)
176
+
177
+ # Use MLX generation
178
+ result = self._mlx_image_gen.generate(mlx_config)
179
+
180
+ # Convert MLX result to our format
181
+ return self._convert_image_result(result)
182
+
183
+ except Exception as e:
184
+ raise RuntimeError(f"Failed to generate image: {str(e)}")
185
+
186
+ def set_lora(self, lora_id: int) -> None:
187
+ """Set active LoRA adapter."""
188
+ if not self._mlx_image_gen:
189
+ raise RuntimeError("MLX Image Generator not loaded")
190
+
191
+ try:
192
+ self._mlx_image_gen.set_lora(lora_id)
193
+ except Exception as e:
194
+ raise RuntimeError(f"Failed to set LoRA: {str(e)}")
195
+
196
+ def add_lora(self, lora_path: str) -> int:
197
+ """Add LoRA adapter and return its ID."""
198
+ if not self._mlx_image_gen:
199
+ raise RuntimeError("MLX Image Generator not loaded")
200
+
201
+ try:
202
+ return self._mlx_image_gen.add_lora(lora_path)
203
+ except Exception as e:
204
+ raise RuntimeError(f"Failed to add LoRA: {str(e)}")
205
+
206
+ def remove_lora(self, lora_id: int) -> None:
207
+ """Remove LoRA adapter."""
208
+ if not self._mlx_image_gen:
209
+ raise RuntimeError("MLX Image Generator not loaded")
210
+
211
+ try:
212
+ self._mlx_image_gen.remove_lora(lora_id)
213
+ except Exception as e:
214
+ raise RuntimeError(f"Failed to remove LoRA: {str(e)}")
215
+
216
+ def list_loras(self) -> List[int]:
217
+ """List available LoRA adapters."""
218
+ if not self._mlx_image_gen:
219
+ raise RuntimeError("MLX Image Generator not loaded")
220
+
221
+ try:
222
+ return self._mlx_image_gen.list_loras()
223
+ except Exception as e:
224
+ raise RuntimeError(f"Failed to list LoRAs: {str(e)}")
225
+
226
+ def _convert_generation_config(self, config: ImageGenerationConfig):
227
+ """Convert our config to MLX format."""
228
+ import sys
229
+ mlx_path = self._get_mlx_path()
230
+ if mlx_path not in sys.path:
231
+ sys.path.insert(0, mlx_path)
232
+ from sd.interface import ImageGenerationConfig as MLXImageGenerationConfig, ImageSamplerConfig as MLXImageSamplerConfig
233
+
234
+ mlx_sampler_config = None
235
+ if config.sampler_config:
236
+ mlx_sampler_config = MLXImageSamplerConfig(
237
+ method=config.sampler_config.method,
238
+ steps=config.sampler_config.steps,
239
+ guidance_scale=config.sampler_config.guidance_scale,
240
+ eta=config.sampler_config.eta,
241
+ seed=config.sampler_config.seed
242
+ )
243
+
244
+ mlx_init_image = None
245
+ if config.init_image:
246
+ from sd.interface import Image as MLXImage
247
+ mlx_init_image = MLXImage(
248
+ data=config.init_image.data,
249
+ width=config.init_image.width,
250
+ height=config.init_image.height,
251
+ channels=config.init_image.channels
252
+ )
253
+
254
+ return MLXImageGenerationConfig(
255
+ prompts=config.prompts,
256
+ negative_prompts=config.negative_prompts,
257
+ height=config.height,
258
+ width=config.width,
259
+ sampler_config=mlx_sampler_config,
260
+ lora_id=config.lora_id,
261
+ init_image=mlx_init_image,
262
+ strength=config.strength,
263
+ n_images=config.n_images,
264
+ n_rows=config.n_rows,
265
+ decoding_batch_size=config.decoding_batch_size
266
+ )
267
+
268
+ def _convert_image_result(self, mlx_image):
269
+ """Convert MLX image to our format."""
270
+ return Image(
271
+ data=mlx_image.data,
272
+ width=mlx_image.width,
273
+ height=mlx_image.height,
274
+ channels=mlx_image.channels
275
+ )
276
+
277
+ @staticmethod
278
+ def _get_mlx_path():
279
+ """Get the MLX py-lib path."""
280
+ from pathlib import Path
281
+ current_dir = Path(__file__).parent.parent.parent.parent # Go back to nexa root
282
+ possible_paths = [
283
+ current_dir / "plugins" / "mlx" / "py-lib",
284
+ Path(os.environ.get("NEXA_MLX_PATH", "")) if os.environ.get("NEXA_MLX_PATH") else None,
285
+ ]
286
+
287
+ for path in possible_paths:
288
+ if path and path.exists() and (path / "sd" / "interface.py").exists():
289
+ return str(path.absolute())
290
+
291
+ raise ImportError("Could not find MLX py-lib directory")
@@ -0,0 +1,84 @@
1
+ from typing import List, Optional
2
+
3
+ from nexaai.image_gen import ImageGen, ImageGenerationConfig, ImageSamplerConfig, SchedulerConfig, Image
4
+
5
+
6
+ class PyBindImageGenImpl(ImageGen):
7
+ def __init__(self):
8
+ """Initialize PyBind Image Generation implementation."""
9
+ super().__init__()
10
+ # TODO: Add PyBind-specific initialization
11
+
12
+ @classmethod
13
+ def _load_from(cls,
14
+ model_path: str,
15
+ scheduler_config_path: str = "",
16
+ plugin_id: str = "llama_cpp",
17
+ device_id: Optional[str] = None,
18
+ float16: bool = True,
19
+ quantize: bool = False
20
+ ) -> 'PyBindImageGenImpl':
21
+ """Load image generation model from local path using PyBind backend."""
22
+ # TODO: Implement PyBind image generation loading
23
+ instance = cls()
24
+ return instance
25
+
26
+ def eject(self):
27
+ """Destroy the model and free resources."""
28
+ # TODO: Implement PyBind image generation cleanup
29
+ pass
30
+
31
+ def load_model(self, model_path: str, extra_data: Optional[str] = None) -> bool:
32
+ """Load model from path."""
33
+ # TODO: Implement PyBind image generation model loading
34
+ raise NotImplementedError("PyBind image generation model loading not yet implemented")
35
+
36
+ def set_scheduler(self, config: SchedulerConfig) -> None:
37
+ """Set scheduler configuration."""
38
+ # TODO: Implement PyBind scheduler setting
39
+ raise NotImplementedError("PyBind scheduler setting not yet implemented")
40
+
41
+ def set_sampler(self, config: ImageSamplerConfig) -> None:
42
+ """Set sampler configuration."""
43
+ # TODO: Implement PyBind sampler setting
44
+ raise NotImplementedError("PyBind sampler setting not yet implemented")
45
+
46
+ def reset_sampler(self) -> None:
47
+ """Reset sampler to default configuration."""
48
+ # TODO: Implement PyBind sampler reset
49
+ raise NotImplementedError("PyBind sampler reset not yet implemented")
50
+
51
+ def txt2img(self, prompt: str, config: ImageGenerationConfig) -> Image:
52
+ """Generate image from text prompt."""
53
+ # TODO: Implement PyBind text-to-image
54
+ raise NotImplementedError("PyBind text-to-image not yet implemented")
55
+
56
+ def img2img(self, init_image: Image, prompt: str, config: ImageGenerationConfig) -> Image:
57
+ """Generate image from initial image and text prompt."""
58
+ # TODO: Implement PyBind image-to-image
59
+ raise NotImplementedError("PyBind image-to-image not yet implemented")
60
+
61
+ def generate(self, config: ImageGenerationConfig) -> Image:
62
+ """Generate image from configuration."""
63
+ # TODO: Implement PyBind image generation
64
+ raise NotImplementedError("PyBind image generation not yet implemented")
65
+
66
+ def set_lora(self, lora_id: int) -> None:
67
+ """Set active LoRA adapter."""
68
+ # TODO: Implement PyBind LoRA setting
69
+ raise NotImplementedError("PyBind LoRA setting not yet implemented")
70
+
71
+ def add_lora(self, lora_path: str) -> int:
72
+ """Add LoRA adapter and return its ID."""
73
+ # TODO: Implement PyBind LoRA addition
74
+ raise NotImplementedError("PyBind LoRA addition not yet implemented")
75
+
76
+ def remove_lora(self, lora_id: int) -> None:
77
+ """Remove LoRA adapter."""
78
+ # TODO: Implement PyBind LoRA removal
79
+ raise NotImplementedError("PyBind LoRA removal not yet implemented")
80
+
81
+ def list_loras(self) -> List[int]:
82
+ """List available LoRA adapters."""
83
+ # TODO: Implement PyBind LoRA listing
84
+ raise NotImplementedError("PyBind LoRA listing not yet implemented")
nexaai/llm.py ADDED
@@ -0,0 +1,89 @@
1
+ from typing import Generator, Optional
2
+ from abc import abstractmethod
3
+ import queue
4
+ import threading
5
+
6
+ from nexaai.common import ModelConfig, GenerationConfig, ChatMessage
7
+ from nexaai.base import BaseModel
8
+
9
+ class LLM(BaseModel):
10
+ def __init__(self, m_cfg: ModelConfig = ModelConfig()):
11
+ """Initialize base LLM class."""
12
+ self._m_cfg = m_cfg
13
+ self._cancel_event = threading.Event() # New attribute to control cancellation
14
+
15
+ @classmethod
16
+ def _load_from(cls,
17
+ local_path: str,
18
+ tokenizer_path: Optional[str] = None,
19
+ m_cfg: ModelConfig = ModelConfig(),
20
+ plugin_id: str = "llama_cpp",
21
+ device_id: Optional[str] = None
22
+ ) -> 'LLM':
23
+ """Load model from local path, routing to appropriate implementation."""
24
+ if plugin_id == "mlx":
25
+ from nexaai.llm_impl.mlx_llm_impl import MLXLLMImpl
26
+ return MLXLLMImpl._load_from(local_path, tokenizer_path, m_cfg, plugin_id, device_id)
27
+ else:
28
+ from nexaai.llm_impl.pybind_llm_impl import PyBindLLMImpl
29
+ return PyBindLLMImpl._load_from(local_path, tokenizer_path, m_cfg, plugin_id, device_id)
30
+
31
+ def cancel_generation(self):
32
+ """Signal to cancel any ongoing stream generation."""
33
+ self._cancel_event.set()
34
+
35
+ def reset_cancel(self):
36
+ """Reset the cancel event. Call before starting a new generation if needed."""
37
+ self._cancel_event.clear()
38
+
39
+ @abstractmethod
40
+ def apply_chat_template(self, messages: list[ChatMessage]) -> str:
41
+ """Apply the chat template to messages."""
42
+ pass
43
+
44
+ @abstractmethod
45
+ def generate_stream(self, prompt: str, g_cfg: GenerationConfig = GenerationConfig()) -> Generator[str, None, None]:
46
+ """Generate text with streaming."""
47
+ pass
48
+
49
+ @abstractmethod
50
+ def generate(self, prompt: str, g_cfg: GenerationConfig = GenerationConfig()) -> str:
51
+ """
52
+ Generate text without streaming.
53
+
54
+ Args:
55
+ prompt (str): The prompt to generate text from. For chat models, this is the chat messages after chat template is applied.
56
+ g_cfg (GenerationConfig): Generation configuration.
57
+
58
+ Returns:
59
+ str: The generated text.
60
+ """
61
+ pass
62
+
63
+ @abstractmethod
64
+ def save_kv_cache(self, path: str):
65
+ """
66
+ Save the key-value cache to the file.
67
+
68
+ Args:
69
+ path (str): The path to the file.
70
+ """
71
+ pass
72
+
73
+ @abstractmethod
74
+ def load_kv_cache(self, path: str):
75
+ """
76
+ Load the key-value cache from the file.
77
+
78
+ Args:
79
+ path (str): The path to the file.
80
+ """
81
+ pass
82
+
83
+ @abstractmethod
84
+ def reset(self):
85
+ """
86
+ Reset the LLM model context and KV cache. If not reset, the model will skip the number of evaluated tokens and treat tokens after those as the new incremental tokens.
87
+ If your past chat history changed, or you are starting a new chat, you should always reset the model before running generate.
88
+ """
89
+ pass
File without changes