nexaai 1.0.7__cp310-cp310-macosx_13_0_x86_64.whl → 1.0.9__cp310-cp310-macosx_13_0_x86_64.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.

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.7"
4
+ __version__ = "1.0.9"
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -14,6 +14,7 @@ from .progress_tracker import CustomProgressTqdm, DownloadProgressTracker
14
14
  from .avatar_fetcher import get_avatar_url_for_repo
15
15
  from .manifest_utils import (
16
16
  load_download_metadata,
17
+ save_download_metadata,
17
18
  save_manifest_with_files_metadata,
18
19
  )
19
20
 
@@ -117,6 +118,13 @@ def _get_directory_size_and_files(directory_path: str) -> tuple[int, List[str]]:
117
118
  return total_size, files
118
119
 
119
120
 
121
+ def _has_valid_metadata(directory_path: str) -> bool:
122
+ """Check if directory has either nexa.manifest or download_metadata.json (for backward compatibility)."""
123
+ manifest_path = os.path.join(directory_path, 'nexa.manifest')
124
+ old_metadata_path = os.path.join(directory_path, 'download_metadata.json')
125
+ return os.path.exists(manifest_path) or os.path.exists(old_metadata_path)
126
+
127
+
120
128
  def _scan_for_repo_folders(base_path: str) -> List[DownloadedModel]:
121
129
  """Scan a directory for repository folders and return model information."""
122
130
  models = []
@@ -142,9 +150,8 @@ def _scan_for_repo_folders(base_path: str) -> List[DownloadedModel]:
142
150
  if os.path.isdir(subitem_path):
143
151
  has_subdirs = True
144
152
  # This looks like owner/repo structure
145
- # Only include if nexa.manifest exists
146
- manifest_path = os.path.join(subitem_path, 'nexa.manifest')
147
- if os.path.exists(manifest_path):
153
+ # Only include if nexa.manifest or download_metadata.json exists (backward compatibility)
154
+ if _has_valid_metadata(subitem_path):
148
155
  size_bytes, files = _get_directory_size_and_files(subitem_path)
149
156
  if files: # Only include if there are files
150
157
  # Check if the download is complete
@@ -172,9 +179,8 @@ def _scan_for_repo_folders(base_path: str) -> List[DownloadedModel]:
172
179
 
173
180
  # Direct repo folder (no owner structure)
174
181
  if not has_subdirs and direct_files:
175
- # Only include if nexa.manifest exists
176
- manifest_path = os.path.join(item_path, 'nexa.manifest')
177
- if os.path.exists(manifest_path):
182
+ # Only include if nexa.manifest or download_metadata.json exists (backward compatibility)
183
+ if _has_valid_metadata(item_path):
178
184
  size_bytes, files = _get_directory_size_and_files(item_path)
179
185
  if files: # Only include if there are files
180
186
  # Check if the download is complete
@@ -723,38 +729,57 @@ class HuggingFaceDownloader:
723
729
 
724
730
  def _fetch_and_save_metadata(self, repo_id: str, local_dir: str) -> None:
725
731
  """Fetch model info and save metadata after successful download."""
732
+ # Initialize metadata with defaults to ensure manifest is always created
733
+ old_metadata = {
734
+ 'pipeline_tag': "text-generation", # Default to text-generation pipeline-tag
735
+ 'download_time': datetime.now().isoformat(),
736
+ 'avatar_url': None
737
+ }
738
+
739
+ # Try to fetch additional metadata, but don't let failures prevent manifest creation
726
740
  try:
727
741
  # Fetch model info to get pipeline_tag
728
742
  info = self.api.model_info(repo_id, token=self.token)
729
- pipeline_tag = info.pipeline_tag if hasattr(info, 'pipeline_tag') else None
730
-
743
+ if hasattr(info, 'pipeline_tag'):
744
+ old_metadata['pipeline_tag'] = info.pipeline_tag
745
+ except Exception as e:
746
+ # Log the error but continue with manifest creation
747
+ print(f"Warning: Could not fetch model info for {repo_id}: {e}")
748
+
749
+ try:
731
750
  # Get avatar URL
732
751
  avatar_url = get_avatar_url_for_repo(repo_id, custom_endpoint=self.endpoint)
