bigdl-core-cpp 2.5.0rc1__py3-none-win_amd64.whl → 2.6.0__py3-none-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.
Files changed (92) hide show
  1. bigdl/cpp/{convert-hf-to-gguf.py → convert_hf_to_gguf.py} +1673 -278
  2. bigdl/cpp/convert_hf_to_gguf_update.py +381 -0
  3. bigdl/cpp/convert_llama_ggml_to_gguf.py +450 -0
  4. bigdl/cpp/convert_lora_to_gguf.py +461 -0
  5. bigdl/cpp/gguf-py/gguf/__init__.py +1 -1
  6. bigdl/cpp/gguf-py/gguf/constants.py +698 -171
  7. bigdl/cpp/gguf-py/gguf/gguf.py +1 -1
  8. bigdl/cpp/gguf-py/gguf/gguf_reader.py +5 -6
  9. bigdl/cpp/gguf-py/gguf/gguf_writer.py +108 -17
  10. bigdl/cpp/gguf-py/gguf/lazy.py +3 -1
  11. bigdl/cpp/gguf-py/gguf/metadata.py +195 -76
  12. bigdl/cpp/gguf-py/gguf/quants.py +1210 -64
  13. bigdl/cpp/gguf-py/gguf/tensor_mapping.py +262 -43
  14. bigdl/cpp/gguf-py/gguf/utility.py +2 -2
  15. bigdl/cpp/gguf-py/gguf/vocab.py +325 -3
  16. bigdl/cpp/libs/common.lib +0 -0
  17. bigdl/cpp/libs/ggml-base.dll +0 -0
  18. bigdl/cpp/libs/ggml-cpu.dll +0 -0
  19. bigdl/cpp/libs/ggml-sycl.dll +0 -0
  20. bigdl/cpp/libs/ggml.dll +0 -0
  21. bigdl/cpp/libs/libc++.dll +0 -0
  22. bigdl/cpp/libs/llama-batched.exe +0 -0
  23. bigdl/cpp/libs/llama-bench.exe +0 -0
  24. bigdl/cpp/libs/llama-cli.exe +0 -0
  25. bigdl/cpp/libs/llama-embedding.exe +0 -0
  26. bigdl/cpp/libs/llama-gemma3-cli.exe +0 -0
  27. bigdl/cpp/libs/llama-gguf.exe +0 -0
  28. bigdl/cpp/libs/llama-llava-cli.exe +0 -0
  29. bigdl/cpp/libs/llama-lookup.exe +0 -0
  30. bigdl/cpp/libs/llama-ls-sycl-device.exe +0 -0
  31. bigdl/cpp/libs/llama-minicpmv-cli.exe +0 -0
  32. bigdl/cpp/libs/llama-perplexity.exe +0 -0
  33. bigdl/cpp/libs/llama-quantize.exe +0 -0
  34. bigdl/cpp/libs/llama-server.exe +0 -0
  35. bigdl/cpp/libs/llama-simple.exe +0 -0
  36. bigdl/cpp/libs/llama-speculative.exe +0 -0
  37. bigdl/cpp/libs/llama-tokenize.exe +0 -0
  38. bigdl/cpp/libs/llama.dll +0 -0
  39. bigdl/cpp/libs/llava_shared.dll +0 -0
  40. bigdl/cpp/libs/ollama-ggml-base.dll +0 -0
  41. bigdl/cpp/libs/ollama-ggml-cpu.dll +0 -0
  42. bigdl/cpp/libs/ollama-ggml-sycl.dll +0 -0
  43. bigdl/cpp/libs/ollama-lib.exe +0 -0
  44. bigdl/cpp/libs/ollama.exe +0 -0
  45. bigdl/cpp/libs/ollama_ggml.dll +0 -0
  46. bigdl/cpp/libs/ollama_llama.dll +0 -0
  47. bigdl/cpp/libs/ollama_llava_shared.dll +0 -0
  48. {bigdl_core_cpp-2.5.0rc1.data → bigdl_core_cpp-2.6.0.data}/scripts/init-llama-cpp.bat +7 -2
  49. bigdl_core_cpp-2.6.0.data/scripts/init-ollama.bat +16 -0
  50. {bigdl_core_cpp-2.5.0rc1.dist-info → bigdl_core_cpp-2.6.0.dist-info}/METADATA +9 -5
  51. bigdl_core_cpp-2.6.0.dist-info/RECORD +57 -0
  52. {bigdl_core_cpp-2.5.0rc1.dist-info → bigdl_core_cpp-2.6.0.dist-info}/WHEEL +1 -1
  53. bigdl/cpp/convert.py +0 -1714
  54. bigdl/cpp/libs/baby-llama.exe +0 -0
  55. bigdl/cpp/libs/batched-bench.exe +0 -0
  56. bigdl/cpp/libs/batched.exe +0 -0
  57. bigdl/cpp/libs/beam-search.exe +0 -0
  58. bigdl/cpp/libs/benchmark.exe +0 -0
  59. bigdl/cpp/libs/convert-llama2c-to-ggml.exe +0 -0
  60. bigdl/cpp/libs/dist/windows-amd64/ollama_runners/cpu/ollama_llama_server.exe +0 -0
  61. bigdl/cpp/libs/dist/windows-amd64/ollama_runners/cpu_avx/ollama_llama_server.exe +0 -0
  62. bigdl/cpp/libs/dist/windows-amd64/ollama_runners/cpu_avx2/ollama_llama_server.exe +0 -0
  63. bigdl/cpp/libs/embedding.exe +0 -0
  64. bigdl/cpp/libs/export-lora.exe +0 -0
  65. bigdl/cpp/libs/finetune.exe +0 -0
  66. bigdl/cpp/libs/ggml_shared.dll +0 -0
  67. bigdl/cpp/libs/gguf.exe +0 -0
  68. bigdl/cpp/libs/gritlm.exe +0 -0
  69. bigdl/cpp/libs/imatrix.exe +0 -0
  70. bigdl/cpp/libs/infill.exe +0 -0
  71. bigdl/cpp/libs/llava-cli.exe +0 -0
  72. bigdl/cpp/libs/lookahead.exe +0 -0
  73. bigdl/cpp/libs/lookup.exe +0 -0
  74. bigdl/cpp/libs/ls-sycl-device.exe +0 -0
  75. bigdl/cpp/libs/main.exe +0 -0
  76. bigdl/cpp/libs/parallel.exe +0 -0
  77. bigdl/cpp/libs/passkey.exe +0 -0
  78. bigdl/cpp/libs/perplexity.exe +0 -0
  79. bigdl/cpp/libs/q8dot.exe +0 -0
  80. bigdl/cpp/libs/quantize-stats.exe +0 -0
  81. bigdl/cpp/libs/quantize.exe +0 -0
  82. bigdl/cpp/libs/save-load-state.exe +0 -0
  83. bigdl/cpp/libs/server.exe +0 -0
  84. bigdl/cpp/libs/simple.exe +0 -0
  85. bigdl/cpp/libs/speculative.exe +0 -0
  86. bigdl/cpp/libs/tokenize.exe +0 -0
  87. bigdl/cpp/libs/train-text-from-scratch.exe +0 -0
  88. bigdl/cpp/libs/vdot.exe +0 -0
  89. bigdl_core_cpp-2.5.0rc1.data/scripts/init-ollama.bat +0 -13
  90. bigdl_core_cpp-2.5.0rc1.dist-info/RECORD +0 -63
  91. {bigdl_core_cpp-2.5.0rc1.data → bigdl_core_cpp-2.6.0.data}/scripts/init-llama-cpp.ps1 +0 -0
  92. {bigdl_core_cpp-2.5.0rc1.dist-info → bigdl_core_cpp-2.6.0.dist-info}/top_level.txt +0 -0
