first commit

This commit is contained in:
2026-10-23 15:00:59 +08:00
commit 4627899899
156 changed files with 398139 additions and 0 deletions

View File

@@ -0,0 +1,185 @@
import json
import re
from collections import Counter
def should_ignore(weight_name, exact_ignore: list, regex_ignore: list):
if any(weight_name.startswith(ig) for ig in exact_ignore):
return True
if any(p.match(weight_name) for p in regex_ignore):
return True
return False
def compile_ignore(ignore_list: list | None = None,
extra_ignore_list: list | None = None):
exact = set()
regex = []
for x in (ignore_list or []) + (extra_ignore_list or []):
if x.startswith("re:"):
regex.append(re.compile(x[3:]))
else:
exact.add(x)
return exact, regex
def normalize_to_regex(weight_name: str) -> str:
parts = []
for p in weight_name.split("."):
if p.isdigit():
parts.append(r"\d+")
else:
parts.append(p)
return "re:" + ".".join(parts) + ".*"
def infer_default_quant_target(quant_config: dict) -> str:
classes = quant_config.get("class") or {}
int4_list = classes.get("int4") or []
int8_list = classes.get("int8") or []
if int4_list and not int8_list:
return "int4"
if int8_list and not int4_list:
return "int8"
if len(int4_list) >= len(int8_list):
return "int4"
return "int8"
def suggest_category(weight_name: str, default_quant_target: str) -> tuple[str, str]:
wn = weight_name.lower()
ignore_keywords = [
"lm_head",
"embed_tokens",
".input_layernorm.",
".post_attention_layernorm.",
".self_attn.k_norm.",
".self_attn.q_norm.",
".norm.",
".bias",
".e_score_correction_bias",
]
if any(k in wn for k in ignore_keywords):
return "ignore", "norm/embed/bias 类型,通常放在 ignore"
quant_keywords = [
".self_attn.",
".mlp.",
".experts.",
"_proj.",
".proj.",
".linear.",
]
if any(k in wn for k in quant_keywords):
return default_quant_target, f"线性/投影权重,建议放在 {default_quant_target}"
return "manual-review", "命名不典型,建议人工确认后归类"
def collect_quant_ignore_list(quant_config: dict) -> list[str]:
classes = quant_config.get("class") or {}
ignore_list = []
ignore_list += quant_config.get("ignore") or []
ignore_list += classes.get("int4") or []
ignore_list += classes.get("int8") or []
return ignore_list
def build_missing_summary(missing: list[str], quant_config: dict, max_show: int) -> dict:
default_quant_target = infer_default_quant_target(quant_config)
category_counter = Counter()
rows = []
for wn in missing:
category, reason = suggest_category(wn, default_quant_target)
category_counter[category] += 1
rows.append(
{
"weight_name": wn,
"suggested_category": category,
"suggested_pattern": normalize_to_regex(wn),
"reason": reason,
}
)
return {
"missing_total": len(missing),
"default_quant_target": default_quant_target,
"category_summary": {
"ignore": category_counter.get("ignore", 0),
"int4": category_counter.get("int4", 0),
"int8": category_counter.get("int8", 0),
"manual-review": category_counter.get("manual-review", 0),
},
"top_missing": rows[:max_show],
}
def summarize_missing(missing: list[str], quant_config: dict, max_show: int):
summary = build_missing_summary(missing=missing, quant_config=quant_config, max_show=max_show)
print(f"Missing total: {len(missing)}")
print(f"Default quant target inferred from config: {summary['default_quant_target']}")
print("Suggested category summary:")
for cat, count in summary["category_summary"].items():
print(f" - {cat}: {count}")
if not missing:
print("All weights are covered by quant.ignore/int4/int8.")
return
print(f"\nTop {len(summary['top_missing'])} missing items:")
for idx, row in enumerate(summary["top_missing"], start=1):
print(f"[{idx}] {row['weight_name']}")
print(f" suggestion: {row['suggested_category']}")
print(f" reason: {row['reason']}")
print(f" pattern: {row['suggested_pattern']}")
def check(weight_names, ignore_list):
exact_ignore, regex_ignore = compile_ignore(ignore_list)
missing = []
for wn in weight_names:
if not should_ignore(wn, exact_ignore, regex_ignore):
missing.append(wn)
return missing
def build_validation_result(
weight_names: list[str], quant_config: dict, max_show: int = 20
) -> dict:
ignore_list = collect_quant_ignore_list(quant_config)
missing = check(weight_names, ignore_list)
return build_missing_summary(missing=missing, quant_config=quant_config, max_show=max_show)
if __name__ == "__main__":
import yaml
from argparse import ArgumentParser
parser = ArgumentParser()
parser.add_argument("--weight-map", type=str)
parser.add_argument("--model-info", type=str)
parser.add_argument("--max-show", type=int, default=20)
args = parser.parse_args()
with open(args.model_info, "r") as f:
cfg = yaml.safe_load(f)
quant_config = cfg['quant']
ignore_list = collect_quant_ignore_list(quant_config)
with open(args.weight_map, "r") as f:
weight_names = json.load(f)['weight_map'].keys()
missing = check(list(weight_names), ignore_list)
summarize_missing(missing, quant_config, args.max_show)