733
-
734
- # Prepare old-style metadata for compatibility
735
- old_metadata = {
736
- 'pipeline_tag': pipeline_tag,
737
- 'download_time': datetime.now().isoformat(),
738
- 'avatar_url': avatar_url
739
- }
740
-
741
- # Get list of files in the directory
742
- files = []
743
- try:
744
- for root, dirs, filenames in os.walk(local_dir):
745
- for filename in filenames:
746
- # Store relative path from the directory
747
- rel_path = os.path.relpath(os.path.join(root, filename), local_dir)
748
- files.append(rel_path)
749
- except (OSError, IOError):
750
- pass
751
-
752
- # Create and save manifest using the new utility function
752
+ if avatar_url:
753
+ old_metadata['avatar_url'] = avatar_url
754
+ except Exception as e:
755
+ # Log the error but continue with manifest creation
756
+ print(f"Warning: Could not fetch avatar URL for {repo_id}: {e}")
757
+
758
+ # CRITICAL: Always create the manifest file, regardless of metadata fetch failures
759
+ try:
753
760
  save_manifest_with_files_metadata(repo_id, local_dir, old_metadata)
754
-
755
- except Exception:
756
- # Don't fail the download if metadata fetch fails
757
- pass
761
+ print(f"[OK] Successfully created nexa.manifest for {repo_id}")
762
+ except Exception as e:
763
+ # This is critical - if manifest creation fails, we should know about it
764
+ print(f"ERROR: Failed to create nexa.manifest for {repo_id}: {e}")
765
+ # Try a fallback approach - create a minimal manifest
766
+ try:
767
+ minimal_manifest = {
768
+ "Name": repo_id,
769
+ "ModelType": "other",
770
+ "PluginId": "unknown",
771
+ "ModelFile": {},
772
+ "MMProjFile": {"Name": "", "Downloaded": False, "Size": 0},
773
+ "TokenizerFile": {"Name": "", "Downloaded": False, "Size": 0},
774
+ "ExtraFiles": None,
775
+ "pipeline_tag": old_metadata.get('pipeline_tag'),
776
+ "download_time": old_metadata.get('download_time'),
777
+ "avatar_url": old_metadata.get('avatar_url')
778
+ }
779
+ save_download_metadata(local_dir, minimal_manifest)
780
+ print(f"[OK] Created minimal nexa.manifest for {repo_id} as fallback")
781
+ except Exception as fallback_error:
782
+ print(f"CRITICAL ERROR: Could not create even minimal manifest for {repo_id}: {fallback_error}")
758
783
 