@@ -12,4 +12,4 @@ sys.path.insert(0, str(Path(__file__).parent.parent))
12
12
  importlib.invalidate_caches()
13
13
  import gguf # noqa: E402
14
14
 
15
- importlib.reload(gguf)
15
+ importlib.reload(gguf)
@@ -145,11 +145,10 @@ class GGUFReader:
145
145
  count = int(count)
146
146
  itemsize = int(np.empty([], dtype = dtype).itemsize)
147
147
  end_offs = offset + itemsize * count
148
- return (
149
- self.data[offset:end_offs]
150
- .view(dtype = dtype)[:count]
151
- .newbyteorder(override_order or self.byte_order)
152
- )
148
+ arr = self.data[offset:end_offs].view(dtype=dtype)[:count]
149
+ if override_order is None:
150
+ return arr
151
+ return arr.view(arr.dtype.newbyteorder(override_order))
153
152
 
154
153
  def _push_field(self, field: ReaderField, skip_sum: bool = False) -> int:
155
154
  if field.name in self.fields:
@@ -314,4 +313,4 @@ class GGUFReader:
314
313
  data = self._get(data_offs, item_type, item_count).reshape(np_dims),
315
314
  field = field,
316
315
  ))
317
- self.tensors = tensors
316
+ self.tensors = tensors
@@ -26,6 +26,7 @@ from .constants import (
26
26
  RopeScalingType,
27
27
  PoolingType,
28
28
  TokenType,
29
+ ExpertGatingFuncType,
29
30
  )
30
31
 
31
32
  from .quants import quant_shape_from_byte_shape
@@ -312,6 +313,8 @@ class GGUFWriter:
312
313
  self.add_key_value(key, val, GGUFValueType.STRING)
313
314
 
314
315
  def add_array(self, key: str, val: Sequence[Any]) -> None:
316
+ if len(val) == 0:
317
+ return
315
318
  self.add_key_value(key, val, GGUFValueType.ARRAY)
316
319
 
317
320
  @staticmethod
@@ -566,6 +569,9 @@ class GGUFWriter:
566
569
  def add_base_model_organization(self, source_id: int, organization: str) -> None:
567
570
  self.add_string(Keys.General.BASE_MODEL_ORGANIZATION.format(id=source_id), organization)
568
571
 
572
+ def add_base_model_description(self, source_id: int, description: str) -> None:
573
+ self.add_string(Keys.General.BASE_MODEL_DESCRIPTION.format(id=source_id), description)
574
+
569
575
  def add_base_model_url(self, source_id: int, url: str) -> None:
570
576
  self.add_string(Keys.General.BASE_MODEL_URL.format(id=source_id), url)
571
577
 
@@ -578,15 +584,42 @@ class GGUFWriter:
578
584
  def add_base_model_repo_url(self, source_id: int, repo_url: str) -> None:
579
585
  self.add_string(Keys.General.BASE_MODEL_REPO_URL.format(id=source_id), repo_url)
580
586
 
587
+ def add_dataset_count(self, source_count: int) -> None:
588
+ self.add_uint32(Keys.General.DATASET_COUNT, source_count)
589
+
590
+ def add_dataset_name(self, source_id: int, name: str) -> None:
591
+ self.add_string(Keys.General.DATASET_NAME.format(id=source_id), name)
592
+
593
+ def add_dataset_author(self, source_id: int, author: str) -> None:
594
+ self.add_string(Keys.General.DATASET_AUTHOR.format(id=source_id), author)
595
+
596
+ def add_dataset_version(self, source_id: int, version: str) -> None:
597
+ self.add_string(Keys.General.DATASET_VERSION.format(id=source_id), version)
598
+
599
+ def add_dataset_organization(self, source_id: int, organization: str) -> None:
600
+ self.add_string(Keys.General.DATASET_ORGANIZATION.format(id=source_id), organization)
601
+
602
+ def add_dataset_description(self, source_id: int, description: str) -> None:
603
+ self.add_string(Keys.General.DATASET_DESCRIPTION.format(id=source_id), description)
604
+
605
+ def add_dataset_url(self, source_id: int, url: str) -> None:
606
+ self.add_string(Keys.General.DATASET_URL.format(id=source_id), url)
607
+
608
+ def add_dataset_doi(self, source_id: int, doi: str) -> None:
609
+ self.add_string(Keys.General.DATASET_DOI.format(id=source_id), doi)
610
+
611
+ def add_dataset_uuid(self, source_id: int, uuid: str) -> None:
612
+ self.add_string(Keys.General.DATASET_UUID.format(id=source_id), uuid)
613
+
614
+ def add_dataset_repo_url(self, source_id: int, repo_url: str) -> None:
615
+ self.add_string(Keys.General.DATASET_REPO_URL.format(id=source_id), repo_url)
616
+
581
617
  def add_tags(self, tags: Sequence[str]) -> None:
582
618
  self.add_array(Keys.General.TAGS, tags)
583
619
 
584
620
  def add_languages(self, languages: Sequence[str]) -> None:
585
621
  self.add_array(Keys.General.LANGUAGES, languages)
586
622
 
587
- def add_datasets(self, datasets: Sequence[str]) -> None:
588
- self.add_array(Keys.General.DATASETS, datasets)
589
-
590
623
  def add_tensor_data_layout(self, layout: str) -> None:
591
624
  self.add_string(Keys.LLM.TENSOR_DATA_LAYOUT.format(arch=self.arch), layout)
592
625
 
@@ -599,6 +632,21 @@ class GGUFWriter:
599
632
  def add_embedding_length(self, length: int) -> None:
600
633
  self.add_uint32(Keys.LLM.EMBEDDING_LENGTH.format(arch=self.arch), length)
601
634
 
635
+ def add_features_length(self, length: int) -> None:
636
+ self.add_uint32(Keys.LLM.FEATURES_LENGTH.format(arch=self.arch), length)
637
+
638
+ def add_posnet_embedding_length(self, length: int) -> None:
639
+ self.add_uint32(Keys.PosNet.EMBEDDING_LENGTH.format(arch=self.arch), length)
640
+
641
+ def add_posnet_block_count(self, length: int) -> None:
642
+ self.add_uint32(Keys.PosNet.BLOCK_COUNT.format(arch=self.arch), length)
643
+
644
+ def add_convnext_embedding_length(self, length: int) -> None:
645
+ self.add_uint32(Keys.ConvNext.EMBEDDING_LENGTH.format(arch=self.arch), length)
646
+
647
+ def add_convnext_block_count(self, length: int) -> None:
648
+ self.add_uint32(Keys.ConvNext.BLOCK_COUNT.format(arch=self.arch), length)
649
+
602
650
  def add_block_count(self, length: int) -> None:
603
651
  self.add_uint32(Keys.LLM.BLOCK_COUNT.format(arch=self.arch), length)
604
652
 
@@ -668,12 +716,48 @@ class GGUFWriter:
668
716
  def add_expert_weights_scale(self, value: float) -> None:
669
717
  self.add_float32(Keys.LLM.EXPERT_WEIGHTS_SCALE.format(arch=self.arch), value)
670
718
 
