nexaai 1.0.17rc3__cp310-cp310-macosx_14_0_universal2.whl → 1.0.17rc5__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.

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.17-rc3"
4
+ __version__ = "1.0.17-rc5"
Binary file
@@ -35,15 +35,8 @@ def process_manifest_metadata(manifest: Dict[str, Any], repo_id: str) -> Dict[st
35
35
  # Handle download_time - keep as null if missing
36
36
  download_time = manifest.get('download_time')
37
37
 
38
- # Handle avatar_url - fetch on-the-fly if missing/null
38
+ # Handle avatar_url - leave it null if missing/null
39
39
  avatar_url = manifest.get('avatar_url')
40
- if not avatar_url:
41
- try:
42
- from .avatar_fetcher import get_avatar_url_for_repo
43
- avatar_url = get_avatar_url_for_repo(repo_id)
44
- except Exception:
45
- # If fetching fails, leave as None
46
- avatar_url = None
47
40
 
48
41
  # Return processed metadata
49
42
  processed_manifest = manifest.copy()
@@ -171,9 +164,9 @@ def create_gguf_manifest(repo_id: str, files: List[str], directory_path: str, ol
171
164
  },
172
165
  "ExtraFiles": None,
173
166
  # Preserve old metadata fields
174
- "pipeline_tag": old_metadata.get('pipeline_tag'),
175
- "download_time": old_metadata.get('download_time'),
176
- "avatar_url": old_metadata.get('avatar_url')
167
+ "pipeline_tag": old_metadata.get('pipeline_tag') if old_metadata.get('pipeline_tag') else existing_manifest.get('pipeline_tag'),
168
+ "download_time": old_metadata.get('download_time') if old_metadata.get('download_time') else existing_manifest.get('download_time'),
169
+ "avatar_url": old_metadata.get('avatar_url') if old_metadata.get('avatar_url') else existing_manifest.get('avatar_url')
177
170
  }
178
171
 
179
172
  return manifest
@@ -182,6 +175,9 @@ def create_gguf_manifest(repo_id: str, files: List[str], directory_path: str, ol
182
175
  def create_mlx_manifest(repo_id: str, files: List[str], directory_path: str, old_metadata: Dict[str, Any], is_mmproj: bool = False, file_name: Optional[Union[str, List[str]]] = None) -> Dict[str, Any]:
183
176
  """Create MLX format manifest."""
184
177
 
178
+ # Load existing manifest to merge MLX files if it exists
179
+ existing_manifest = load_nexa_manifest(directory_path)
180
+
185
181
  model_files = {}
186
182
  extra_files = []
187
183
 
@@ -250,9 +246,9 @@ def create_mlx_manifest(repo_id: str, files: List[str], directory_path: str, old
250
246
  },
251
247
  "ExtraFiles": extra_files if extra_files else None,
252
248
  # Preserve old metadata fields
253
- "pipeline_tag": old_metadata.get('pipeline_tag'),
254
- "download_time": old_metadata.get('download_time'),
255
- "avatar_url": old_metadata.get('avatar_url')
249
+ "pipeline_tag": old_metadata.get('pipeline_tag') if old_metadata.get('pipeline_tag') else existing_manifest.get('pipeline_tag'),
250
+ "download_time": old_metadata.get('download_time') if old_metadata.get('download_time') else existing_manifest.get('download_time'),
251
+ "avatar_url": old_metadata.get('avatar_url') if old_metadata.get('avatar_url') else existing_manifest.get('avatar_url')
256
252
  }
257
253
 
258
254
  return manifest
@@ -11,7 +11,6 @@ from huggingface_hub import HfApi
11
11
  from huggingface_hub.utils import HfHubHTTPError, RepositoryNotFoundError
12
12
 
13
13
  from .progress_tracker import CustomProgressTqdm, DownloadProgressTracker