759
784
  def _download_single_file(
760
785
  self,
@@ -771,7 +796,7 @@ class HuggingFaceDownloader:
771
796
  # Check if file already exists
772
797
  local_file_path = os.path.join(file_local_dir, file_name)
773
798
  if not force_download and self._check_file_exists_and_valid(local_file_path):
774
- print(f" File already exists, skipping: {file_name}")
799
+ print(f"[SKIP] File already exists: {file_name}")
775
800
  # Stop progress tracking
776
801
  if progress_tracker:
777
802
  progress_tracker.stop_tracking()
@@ -878,7 +903,7 @@ class HuggingFaceDownloader:
878
903
  # Check if file already exists
879
904
  local_file_path = os.path.join(repo_local_dir, file_name)
880
905
  if not force_download and self._check_file_exists_and_valid(local_file_path):
881
- print(f" File already exists, skipping: {file_name}")
906
+ print(f"[SKIP] File already exists: {file_name}")
882
907
  overall_progress.update(1)
883
908
  continue
884
909
 
@@ -249,11 +249,11 @@ class DownloadProgressTracker:
249
249
  if known_total and total_size_raw > 0:
250
250
  # Known total size - show actual progress
251
251
  filled_width = int(bar_width * min(percentage, 100) / 100)
252
- bar = '' * filled_width + '' * (bar_width - filled_width)
252
+ bar = '#' * filled_width + '-' * (bar_width - filled_width)
253
253
  else:
254
254
  # Unknown total size - show animated progress
255
255
  animation_pos = int(time.time() * 2) % bar_width
256
- bar = '' * animation_pos + '' + '' * (bar_width - animation_pos - 1)
256
+ bar = '-' * animation_pos + '#' + '-' * (bar_width - animation_pos - 1)
257
257
 
258
258
  # Format the progress line
259
259
  status = progress_data.get('status', 'unknown')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nexaai
3
- Version: 1.0.7
3
+ Version: 1.0.9
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
@@ -1,6 +1,6 @@
1
1
  nexaai/__init__.py,sha256=jXdC4vv6DBK1fVewYTYSUhOOYfvf_Mk81UIeMGGIKUg,2029
2
- nexaai/_stub.cpython-310-darwin.so,sha256=kCIU_fKCs9GKTHji-U-bFCMzrUVmhXsIavpCgiO9otE,49832
3
- nexaai/_version.py,sha256=HMQ_cuen1UlESzaxkeIlsIDBtPl1Uc9t60FOoMWVLcM,138
2
+ nexaai/_stub.cpython-310-darwin.so,sha256=kLUvt-wsOlpvaFT0rv2wWDEzwfsvIlRkBAX_SpOLavA,49832
3
+ nexaai/_version.py,sha256=X32yXPerNFCcC9vyv0thXa3X8Z3ftJ4GXv2LbN7omGs,138
4
4
  nexaai/asr.py,sha256=NljMXDErwPNMOPaRkJZMEDka9Nk8xyur7L8i924TStY,2054
5
5
  nexaai/base.py,sha256=N8PRgDFA-XPku2vWnQIofQ7ipz3pPlO6f8YZGnuhquE,982
6
6
  nexaai/common.py,sha256=yBnIbqYaQYnfrl7IczOBh6MDibYZVxwaRJEglYcKgGs,3422
@@ -19,16 +19,16 @@ nexaai/binds/__init__.py,sha256=T9Ua7SzHNglSeEqXlfH5ymYXRyXhNKkC9z_y_bWCNMo,80
19
19
  nexaai/binds/common_bind.cpython-310-darwin.so,sha256=FF5WuJj0fNCim_HjseBQu38vL-1M5zI_7EVTD7Bs-Bc,233960
20
20
  nexaai/binds/embedder_bind.cpython-310-darwin.so,sha256=mU6hP0SyH8vcmPpC2GIr7ioK7539dsg_YbmrBdmj7l0,202032
21
21
  nexaai/binds/libcrypto.dylib,sha256=ysW8ydmDPnnNRy3AHESjJwMTFfmGDKU9eLIaiR37ca0,5091432
22
- nexaai/binds/libnexa_bridge.dylib,sha256=APoxDEOU9vLEoNGV8vFWDXUQxf6XlNu_ue1crcmecek,250712
22
+ nexaai/binds/libnexa_bridge.dylib,sha256=bjoa5-DUnymTvOtIXEDIOI6Ec3FiVZbRcxBMJNuenNQ,250712
23
23
  nexaai/binds/libssl.dylib,sha256=JHPTSbRFnImmoWDO9rFdiKb0lJMT3q78VEsx-5-S0sk,889520
24
24
  nexaai/binds/llm_bind.cpython-310-darwin.so,sha256=aYqMs5VhC07RNZZgyS9JeYJJgWCl-toZOmt6vXu5yp0,183008
25
- nexaai/binds/nexa_llama_cpp/libggml-base.dylib,sha256=oikz7Qxzx6A0mPROq7uHTUwWn66LvvOjcdVstG-M8Fw,629528
26
- nexaai/binds/nexa_llama_cpp/libggml-cpu.so,sha256=WepzOOeElmdOlsoMv7loLHsj8-Qx2O9ZJPlNnX11KJI,1039800
27
- nexaai/binds/nexa_llama_cpp/libggml-metal.so,sha256=ssn3Bqmnu7YA_FKL513Y18gbxG8WP9Udw71DNKV34eo,713680
28
- nexaai/binds/nexa_llama_cpp/libggml.dylib,sha256=Z2ZvkyEEpPtHhMYap-44p9Q0M6TXJbLcMy-smR2X5sk,58336
29
- nexaai/binds/nexa_llama_cpp/libllama.dylib,sha256=QZBn_w32g8NAJLE1unC_qx1BCVM531LeqTUqWipt9ks,1982280
30
- nexaai/binds/nexa_llama_cpp/libmtmd.dylib,sha256=F1QLNlfjiECRssUtEZeuqNqej-8COYcQjMZKPAB0CGk,701504
31
- nexaai/binds/nexa_llama_cpp/libnexa_plugin.dylib,sha256=csMdM6l21qpj-3_4z0xGsYM1snOBg4cJPfLXOQ8oTcI,2644752
25
+ nexaai/binds/nexa_llama_cpp/libggml-base.dylib,sha256=THe7d5VNjazmzN_8rM8GRebUFUGM8ZlXLULigOAugCg,626776
26
+ nexaai/binds/nexa_llama_cpp/libggml-cpu.so,sha256=LH1q-tznZg4PAYfP9iAKlbCZdhdtQsgNLwqYloxN3MI,1004304
27
+ nexaai/binds/nexa_llama_cpp/libggml-metal.so,sha256=7m61FqGB4G-I1jJjnReW9k3GK5NTxBzrDOMH3Yu_8v0,713680
28
+ nexaai/binds/nexa_llama_cpp/libggml.dylib,sha256=rj6BFW9-20D2kfPAxmuekucHFal8PCy9BNBf_fhz-G0,58336
29
+ nexaai/binds/nexa_llama_cpp/libllama.dylib,sha256=kTm5roZm7AioxkPMLQ2CRSnr6b9-nTLbjFy-ROXadUk,1958056
30
+ nexaai/binds/nexa_llama_cpp/libmtmd.dylib,sha256=tUUCuTFrY6xuxxcQtG9iN7RxqnQv_rfhLKbHD2kG4e0,682264
31
+ nexaai/binds/nexa_llama_cpp/libnexa_plugin.dylib,sha256=V4k34ZHPfx2HJEmi_XdtFCe9OhbL1PgXTrOAXeqrHTw,2532312
32
32
  nexaai/cv_impl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
33
33
  nexaai/cv_impl/mlx_cv_impl.py,sha256=gKECQOv8iaWwG3bl7xeqVy2NN_9K7tYerIFzfn4eLo4,3228
34
34
  nexaai/cv_impl/pybind_cv_impl.py,sha256=uSmwBste4cT7c8DQmXzRLmzwDf773PAbXNYWW1UzVls,1064
@@ -359,14 +359,14 @@ nexaai/tts_impl/pybind_tts_impl.py,sha256=mpn44r6pfYLIl-NrEy2dXHjGtWtNCmM7HRyxiA
359
359
  nexaai/utils/avatar_fetcher.py,sha256=bWy8ujgbOiTHFCjFxTwkn3uXbZ84PgEGUkXkR3MH4bI,3821
360
360
  nexaai/utils/decode.py,sha256=61n4Zf6c5QLyqGoctEitlI9BX3tPlP2a5aaKNHbw3T4,404
361
361
  nexaai/utils/manifest_utils.py,sha256=2waOuQErodNHhoAETQqlQgXdVes-T5A4HMb8pUIN9hg,9765
362
- nexaai/utils/model_manager.py,sha256=xzerYqXkvRrHEqpEQvhOeg_6XQho2BvYw6ee4dlz69A,48575
362
+ nexaai/utils/model_manager.py,sha256=wngqu5uISyoXlytJXgDldBLMnNyFWbun5g17TqyiLkA,50247
363
363
  nexaai/utils/model_types.py,sha256=-DER8L4lAUR_iLS99F0r57avwqWtuN21ug5pX2p24_E,1369
364
- nexaai/utils/progress_tracker.py,sha256=mTw7kaKH8BkmecYm7iBMqRHd9uUH4Ch0S8CzbpARDCk,15404
364
+ nexaai/utils/progress_tracker.py,sha256=jdUqtmPqyhwC9uSKvQcJEYETwSt-OhP4oitdJ94614o,15394
365
365
  nexaai/utils/quantization_utils.py,sha256=4gvp6UQfSO9G1FYBwnFtQspTzH9sDbi1PBXw2t1N69M,7650
366
366
  nexaai/vlm_impl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
367
367
  nexaai/vlm_impl/mlx_vlm_impl.py,sha256=od1R1mRoIgPG3NHC7JiDlcB_YJY8aklX8Em3ZkeHNpE,10734
368
368
  nexaai/vlm_impl/pybind_vlm_impl.py,sha256=5ZMFgDATthmMzjrd-vE5KX5ZAMoWPYbF_FTLz8DBKIk,8908
369
- nexaai-1.0.7.dist-info/METADATA,sha256=DMyi7lxZHVYv62pJQ6SemiNzIqHSGuS4-r5vHO9llJw,1197
370
- nexaai-1.0.7.dist-info/WHEEL,sha256=0KYp5feZ1CMUhsfFXKpSQTbSmQbXy4mv6yPPVBXg2EM,110
371
- nexaai-1.0.7.dist-info/top_level.txt,sha256=LRE2YERlrZk2vfuygnSzsEeqSknnZbz3Z1MHyNmBU4w,7
372
- nexaai-1.0.7.dist-info/RECORD,,
369
+ nexaai-1.0.9.dist-info/METADATA,sha256=uEyssCVhZdf5ZnkVgTHJ-rihcXEH1TYkzzEmKYOyxwo,1197
370
+ nexaai-1.0.9.dist-info/WHEEL,sha256=0KYp5feZ1CMUhsfFXKpSQTbSmQbXy4mv6yPPVBXg2EM,110
371
+ nexaai-1.0.9.dist-info/top_level.txt,sha256=LRE2YERlrZk2vfuygnSzsEeqSknnZbz3Z1MHyNmBU4w,7
372
+ nexaai-1.0.9.dist-info/RECORD,,
File without changes