719
+ def add_expert_weights_norm(self, value: bool) -> None:
720
+ self.add_bool(Keys.LLM.EXPERT_WEIGHTS_NORM.format(arch=self.arch), value)
721
+
722
+ def add_expert_gating_func(self, value: ExpertGatingFuncType) -> None:
723
+ self.add_uint32(Keys.LLM.EXPERT_GATING_FUNC.format(arch=self.arch), value.value)
724
+
725
+ def add_swin_norm(self, value: bool) -> None:
726
+ self.add_bool(Keys.LLM.SWIN_NORM.format(arch=self.arch), value)
727
+
728
+ def add_rescale_every_n_layers(self, count: int) -> None:
729
+ self.add_uint32(Keys.LLM.RESCALE_EVERY_N_LAYERS.format(arch=self.arch), count)
730
+
731
+ def add_time_mix_extra_dim(self, dim: int) -> None:
732
+ self.add_uint32(Keys.LLM.TIME_MIX_EXTRA_DIM.format(arch=self.arch), dim)
733
+
734
+ def add_time_decay_extra_dim(self, dim: int) -> None:
735
+ self.add_uint32(Keys.LLM.TIME_DECAY_EXTRA_DIM.format(arch=self.arch), dim)
736
+
737
+ def add_residual_scale(self, value: float) -> None:
738
+ self.add_float32(Keys.LLM.RESIDUAL_SCALE.format(arch=self.arch), value)
739
+
740
+ def add_embedding_scale(self, value: float) -> None:
741
+ self.add_float32(Keys.LLM.EMBEDDING_SCALE.format(arch=self.arch), value)
742
+
743
+ def add_wkv_head_size(self, size: int) -> None:
744
+ self.add_uint32(Keys.WKV.HEAD_SIZE.format(arch=self.arch), size)
745
+
746
+ def add_token_shift_count(self, count: int) -> None:
747
+ self.add_uint32(Keys.LLM.TOKEN_SHIFT_COUNT.format(arch=self.arch), count)
748
+
671
749
  def add_layer_norm_eps(self, value: float) -> None:
672
750
  self.add_float32(Keys.Attention.LAYERNORM_EPS.format(arch=self.arch), value)
673
751
 
674
752
  def add_layer_norm_rms_eps(self, value: float) -> None:
675
753
  self.add_float32(Keys.Attention.LAYERNORM_RMS_EPS.format(arch=self.arch), value)
676
754
 
755
+ def add_group_norm_eps(self, value: float) -> None:
756
+ self.add_float32(Keys.Attention.GROUPNORM_EPS.format(arch=self.arch), value)
757
+
758
+ def add_group_norm_groups(self, value: int) -> None:
759
+ self.add_uint32(Keys.Attention.GROUPNORM_GROUPS.format(arch=self.arch), value)
760
+
677
761
  def add_causal_attention(self, value: bool) -> None:
678
762
  self.add_bool(Keys.Attention.CAUSAL.format(arch=self.arch), value)
679
763
 
@@ -689,12 +773,18 @@ class GGUFWriter:
689
773
  def add_sliding_window(self, value: int) -> None:
690
774
  self.add_uint32(Keys.Attention.SLIDING_WINDOW.format(arch=self.arch), value)
691
775
 
776
+ def add_attention_scale(self, value: float) -> None:
777
+ self.add_float32(Keys.Attention.SCALE.format(arch=self.arch), value)
778
+
692
779
  def add_pooling_type(self, value: PoolingType) -> None:
693
780
  self.add_uint32(Keys.LLM.POOLING_TYPE.format(arch=self.arch), value.value)
694
781
 
695
782
  def add_rope_dimension_count(self, count: int) -> None:
696
783
  self.add_uint32(Keys.Rope.DIMENSION_COUNT.format(arch=self.arch), count)
697
784
 
785
+ def add_rope_dimension_sections(self, dims: Sequence[int]) -> None:
786
+ self.add_array(Keys.Rope.DIMENSION_SECTIONS.format(arch=self.arch), dims)
787
+
698
788
  def add_rope_freq_base(self, value: float) -> None:
699
789
  self.add_float32(Keys.Rope.FREQ_BASE.format(arch=self.arch), value)
700
790
 
@@ -728,6 +818,9 @@ class GGUFWriter:
728
818
  def add_ssm_time_step_rank(self, value: int) -> None:
729
819
  self.add_uint32(Keys.SSM.TIME_STEP_RANK.format(arch=self.arch), value)
730
820
 
821
+ def add_ssm_dt_b_c_rms(self, value: bool) -> None:
822
+ self.add_bool(Keys.SSM.DT_B_C_RMS.format(arch=self.arch), value)
823
+
731
824
  def add_tokenizer_model(self, model: str) -> None:
732
825
  self.add_string(Keys.Tokenizer.MODEL, model)
733
826
 
@@ -764,9 +857,6 @@ class GGUFWriter:
764
857
  def add_pad_token_id(self, id: int) -> None:
765
858
  self.add_uint32(Keys.Tokenizer.PAD_ID, id)
766
859
 
767
- def add_cls_token_id(self, id: int) -> None:
768
- self.add_uint32(Keys.Tokenizer.CLS_ID, id)
769
-
770
860
  def add_mask_token_id(self, id: int) -> None:
771
861
  self.add_uint32(Keys.Tokenizer.MASK_ID, id)
772
862
 
@@ -814,18 +904,12 @@ class GGUFWriter:
814
904
 
815
905
  self.add_string(Keys.Tokenizer.CHAT_TEMPLATE, value)
816
906
 
