Spaces:
Running
Running
zhan1206
fix: comprehensive audit fixes - Thinking Dial unification, deployment scripts, README, bilingual filter, data download
bce487e | """ | |
| GGUF 部署 — 将 FusionModel 导出为 GGUF 格式(用于 llama.cpp) | |
| 使用方式: | |
| python deployment/export_gguf.py --checkpoint output/mini_model --output output/gguf/model.gguf | |
| python deployment/export_gguf.py --checkpoint output/mini_model --output output/gguf/model-Q4_K_M.gguf --quantize Q4_K_M | |
| 依赖: llama.cpp (自动检测) | |
| """ | |
| import sys | |
| import os | |
| import json | |
| import argparse | |
| import struct | |
| from pathlib import Path | |
| sys.path.insert(0, '.') | |
| def find_llama_cpp(): | |
| """Find llama.cpp installation.""" | |
| candidates = [ | |
| os.path.expanduser("~/llama.cpp"), | |
| os.path.expanduser("~/src/llama.cpp"), | |
| "/usr/local/bin/llama-cli", | |
| "llama-cli", | |
| ] | |
| for c in candidates: | |
| if os.path.isfile(c) or os.path.isdir(c): | |
| return c | |
| # Check PATH | |
| import shutil | |
| if shutil.which("llama-cli") or shutil.which("llama-cpp"): | |
| return shutil.which("llama-cli") or shutil.which("llama-cpp") | |
| return None | |
| def export_to_hf_format(model, output_dir): | |
| """Export model to HuggingFace format (safetensors + config.json). | |
| This is the canonical intermediate format. Use llama.cpp's convert | |
| script to produce GGUF from this. | |
| """ | |
| output_dir = Path(output_dir) | |
| output_dir.mkdir(parents=True, exist_ok=True) | |
| # Save model using HF's save_pretrained (produces safetensors) | |
| model.save_pretrained(str(output_dir), safe_serialization=True) | |
| # Write tokenizer config for llama.cpp compatibility | |
| tokenizer_config = { | |
| "model_type": "fusion", | |
| "vocab_size": model.config.vocab_size, | |
| "bos_token_id": 1, | |
| "eos_token_id": 2, | |
| "pad_token_id": 0, | |
| } | |
| with open(output_dir / "tokenizer_config.json", "w", encoding="utf-8") as f: | |
| json.dump(tokenizer_config, f, indent=2) | |
| print(f"[EXPORT] HF format saved to {output_dir}") | |
| return output_dir | |
| def convert_to_gguf(hf_dir, output_path, llama_cpp_path=None, quantize=None): | |
| """Convert HuggingFace format to GGUF using llama.cpp's convert script. | |
| Args: | |
| hf_dir: Path to HF format directory | |
| output_path: Output GGUF file path | |
| llama_cpp_path: Path to llama.cpp installation | |
| quantize: Quantization type (e.g. Q4_K_M, Q5_K_M, Q8_0) | |
| """ | |
| import subprocess | |
| llama_cpp = llama_cpp_path or find_llama_cpp() | |
| if llama_cpp is None: | |
| print("[WARNING] llama.cpp not found. Saving HF format only.") | |
| print(" To convert to GGUF, install llama.cpp and run:") | |
| print(f" python convert_hf_to_gguf.py {hf_dir} --outfile {output_path}") | |
| return False | |
| # Find convert script | |
| convert_script = None | |
| if os.path.isdir(llama_cpp): | |
| for name in ["convert_hf_to_gguf.py", "convert.py"]: | |
| candidate = os.path.join(llama_cpp, name) | |
| if os.path.isfile(candidate): | |
| convert_script = candidate | |
| break | |
| if convert_script is None: | |
| print("[WARNING] llama.cpp convert script not found. Saving HF format only.") | |
| print(f" Manual conversion: python convert_hf_to_gguf.py {hf_dir} --outfile {output_path}") | |
| return False | |
| # Run conversion | |
| cmd = [sys.executable, convert_script, str(hf_dir), "--outfile", str(output_path)] | |
| print(f"[CONVERT] Running: {' '.join(cmd)}") | |
| result = subprocess.run(cmd, capture_output=True, text=True) | |
| if result.returncode != 0: | |
| print(f"[ERROR] Conversion failed: {result.stderr}") | |
| return False | |
| print(f"[CONVERT] GGUF saved to {output_path}") | |
| # Quantize if requested | |
| if quantize and os.path.isdir(llama_cpp): | |
| quantize_bin = os.path.join(llama_cpp, "llama-quantize") | |
| if not os.path.isfile(quantize_bin): | |
| quantize_bin = os.path.join(llama_cpp, "quantize") | |
| if os.path.isfile(quantize_bin): | |
| quantized_path = str(output_path).replace(".gguf", f"-{quantize}.gguf") | |
| cmd = [quantize_bin, str(output_path), quantized_path, quantize] | |
| print(f"[QUANTIZE] Running: {' '.join(cmd)}") | |
| subprocess.run(cmd) | |
| print(f"[QUANTIZE] Quantized model saved to {quantized_path}") | |
| else: | |
| print(f"[WARNING] Quantize binary not found. Skipping quantization.") | |
| return True | |
| def export_gguf(model, output_path, llama_cpp_path=None, quantize=None): | |
| """Full export pipeline: FusionModel -> HF format -> GGUF. | |
| Args: | |
| model: FusionModel instance | |
| output_path: Output GGUF file path | |
| llama_cpp_path: Path to llama.cpp installation (optional) | |
| quantize: Quantization type (e.g. Q4_K_M) | |
| """ | |
| output_path = Path(output_path) | |
| hf_dir = output_path.parent / "hf_intermediate" | |
| # Step 1: Export to HF format | |
| export_to_hf_format(model, hf_dir) | |
| # Step 2: Convert to GGUF | |
| success = convert_to_gguf(hf_dir, output_path, llama_cpp_path, quantize) | |
| if success: | |
| print(f"\n[DONE] GGUF export complete: {output_path}") | |
| else: | |
| print(f"\n[PARTIAL] HF format saved at {hf_dir}") | |
| print(" Install llama.cpp to complete GGUF conversion.") | |
| return success | |
| if __name__ == "__main__": | |
| parser = argparse.ArgumentParser(description="Export FusionModel to GGUF format") | |
| parser.add_argument("--checkpoint", required=True, help="Path to model checkpoint") | |
| parser.add_argument("--output", default="output/gguf/model.gguf", help="Output GGUF path") | |
| parser.add_argument("--llama-cpp", default=None, help="Path to llama.cpp installation") | |
| parser.add_argument("--quantize", default=None, help="Quantization type (Q4_K_M, Q5_K_M, Q8_0)") | |
| args = parser.parse_args() | |
| from models.fusion_model import FusionModel | |
| model = FusionModel.from_pretrained(args.checkpoint) | |
| export_gguf(model, args.output, args.llama_cpp, args.quantize) | |