14
- from .avatar_fetcher import get_avatar_url_for_repo
15
14
  from .manifest_utils import (
16
15
  load_download_metadata,
17
16
  save_download_metadata,
@@ -790,7 +789,7 @@ class HuggingFaceDownloader:
790
789
  # If no expected size, just check that file is not empty
791
790
  return os.path.getsize(file_path) > 0
792
791
 
793
- def _fetch_and_save_metadata(self, repo_id: str, local_dir: str, is_mmproj: bool = False, file_name: Optional[Union[str, List[str]]] = None) -> None:
792
+ 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:
794
793
  """Fetch model info and save metadata after successful download."""
795
794
  # Initialize metadata with defaults to ensure manifest is always created
796
795
  old_metadata = {
@@ -809,14 +808,9 @@ class HuggingFaceDownloader:
809
808
  # Log the error but continue with manifest creation
810
809
  print(f"Warning: Could not fetch model info for {repo_id}: {e}")
811
810
 
812
- try:
813
- # Get avatar URL
814
- avatar_url = get_avatar_url_for_repo(repo_id, custom_endpoint=self.endpoint)
815
- if avatar_url:
816
- old_metadata['avatar_url'] = avatar_url
817
- except Exception as e:
818
- # Log the error but continue with manifest creation
819
- print(f"Warning: Could not fetch avatar URL for {repo_id}: {e}")
811
+ # Use input avater url if provided
812
+ old_metadata['avatar_url'] = kwargs.get('avatar_url')
813
+
820
814
 
821
815
  # CRITICAL: Always create the manifest file, regardless of metadata fetch failures
822
816
  try:
@@ -850,7 +844,8 @@ class HuggingFaceDownloader:
850
844
  file_name: str,
851
845
  local_dir: str,
852
846
  progress_tracker: Optional[DownloadProgressTracker],
853
- force_download: bool = False
847
+ force_download: bool = False,
848
+ **kwargs
854
849
  ) -> str:
855
850
  """Download a single file from the repository using HuggingFace Hub API."""
856
851
  # Create repo-specific directory for the single file
@@ -882,7 +877,7 @@ class HuggingFaceDownloader:
882
877
  progress_tracker.stop_tracking()
883
878
 
884
879
  # Save metadata after successful download
885
- self._fetch_and_save_metadata(repo_id, file_local_dir, self._current_is_mmproj, self._current_file_name)
880
+ self._fetch_and_save_metadata(repo_id, file_local_dir, self._current_is_mmproj, self._current_file_name, **kwargs)
886
881
 
887
882
  return downloaded_path
888
883
 
@@ -901,7 +896,8 @@ class HuggingFaceDownloader:
901
896
  repo_id: str,
902
897
  local_dir: str,
903
898
  progress_tracker: Optional[DownloadProgressTracker],
904
- force_download: bool = False
899
+ force_download: bool = False,
900
+ **kwargs
905
901
  ) -> str:
906
902
  """Download the entire repository."""
907
903
  # Create a subdirectory for this specific repo
@@ -927,7 +923,7 @@ class HuggingFaceDownloader:
927
923
  progress_tracker.stop_tracking()
928
924
 
929
925
  # Save metadata after successful download
930
- self._fetch_and_save_metadata(repo_id, repo_local_dir, self._current_is_mmproj, self._current_file_name)
926
+ self._fetch_and_save_metadata(repo_id, repo_local_dir, self._current_is_mmproj, self._current_file_name, **kwargs)
931
927
 
932
928
  return downloaded_path
933
929
 
@@ -944,7 +940,8 @@ class HuggingFaceDownloader:
944
940
  file_names: List[str],
945
941
  local_dir: str,
946
942
  progress_tracker: Optional[DownloadProgressTracker],
947
- force_download: bool = False
943
+ force_download: bool = False,
944
+ **kwargs
948
945
  ) -> str:
949
946
  """Download multiple specific files from HuggingFace Hub."""
950
947
  # Create repo-specific directory
@@ -989,7 +986,7 @@ class HuggingFaceDownloader:
989
986
  progress_tracker.stop_tracking()
990
987
 
991
988
  # Save metadata after successful download
992
- self._fetch_and_save_metadata(repo_id, repo_local_dir, self._current_is_mmproj, self._current_file_name)
989
+ self._fetch_and_save_metadata(repo_id, repo_local_dir, self._current_is_mmproj, self._current_file_name, **kwargs)
993
990
 
994
991
  return repo_local_dir
995
992
 
@@ -1015,7 +1012,8 @@ class HuggingFaceDownloader:
1015
1012
  progress_callback: Optional[Callable[[Dict[str, Any]], None]] = None,
1016
1013
  show_progress: bool = True,
1017
1014
  force_download: bool = False,
1018
- is_mmproj: bool = False
1015
+ is_mmproj: bool = False,
1016
+ **kwargs
1019
1017
  ) -> str:
1020
1018
  """
1021
1019
  Main download method that handles all download scenarios.
@@ -1062,13 +1060,13 @@ class HuggingFaceDownloader:
1062
1060
  if file_name is None:
1063
1061
  # Download entire repository
1064
1062
  return self._download_entire_repository(
1065
- repo_id, local_dir, progress_tracker, force_download
1063
+ repo_id, local_dir, progress_tracker, force_download, **kwargs
1066
1064
  )
1067
1065
  elif isinstance(file_name, str):
1068
1066
  # Download specific single file
1069
1067
  self._validate_file_exists_in_repo(file_name, info, repo_id, progress_tracker)
1070
1068
  return self._download_single_file(
1071
- repo_id, file_name, local_dir, progress_tracker, force_download
1069
+ repo_id, file_name, local_dir, progress_tracker, force_download, **kwargs
1072
1070
  )
1073
1071
  else: # file_name is a list
1074
1072
  # Download multiple specific files
@@ -1077,7 +1075,7 @@ class HuggingFaceDownloader:
1077
1075
  self._validate_file_exists_in_repo(fname, info, repo_id, progress_tracker)
1078
1076
 
1079
1077
  return self._download_multiple_files_from_hf(
1080
- repo_id, file_name, local_dir, progress_tracker, force_download
1078
+ repo_id, file_name, local_dir, progress_tracker, force_download, **kwargs
1081
1079
  )
1082
1080
 
1083
1081
  except Exception as e:
@@ -1107,7 +1105,8 @@ def download_from_huggingface(
1107
1105
  token: Union[bool, str, None] = None,
1108
1106
  custom_endpoint: Optional[str] = None,
1109
1107
  force_download: bool = False,
1110
- is_mmproj: Optional[bool] = None
1108
+ is_mmproj: Optional[bool] = None,
1109
+ **kwargs
1111
1110
  ) -> str:
1112
1111
  """
1113
1112
  Download models or files from HuggingFace Hub or custom mirror endpoints.
@@ -1197,7 +1196,8 @@ def download_from_huggingface(
1197
1196
  progress_callback=progress_callback,
1198
1197
  show_progress=show_progress,
1199
1198
  force_download=force_download,
1200
- is_mmproj=is_mmproj
1199
+ is_mmproj=is_mmproj,
1200
+ **kwargs
1201
1201
  )
1202
1202
 
1203
1203
 
@@ -1211,7 +1211,8 @@ def _download_model_if_needed(
1211
1211
  param_name: str,
1212
1212
  progress_callback: Optional[Callable[[Dict[str, Any]], None]] = None,
1213
1213
  token: Union[bool, str, None] = None,
1214
- is_mmproj: bool = False
1214
+ is_mmproj: bool = False,
1215
+ **kwargs
1215
1216
  ) -> str:
1216
1217
  """
1217
1218
  Helper function to download a model from HuggingFace if it doesn't exist locally.
@@ -1247,7 +1248,8 @@ def _download_model_if_needed(
1247
1248
  progress_callback=progress_callback,
1248
1249
  show_progress=True,
1249
1250
  token=token,
1250
- is_mmproj=is_mmproj
1251
+ is_mmproj=is_mmproj,
1252
+ **kwargs
1251
1253
  )
1252
1254
 
1253
1255
  return downloaded_path
@@ -1320,7 +1322,7 @@ def auto_download_model(func: Callable) -> Callable:
1320
1322
  if name_or_path is not None:
1321
1323
  try:
1322
1324
  downloaded_name_path = _download_model_if_needed(
1323
- name_or_path, 'name_or_path', progress_callback, token
1325
+ name_or_path, 'name_or_path', progress_callback, token, **kwargs
1324
1326
  )
1325
1327
 
1326
1328
  # Replace name_or_path with downloaded path
@@ -1338,7 +1340,7 @@ def auto_download_model(func: Callable) -> Callable:
1338
1340
  if mmproj_path is not None:
1339
1341
  try:
1340
1342
  downloaded_mmproj_path = _download_model_if_needed(
1341
- mmproj_path, 'mmproj_path', progress_callback, token, is_mmproj=True
1343
+ mmproj_path, 'mmproj_path', progress_callback, token, is_mmproj=True, **kwargs
1342
1344
  )
1343
1345
 
1344
1346
  # Replace mmproj_path with downloaded path
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nexaai
3
- Version: 1.0.17rc3
3
+ Version: 1.0.17rc5
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=L8oB7GFZZMGnUpCg0PecDbI_ycKuQak-ZEJ4Y12_QIw,2184
2
- nexaai/_stub.cpython-310-darwin.so,sha256=EESW_m6rs5Wlme_i2eC5SBJNYxhWpP2ZbxMKx3K8FFg,66768
3
- nexaai/_version.py,sha256=m8oymb8W-f11Ra9dj3cr9xkH66hL0S5SPIlATwANYmU,143
2
+ nexaai/_stub.cpython-310-darwin.so,sha256=8bcJLd34iGDb2YnRTI5DCDqIeQKR3hWJ8RZVh01uWyE,66768
3
+ nexaai/_version.py,sha256=F_da1d4cWkmF90PfAVUtepv8hmGILywCGDFetA8CeKk,143
4
4
  nexaai/asr.py,sha256=NljMXDErwPNMOPaRkJZMEDka9Nk8xyur7L8i924TStY,2054
5
5
  nexaai/base.py,sha256=N8PRgDFA-XPku2vWnQIofQ7ipz3pPlO6f8YZGnuhquE,982
6
6
  nexaai/common.py,sha256=Y0NJNLTi4Nq4x1WL6PQsSvGUto0eGmWhjpsC6jcekfA,3444
@@ -19,7 +19,7 @@ nexaai/asr_impl/pybind_asr_impl.py,sha256=pE9Hb_hMi5yAc4MF83bLVOb8zDtreCkB3_u7XE
19
19
  nexaai/binds/__init__.py,sha256=eYuay_8DDXeOUWz2_R9HFSabohxs6hvZn391t2L0Po0,104
20
20
  nexaai/binds/common_bind.cpython-310-darwin.so,sha256=ya8gz7NnUtHlniGnRyExdwWfdHimEHiJ7Dry4I7_y44,235264
21
21
  nexaai/binds/embedder_bind.cpython-310-darwin.so,sha256=tPa0c0Dv_GiW66fgmAGWGCHXRGNApznqoQS0eQx9GFM,202064
22
- nexaai/binds/libnexa_bridge.dylib,sha256=udoZzHIJvexfdqAaBZUIUAXRbmqvqKWolI7hNFwRqoo,251192
22
+ nexaai/binds/libnexa_bridge.dylib,sha256=-PciDq_xpsOLKyIOW0g5RQs9Fd4X8fuK-8wrvm3YGX8,251192
23
23
  nexaai/binds/llm_bind.cpython-310-darwin.so,sha256=TAWfa1Hzq00TjtC1xVsiAeLp6hv2LrL5afDz4omUghc,182784
24
24
  nexaai/binds/vlm_bind.cpython-310-darwin.so,sha256=nd6eG_m2EiPthzkSZ97hlXWUOZQir4cQfFJZ4p6eR2U,182704
25
25
  nexaai/binds/nexa_llama_cpp/libggml-base.dylib,sha256=JM4oOkie1su0ES5hMdtILeQHlRukRzH1vTleTupUXhg,650736
@@ -188,7 +188,7 @@ nexaai/binds/nexa_nexaml/libggml-metal.so,sha256=zfaX7rIBYQazH2lf-vza007BMhPTK1A
188
188
  nexaai/binds/nexa_nexaml/libggml.dylib,sha256=aOTj_6RrAMkfDO0ZI28_3nfcC-l4Y3dRCiS3C0d0_eI,58592
189
189
  nexaai/binds/nexa_nexaml/libnexa-mm-process.dylib,sha256=3mITty3oYhoi5yc690CxS0tf4LGanqrPCR0meE-h9HQ,8568120
190
190
  nexaai/binds/nexa_nexaml/libnexa-sampling.dylib,sha256=OliTBr-r2y22Ebjc1Y33Ax56XpLMFQKtsHgfouj6TQM,7865400
191
- nexaai/binds/nexa_nexaml/libnexa_plugin.dylib,sha256=OiQtbPidObQaKFdr1nHKQA9PaDv_a1TQeDQ26x07GxM,249848
191
+ nexaai/binds/nexa_nexaml/libnexa_plugin.dylib,sha256=41VEU8yhk2aQlpfoSFeYkhLLhBSbzCcMns0IGyZvpNg,249848
192
192
  nexaai/binds/nexa_nexaml/libnexaproc.dylib,sha256=Pnxgm2k29hfedLjNP4t44gvioh-NWbE_3BW-VsCdHp8,880560
193
193
  nexaai/binds/nexa_nexaml/libqwen3-vl.dylib,sha256=hd8VPINYTH8mbU3BPxnjrPOKTw-NkWn7zkDB7p074-U,753168
194
194
  nexaai/binds/nexa_nexaml/libqwen3vl-vision.dylib,sha256=AmUk-DBtBAp5DOR14ICZcsiAcKjxxAx1y6mHAaETQu8,570024
@@ -541,17 +541,16 @@ nexaai/rerank_impl/pybind_rerank_impl.py,sha256=CtwkG7YrW58GPMDERJSnISGTVCXWNju5
541
541
  nexaai/tts_impl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
542
542
  nexaai/tts_impl/mlx_tts_impl.py,sha256=i_uNPdvlXYtL3e01oKjDlP9jgkWCRt1bBHsExaaiJi8,3101
543
543
  nexaai/tts_impl/pybind_tts_impl.py,sha256=mpn44r6pfYLIl-NrEy2dXHjGtWtNCmM7HRyxiANxUI4,1444
544
- nexaai/utils/avatar_fetcher.py,sha256=bWy8ujgbOiTHFCjFxTwkn3uXbZ84PgEGUkXkR3MH4bI,3821
545
544
  nexaai/utils/decode.py,sha256=61n4Zf6c5QLyqGoctEitlI9BX3tPlP2a5aaKNHbw3T4,404
546
- nexaai/utils/manifest_utils.py,sha256=sR9Nme4GbD3Cb3fMd55yLvGZpqxb71vd6b2XZTsrIGM,12328
547
- nexaai/utils/model_manager.py,sha256=p2kJKK63Zk-rEUucFsgY0T5PyXi_IvJY0gKewUVcAV4,56081
545
+ nexaai/utils/manifest_utils.py,sha256=PA84obFP7W1dlneURlIHIzJjWIF5dbDHGdNeHouUy68,12659
546
+ nexaai/utils/model_manager.py,sha256=_WKJP7YVk7q587OoOWwDNWVR-8tbKZkmHKjcCZN8Q4M,55979
548
547
  nexaai/utils/model_types.py,sha256=-DER8L4lAUR_iLS99F0r57avwqWtuN21ug5pX2p24_E,1369
549
548
  nexaai/utils/progress_tracker.py,sha256=jdUqtmPqyhwC9uSKvQcJEYETwSt-OhP4oitdJ94614o,15394
550
549
  nexaai/utils/quantization_utils.py,sha256=FYcNSAKGlBqFDUTx3jSKOr2lnq4nyiyC0ZG8oSxFwiU,7825
551
550
  nexaai/vlm_impl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
552
551
  nexaai/vlm_impl/mlx_vlm_impl.py,sha256=pLtWm_ckz8a0U-AtAOMVseFDO4OVPvHyYO2KlfBaGYk,10833
553
552
  nexaai/vlm_impl/pybind_vlm_impl.py,sha256=FAbhpRJzHgI78r0mUvKybO97R1szvNhH0aTn_I52oT4,8597
554
- nexaai-1.0.17rc3.dist-info/METADATA,sha256=qUwlQ7ioHaewOQ--gpTZsFkQDerm78q4okTIbDyTZ2E,1201
555
- nexaai-1.0.17rc3.dist-info/WHEEL,sha256=T2p57lol9__xkoU6aJTyN1Pm43ZpRU3q6km7mIbrAMs,114
556
- nexaai-1.0.17rc3.dist-info/top_level.txt,sha256=LRE2YERlrZk2vfuygnSzsEeqSknnZbz3Z1MHyNmBU4w,7
557
- nexaai-1.0.17rc3.dist-info/RECORD,,
553
+ nexaai-1.0.17rc5.dist-info/METADATA,sha256=UP8ZerQ7zCuBdjENEvuIzgSkgEMylmN6G0UTs6VcifQ,1201
554
+ nexaai-1.0.17rc5.dist-info/WHEEL,sha256=T2p57lol9__xkoU6aJTyN1Pm43ZpRU3q6km7mIbrAMs,114
555
+ nexaai-1.0.17rc5.dist-info/top_level.txt,sha256=LRE2YERlrZk2vfuygnSzsEeqSknnZbz3Z1MHyNmBU4w,7
556
+ nexaai-1.0.17rc5.dist-info/RECORD,,
@@ -1,104 +0,0 @@
1
- """Utility for fetching avatar URLs from HuggingFace."""
2
-
3
- import logging
4
- from typing import Dict, Optional
5
- import httpx
6
-
7
- logger = logging.getLogger(__name__)
8
-
9
-
10
- def fetch_avatar_urls_from_hf_api(query: str, custom_endpoint: Optional[str] = None) -> Dict[str, str]:
11
- """
12
- Fetch avatar URLs from HuggingFace models-json endpoint.
13
-
14
- Args:
15
- query: Search query to fetch models for
16
- custom_endpoint: Optional custom HuggingFace endpoint
17
-
18
- Returns:
19
- Dictionary mapping author names to avatar URLs
20
- """
21
- avatar_map = {}
22
- try:
23
- # Use the base URL from the configured endpoint
24
- base_url = custom_endpoint if custom_endpoint else "https://huggingface.co"
25
-
26
- # Build the URL with query parameter
27
- url = f"{base_url}/models-json?sort=trending&search={query}&withCount=true"
28
-
29
- # Make the HTTP request with a timeout
30
- with httpx.Client(timeout=2.0) as client:
31
- response = client.get(url)
32
-
33
- if response.status_code == 200:
34
- data = response.json()
35
- models = data.get("models", [])
36
-
37
- # Build a map of author names to avatar URLs
38
- for model in models:
39
- author = model.get("author")
40
- author_data = model.get("authorData", {})
41
- avatar_url = author_data.get("avatarUrl")
42
-
43
- if author and avatar_url:
44
- # Handle relative URLs by prepending appropriate base URL
45
- if avatar_url.startswith("/"):
46
- avatar_url = f"{base_url}{avatar_url}"
47
- avatar_map[author] = avatar_url
48
-
49
- logger.debug(f"Fetched {len(avatar_map)} avatar URLs from HuggingFace API")
50
- else:
51
- logger.warning(f"Failed to fetch avatar URLs: HTTP {response.status_code}")
52
-
53
- except Exception as e:
54
- logger.warning(f"Error fetching avatar URLs from HuggingFace API: {e}")
55
- # Return empty map on error - we'll fall back to default behavior
56
-
57
- return avatar_map
58
-
59
-
60
- def get_avatar_url_for_repo(repo_id: str, search_query: Optional[str] = None,
61
- custom_endpoint: Optional[str] = None) -> Optional[str]:
62
- """
63
- Get avatar URL for a repository ID.
64
-
65
- This method tries multiple strategies:
66
- 1. If search_query is provided, fetch from HuggingFace API with that query
67
- 2. Try fetching with the full repo_id as query
68
- 3. Try fetching with just the organization name as query
69
- 4. Fall back to CDN URL pattern
70
-
71
- Args:
72
- repo_id: Repository ID in format "owner/repo"
73
- search_query: Optional search query to use for fetching avatars
74
- custom_endpoint: Optional custom HuggingFace endpoint
75
-
76
- Returns:
77
- Avatar URL or None if not found
78
- """
79
- if "/" not in repo_id:
80
- return None
81
-
82
- org_name = repo_id.split("/")[0]
83
-
84
- # Try with search query if provided
85
- if search_query:
86
- avatar_map = fetch_avatar_urls_from_hf_api(search_query, custom_endpoint)
87
- avatar_url = avatar_map.get(org_name)
88
- if avatar_url:
89
- return avatar_url
90
-
91
- # Try with full repo_id
92
- avatar_map = fetch_avatar_urls_from_hf_api(repo_id, custom_endpoint)
93
- avatar_url = avatar_map.get(org_name)
94
- if avatar_url:
95
- return avatar_url
96
-
97
- # Try with just organization name
98
- avatar_map = fetch_avatar_urls_from_hf_api(org_name, custom_endpoint)
99
- avatar_url = avatar_map.get(org_name)
100
- if avatar_url:
101
- return avatar_url
102
-
103
- # Fallback to CDN URL pattern
104
- return f"https://cdn-thumbnails.huggingface.co/social-thumbnails/{org_name}.png"