817
- def add_prefix_token_id(self, id: int) -> None:
818
- self.add_uint32(Keys.Tokenizer.PREFIX_ID, id)
819
-
820
- def add_suffix_token_id(self, id: int) -> None:
821
- self.add_uint32(Keys.Tokenizer.SUFFIX_ID, id)
822
-
823
- def add_middle_token_id(self, id: int) -> None:
824
- self.add_uint32(Keys.Tokenizer.MIDDLE_ID, id)
825
-
826
907
  def add_eot_token_id(self, id: int) -> None:
827
908
  self.add_uint32(Keys.Tokenizer.EOT_ID, id)
828
909
 
910
+ def add_eom_token_id(self, id: int) -> None:
911
+ self.add_uint32(Keys.Tokenizer.EOM_ID, id)
912
+
829
913
  def _pack(self, fmt: str, value: Any, skip_pack_prefix: bool = False) -> bytes:
830
914
  pack_prefix = ''
831
915
  if not skip_pack_prefix:
@@ -845,7 +929,14 @@ class GGUFWriter:
845
929
  encoded_val = val.encode("utf-8") if isinstance(val, str) else val
846
930
  kv_data += self._pack("Q", len(encoded_val))
847
931
  kv_data += encoded_val
848
- elif vtype == GGUFValueType.ARRAY and isinstance(val, Sequence) and val:
932
+ elif vtype == GGUFValueType.ARRAY:
933
+
934
+ if not isinstance(val, Sequence):
935
+ raise ValueError("Invalid GGUF metadata array, expecting sequence")
936
+
937
+ if len(val) == 0:
938
+ raise ValueError("Invalid GGUF metadata array. Empty array")
939
+
849
940
  if isinstance(val, bytes):
850
941
  ltype = GGUFValueType.UINT8
851
942
  else:
@@ -870,4 +961,4 @@ class GGUFWriter:
870
961
  if abs(fnum) < 1000.0:
871
962
  return f"{fnum:3.1f}{unit}"
872
963
  fnum /= 1000.0
873
- return f"{fnum:.1f}T - over 1TB, split recommended"
964
+ return f"{fnum:.1f}T - over 1TB, split recommended"
@@ -191,6 +191,8 @@ class LazyBase(ABC, metaclass=LazyMeta):
191
191
  class LazyNumpyTensor(LazyBase):
192
192
  _tensor_type = np.ndarray
193
193
 
194
+ shape: tuple[int, ...] # Makes the type checker happy in quants.py
195
+
194
196
  @classmethod
195
197
  def meta_with_dtype_and_shape(cls, dtype: DTypeLike, shape: tuple[int, ...]) -> np.ndarray[Any, Any]:
196
198
  # The initial idea was to use np.nan as the fill value,
@@ -208,4 +210,4 @@ class LazyNumpyTensor(LazyBase):
208
210
  eager = LazyNumpyTensor.to_eager(self)
209
211
  return eager.tofile(*args, **kwargs)
210
212
 
211
- # TODO: __array_function__
213
+ # TODO: __array_function__
@@ -41,7 +41,7 @@ class Metadata:
41
41
  base_models: Optional[list[dict]] = None
42
42
  tags: Optional[list[str]] = None
43
43
  languages: Optional[list[str]] = None
44
- datasets: Optional[list[str]] = None
44
+ datasets: Optional[list[dict]] = None
45
45
 
46
46
  @staticmethod
47
47
  def load(metadata_override_path: Optional[Path] = None, model_path: Optional[Path] = None, model_name: Optional[str] = None, total_params: int = 0) -> Metadata:
@@ -91,9 +91,11 @@ class Metadata:
91
91
  # Base Models is received here as an array of models
92
92
  metadata.base_models = metadata_override.get("general.base_models", metadata.base_models)
93
93
 
94
+ # Datasets is received here as an array of datasets
95
+ metadata.datasets = metadata_override.get("general.datasets", metadata.datasets)
96
+
94
97
  metadata.tags = metadata_override.get(Keys.General.TAGS, metadata.tags)
95
98
  metadata.languages = metadata_override.get(Keys.General.LANGUAGES, metadata.languages)
96
- metadata.datasets = metadata_override.get(Keys.General.DATASETS, metadata.datasets)
97
99
 
98
100
  # Direct Metadata Override (via direct cli argument)
99
101
  if model_name is not None:
@@ -174,7 +176,7 @@ class Metadata:
174
176
  org_component, model_full_name_component = None, model_id
175
177
 
176
178
  # Check if we erroneously matched against './' or '../' etc...
177
- if org_component is not None and org_component[0] == '.':
179
+ if org_component is not None and len(org_component) > 0 and org_component[0] == '.':
178
180
  org_component = None
179
181
 
180
182
  name_parts: list[str] = model_full_name_component.split('-')
@@ -284,27 +286,74 @@ class Metadata:
284
286
  ########################
285
287
  if model_card is not None:
286
288
 
