Skip to content

Commit 8c9b3cb

Browse files
committed
add additional metadata support while porting
1 parent 5133cc2 commit 8c9b3cb

File tree

4 files changed

+92
-9
lines changed

4 files changed

+92
-9
lines changed

convert.py

Lines changed: 84 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,39 @@ def load(model_plus: ModelPlus) -> "Params":
380380
return params
381381

382382

383+
@dataclass
384+
class Metadata:
385+
name: Optional[str] = None
386+
author: Optional[str] = None
387+
version: Optional[str] = None
388+
url: Optional[str] = None
389+
description: Optional[str] = None
390+
licence: Optional[str] = None
391+
source_url: Optional[str] = None
392+
source_hf_repo: Optional[str] = None
393+
394+
@staticmethod
395+
def load(metadata_path: Path) -> "Metadata":
396+
if metadata_path is None or not metadata_path.exists():
397+
return Metadata()
398+
399+
with open(metadata_path, 'r') as file:
400+
data = json.load(file)
401+
402+
# Create a new Metadata instance
403+
metadata = Metadata()
404+
405+
# Assigning values to Metadata attributes if they exist in the JSON file
406+
metadata.name = data.get("general.name")
407+
metadata.author = data.get("general.author")
408+
metadata.version = data.get("general.version")
409+
metadata.url = data.get("general.url")
410+
metadata.description = data.get("general.description")
411+
metadata.license = data.get("general.license")
412+
413+
return metadata
414+
415+
383416
class BpeVocab: # GPT
384417
def __init__(
385418
self, fname_tokenizer: Path, fname_added_tokens: Optional[Path]
@@ -1026,16 +1059,37 @@ def __init__(
10261059
fname_out, gguf.MODEL_ARCH_NAMES[ARCH], endianess=endianess
10271060
)
10281061

1029-
def add_meta_arch(self, params: Params) -> None:
1062+
def add_meta_model(self, params: Params, metadata: Metadata) -> None:
1063+
# Metadata About The Model And It's Provenence
10301064
name = "LLaMA"
1031-
1032-
# TODO: better logic to determine model name
1033-
if params.n_ctx == 4096:
1034-
name = "LLaMA v2"
1065+
if metadata is not None and metadata.name is not None:
1066+
name = metadata.name
10351067
elif params.path_model is not None:
10361068
name = str(params.path_model.parent).split("/")[-1]
1069+
elif params.n_ctx == 4096:
1070+
# Heuristic detection of LLaMA v2 model
1071+
name = "LLaMA v2"
10371072

10381073
self.gguf.add_name(name)
1074+
1075+
if metadata is not None:
1076+
if metadata.author is not None:
1077+
self.gguf.add_author(metadata.author)
1078+
if metadata.version is not None:
1079+
self.gguf.add_version(metadata.version)
1080+
if metadata.url is not None:
1081+
self.gguf.add_url(metadata.url)
1082+
if metadata.description is not None:
1083+
self.gguf.add_description(metadata.description)
1084+
if metadata.licence is not None:
1085+
self.gguf.add_licence(metadata.licence)
1086+
if metadata.source_url is not None:
1087+
self.gguf.add_source_url(metadata.source_url)
1088+
if metadata.source_hf_repo is not None:
1089+
self.gguf.add_source_hf_repo(metadata.source_hf_repo)
1090+
1091+
def add_meta_arch(self, params: Params) -> None:
1092+
# Metadata About The Neural Architecture Itself
10391093
self.gguf.add_context_length(params.n_ctx)
10401094
self.gguf.add_embedding_length(params.n_embd)
10411095
self.gguf.add_block_count(params.n_layer)
@@ -1146,12 +1200,14 @@ def write_vocab_only(
11461200
svocab: gguf.SpecialVocab,
11471201
endianess: gguf.GGUFEndian = gguf.GGUFEndian.LITTLE,
11481202
pad_vocab: bool = False,
1203+
metadata: Metadata = None,
11491204
) -> None:
11501205
check_vocab_size(params, vocab, pad_vocab=pad_vocab)
11511206

11521207
of = OutputFile(fname_out, endianess=endianess)
11531208

11541209
# meta data
1210+
of.add_meta_model(params, metadata)
11551211
of.add_meta_arch(params)
11561212
of.add_meta_vocab(vocab)
11571213
of.add_meta_special_vocab(svocab)
@@ -1184,12 +1240,14 @@ def write_all(
11841240
concurrency: int = DEFAULT_CONCURRENCY,
11851241
endianess: gguf.GGUFEndian = gguf.GGUFEndian.LITTLE,
11861242
pad_vocab: bool = False,
1243+
metadata: Metadata = None,
11871244
) -> None:
11881245
check_vocab_size(params, vocab, pad_vocab=pad_vocab)
11891246

11901247
of = OutputFile(fname_out, endianess=endianess)
11911248

11921249
# meta data
1250+
of.add_meta_model(params, metadata)
11931251
of.add_meta_arch(params)
11941252
of.add_meta_vocab(vocab)
11951253
of.add_meta_special_vocab(svocab)
@@ -1463,7 +1521,7 @@ def load_vocab(
14631521
return vocab, special_vocab
14641522

14651523

1466-
def default_outfile(model_paths: list[Path], file_type: GGMLFileType, params: Params, model_params_count: int) -> Path:
1524+
def default_outfile(model_paths: list[Path], file_type: GGMLFileType, params: Params, model_params_count: int, metadata: Metadata) -> Path:
14671525
quantization = {
14681526
GGMLFileType.AllF32: "f32",
14691527
GGMLFileType.MostlyF16: "f16",
@@ -1472,11 +1530,17 @@ def default_outfile(model_paths: list[Path], file_type: GGMLFileType, params: Pa
14721530

14731531
parameters = model_parameter_count_rounded_notation(model_params_count)
14741532

1533+
version = ""
1534+
if metadata is not None and metadata.version is not None:
1535+
version = f"-{metadata.version}"
1536+
14751537
name = "ggml-model"
1476-
if params.path_model is not None:
1538+
if metadata is not None and metadata.name is not None:
1539+
name = metadata.name
1540+
elif params.path_model is not None:
14771541
name = params.path_model.name
14781542

1479-
ret = model_paths[0].parent / f"{name}-{parameters}-{quantization}.gguf"
1543+
ret = model_paths[0].parent / f"{name}{version}-{parameters}-{quantization}.gguf"
14801544
if ret in model_paths:
14811545
sys.stderr.write(
14821546
f"Error: Default output path ({ret}) would overwrite the input. "
@@ -1585,13 +1649,22 @@ def get_argument_parser() -> ArgumentParser:
15851649
help="Indicate that the model is executed on a big-endian machine",
15861650
)
15871651

1652+
# https://github.com/ggerganov/ggml/blob/master/docs/gguf.md#general-metadata
1653+
parser.add_argument(
1654+
"--metadata",
1655+
type=Path,
1656+
help="Specify the path for a metadata file",
1657+
)
1658+
15881659
return parser
15891660

15901661

15911662
def main(argv: Optional[list[str]] = None) -> None:
15921663
parser = get_argument_parser()
15931664
args = parser.parse_args(argv)
15941665

1666+
metadata = Metadata.load(args.metadata)
1667+
15951668
if args.awq_path:
15961669
sys.path.insert(1, str(Path(__file__).resolve().parent / "awq-py"))
15971670
from awq.apply_awq import add_scale_weights
@@ -1665,6 +1738,7 @@ def main(argv: Optional[list[str]] = None) -> None:
16651738
special_vocab,
16661739
endianess=endianess,
16671740
pad_vocab=args.pad_vocab,
1741+
metadata=metadata,
16681742
)
16691743
print(f"Wrote {outfile}")
16701744
return
@@ -1683,7 +1757,7 @@ def main(argv: Optional[list[str]] = None) -> None:
16831757
model = convert_model_names(model, params)
16841758
ftype = pick_output_type(model, args.outtype)
16851759
model = convert_to_output_type(model, ftype)
1686-
outfile = args.outfile or default_outfile(model_plus.paths, ftype, params, model_params_count)
1760+
outfile = args.outfile or default_outfile(model_plus.paths, ftype, params, model_params_count, metadata)
16871761

16881762
params.ftype = ftype
16891763
print(f"Writing {outfile}, format {ftype}")
@@ -1698,6 +1772,7 @@ def main(argv: Optional[list[str]] = None) -> None:
16981772
concurrency=args.concurrency,
16991773
endianess=endianess,
17001774
pad_vocab=args.pad_vocab,
1775+
metadata=metadata,
17011776
)
17021777
print(f"Wrote {outfile}")
17031778

gguf-py/gguf/constants.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class General:
2424
ALIGNMENT = "general.alignment"
2525
NAME = "general.name"
2626
AUTHOR = "general.author"
27+
VERSION = "general.version"
2728
URL = "general.url"
2829
DESCRIPTION = "general.description"
2930
LICENSE = "general.license"

gguf-py/gguf/gguf_writer.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,9 @@ def add_architecture(self) -> None:
283283
def add_author(self, author: str) -> None:
284284
self.add_string(Keys.General.AUTHOR, author)
285285

286+
def add_version(self, version: str) -> None:
287+
self.add_string(Keys.General.VERSION, version)
288+
286289
def add_tensor_data_layout(self, layout: str) -> None:
287290
self.add_string(Keys.LLM.TENSOR_DATA_LAYOUT.format(arch=self.arch), layout)
288291

@@ -292,6 +295,9 @@ def add_url(self, url: str) -> None:
292295
def add_description(self, description: str) -> None:
293296
self.add_string(Keys.General.DESCRIPTION, description)
294297

298+
def add_licence(self, licence: str) -> None:
299+
self.add_string(Keys.General.LICENSE, licence)
300+
295301
def add_source_url(self, url: str) -> None:
296302
self.add_string(Keys.General.SOURCE_URL, url)
297303

requirements/requirements-convert.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ sentencepiece~=0.1.98
33
transformers>=4.35.2,<5.0.0
44
gguf>=0.1.0
55
protobuf>=4.21.0,<5.0.0
6+
python-frontmatter>=1.0.1

0 commit comments

Comments
 (0)