Download hos_optimizer/quantize.py from lxcxjxhx/HOS-Model-Optimizer: direct link, hf CLI and curl.
- Browser
- Download file 23.3 kB
-
https://huggingface.co/lxcxjxhx/HOS-Model-Optimizer/resolve/main/hos_optimizer/quantize.py
- Command line
-
hf download hf://lxcxjxhx/HOS-Model-Optimizer/hos_optimizer/quantize.py
-
curl -L -o quantize.py https://huggingface.co/lxcxjxhx/HOS-Model-Optimizer/resolve/main/hos_optimizer/quantize.py
23.3 kB
| #!/usr/bin/env python3 | |
| """ | |
| HOS Model Optimizer - 量化模块 | |
| 提供多种量化方法支持: | |
| - GGUF 量化:使用 llama.cpp 工具链 | |
| - AWQ 4-bit 量化:激活感知量化,精度损失最小 | |
| - GPTQ 4/8-bit 量化:基于 GPU 的 Post-Training 量化 | |
| - 量化质量评估:PPL (Perplexity) 计算 | |
| - 格式转换工具:支持不同量化格式间的转换 | |
| 针对 8GB VRAM 场景进行了优化配置。 | |
| 使用方法: | |
| # GGUF 量化 | |
| python quantize.py --method gguf --model ./model_path --output ./output_path | |
| # AWQ 4-bit 量化 | |
| python quantize.py --method awq --bits 4 --model ./model_path | |
| # GPTQ 量化 | |
| python quantize.py --method gptq --bits 4 --model ./model_path | |
| # 评估量化质量 | |
| python quantize.py --method evaluate --model ./quantized_model_path | |
| # 格式转换 | |
| python quantize.py --method convert --from gguf --to awq --model ./model_path | |
| """ | |
| import argparse | |
| import os | |
| import sys | |
| import json | |
| import subprocess | |
| import tempfile | |
| from pathlib import Path | |
| from typing import Optional, Dict, Any, List | |
| import torch | |
| import time | |
| # 8GB VRAM 优化配置 | |
| VRAM_8GB_CONFIG = { | |
| "max_batch_size": 1, | |
| "max_seq_length": 512, | |
| "gradient_checkpointing": True, | |
| "offload_to_cpu": True, | |
| "calibration_samples": 128, | |
| } | |
| class QuantizationError(Exception): | |
| """量化过程中的异常""" | |
| pass | |
| def check_vram_availability() -> Dict[str, Any]: | |
| """检查 GPU VRAM 可用性 | |
| Returns: | |
| 包含 VRAM 信息的字典 | |
| """ | |
| if not torch.cuda.is_available(): | |
| return { | |
| "available": False, | |
| "total_vram_gb": 0, | |
| "free_vram_gb": 0, | |
| "device": "cpu" | |
| } | |
| device = torch.cuda.current_device() | |
| total_vram = torch.cuda.get_device_properties(device).total_memory | |
| free_vram = total_vram - torch.cuda.memory_allocated(device) | |
| return { | |
| "available": True, | |
| "total_vram_gb": total_vram / (1024 ** 3), | |
| "free_vram_gb": free_vram / (1024 ** 3), | |
| "device": torch.cuda.get_device_name(device) | |
| } | |
| def optimize_for_low_vram(config: Dict[str, Any]) -> Dict[str, Any]: | |
| """根据 VRAM 限制优化配置 | |
| Args: | |
| config: 原始配置 | |
| Returns: | |
| 优化后的配置 | |
| """ | |
| vram_info = check_vram_availability() | |
| if not vram_info["available"] or vram_info["free_vram_gb"] <= 8: | |
| print(f"⚠️ 检测到 VRAM <= 8GB ({vram_info['free_vram_gb']:.2f}GB 可用)") | |
| print(" 启用低 VRAM 优化配置...") | |
| # 合并优化配置 | |
| optimized = config.copy() | |
| optimized.update(VRAM_8GB_CONFIG) | |
| return optimized | |
| return config | |
| def quantize_gguf( | |
| model_path: str, | |
| output_path: str, | |
| quant_type: str = "Q4_K_M", | |
| llama_cpp_path: Optional[str] = None | |
| ) -> str: | |
| """GGUF 量化 - 使用 llama.cpp 工具链 | |
| Args: | |
| model_path: 输入模型路径(HuggingFace 格式) | |
| output_path: 输出 GGUF 文件路径 | |
| quant_type: 量化类型,如 Q4_K_M, Q5_K_M, Q8_0 等 | |
| llama_cpp_path: llama.cpp 安装路径,如果为 None 则从 PATH 查找 | |
| Returns: | |
| 输出文件路径 | |
| Raises: | |
| QuantizationError: 量化失败时抛出 | |
| """ | |
| print(f"=== GGUF {quant_type} 量化 ===") | |
| print(f"输入模型: {model_path}") | |
| print(f"输出路径: {output_path}") | |
| # 检查 llama-quantize 工具 | |
| quantize_tool = "llama-quantize" | |
| if llama_cpp_path: | |
| quantize_tool = os.path.join(llama_cpp_path, "llama-quantize") | |
| try: | |
| # 检查工具是否存在 | |
| result = subprocess.run( | |
| [quantize_tool, "--help"], | |
| capture_output=True, | |
| text=True, | |
| timeout=5 | |
| ) | |
| except (FileNotFoundError, subprocess.TimeoutExpired): | |
| raise QuantizationError( | |
| "找不到 llama-quantize 工具。请确保已安装 llama.cpp 并将其添加到 PATH," | |
| "或通过 --llama-cpp-path 指定安装路径。\n" | |
| "安装指南: https://github.com/ggerganov/llama.cpp" | |
| ) | |
| # 转换模型为 GGUF 格式 | |
| print("步骤 1/2: 转换模型为 GGUF 格式...") | |
| try: | |
| from transformers import AutoModelForCausalLM, AutoTokenizer | |
| # 加载模型 | |
| model = AutoModelForCausalLM.from_pretrained( | |
| model_path, | |
| torch_dtype=torch.float16, | |
| trust_remote_code=True | |
| ) | |
| tokenizer = AutoTokenizer.from_pretrained( | |
| model_path, | |
| trust_remote_code=True | |
| ) | |
| # 创建临时目录 | |
| with tempfile.TemporaryDirectory() as tmpdir: | |
| # 保存为 GGUF 兼容格式 | |
| temp_model_path = os.path.join(tmpdir, "model") | |
| model.save_pretrained(temp_model_path) | |
| tokenizer.save_pretrained(temp_model_path) | |
| # 使用 llama.cpp 转换工具 | |
| convert_script = "convert.py" | |
| if llama_cpp_path: | |
| convert_script = os.path.join(llama_cpp_path, "convert.py") | |
| f16_path = os.path.join(tmpdir, "model-f16.gguf") | |
| print(" 转换为 FP16 GGUF...") | |
| subprocess.run( | |
| [sys.executable, convert_script, temp_model_path, "--outfile", f16_path], | |
| check=True, | |
| capture_output=True, | |
| text=True | |
| ) | |
| # 量化 | |
| print(f"步骤 2/2: 量化为 {quant_type}...") | |
| subprocess.run( | |
| [quantize_tool, f16_path, output_path, quant_type], | |
| check=True, | |
| capture_output=True, | |
| text=True | |
| ) | |
| except subprocess.CalledProcessError as e: | |
| raise QuantizationError(f"GGUF 量化失败: {e.stderr}") | |
| except Exception as e: | |
| raise QuantizationError(f"GGUF 量化过程中发生错误: {str(e)}") | |
| print("✓ GGUF 量化完成!") | |
| return output_path | |
| def quantize_awq( | |
| model_path: str, | |
| output_path: str, | |
| bits: int = 4, | |
| group_size: int = 128 | |
| ) -> str: | |
| """AWQ 4-bit 量化 | |
| AWQ (Activation-aware Weight Quantization) 通过保护显著权重通道 | |
| 实现高精度 4-bit 量化,适合小模型。 | |
| Args: | |
| model_path: 输入模型路径 | |
| output_path: 输出模型路径 | |
| bits: 量化位数,默认 4 | |
| group_size: 分组大小,默认 128 | |
| Returns: | |
| 输出模型路径 | |
| Raises: | |
| QuantizationError: 量化失败时抛出 | |
| """ | |
| print(f"=== AWQ {bits}-bit 量化 ===") | |
| print(f"输入模型: {model_path}") | |
| print(f"输出路径: {output_path}") | |
| try: | |
| from awq import AutoAWQForCausalLM | |
| from transformers import AutoTokenizer | |
| # 检查 VRAM 并优化配置 | |
| config = { | |
| "zero_point": True, | |
| "q_group_size": group_size, | |
| "w_bit": bits, | |
| "version": "GEMM", | |
| } | |
| config = optimize_for_low_vram(config) | |
| # 加载模型和分词器 | |
| print("加载模型...") | |
| model = AutoAWQForCausalLM.from_pretrained( | |
| model_path, | |
| trust_remote_code=True, | |
| ) | |
| tokenizer = AutoTokenizer.from_pretrained( | |
| model_path, | |
| trust_remote_code=True, | |
| ) | |
| print(f"开始 AWQ {bits}-bit 量化...") | |
| print(f" 配置: zero_point={config['zero_point']}, " | |
| f"group_size={config['q_group_size']}, version={config['version']}") | |
| model.quantize(tokenizer, quant_config=config) | |
| # 保存量化模型 | |
| print(f"保存量化模型到: {output_path}") | |
| model.save_quantized(output_path) | |
| tokenizer.save_pretrained(output_path) | |
| print("✓ AWQ 量化完成!") | |
| return output_path | |
| except ImportError as e: | |
| raise QuantizationError( | |
| f"缺少依赖: {e.name}\n" | |
| f"请安装: pip install autoawq" | |
| ) | |
| except Exception as e: | |
| raise QuantizationError(f"AWQ 量化失败: {str(e)}") | |
| def quantize_gptq( | |
| model_path: str, | |
| output_path: str, | |
| bits: int = 4, | |
| group_size: int = 128, | |
| desc_act: bool = False | |
| ) -> str: | |
| """GPTQ 量化 | |
| GPTQ 基于 Optimal Brain Quantization 框架,通过逐层量化 | |
| 和误差补偿实现高精度量化。 | |
| Args: | |
| model_path: 输入模型路径 | |
| output_path: 输出模型路径 | |
| bits: 量化位数,4 或 8 | |
| group_size: 分组大小,默认 128 | |
| desc_act: 是否按激活值排序,默认 False | |
| Returns: | |
| 输出模型路径 | |
| Raises: | |
| QuantizationError: 量化失败时抛出 | |
| """ | |
| if bits not in [4, 8]: | |
| raise ValueError(f"GPTQ 仅支持 4-bit 或 8-bit 量化,收到: {bits}") | |
| print(f"=== GPTQ {bits}-bit 量化 ===") | |
| print(f"输入模型: {model_path}") | |
| print(f"输出路径: {output_path}") | |
| try: | |
| from transformers import AutoTokenizer | |
| from auto_gptq import AutoGPTQForCausalLM, BaseQuantizeConfig | |
| # GPTQ 量化配置 | |
| quantize_config = BaseQuantizeConfig( | |
| bits=bits, | |
| group_size=group_size, | |
| desc_act=desc_act, | |
| damp_percent=0.1, | |
| ) | |
| print("加载模型...") | |
| model = AutoGPTQForCausalLM.from_pretrained( | |
| model_path, | |
| quantize_config, | |
| trust_remote_code=True, | |
| ) | |
| tokenizer = AutoTokenizer.from_pretrained( | |
| model_path, | |
| trust_remote_code=True, | |
| ) | |
| # 准备校准数据 | |
| print("准备校准数据...") | |
| calibration_texts = [ | |
| "信息安全是保护计算机系统和网络免受未经授权的访问、攻击或破坏的实践。", | |
| "SQL注入是一种常见的Web安全漏洞,攻击者通过注入恶意SQL代码来操纵数据库。", | |
| "渗透测试是一种模拟真实攻击者的方法来评估系统安全性的技术。", | |
| "防火墙是网络安全的第一道防线,用于监控和控制进出网络的流量。", | |
| "加密技术用于保护数据在传输和存储过程中的机密性和完整性。", | |
| "身份验证是确认用户身份的过程,通常使用密码、生物特征或多因素认证。", | |
| "网络监控用于检测和分析网络流量,以识别潜在的安全威胁。", | |
| "数据备份是防止数据丢失的重要措施,应定期进行并存储在安全位置。", | |
| ] | |
| calibration_data = [ | |
| tokenizer(text, return_tensors="pt", max_length=512, truncation=True) | |
| for text in calibration_texts | |
| ] | |
| print(f"开始 GPTQ {bits}-bit 量化...") | |
| print(f" 配置: bits={bits}, group_size={group_size}, desc_act={desc_act}") | |
| model.quantize(calibration_data) | |
| print(f"保存量化模型到: {output_path}") | |
| model.save_quantized(output_path) | |
| tokenizer.save_pretrained(output_path) | |
| print("✓ GPTQ 量化完成!") | |
| return output_path | |
| except ImportError as e: | |
| raise QuantizationError( | |
| f"缺少依赖: {e.name}\n" | |
| f"请安装: pip install auto-gptq" | |
| ) | |
| except Exception as e: | |
| raise QuantizationError(f"GPTQ 量化失败: {str(e)}") | |
| def evaluate_perplexity( | |
| model_path: str, | |
| dataset: str = "wikitext", | |
| max_samples: int = 100, | |
| stride: int = 512 | |
| ) -> float: | |
| """评估量化模型的 PPL (Perplexity) | |
| Args: | |
| model_path: 模型路径 | |
| dataset: 评估数据集名称,默认 wikitext | |
| max_samples: 最大评估样本数 | |
| stride: 滑动窗口步长 | |
| Returns: | |
| PPL 值 | |
| Raises: | |
| QuantizationError: 评估失败时抛出 | |
| """ | |
| print(f"=== 评估模型 PPL ===") | |
| print(f"模型: {model_path}") | |
| print(f"数据集: {dataset}") | |
| try: | |
| # 导入评测模块 | |
| from hos_optimizer.evaluate import EvaluationEngine, EvaluationConfig, MetricLoader | |
| # 创建评测配置 | |
| config = EvaluationConfig( | |
| model_path=model_path, | |
| dataset_path="", # PPL 计算不需要数据集文件 | |
| metrics=["ppl"], | |
| task_type="perplexity", | |
| max_samples=max_samples, | |
| batch_size=1, | |
| device_map="auto", | |
| ) | |
| # 创建评测引擎 | |
| engine = EvaluationEngine(config) | |
| # 加载模型 | |
| print("加载模型...") | |
| engine.load_model() | |
| # 加载评估数据集 | |
| print(f"加载评估数据: {dataset}...") | |
| from datasets import load_dataset | |
| test_data = load_dataset(dataset, "wikitext-2-raw-v1", split="test") | |
| # 使用参考文本计算 PPL | |
| references = [] | |
| for i, text in enumerate(test_data["text"]): | |
| if text and text.strip(): | |
| references.append(text) | |
| if len(references) >= max_samples: | |
| break | |
| if not references: | |
| raise QuantizationError("数据集中没有有效的文本样本") | |
| # 计算 PPL | |
| print("计算 PPL...") | |
| metrics_result = engine.compute_metrics( | |
| predictions=references, | |
| references=references | |
| ) | |
| ppl_value = metrics_result.get("ppl", 0.0) | |
| # 释放资源 | |
| engine.shutdown() | |
| print(f"✓ PPL 评估完成: {ppl_value:.2f}") | |
| return ppl_value | |
| except ImportError as e: | |
| raise QuantizationError( | |
| f"缺少依赖: {e.name}\n" | |
| f"请安装: pip install datasets evaluate" | |
| ) | |
| except Exception as e: | |
| raise QuantizationError(f"PPL 评估失败: {str(e)}") | |
| def convert_format( | |
| model_path: str, | |
| output_path: str, | |
| from_format: str, | |
| to_format: str, | |
| **kwargs | |
| ) -> str: | |
| """量化格式转换工具 | |
| Args: | |
| model_path: 输入模型路径 | |
| output_path: 输出模型路径 | |
| from_format: 源格式 (gguf, awq, gptq, hf) | |
| to_format: 目标格式 (gguf, awq, gptq, hf) | |
| **kwargs: 其他参数 | |
| Returns: | |
| 输出模型路径 | |
| Raises: | |
| QuantizationError: 转换失败时抛出 | |
| """ | |
| print(f"=== 格式转换: {from_format} -> {to_format} ===") | |
| print(f"输入: {model_path}") | |
| print(f"输出: {output_path}") | |
| # 支持的转换路径 | |
| conversion_map = { | |
| ("hf", "gguf"): lambda: quantize_gguf(model_path, output_path, **kwargs), | |
| ("hf", "awq"): lambda: quantize_awq(model_path, output_path, **kwargs), | |
| ("hf", "gptq"): lambda: quantize_gptq(model_path, output_path, **kwargs), | |
| ("gguf", "hf"): lambda: _convert_gguf_to_hf(model_path, output_path), | |
| ("awq", "hf"): lambda: _convert_awq_to_hf(model_path, output_path), | |
| ("gptq", "hf"): lambda: _convert_gptq_to_hf(model_path, output_path), | |
| } | |
| conversion_key = (from_format.lower(), to_format.lower()) | |
| if conversion_key not in conversion_map: | |
| raise QuantizationError( | |
| f"不支持的转换路径: {from_format} -> {to_format}\n" | |
| f"支持的转换: {', '.join([f'{k[0]}->{k[1]}' for k in conversion_map.keys()])}" | |
| ) | |
| try: | |
| result = conversion_map[conversion_key]() | |
| print(f"✓ 格式转换完成: {from_format} -> {to_format}") | |
| return result | |
| except Exception as e: | |
| raise QuantizationError(f"格式转换失败: {str(e)}") | |
| def _convert_gguf_to_hf(model_path: str, output_path: str) -> str: | |
| """GGUF 转 HuggingFace 格式""" | |
| # 这里需要实现具体的转换逻辑 | |
| # 通常需要使用 llama.cpp 的转换工具 | |
| raise NotImplementedError("GGUF -> HF 转换尚未实现") | |
| def _convert_awq_to_hf(model_path: str, output_path: str) -> str: | |
| """AWQ 转 HuggingFace 格式""" | |
| from transformers import AutoModelForCausalLM, AutoTokenizer | |
| print("加载 AWQ 模型...") | |
| model = AutoModelForCausalLM.from_pretrained( | |
| model_path, | |
| trust_remote_code=True, | |
| torch_dtype=torch.float16 | |
| ) | |
| tokenizer = AutoTokenizer.from_pretrained( | |
| model_path, | |
| trust_remote_code=True | |
| ) | |
| print(f"保存到: {output_path}") | |
| model.save_pretrained(output_path) | |
| tokenizer.save_pretrained(output_path) | |
| return output_path | |
| def _convert_gptq_to_hf(model_path: str, output_path: str) -> str: | |
| """GPTQ 转 HuggingFace 格式""" | |
| from transformers import AutoModelForCausalLM, AutoTokenizer | |
| print("加载 GPTQ 模型...") | |
| model = AutoModelForCausalLM.from_pretrained( | |
| model_path, | |
| trust_remote_code=True, | |
| torch_dtype=torch.float16 | |
| ) | |
| tokenizer = AutoTokenizer.from_pretrained( | |
| model_path, | |
| trust_remote_code=True | |
| ) | |
| print(f"保存到: {output_path}") | |
| model.save_pretrained(output_path) | |
| tokenizer.save_pretrained(output_path) | |
| return output_path | |
| def get_model_size(model_path: str) -> float: | |
| """获取模型文件大小 (GB) | |
| Args: | |
| model_path: 模型路径 | |
| Returns: | |
| 模型大小 (GB) | |
| """ | |
| total_size = 0 | |
| for dirpath, _, filenames in os.walk(model_path): | |
| for f in filenames: | |
| if f.endswith((".safetensors", ".bin", ".pt", ".gguf")): | |
| fp = os.path.join(dirpath, f) | |
| total_size += os.path.getsize(fp) | |
| return total_size / (1024 ** 3) | |
| def main(): | |
| """命令行入口""" | |
| parser = argparse.ArgumentParser( | |
| description="HOS Model Optimizer - 量化工具", | |
| formatter_class=argparse.RawDescriptionHelpFormatter, | |
| epilog=""" | |
| 示例: | |
| # GGUF 量化 | |
| python quantize.py --method gguf --model ./model --output ./model.gguf --quant-type Q4_K_M | |
| # AWQ 4-bit 量化 | |
| python quantize.py --method awq --bits 4 --model ./model --output ./model-awq | |
| # GPTQ 8-bit 量化 | |
| python quantize.py --method gptq --bits 8 --model ./model --output ./model-gptq | |
| # 评估 PPL | |
| python quantize.py --method evaluate --model ./quantized-model | |
| # 格式转换 | |
| python quantize.py --method convert --from hf --to awq --model ./model --output ./model-awq | |
| """ | |
| ) | |
| parser.add_argument( | |
| "--method", | |
| type=str, | |
| required=True, | |
| choices=["gguf", "awq", "gptq", "evaluate", "convert"], | |
| help="量化方法" | |
| ) | |
| parser.add_argument( | |
| "--model", | |
| type=str, | |
| required=True, | |
| help="输入模型路径" | |
| ) | |
| parser.add_argument( | |
| "--output", | |
| type=str, | |
| default=None, | |
| help="输出路径(默认自动生成)" | |
| ) | |
| parser.add_argument( | |
| "--bits", | |
| type=int, | |
| default=4, | |
| choices=[4, 8], | |
| help="量化位数(默认: 4)" | |
| ) | |
| parser.add_argument( | |
| "--quant-type", | |
| type=str, | |
| default="Q4_K_M", | |
| help="GGUF 量化类型(默认: Q4_K_M)" | |
| ) | |
| parser.add_argument( | |
| "--group-size", | |
| type=int, | |
| default=128, | |
| help="量化分组大小(默认: 128)" | |
| ) | |
| parser.add_argument( | |
| "--llama-cpp-path", | |
| type=str, | |
| default=None, | |
| help="llama.cpp 安装路径(用于 GGUF 量化)" | |
| ) | |
| parser.add_argument( | |
| "--from", | |
| dest="from_format", | |
| type=str, | |
| choices=["gguf", "awq", "gptq", "hf"], | |
| help="源格式(用于格式转换)" | |
| ) | |
| parser.add_argument( | |
| "--to", | |
| dest="to_format", | |
| type=str, | |
| choices=["gguf", "awq", "gptq", "hf"], | |
| help="目标格式(用于格式转换)" | |
| ) | |
| args = parser.parse_args() | |
| # 自动生成输出路径 | |
| if args.output is None: | |
| model_name = os.path.basename(args.model) | |
| if args.method == "gguf": | |
| args.output = f"{model_name}-{args.quant_type}.gguf" | |
| elif args.method == "convert": | |
| args.output = f"{model_name}-{args.to_format}" | |
| elif args.method == "evaluate": | |
| print("错误: 评估模式需要指定 --output 参数") | |
| sys.exit(1) | |
| else: | |
| args.output = f"{model_name}-{args.method}-{args.bits}bit" | |
| # 显示 VRAM 信息 | |
| vram_info = check_vram_availability() | |
| if vram_info["available"]: | |
| print(f"GPU: {vram_info['device']}") | |
| print(f"VRAM: {vram_info['free_vram_gb']:.2f}GB / {vram_info['total_vram_gb']:.2f}GB") | |
| else: | |
| print("⚠️ 未检测到 GPU,将使用 CPU(速度较慢)") | |
| # 显示原始模型大小 | |
| if os.path.exists(args.model): | |
| original_size = get_model_size(args.model) | |
| print(f"原始模型大小: {original_size:.2f} GB") | |
| # 执行量化 | |
| try: | |
| if args.method == "gguf": | |
| result = quantize_gguf( | |
| args.model, | |
| args.output, | |
| quant_type=args.quant_type, | |
| llama_cpp_path=args.llama_cpp_path | |
| ) | |
| elif args.method == "awq": | |
| result = quantize_awq( | |
| args.model, | |
| args.output, | |
| bits=args.bits, | |
| group_size=args.group_size | |
| ) | |
| elif args.method == "gptq": | |
| result = quantize_gptq( | |
| args.model, | |
| args.output, | |
| bits=args.bits, | |
| group_size=args.group_size | |
| ) | |
| elif args.method == "evaluate": | |
| ppl = evaluate_perplexity(args.model) | |
| print(f"\n最终 PPL: {ppl:.2f}") | |
| result = None | |
| elif args.method == "convert": | |
| if not args.from_format or not args.to_format: | |
| print("错误: 格式转换需要指定 --from 和 --to 参数") | |
| sys.exit(1) | |
| result = convert_format( | |
| args.model, | |
| args.output, | |
| args.from_format, | |
| args.to_format, | |
| bits=args.bits, | |
| quant_type=args.quant_type | |
| ) | |
| # 显示量化后模型大小 | |
| if result and os.path.exists(result): | |
| quantized_size = get_model_size(result) | |
| print(f"\n量化后模型大小: {quantized_size:.2f} GB") | |
| if os.path.exists(args.model): | |
| compression = (1 - quantized_size / original_size) * 100 | |
| print(f"压缩率: {compression:.1f}%") | |
| except QuantizationError as e: | |
| print(f"\n❌ 量化失败: {e}", file=sys.stderr) | |
| sys.exit(1) | |
| except Exception as e: | |
| print(f"\n❌ 发生未预期的错误: {e}", file=sys.stderr) | |
| import traceback | |
| traceback.print_exc() | |
| sys.exit(1) | |
| if __name__ == "__main__": | |
| main() | |