287
- if "model_name" in model_card and metadata.name is None:
288
- # Not part of huggingface model card standard but notice some model creator using it
289
- # such as TheBloke in 'TheBloke/Mistral-7B-Instruct-v0.2-GGUF'
290
- metadata.name = model_card.get("model_name")
289
+ def use_model_card_metadata(metadata_key: str, model_card_key: str):
290
+ if model_card_key in model_card and getattr(metadata, metadata_key, None) is None:
291
+ setattr(metadata, metadata_key, model_card.get(model_card_key))
291
292
 
292
- if "model_creator" in model_card and metadata.author is None:
293
- # Not part of huggingface model card standard but notice some model creator using it
294
- # such as TheBloke in 'TheBloke/Mistral-7B-Instruct-v0.2-GGUF'
295
- metadata.author = model_card.get("model_creator")
293
+ def use_array_model_card_metadata(metadata_key: str, model_card_key: str):
294
+ # Note: Will append rather than replace if already exist
295
+ tags_value = model_card.get(model_card_key, None)
296
+ if tags_value is None:
297
+ return
296
298
 
297
- if "model_type" in model_card and metadata.basename is None:
298
- # Not part of huggingface model card standard but notice some model creator using it
299
- # such as TheBloke in 'TheBloke/Mistral-7B-Instruct-v0.2-GGUF'
300
- metadata.basename = model_card.get("model_type")
299
+ current_value = getattr(metadata, metadata_key, None)
300
+ if current_value is None:
301
+ current_value = []
301
302
 
302
- if "base_model" in model_card:
303
+ if isinstance(tags_value, str):
304
+ current_value.append(tags_value)
305
+ elif isinstance(tags_value, list):
306
+ current_value.extend(tags_value)
307
+
308
+ setattr(metadata, metadata_key, current_value)
309
+
310
+ # LLAMA.cpp's direct internal convention
311
+ # (Definitely not part of hugging face formal/informal standard)
312
+ #########################################
313
+ use_model_card_metadata("name", "name")
314
+ use_model_card_metadata("author", "author")
315
+ use_model_card_metadata("version", "version")
316
+ use_model_card_metadata("organization", "organization")
317
+ use_model_card_metadata("description", "description")
318
+ use_model_card_metadata("finetune", "finetune")
319
+ use_model_card_metadata("basename", "basename")
320
+ use_model_card_metadata("size_label", "size_label")
321
+ use_model_card_metadata("source_url", "url")
322
+ use_model_card_metadata("source_doi", "doi")
323
+ use_model_card_metadata("source_uuid", "uuid")
324
+ use_model_card_metadata("source_repo_url", "repo_url")
325
+
326
+ # LLAMA.cpp's huggingface style convention
327
+ # (Definitely not part of hugging face formal/informal standard... but with model_ appended to match their style)
328
+ ###########################################
329
+ use_model_card_metadata("name", "model_name")
330
+ use_model_card_metadata("author", "model_author")
331
+ use_model_card_metadata("version", "model_version")
332
+ use_model_card_metadata("organization", "model_organization")
333
+ use_model_card_metadata("description", "model_description")
334
+ use_model_card_metadata("finetune", "model_finetune")
335
+ use_model_card_metadata("basename", "model_basename")
336
+ use_model_card_metadata("size_label", "model_size_label")
337
+ use_model_card_metadata("source_url", "model_url")
338
+ use_model_card_metadata("source_doi", "model_doi")
339
+ use_model_card_metadata("source_uuid", "model_uuid")
340
+ use_model_card_metadata("source_repo_url", "model_repo_url")
341
+
342
+ # Hugging Face Direct Convention
343
+ #################################
344
+
345
+ # Not part of huggingface model card standard but notice some model creator using it
346
+ # such as TheBloke in 'TheBloke/Mistral-7B-Instruct-v0.2-GGUF'
347
+ use_model_card_metadata("name", "model_name")
348
+ use_model_card_metadata("author", "model_creator")
349
+ use_model_card_metadata("basename", "model_type")
350
+
351
+ if "base_model" in model_card or "base_models" in model_card or "base_model_sources" in model_card:
303
352
  # This represents the parent models that this is based on
304
353
  # Example: stabilityai/stable-diffusion-xl-base-1.0. Can also be a list (for merges)
305
354
  # Example of merges: https://huggingface.co/EmbeddedLLM/Mistral-7B-Merge-14-v0.1/blob/main/README.md
306
355
  metadata_base_models = []
307
- base_model_value = model_card.get("base_model", None)
356
+ base_model_value = model_card.get("base_model", model_card.get("base_models", model_card.get("base_model_sources", None)))
308
357
 
309
358
  if base_model_value is not None:
310
359
  if isinstance(base_model_value, str):
@@ -317,70 +366,115 @@ class Metadata:
317
366
 
318
367
  for model_id in metadata_base_models:
319
368
  # NOTE: model size of base model is assumed to be similar to the size of the current model
320
- model_full_name_component, org_component, basename, finetune, version, size_label = Metadata.get_model_id_components(model_id, total_params)
321
369
  base_model = {}
