From a42c2b7efc720d4d36a258d7430b33c82ec3bfd0 Mon Sep 17 00:00:00 2001 From: brian khuu Date: Fri, 31 May 2024 03:14:11 +1000 Subject: [PATCH] convert-*.py: add basename and finetune metadata --- convert_hf_to_gguf.py | 10 +++++++++- examples/convert_legacy_llama.py | 12 +++++++++++- gguf-py/gguf/constants.py | 2 ++ gguf-py/gguf/gguf_writer.py | 6 ++++++ gguf-py/gguf/utility.py | 29 ++++++++++++++++++++++------- 5 files changed, 50 insertions(+), 9 deletions(-) diff --git a/convert_hf_to_gguf.py b/convert_hf_to_gguf.py index 7ecedfcde..a79898350 100755 --- a/convert_hf_to_gguf.py +++ b/convert_hf_to_gguf.py @@ -33,6 +33,8 @@ logger = logging.getLogger("hf-to-gguf") @dataclass class Metadata: name: Optional[str] = None + basename: Optional[str] = None + finetune: Optional[str] = None author: Optional[str] = None version: Optional[str] = None url: Optional[str] = None @@ -55,6 +57,8 @@ class Metadata: # Assigning values to Metadata attributes if they exist in the JSON file # This is based on LLM_KV_NAMES mapping in llama.cpp metadata.name = data.get("general.name") + metadata.basename = data.get("general.basename") + metadata.finetune = data.get("general.finetune") metadata.author = data.get("general.author") metadata.version = data.get("general.version") metadata.url = data.get("general.url") @@ -201,7 +205,7 @@ class Model: weight_estimate = per_model_weight_count_estimation(model_tensors, expert_count) # Generate default filename based on model specification and available metadata - self.fname_default = gguf.naming_convention(self.model_name, self.metadata.version, expert_count, weight_estimate, encodingScheme) + self.fname_default = gguf.naming_convention(self.model_name, self.metadata.basename, self.metadata.finetune, self.metadata.version, expert_count, weight_estimate, encodingScheme) # Filename Output if fname_out is not None: @@ -311,6 +315,10 @@ class Model: self.gguf_writer.add_name(self.model_name) if self.metadata is not None: + if self.metadata.basename is not None: + self.gguf_writer.add_basename(self.metadata.basename) + if self.metadata.finetune is not None: + self.gguf_writer.add_finetune(self.metadata.finetune) if self.metadata.author is not None: self.gguf_writer.add_author(self.metadata.author) if self.metadata.version is not None: diff --git a/examples/convert_legacy_llama.py b/examples/convert_legacy_llama.py index eee8f1fee..874f8f8e6 100755 --- a/examples/convert_legacy_llama.py +++ b/examples/convert_legacy_llama.py @@ -349,6 +349,8 @@ class Params: @dataclass class Metadata: name: Optional[str] = None + basename: Optional[str] = None + finetune: Optional[str] = None author: Optional[str] = None version: Optional[str] = None url: Optional[str] = None @@ -371,6 +373,8 @@ class Metadata: # Assigning values to Metadata attributes if they exist in the JSON file # This is based on LLM_KV_NAMES mapping in llama.cpp metadata.name = data.get("general.name") + metadata.basename = data.get("general.basename") + metadata.finetune = data.get("general.finetune") metadata.author = data.get("general.author") metadata.version = data.get("general.version") metadata.url = data.get("general.url") @@ -820,6 +824,10 @@ class OutputFile: self.gguf.add_name(name) if metadata is not None: + if metadata.basename is not None: + self.gguf.add_basename(metadata.basename) + if metadata.finetune is not None: + self.gguf.add_finetune(metadata.finetune) if metadata.author is not None: self.gguf.add_author(metadata.author) if metadata.version is not None: @@ -1226,6 +1234,8 @@ class VocabFactory: def default_convention_outfile(file_type: GGMLFileType, model_name:str, expert_count:int, model_params_count: int, metadata: Metadata) -> str: name = metadata.name if metadata is not None and metadata.name is not None else model_name + basename = metadata.basename if metadata is not None and metadata.basename is not None else None + finetune = metadata.finetune if metadata is not None and metadata.finetune is not None else None version = metadata.version if metadata is not None and metadata.version is not None else None encodingScheme = { @@ -1234,7 +1244,7 @@ def default_convention_outfile(file_type: GGMLFileType, model_name:str, expert_c GGMLFileType.MostlyQ8_0: "Q8_0", }[file_type] - return gguf.naming_convention(name, version, expert_count, model_params_count, encodingScheme) + return gguf.naming_convention(name, basename, finetune, version, expert_count, model_params_count, encodingScheme) def default_outfile(model_paths: list[Path], file_type: GGMLFileType, model_name:str, expert_count:int, model_params_count: int, metadata: Metadata) -> Path: diff --git a/gguf-py/gguf/constants.py b/gguf-py/gguf/constants.py index 5eb3df706..69360a4fb 100644 --- a/gguf-py/gguf/constants.py +++ b/gguf-py/gguf/constants.py @@ -24,6 +24,8 @@ class Keys: QUANTIZATION_VERSION = "general.quantization_version" ALIGNMENT = "general.alignment" NAME = "general.name" + BASENAME = "general.basename" + FINETUNE = "general.finetune" AUTHOR = "general.author" VERSION = "general.version" URL = "general.url" diff --git a/gguf-py/gguf/gguf_writer.py b/gguf-py/gguf/gguf_writer.py index 3b94af25e..a02882f8f 100644 --- a/gguf-py/gguf/gguf_writer.py +++ b/gguf-py/gguf/gguf_writer.py @@ -430,6 +430,12 @@ class GGUFWriter: def add_architecture(self) -> None: self.add_string(Keys.General.ARCHITECTURE, self.arch) + def add_basename(self, basename: str) -> None: + self.add_string(Keys.General.BASENAME, basename) + + def add_finetune(self, finetune: str) -> None: + self.add_string(Keys.General.FINETUNE, finetune) + def add_author(self, author: str) -> None: self.add_string(Keys.General.AUTHOR, author) diff --git a/gguf-py/gguf/utility.py b/gguf-py/gguf/utility.py index e375b687d..dd08a36d2 100644 --- a/gguf-py/gguf/utility.py +++ b/gguf-py/gguf/utility.py @@ -25,11 +25,26 @@ def model_weight_count_rounded_notation(model_params_count: int) -> str: return f"{round(scaled_model_params)}{scale_suffix}" -def naming_convention(model_name: str, version_string:str, expert_count_int:int, model_params_count: int, encodingScheme: str) -> str: +def naming_convention(model_name: str, base_name: str, finetune_string:str, version_string:str, expert_count_int:int, model_params_count: int, encoding_scheme: str) -> str: # Reference: https://github.com/ggerganov/ggml/blob/master/docs/gguf.md#gguf-naming-convention - name = model_name.strip().replace(' ', '-') if model_name is not None else "ggml-model" - version = f"-{version_string}" if version_string is not None else "" - expert_count_chunk = f"{expert_count_int}x" if expert_count_int is not None and expert_count_int > 0 else "" - parameters = model_weight_count_rounded_notation(model_params_count) - encodingScheme = encodingScheme.upper() - return f"{name}{version}-{expert_count_chunk}{parameters}-{encodingScheme}" + + if base_name is not None: + name = base_name.strip().title().replace(' ', '_') + elif model_name is not None: + name = model_name.strip().title().replace(' ', '_') + else: + name = "ggml-model" + + per_model_rounded_weight_estimate = model_weight_count_rounded_notation(model_params_count) + if expert_count_int is not None and expert_count_int > 0: + parameters = f"-{expert_count_int}x{per_model_rounded_weight_estimate}" + else: + parameters = f"-{per_model_rounded_weight_estimate}" + + finetune = f"-{finetune_string.strip().title().replace(' ', '_')}" if finetune_string is not None else "" + + version = f"-{version_string.strip().replace(' ', '_')}" if version_string is not None else "" + + encoding = f"-{encoding_scheme.strip().replace(' ', '_').upper()}" + + return f"{name}{parameters}{finetune}{version}{encoding}"