char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
b3c3b96a1
char/aliceai-t5-moe
1from __future__import annotations 2 3import re 4import json 5import yaml 6import logging 7from pathlib import Path 8from typing import Any ,Literal ,Optional 9from dataclasses import dataclass 10 11from .constants import Keys 12 13import gguf 14 15logger = logging .getLogger ("metadata" ) 16 17 18@dataclass 19class Metadata : 20# Recommended Sampler Parameters to be written to GGUF KV Store 21sampling_sequence :Optional [str ]= None 22sampling_top_k :Optional [int ]= None 23sampling_top_p :Optional [float ]= None 24sampling_min_p :Optional [float ]= None 25sampling_xtc_probability :Optional [float ]= None 26sampling_xtc_threshold :Optional [float ]= None 27sampling_temp :Optional [float ]= None 28sampling_penalty_last_n :Optional [int ]= None 29sampling_penalty_repeat :Optional [float ]= None 30sampling_mirostat :Optional [int ]= None 31sampling_mirostat_tau :Optional [float ]= None 32sampling_mirostat_eta :Optional [float ]= None 33 34# Authorship Metadata to be written to GGUF KV Store 35name :Optional [str ]= None 36author :Optional [str ]= None 37version :Optional [str ]= None 38organization :Optional [str ]= None 39finetune :Optional [str ]= None 40basename :Optional [str ]= None 41description :Optional [str ]= None 42quantized_by :Optional [str ]= None 43size_label :Optional [str ]= None 44url :Optional [str ]= None 45doi :Optional [str ]= None 46uuid :Optional [str ]= None 47repo_url :Optional [str ]= None 48source_url :Optional [str ]= None 49source_doi :Optional [str ]= None 50source_uuid :Optional [str ]= None 51source_repo_url :Optional [str ]= None 52license :Optional [str ]= None 53license_name :Optional [str ]= None 54license_link :Optional [str ]= None 55base_models :Optional [list [dict ]]= None 56tags :Optional [list [str ]]= None 57languages :Optional [list [str ]]= None 58datasets :Optional [list [dict ]]= None 59 60@staticmethod 61def load (metadata_override_path :Optional [Path ]= None ,model_path :Optional [Path ]= None ,model_name :Optional [str ]= None ,total_params :int = 0 )-> Metadata : 62# This grabs as many contextual authorship metadata as possible from the model repository 63# making any conversion as required to match the gguf kv store metadata format 64# as well as giving users the ability to override any authorship metadata that may be incorrect 65 66# Create a new Metadata instance 67metadata = Metadata () 68 69model_card = Metadata .load_model_card (model_path ) 70hf_params = Metadata .load_hf_parameters (model_path ) 71gen_config = Metadata .load_generation_config (model_path ) 72# TODO: load adapter_config.json when possible, it usually contains the base model of the LoRA adapter 73 74# heuristics 75metadata = Metadata .apply_metadata_heuristic (metadata ,model_card ,hf_params ,model_path ,total_params ) 76 77if gen_config : 78metadata .sampling_sequence = gen_config .get ("sequence" ,metadata .sampling_sequence ) 79metadata .sampling_top_k = gen_config .get ("top_k" ,metadata .sampling_top_k ) 80metadata .sampling_top_p = gen_config .get ("top_p" ,metadata .sampling_top_p ) 81metadata .sampling_min_p = gen_config .get ("min_p" ,metadata .sampling_min_p ) 82metadata .sampling_xtc_probability = gen_config .get ("xtc_probability" ,metadata .sampling_xtc_probability ) 83metadata .sampling_xtc_threshold = gen_config .get ("xtc_threshold" ,metadata .sampling_xtc_threshold ) 84metadata .sampling_temp = gen_config .get ("temperature" ,metadata .sampling_temp ) 85metadata .sampling_penalty_last_n = gen_config .get ("penalty_last_n" ,metadata .sampling_penalty_last_n ) 86metadata .sampling_penalty_repeat = gen_config .get ("penalty_repeat" ,gen_config .get ("repetition_penalty" ,metadata .sampling_penalty_repeat )) 87metadata .sampling_mirostat = gen_config .get ("mirostat" ,metadata .sampling_mirostat ) 88metadata .sampling_mirostat_tau = gen_config .get ("mirostat_tau" ,metadata .sampling_mirostat_tau ) 89metadata .sampling_mirostat_eta = gen_config .get ("mirostat_eta" ,metadata .sampling_mirostat_eta ) 90 91# Metadata Override File Provided 92# This is based on LLM_KV_NAMES mapping in llama.cpp 93metadata_override = Metadata .load_metadata_override (metadata_override_path ) 94 95metadata .sampling_sequence = metadata_override .get (Keys .General .SAMPLING_SEQUENCE ,metadata .sampling_sequence ) 96metadata .sampling_top_k = metadata_override .get (Keys .General .SAMPLING_TOP_K ,metadata .sampling_top_k ) 97metadata .sampling_top_p = metadata_override .get (Keys .General .SAMPLING_TOP_P ,metadata .sampling_top_p ) 98metadata .sampling_min_p = metadata_override .get (Keys .General .SAMPLING_MIN_P ,metadata .sampling_min_p ) 99metadata .sampling_xtc_probability = metadata_override .get (Keys .General .SAMPLING_XTC_PROBABILITY ,metadata .sampling_xtc_probability ) 100metadata .sampling_xtc_threshold = metadata_override .get (Keys .General .SAMPLING_XTC_THRESHOLD ,metadata .sampling_xtc_threshold ) 101metadata .sampling_temp = metadata_override .get (Keys .General .SAMPLING_TEMP ,metadata .sampling_temp ) 102metadata .sampling_penalty_last_n = metadata_override .get (Keys .General .SAMPLING_PENALTY_LAST_N ,metadata .sampling_penalty_last_n ) 103metadata .sampling_penalty_repeat = metadata_override .get (Keys .General .SAMPLING_PENALTY_REPEAT ,metadata .sampling_penalty_repeat ) 104metadata .sampling_mirostat = metadata_override .get (Keys .General .SAMPLING_MIROSTAT ,metadata .sampling_mirostat ) 105metadata .sampling_mirostat_tau = metadata_override .get (Keys .General .SAMPLING_MIROSTAT_TAU ,metadata .sampling_mirostat_tau ) 106metadata .sampling_mirostat_eta = metadata_override .get (Keys .General .SAMPLING_MIROSTAT_ETA ,metadata .sampling_mirostat_eta ) 107 108metadata .name = metadata_override .get (Keys .General .NAME ,metadata .name ) 109metadata .author = metadata_override .get (Keys .General .AUTHOR ,metadata .author ) 110metadata .version = metadata_override .get (Keys .General .VERSION ,metadata .version ) 111metadata .organization = metadata_override .get (Keys .General .ORGANIZATION ,metadata .organization ) 112 113metadata .finetune = metadata_override .get (Keys .General .FINETUNE ,metadata .finetune ) 114metadata .basename = metadata_override .get (Keys .General .BASENAME ,metadata .basename ) 115 116metadata .description = metadata_override .get (Keys .General .DESCRIPTION ,metadata .description ) 117metadata .quantized_by = metadata_override .get (Keys .General .QUANTIZED_BY ,metadata .quantized_by ) 118 119metadata .size_label = metadata_override .get (Keys .General .SIZE_LABEL ,metadata .size_label ) 120metadata .license_name = metadata_override .get (Keys .General .LICENSE_NAME ,metadata .license_name ) 121metadata .license_link = metadata_override .get (Keys .General .LICENSE_LINK ,metadata .license_link ) 122 123metadata .url = metadata_override .get (Keys .General .URL ,metadata .url ) 124metadata .doi = metadata_override .get (Keys .General .DOI ,metadata .doi ) 125metadata .uuid = metadata_override .get (Keys .General .UUID ,metadata .uuid ) 126metadata .repo_url = metadata_override .get (Keys .General .REPO_URL ,metadata .repo_url ) 127 128metadata .source_url = metadata_override .get (Keys .General .SOURCE_URL ,metadata .source_url ) 129metadata .source_doi = metadata_override .get (Keys .General .SOURCE_DOI ,metadata .source_doi ) 130metadata .source_uuid = metadata_override .get (Keys .General .SOURCE_UUID ,metadata .source_uuid ) 131metadata .source_repo_url = metadata_override .get (Keys .General .SOURCE_REPO_URL ,metadata .source_repo_url ) 132 133# Base Models is received here as an array of models 134metadata .base_models = metadata_override .get ("general.base_models" ,metadata .base_models ) 135 136# Datasets is received here as an array of datasets 137metadata .datasets = metadata_override .get ("general.datasets" ,metadata .datasets ) 138 139metadata .tags = metadata_override .get (Keys .General .TAGS ,metadata .tags ) 140metadata .languages = metadata_override .get (Keys .General .LANGUAGES ,metadata .languages ) 141 142# Direct Metadata Override (via direct cli argument) 143if model_name is not None : 144metadata .name = model_name 145 146return metadata 147 148@staticmethod 149def load_metadata_override (metadata_override_path :Optional [Path ]= None )-> dict [str ,Any ]: 150if metadata_override_path is None or not metadata_override_path .is_file (): 151return {} 152 153with open (metadata_override_path ,"r" ,encoding = "utf-8" )as f : 154return json .load (f ) 155 156@staticmethod 157def load_model_card (model_path :Optional [Path ]= None )-> dict [str ,Any ]: 158if model_path is None or not model_path .is_dir (): 159return {} 160 161model_card_path = model_path / "README.md" 162 163if not model_card_path .is_file (): 164return {} 165 166# The model card metadata is assumed to always be in YAML (frontmatter) 167# ref: https://github.com/huggingface/transformers/blob/a5c642fe7a1f25d3bdcd76991443ba6ff7ee34b2/src/transformers/modelcard.py#L468-L473 168yaml_content :str = "" 169with open (model_card_path ,"r" ,encoding = "utf-8" )as f : 170content = f .read () 171lines = content .splitlines () 172lines_yaml = [] 173if len (lines )== 0 : 174# Empty file 175return {} 176if len (lines )> 0 and lines [0 ]!= "---" : 177# No frontmatter 178return {} 179for line in lines [1 :]: 180if line == "---" : 181break # End of frontmatter 182else : 183lines_yaml .append (line ) 184yaml_content = "\n" .join (lines_yaml )+ "\n" 185 186# Quick hack to fix the Norway problem 187# https://hitchdev.com/strictyaml/why/implicit-typing-removed/ 188yaml_content = yaml_content .replace ("- no\n" ,"- \"no\"\n" ) 189# yaml should use 2 spaces instead of tab 190# this issue has came up with the Qwen/Qwen3-235B-A22B-Instruct-2507 model card 191# (I've also sent a pr tp fix the modelcard too) 192yaml_content = yaml_content .replace ("\t" ," " ) 193 194if yaml_content : 195data = yaml .safe_load (yaml_content ) 196if isinstance (data ,dict ): 197return data 198else : 199logger .error (f"while reading YAML model card frontmatter, data is { type ( data ) } instead of dict" ) 200return {} 201else : 202return {} 203 204@staticmethod 205def load_hf_parameters (model_path :Optional [Path ]= None )-> dict [str ,Any ]: 206if model_path is None or not model_path .is_dir (): 207return {} 208 209config_path = model_path / "config.json" 210 211if not config_path .is_file (): 212return {} 213 214with open (config_path ,"r" ,encoding = "utf-8" )as f : 215return json .load (f ) 216 217@staticmethod 218def load_generation_config (model_path :Optional [Path ]= None )-> dict [str ,Any ]: 219if model_path is None or not model_path .is_dir (): 220return {} 221 222generation_config_path = model_path / "generation_config.json" 223 224if not generation_config_path .is_file (): 225return {} 226 227try : 228with open (generation_config_path ,"r" ,encoding = "utf-8" )as f : 229return json .load (f ) 230except (json .JSONDecodeError ,IOError ): 231# not all models have valid generation_config.json 232return {} 233 234@staticmethod 235def id_to_title (string ): 236# Convert capitalization into title form unless acronym or version number 237return ' ' .join ([w .title ()if w .islower ()and not re .match (r'^(v\d+(?:\.\d+)*|\d.*)$' ,w )else w for w in string .strip ().replace ('-' ,' ' ).split ()]) 238 239@staticmethod 240def get_model_id_components (model_id :Optional [str ]= None ,total_params :int = 0 )-> tuple [str | None ,str | None ,str | None ,str | None ,str | None ,str | None ]: 241# Huggingface often store model id as '<org>/<model name>' 242# so let's parse it and apply some heuristics if possible for model name components 243 244if model_id is None : 245# model ID missing 246return None ,None ,None ,None ,None ,None 247 248if ' ' in model_id : 249# model ID is actually a normal human sentence 250# which means its most likely a normal model name only 251# not part of the hugging face naming standard, but whatever 252return model_id ,None ,None ,None ,None ,None 253 254if '/' in model_id : 255# model ID (huggingface style) 256org_component ,model_full_name_component = model_id .split ('/' ,1 ) 257else : 258# model ID but missing org components 259org_component ,model_full_name_component = None ,model_id 260 261# Check if we erroneously matched against './' or '../' etc... 262if org_component is not None and len (org_component )> 0 and org_component [0 ]== '.' : 263org_component = None 264 265name_parts :list [str ]= model_full_name_component .split ('-' ) 266 267# Remove empty parts 268for i in reversed (range (len (name_parts ))): 269if len (name_parts [i ])== 0 : 270del name_parts [i ] 271 272name_types :list [ 273set [Literal ["basename" ,"size_label" ,"finetune" ,"version" ,"type" ]] 274 ]= [set ()for _ in name_parts ] 275 276# Annotate the name 277for i ,part in enumerate (name_parts ): 278# Version 279if re .fullmatch (r'(v|iter)?\d+([.]\d+)*' ,part ,re .IGNORECASE ): 280name_types [i ].add ("version" ) 281# Quant type (should not be there for base models, but still annotated) 282elif re .fullmatch (r'i?q\d(_\w)*|b?fp?(16|32)' ,part ,re .IGNORECASE ): 283name_types [i ].add ("type" ) 284name_parts [i ]= part .upper () 285# Model size 286elif i > 0 and re .fullmatch (r'(([A]|\d+[x])?\d+([._]\d+)?[KMBT][\d]?|small|mini|medium|large|x?xl)' ,part ,re .IGNORECASE ): 287part = part .replace ("_" ,"." ) 288# Handle weird bloom-7b1 notation 289if part [- 1 ].isdecimal (): 290part = part [:- 2 ]+ "." + part [- 1 ]+ part [- 2 ] 291# Normalize the size suffixes 292if len (part )> 1 and part [- 2 ].isdecimal (): 293if part [- 1 ]in "kmbt" : 294part = part [:- 1 ]+ part [- 1 ].upper () 295if total_params != 0 : 296try : 297label_params = float (part [:- 1 ])* pow (1000 ," KMBT" .find (part [- 1 ])) 298# Only use it as a size label if it's close or bigger than the model size 299# Note that LoRA adapters don't necessarily include all layers, 300# so this is why bigger label sizes are accepted. 301# Do not use the size label when it's smaller than 1/8 of the model size 302if (total_params < 0 and label_params < abs (total_params )// 8 )or ( 303# Check both directions when the current model isn't a LoRA adapter 304total_params > 0 and abs (label_params - total_params )> 7 * total_params // 8 305 ): 306# Likely a context length 307name_types [i ].add ("finetune" ) 308# Lowercase the size when it's a context length 309part = part [:- 1 ]+ part [- 1 ].lower () 310except ValueError : 311# Failed to convert the size label to float, use it anyway 312pass 313if len (name_types [i ])== 0 : 314name_types [i ].add ("size_label" ) 315name_parts [i ]= part 316# Some easy to recognize finetune names 317elif i > 0 and re .fullmatch (r'chat|instruct|vision|lora' ,part ,re .IGNORECASE ): 318if total_params < 0 and part .lower ()== "lora" : 319# ignore redundant "lora" in the finetune part when the output is a lora adapter 320name_types [i ].add ("type" ) 321else : 322name_types [i ].add ("finetune" ) 323 324# Ignore word-based size labels when there is at least a number-based one present 325# TODO: should word-based size labels always be removed instead? 326if any (c .isdecimal ()for n ,t in zip (name_parts ,name_types )if "size_label" in t for c in n ): 327for n ,t in zip (name_parts ,name_types ): 328if "size_label" in t : 329if all (c .isalpha ()for c in n ): 330t .remove ("size_label" ) 331 332at_start = True 333# Find the basename through the annotated name 334for part ,t in zip (name_parts ,name_types ): 335if at_start and ((len (t )== 0 and part [0 ].isalpha ())or "version" in t ): 336t .add ("basename" ) 337else : 338if at_start : 339at_start = False 340if len (t )== 0 : 341t .add ("finetune" ) 342 343# Remove the basename annotation from trailing version 344for part ,t in zip (reversed (name_parts ),reversed (name_types )): 345if "basename" in t and len (t )> 1 : 346t .remove ("basename" ) 347else : 348break 349 350basename = "-" .join (n for n ,t in zip (name_parts ,name_types )if "basename" in t )or None 351# Deduplicate size labels using order-preserving 'dict' ('set' seems to sort the keys) 352size_label = "-" .join (dict .fromkeys (s for s ,t in zip (name_parts ,name_types )if "size_label" in t ).keys ())or None 353finetune = "-" .join (f for f ,t in zip (name_parts ,name_types )if "finetune" in t )or None 354# TODO: should the basename version always be excluded? 355# NOTE: multiple finetune versions are joined together 356version = "-" .join (v for v ,t ,in zip (name_parts ,name_types )if "version" in t and "basename" not in t )or None 357 358if size_label is None and finetune is None and version is None : 359# Too ambiguous, output nothing 360basename = None 361 362return model_full_name_component ,org_component ,basename ,finetune ,version ,size_label 363 364@staticmethod 365def apply_metadata_heuristic (metadata :Metadata ,model_card :Optional [dict ]= None ,hf_params :Optional [dict ]= None ,model_path :Optional [Path ]= None ,total_params :int = 0 )-> Metadata : 366# Reference Model Card Metadata: https://github.com/huggingface/hub-docs/blob/main/modelcard.md?plain=1 367 368# Model Card Heuristics 369######################## 370if model_card is not None : 371 372def use_model_card_metadata (metadata_key :str ,model_card_key :str ): 373if model_card_key in model_card and getattr (metadata ,metadata_key ,None )is None : 374setattr (metadata ,metadata_key ,model_card .get (model_card_key )) 375 376def use_array_model_card_metadata (metadata_key :str ,model_card_key :str ): 377# Note: Will append rather than replace if already exist 378tags_value = model_card .get (model_card_key ,None ) 379if tags_value is None : 380return 381 382current_value = getattr (metadata ,metadata_key ,None ) 383if current_value is None : 384current_value = [] 385 386if isinstance (tags_value ,str ): 387current_value .append (tags_value ) 388elif isinstance (tags_value ,list ): 389current_value .extend (tags_value ) 390 391setattr (metadata ,metadata_key ,current_value ) 392 393# LLAMA.cpp's direct internal convention 394# (Definitely not part of hugging face formal/informal standard) 395######################################### 396use_model_card_metadata ("name" ,"name" ) 397use_model_card_metadata ("author" ,"author" ) 398use_model_card_metadata ("version" ,"version" ) 399use_model_card_metadata ("organization" ,"organization" ) 400use_model_card_metadata ("description" ,"description" ) 401use_model_card_metadata ("finetune" ,"finetune" ) 402use_model_card_metadata ("basename" ,"basename" ) 403use_model_card_metadata ("size_label" ,"size_label" ) 404use_model_card_metadata ("source_url" ,"url" ) 405use_model_card_metadata ("source_doi" ,"doi" ) 406use_model_card_metadata ("source_uuid" ,"uuid" ) 407use_model_card_metadata ("source_repo_url" ,"repo_url" ) 408 409# LLAMA.cpp's huggingface style convention 410# (Definitely not part of hugging face formal/informal standard... but with model_ appended to match their style) 411########################################### 412use_model_card_metadata ("name" ,"model_name" ) 413use_model_card_metadata ("author" ,"model_author" ) 414use_model_card_metadata ("version" ,"model_version" ) 415use_model_card_metadata ("organization" ,"model_organization" ) 416use_model_card_metadata ("description" ,"model_description" ) 417use_model_card_metadata ("finetune" ,"model_finetune" ) 418use_model_card_metadata ("basename" ,"model_basename" ) 419use_model_card_metadata ("size_label" ,"model_size_label" ) 420use_model_card_metadata ("source_url" ,"model_url" ) 421use_model_card_metadata ("source_doi" ,"model_doi" ) 422use_model_card_metadata ("source_uuid" ,"model_uuid" ) 423use_model_card_metadata ("source_repo_url" ,"model_repo_url" ) 424 425# Hugging Face Direct Convention 426################################# 427 428# Not part of huggingface model card standard but notice some model creator using it 429# such as TheBloke in 'TheBloke/Mistral-7B-Instruct-v0.2-GGUF' 430use_model_card_metadata ("name" ,"model_name" ) 431use_model_card_metadata ("author" ,"model_creator" ) 432use_model_card_metadata ("basename" ,"model_type" ) 433 434if "base_model" in model_card or "base_models" in model_card or "base_model_sources" in model_card : 435# This represents the parent models that this is based on 436# Example: stabilityai/stable-diffusion-xl-base-1.0. Can also be a list (for merges) 437# Example of merges: https://huggingface.co/EmbeddedLLM/Mistral-7B-Merge-14-v0.1/blob/main/README.md 438metadata_base_models = [] 439base_model_value = model_card .get ("base_model" ,model_card .get ("base_models" ,model_card .get ("base_model_sources" ,None ))) 440 441if base_model_value is not None : 442if isinstance (base_model_value ,str ): 443metadata_base_models .append (base_model_value ) 444elif isinstance (base_model_value ,list ): 445metadata_base_models .extend (base_model_value ) 446 447if metadata .base_models is None : 448metadata .base_models = [] 449 450for model_id in metadata_base_models : 451# NOTE: model size of base model is assumed to be similar to the size of the current model 452base_model = {} 453if isinstance (model_id ,str ): 454if model_id .startswith ("http://" )or model_id .startswith ("https://" )or model_id .startswith ("ssh://" ): 455base_model ["repo_url" ]= model_id 456 457# Check if Hugging Face ID is present in URL 458if "huggingface.co" in model_id : 459match = re .match (r"https?://huggingface.co/([^/]+/[^/]+)$" ,model_id ) 460if match : 461model_id_component = match .group (1 ) 462model_full_name_component ,org_component ,basename ,finetune ,version ,size_label = Metadata .get_model_id_components (model_id_component ,total_params ) 463 464# Populate model dictionary with extracted components 465if model_full_name_component is not None : 466base_model ["name" ]= Metadata .id_to_title (model_full_name_component ) 467if org_component is not None : 468base_model ["organization" ]= Metadata .id_to_title (org_component ) 469if version is not None : 470base_model ["version" ]= version 471 472else : 473# Likely a Hugging Face ID 474model_full_name_component ,org_component ,basename ,finetune ,version ,size_label = Metadata .get_model_id_components (model_id ,total_params ) 475 476# Populate model dictionary with extracted components 477if model_full_name_component is not None : 478base_model ["name" ]= Metadata .id_to_title (model_full_name_component ) 479if org_component is not None : 480base_model ["organization" ]= Metadata .id_to_title (org_component ) 481if version is not None : 482base_model ["version" ]= version 483if org_component is not None and model_full_name_component is not None : 484base_model ["repo_url" ]= f"https://huggingface.co/ { org_component } / { model_full_name_component } " 485 486elif isinstance (model_id ,dict ): 487base_model = model_id 488 489else : 490logger .error (f"base model entry ' { str ( model_id ) } ' not in a known format" ) 491 492metadata .base_models .append (base_model ) 493 494if "datasets" in model_card or "dataset" in model_card or "dataset_sources" in model_card : 495# This represents the datasets that this was trained from 496metadata_datasets = [] 497dataset_value = model_card .get ("datasets" ,model_card .get ("dataset" ,model_card .get ("dataset_sources" ,None ))) 498 499if dataset_value is not None : 500if isinstance (dataset_value ,str ): 501metadata_datasets .append (dataset_value ) 502elif isinstance (dataset_value ,list ): 503metadata_datasets .extend (dataset_value ) 504 505if metadata .datasets is None : 506metadata .datasets = [] 507 508for dataset_id in metadata_datasets : 509# NOTE: model size of base model is assumed to be similar to the size of the current model 510dataset = {} 511if isinstance (dataset_id ,str ): 512if dataset_id .startswith (("http://" ,"https://" ,"ssh://" )): 513dataset ["repo_url" ]= dataset_id 514 515# Check if Hugging Face ID is present in URL 516if "huggingface.co" in dataset_id : 517match = re .match (r"https?://huggingface.co/([^/]+/[^/]+)$" ,dataset_id ) 518if match : 519dataset_id_component = match .group (1 ) 520dataset_name_component ,org_component ,basename ,finetune ,version ,size_label = Metadata .get_model_id_components (dataset_id_component ,total_params ) 521 522# Populate dataset dictionary with extracted components 523if dataset_name_component is not None : 524dataset ["name" ]= Metadata .id_to_title (dataset_name_component ) 525if org_component is not None : 526dataset ["organization" ]= Metadata .id_to_title (org_component ) 527if version is not None : 528dataset ["version" ]= version 529 530else : 531# Likely a Hugging Face ID 532dataset_name_component ,org_component ,basename ,finetune ,version ,size_label = Metadata .get_model_id_components (dataset_id ,total_params ) 533 534# Populate dataset dictionary with extracted components 535if dataset_name_component is not None : 536dataset ["name" ]= Metadata .id_to_title (dataset_name_component ) 537if org_component is not None : 538dataset ["organization" ]= Metadata .id_to_title (org_component ) 539if version is not None : 540dataset ["version" ]= version 541if org_component is not None and dataset_name_component is not None : 542dataset ["repo_url" ]= f"https://huggingface.co/ { org_component } / { dataset_name_component } " 543 544elif isinstance (dataset_id ,dict ): 545dataset = dataset_id 546 547else : 548logger .error (f"dataset entry ' { str ( dataset_id ) } ' not in a known format" ) 549 550metadata .datasets .append (dataset ) 551 552use_model_card_metadata ("license" ,"license" ) 553use_model_card_metadata ("license_name" ,"license_name" ) 554use_model_card_metadata ("license_link" ,"license_link" ) 555 556use_array_model_card_metadata ("tags" ,"tags" ) 557use_array_model_card_metadata ("tags" ,"pipeline_tag" ) 558 559use_array_model_card_metadata ("languages" ,"languages" ) 560use_array_model_card_metadata ("languages" ,"language" ) 561 562# Hugging Face Parameter Heuristics 563#################################### 564 565if hf_params is not None : 566 567hf_name_or_path = hf_params .get ("_name_or_path" ) 568if hf_name_or_path is not None and hf_name_or_path .count ('/' )<= 1 : 569# Use _name_or_path only if its actually a model name and not some computer path 570# e.g. 'meta-llama/Llama-2-7b-hf' 571model_id = hf_name_or_path 572model_full_name_component ,org_component ,basename ,finetune ,version ,size_label = Metadata .get_model_id_components (model_id ,total_params ) 573if metadata .name is None and model_full_name_component is not None : 574metadata .name = Metadata .id_to_title (model_full_name_component ) 575if metadata .organization is None and org_component is not None : 576metadata .organization = Metadata .id_to_title (org_component ) 577if metadata .basename is None and basename is not None : 578metadata .basename = basename 579if metadata .finetune is None and finetune is not None : 580metadata .finetune = finetune 581if metadata .version is None and version is not None : 582metadata .version = version 583if metadata .size_label is None and size_label is not None : 584metadata .size_label = size_label 585 586# Directory Folder Name Fallback Heuristics 587############################################ 588if model_path is not None : 589model_id = model_path .name 590model_full_name_component ,org_component ,basename ,finetune ,version ,size_label = Metadata .get_model_id_components (model_id ,total_params ) 591if metadata .name is None and model_full_name_component is not None : 592metadata .name = Metadata .id_to_title (model_full_name_component ) 593if metadata .organization is None and org_component is not None : 594metadata .organization = Metadata .id_to_title (org_component ) 595if metadata .basename is None and basename is not None : 596metadata .basename = basename 597if metadata .finetune is None and finetune is not None : 598metadata .finetune = finetune 599if metadata .version is None and version is not None : 600metadata .version = version 601if metadata .size_label is None and size_label is not None : 602metadata .size_label = size_label 603 604return metadata 605 606def set_gguf_meta_model (self ,gguf_writer :gguf .GGUFWriter ): 607assert self .name is not None 608 609if self .sampling_sequence is not None : 610gguf_writer .add_sampling_sequence (self .sampling_sequence ) 611if self .sampling_top_k is not None : 612gguf_writer .add_sampling_top_k (self .sampling_top_k ) 613if self .sampling_top_p is not None : 614gguf_writer .add_sampling_top_p (self .sampling_top_p ) 615if self .sampling_min_p is not None : 616gguf_writer .add_sampling_min_p (self .sampling_min_p ) 617if self .sampling_xtc_probability is not None : 618gguf_writer .add_sampling_xtc_probability (self .sampling_xtc_probability ) 619if self .sampling_xtc_threshold is not None : 620gguf_writer .add_sampling_xtc_threshold (self .sampling_xtc_threshold ) 621if self .sampling_temp is not None : 622gguf_writer .add_sampling_temp (self .sampling_temp ) 623if self .sampling_penalty_last_n is not None : 624gguf_writer .add_sampling_penalty_last_n (self .sampling_penalty_last_n ) 625if self .sampling_penalty_repeat is not None : 626gguf_writer .add_sampling_penalty_repeat (self .sampling_penalty_repeat ) 627if self .sampling_mirostat is not None : 628gguf_writer .add_sampling_mirostat (self .sampling_mirostat ) 629if self .sampling_mirostat_tau is not None : 630gguf_writer .add_sampling_mirostat_tau (self .sampling_mirostat_tau ) 631if self .sampling_mirostat_eta is not None : 632gguf_writer .add_sampling_mirostat_eta (self .sampling_mirostat_eta ) 633 634gguf_writer .add_name (self .name ) 635 636if self .author is not None : 637gguf_writer .add_author (self .author ) 638if self .version is not None : 639gguf_writer .add_version (self .version ) 640if self .organization is not None : 641gguf_writer .add_organization (self .organization ) 642 643if self .finetune is not None : 644gguf_writer .add_finetune (self .finetune ) 645if self .basename is not None : 646gguf_writer .add_basename (self .basename ) 647 648if self .description is not None : 649gguf_writer .add_description (self .description ) 650if self .quantized_by is not None : 651gguf_writer .add_quantized_by (self .quantized_by ) 652 653if self .size_label is not None : 654gguf_writer .add_size_label (self .size_label ) 655 656if self .license is not None : 657if isinstance (self .license ,list ): 658gguf_writer .add_license ("," .join (self .license )) 659else : 660gguf_writer .add_license (self .license ) 661if self .license_name is not None : 662gguf_writer .add_license_name (self .license_name ) 663if self .license_link is not None : 664gguf_writer .add_license_link (self .license_link ) 665 666if self .url is not None : 667gguf_writer .add_url (self .url ) 668if self .doi is not None : 669gguf_writer .add_doi (self .doi ) 670if self .uuid is not None : 671gguf_writer .add_uuid (self .uuid ) 672if self .repo_url is not None : 673gguf_writer .add_repo_url (self .repo_url ) 674 675if self .source_url is not None : 676gguf_writer .add_source_url (self .source_url ) 677if self .source_doi is not None : 678gguf_writer .add_source_doi (self .source_doi ) 679if self .source_uuid is not None : 680gguf_writer .add_source_uuid (self .source_uuid ) 681if self .source_repo_url is not None : 682gguf_writer .add_source_repo_url (self .source_repo_url ) 683 684if self .base_models is not None : 685gguf_writer .add_base_model_count (len (self .base_models )) 686for key ,base_model_entry in enumerate (self .base_models ): 687if "name" in base_model_entry : 688gguf_writer .add_base_model_name (key ,base_model_entry ["name" ]) 689if "author" in base_model_entry : 690gguf_writer .add_base_model_author (key ,base_model_entry ["author" ]) 691if "version" in base_model_entry : 692gguf_writer .add_base_model_version (key ,base_model_entry ["version" ]) 693if "organization" in base_model_entry : 694gguf_writer .add_base_model_organization (key ,base_model_entry ["organization" ]) 695if "description" in base_model_entry : 696gguf_writer .add_base_model_description (key ,base_model_entry ["description" ]) 697if "url" in base_model_entry : 698gguf_writer .add_base_model_url (key ,base_model_entry ["url" ]) 699if "doi" in base_model_entry : 700gguf_writer .add_base_model_doi (key ,base_model_entry ["doi" ]) 701if "uuid" in base_model_entry : 702gguf_writer .add_base_model_uuid (key ,base_model_entry ["uuid" ]) 703if "repo_url" in base_model_entry : 704gguf_writer .add_base_model_repo_url (key ,base_model_entry ["repo_url" ]) 705 706if self .datasets is not None : 707gguf_writer .add_dataset_count (len (self .datasets )) 708for key ,dataset_entry in enumerate (self .datasets ): 709if "name" in dataset_entry : 710gguf_writer .add_dataset_name (key ,dataset_entry ["name" ]) 711if "author" in dataset_entry : 712gguf_writer .add_dataset_author (key ,dataset_entry ["author" ]) 713if "version" in dataset_entry : 714gguf_writer .add_dataset_version (key ,dataset_entry ["version" ]) 715if "organization" in dataset_entry : 716gguf_writer .add_dataset_organization (key ,dataset_entry ["organization" ]) 717if "description" in dataset_entry : 718gguf_writer .add_dataset_description (key ,dataset_entry ["description" ]) 719if "url" in dataset_entry : 720gguf_writer .add_dataset_url (key ,dataset_entry ["url" ]) 721if "doi" in dataset_entry : 722gguf_writer .add_dataset_doi (key ,dataset_entry ["doi" ]) 723if "uuid" in dataset_entry : 724gguf_writer .add_dataset_uuid (key ,dataset_entry ["uuid" ]) 725if "repo_url" in dataset_entry : 726gguf_writer .add_dataset_repo_url (key ,dataset_entry ["repo_url" ]) 727 728if self .tags is not None : 729gguf_writer .add_tags (self .tags ) 730if self .languages is not None : 731gguf_writer .add_languages (self .languages )