322
- if model_full_name_component is not None:
323
- base_model["name"] = Metadata.id_to_title(model_full_name_component)
324
- if org_component is not None:
325
- base_model["organization"] = Metadata.id_to_title(org_component)
326
- if version is not None:
327
- base_model["version"] = version
328
- if org_component is not None and model_full_name_component is not None:
329
- base_model["repo_url"] = f"https://huggingface.co/{org_component}/{model_full_name_component}"
330
- metadata.base_models.append(base_model)
331
-
332
- if "license" in model_card and metadata.license is None:
333
- metadata.license = model_card.get("license")
334
-
335
- if "license_name" in model_card and metadata.license_name is None:
336
- metadata.license_name = model_card.get("license_name")
337
-
338
- if "license_link" in model_card and metadata.license_link is None:
339
- metadata.license_link = model_card.get("license_link")
340
-
341
- tags_value = model_card.get("tags", None)
342
- if tags_value is not None:
343
-
344
- if metadata.tags is None:
345
- metadata.tags = []
346
-
347
- if isinstance(tags_value, str):
348
- metadata.tags.append(tags_value)
349
- elif isinstance(tags_value, list):
350
- metadata.tags.extend(tags_value)
351
-
352
- pipeline_tags_value = model_card.get("pipeline_tag", None)
353
- if pipeline_tags_value is not None:
354
-
355
- if metadata.tags is None:
356
- metadata.tags = []
370
+ if isinstance(model_id, str):
371
+ if model_id.startswith("http://") or model_id.startswith("https://") or model_id.startswith("ssh://"):
372
+ base_model["repo_url"] = model_id
373
+
374
+ # Check if Hugging Face ID is present in URL
375
+ if "huggingface.co" in model_id:
376
+ match = re.match(r"https?://huggingface.co/([^/]+/[^/]+)$", model_id)
377
+ if match:
378
+ model_id_component = match.group(1)
379
+ model_full_name_component, org_component, basename, finetune, version, size_label = Metadata.get_model_id_components(model_id_component, total_params)
380
+
381
+ # Populate model dictionary with extracted components
382
+ if model_full_name_component is not None:
383
+ base_model["name"] = Metadata.id_to_title(model_full_name_component)
384
+ if org_component is not None:
385
+ base_model["organization"] = Metadata.id_to_title(org_component)
386
+ if version is not None:
387
+ base_model["version"] = version
388
+
389
+ else:
390
+ # Likely a Hugging Face ID
391
+ model_full_name_component, org_component, basename, finetune, version, size_label = Metadata.get_model_id_components(model_id, total_params)
392
+
393
+ # Populate model dictionary with extracted components
394
+ if model_full_name_component is not None:
395
+ base_model["name"] = Metadata.id_to_title(model_full_name_component)
396
+ if org_component is not None:
397
+ base_model["organization"] = Metadata.id_to_title(org_component)
398
+ if version is not None:
399
+ base_model["version"] = version
400
+ if org_component is not None and model_full_name_component is not None:
401
+ base_model["repo_url"] = f"https://huggingface.co/{org_component}/{model_full_name_component}"
402
+
403
+ elif isinstance(model_id, dict):
404
+ base_model = model_id
405
+
406
+ else:
407
+ logger.error(f"base model entry '{str(model_id)}' not in a known format")
357
408
 
358
- if isinstance(pipeline_tags_value, str):
359
- metadata.tags.append(pipeline_tags_value)
360
- elif isinstance(pipeline_tags_value, list):
361
- metadata.tags.extend(pipeline_tags_value)
362
-
363
- language_value = model_card.get("languages", model_card.get("language", None))
364
- if language_value is not None:
365
-
366
- if metadata.languages is None:
367
- metadata.languages = []
409
+ metadata.base_models.append(base_model)
368
410
 
369
- if isinstance(language_value, str):
370
- metadata.languages.append(language_value)
371
- elif isinstance(language_value, list):
372
- metadata.languages.extend(language_value)
411
+ if "datasets" in model_card or "dataset" in model_card or "dataset_sources" in model_card:
412
+ # This represents the datasets that this was trained from
413
+ metadata_datasets = []
414
+ dataset_value = model_card.get("datasets", model_card.get("dataset", model_card.get("dataset_sources", None)))
373
415
 
374
- dataset_value = model_card.get("datasets", model_card.get("dataset", None))
375
- if dataset_value is not None:
416
+ if dataset_value is not None:
417
+ if isinstance(dataset_value, str):
418
+ metadata_datasets.append(dataset_value)
419
+ elif isinstance(dataset_value, list):
420
+ metadata_datasets.extend(dataset_value)
376
421
 
377
422
  if metadata.datasets is None:
378
423
  metadata.datasets = []
379
424
 
380
- if isinstance(dataset_value, str):
381
- metadata.datasets.append(dataset_value)
382
- elif isinstance(dataset_value, list):
383
- metadata.datasets.extend(dataset_value)
425
+ for dataset_id in metadata_datasets:
426
+ # NOTE: model size of base model is assumed to be similar to the size of the current model
427
+ dataset = {}
428
+ if isinstance(dataset_id, str):
429
+ if dataset_id.startswith(("http://", "https://", "ssh://")):
430
+ dataset["repo_url"] = dataset_id
431
+
432
+ # Check if Hugging Face ID is present in URL
433
+ if "huggingface.co" in dataset_id:
434
+ match = re.match(r"https?://huggingface.co/([^/]+/[^/]+)$", dataset_id)
435
+ if match:
436
+ dataset_id_component = match.group(1)
437
+ dataset_name_component, org_component, basename, finetune, version, size_label = Metadata.get_model_id_components(dataset_id_component, total_params)
438
+
439
+ # Populate dataset dictionary with extracted components
440
+ if dataset_name_component is not None:
441
+ dataset["name"] = Metadata.id_to_title(dataset_name_component)
442
+ if org_component is not None:
443
+ dataset["organization"] = Metadata.id_to_title(org_component)
444
+ if version is not None:
445
+ dataset["version"] = version
446
+
447
+ else:
448
+ # Likely a Hugging Face ID
449
+ dataset_name_component, org_component, basename, finetune, version, size_label = Metadata.get_model_id_components(dataset_id, total_params)
450
+
451
+ # Populate dataset dictionary with extracted components
452
+ if dataset_name_component is not None:
453
+ dataset["name"] = Metadata.id_to_title(dataset_name_component)
454
+ if org_component is not None:
455
+ dataset["organization"] = Metadata.id_to_title(org_component)
456
+ if version is not None:
457
+ dataset["version"] = version
458
+ if org_component is not None and dataset_name_component is not None:
459
+ dataset["repo_url"] = f"https://huggingface.co/{org_component}/{dataset_name_component}"
460
+
461
+ elif isinstance(dataset_id, dict):
462
+ dataset = dataset_id
463
+
464
+ else:
465
+ logger.error(f"dataset entry '{str(dataset_id)}' not in a known format")
466
+
467
+ metadata.datasets.append(dataset)
468
+
469
+ use_model_card_metadata("license", "license")
470
+ use_model_card_metadata("license_name", "license_name")
471
+ use_model_card_metadata("license_link", "license_link")
472
+
473
+ use_array_model_card_metadata("tags", "tags")
474
+ use_array_model_card_metadata("tags", "pipeline_tag")
475
+
476
+ use_array_model_card_metadata("languages", "languages")
477
+ use_array_model_card_metadata("languages", "language")
384
478
 
385
479
  # Hugging Face Parameter Heuristics
386
480
  ####################################
@@ -451,7 +545,10 @@ class Metadata:
451
545
  gguf_writer.add_size_label(self.size_label)
452
546
 
453
547
  if self.license is not None:
454
- gguf_writer.add_license(self.license)
548
+ if isinstance(self.license, list):
549
+ gguf_writer.add_license(",".join(self.license))
550
+ else:
551
+ gguf_writer.add_license(self.license)
455
552
  if self.license_name is not None:
456
553
  gguf_writer.add_license_name(self.license_name)
457
554
  if self.license_link is not None:
@@ -486,6 +583,8 @@ class Metadata:
486
583
  gguf_writer.add_base_model_version(key, base_model_entry["version"])
487
584
  if "organization" in base_model_entry:
488
585
  gguf_writer.add_base_model_organization(key, base_model_entry["organization"])
586
+ if "description" in base_model_entry:
587
+ gguf_writer.add_base_model_description(key, base_model_entry["description"])
489
588
  if "url" in base_model_entry:
490
589
  gguf_writer.add_base_model_url(key, base_model_entry["url"])
491
590
  if "doi" in base_model_entry:
@@ -495,9 +594,29 @@ class Metadata:
495
594
  if "repo_url" in base_model_entry:
496
595
  gguf_writer.add_base_model_repo_url(key, base_model_entry["repo_url"])
497
596
 
597
+ if self.datasets is not None:
598
+ gguf_writer.add_dataset_count(len(self.datasets))
599
+ for key, dataset_entry in enumerate(self.datasets):
600
+ if "name" in dataset_entry:
601
+ gguf_writer.add_dataset_name(key, dataset_entry["name"])
602
+ if "author" in dataset_entry:
603
+ gguf_writer.add_dataset_author(key, dataset_entry["author"])
604
+ if "version" in dataset_entry:
605
+ gguf_writer.add_dataset_version(key, dataset_entry["version"])
606
+ if "organization" in dataset_entry:
607
+ gguf_writer.add_dataset_organization(key, dataset_entry["organization"])
608
+ if "description" in dataset_entry:
609
+ gguf_writer.add_dataset_description(key, dataset_entry["description"])
610
+ if "url" in dataset_entry:
611
+ gguf_writer.add_dataset_url(key, dataset_entry["url"])
612
+ if "doi" in dataset_entry:
613
+ gguf_writer.add_dataset_doi(key, dataset_entry["doi"])
614
+ if "uuid" in dataset_entry:
615
+ gguf_writer.add_dataset_uuid(key, dataset_entry["uuid"])
616
+ if "repo_url" in dataset_entry:
617
+ gguf_writer.add_dataset_repo_url(key, dataset_entry["repo_url"])
618
+
498
619
  if self.tags is not None:
499
620
  gguf_writer.add_tags(self.tags)
500
621
  if self.languages is not None:
501
622
  gguf_writer.add_languages(self.languages)
502
- if self.datasets is not None:
503
- gguf_writer.add_datasets(self.datasets)