chaddy81 commited on
Commit
1b762eb
Β·
verified Β·
1 Parent(s): 0ab2061

Upload convert_grpo_gguf.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. convert_grpo_gguf.py +173 -0
convert_grpo_gguf.py ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # /// script
2
+ # dependencies = [
3
+ # "transformers>=4.36.0",
4
+ # "peft>=0.7.0",
5
+ # "torch>=2.0.0",
6
+ # "accelerate>=0.24.0",
7
+ # "huggingface_hub>=0.20.0",
8
+ # "sentencepiece>=0.1.99",
9
+ # "protobuf>=3.20.0",
10
+ # "numpy",
11
+ # "gguf",
12
+ # ]
13
+ # ///
14
+
15
+ """GGUF Conversion for GRPO model (two-step adapter merge)"""
16
+
17
+ import os
18
+ import torch
19
+ from transformers import AutoModelForCausalLM, AutoTokenizer
20
+ from peft import PeftModel
21
+ from huggingface_hub import HfApi
22
+ import subprocess
23
+
24
+ print("πŸ”„ GGUF Conversion Script - GRPO Model")
25
+ print("=" * 60)
26
+
27
+ BASE_MODEL = os.environ.get("BASE_MODEL", "Qwen/Qwen3-0.6B")
28
+ SFT_ADAPTER = os.environ.get("SFT_ADAPTER", "chaddy81/qwen3-0.6b-multicode-sft")
29
+ GRPO_ADAPTER = os.environ.get("GRPO_ADAPTER", "chaddy81/qwen3-0.6b-multicode-grpo")
30
+ OUTPUT_REPO = os.environ.get("OUTPUT_REPO", "chaddy81/qwen3-0.6b-multicode-grpo-gguf")
31
+ QUANT_TYPE = os.environ.get("QUANT_TYPE", "Q8_0")
32
+
33
+ print(f"\nπŸ“¦ Configuration:")
34
+ print(f" Base model: {BASE_MODEL}")
35
+ print(f" SFT adapter: {SFT_ADAPTER}")
36
+ print(f" GRPO adapter: {GRPO_ADAPTER}")
37
+ print(f" Output repo: {OUTPUT_REPO}")
38
+ print(f" Quantization: {QUANT_TYPE}")
39
+
40
+ # Step 1: Load base model
41
+ print("\nπŸ”§ Step 1: Loading base model...")
42
+ base_model = AutoModelForCausalLM.from_pretrained(
43
+ BASE_MODEL,
44
+ dtype=torch.float16,
45
+ device_map="auto",
46
+ trust_remote_code=True,
47
+ )
48
+ print(" βœ… Base model loaded")
49
+
50
+ # Step 2: Apply and merge SFT adapter
51
+ print("\nπŸ”§ Step 2: Applying SFT adapter...")
52
+ sft_model = PeftModel.from_pretrained(base_model, SFT_ADAPTER)
53
+ merged_sft = sft_model.merge_and_unload()
54
+ print(" βœ… SFT adapter merged")
55
+
56
+ # Step 3: Apply and merge GRPO adapter
57
+ print("\nπŸ”§ Step 3: Applying GRPO adapter...")
58
+ grpo_model = PeftModel.from_pretrained(merged_sft, GRPO_ADAPTER)
59
+ final_model = grpo_model.merge_and_unload()
60
+ print(" βœ… GRPO adapter merged")
61
+
62
+ # Load tokenizer from GRPO adapter (has latest config)
63
+ tokenizer = AutoTokenizer.from_pretrained(GRPO_ADAPTER, trust_remote_code=True)
64
+ print(" βœ… Tokenizer loaded")
65
+
66
+ # Step 4: Save merged model
67
+ print("\nπŸ’Ύ Step 4: Saving merged model...")
68
+ merged_dir = "/tmp/merged_model"
69
+ final_model.save_pretrained(merged_dir, safe_serialization=True)
70
+ tokenizer.save_pretrained(merged_dir)
71
+ print(" βœ… Merged model saved")
72
+
73
+ # Step 5: Setup llama.cpp
74
+ print("\nπŸ“₯ Step 5: Setting up llama.cpp...")
75
+ subprocess.run(["apt-get", "update", "-qq"], check=True, capture_output=True)
76
+ subprocess.run(["apt-get", "install", "-y", "-qq", "build-essential", "cmake"], check=True, capture_output=True)
77
+ print(" βœ… Build tools installed")
78
+
79
+ subprocess.run(["git", "clone", "--depth", "1", "https://github.com/ggerganov/llama.cpp.git", "/tmp/llama.cpp"], check=True, capture_output=True)
80
+ print(" βœ… llama.cpp cloned")
81
+
82
+ subprocess.run(["pip", "install", "-q", "-r", "/tmp/llama.cpp/requirements.txt"], check=True, capture_output=True)
83
+ subprocess.run(["pip", "install", "-q", "sentencepiece", "protobuf"], check=True, capture_output=True)
84
+ print(" βœ… Dependencies installed")
85
+
86
+ # Step 6: Convert to GGUF
87
+ print("\nπŸ”„ Step 6: Converting to GGUF format...")
88
+ gguf_output_dir = "/tmp/gguf_output"
89
+ os.makedirs(gguf_output_dir, exist_ok=True)
90
+ model_name = GRPO_ADAPTER.split('/')[-1]
91
+ gguf_fp16 = f"{gguf_output_dir}/{model_name}-f16.gguf"
92
+
93
+ try:
94
+ result = subprocess.run(
95
+ ["python", "/tmp/llama.cpp/convert_hf_to_gguf.py", merged_dir, "--outfile", gguf_fp16, "--outtype", "f16"],
96
+ check=True, capture_output=True, text=True
97
+ )
98
+ print(" βœ… FP16 GGUF created")
99
+ except subprocess.CalledProcessError as e:
100
+ print(f"❌ Conversion failed! STDERR: {e.stderr[-2000:]}")
101
+ raise
102
+
103
+ # Step 7: Quantize
104
+ print(f"\nβš™οΈ Step 7: Creating {QUANT_TYPE} quantization...")
105
+ os.makedirs("/tmp/llama.cpp/build", exist_ok=True)
106
+ subprocess.run(["cmake", "-B", "/tmp/llama.cpp/build", "-S", "/tmp/llama.cpp", "-DGGML_CUDA=OFF"], check=True, capture_output=True, text=True)
107
+ subprocess.run(["cmake", "--build", "/tmp/llama.cpp/build", "--target", "llama-quantize", "-j", "4"], check=True, capture_output=True, text=True)
108
+ print(" βœ… Quantize tool built")
109
+
110
+ quantize_bin = "/tmp/llama.cpp/build/bin/llama-quantize"
111
+ gguf_quant = f"{gguf_output_dir}/{model_name}-{QUANT_TYPE.lower()}.gguf"
112
+ subprocess.run([quantize_bin, gguf_fp16, gguf_quant, QUANT_TYPE], check=True, capture_output=True)
113
+ size_mb = os.path.getsize(gguf_quant) / (1024 * 1024)
114
+ print(f" βœ… {QUANT_TYPE}: {size_mb:.1f} MB")
115
+
116
+ # Step 8: Upload to Hub
117
+ print("\n☁️ Step 8: Uploading to Hub...")
118
+ api = HfApi()
119
+ api.create_repo(repo_id=OUTPUT_REPO, repo_type="model", exist_ok=True)
120
+ print(" βœ… Repository ready")
121
+
122
+ api.upload_file(path_or_fileobj=gguf_quant, path_in_repo=f"{model_name}-{QUANT_TYPE.lower()}.gguf", repo_id=OUTPUT_REPO)
123
+ print(f" βœ… {QUANT_TYPE} uploaded")
124
+
125
+ # Create README
126
+ readme = f"""---
127
+ base_model: {BASE_MODEL}
128
+ tags:
129
+ - gguf
130
+ - llama.cpp
131
+ - quantized
132
+ - trl
133
+ - grpo
134
+ ---
135
+
136
+ # {OUTPUT_REPO.split('/')[-1]}
137
+
138
+ GGUF conversion of [{GRPO_ADAPTER}](https://huggingface.co/{GRPO_ADAPTER}).
139
+
140
+ **Training Pipeline:**
141
+ 1. Base: [{BASE_MODEL}](https://huggingface.co/{BASE_MODEL})
142
+ 2. SFT: [{SFT_ADAPTER}](https://huggingface.co/{SFT_ADAPTER})
143
+ 3. GRPO: [{GRPO_ADAPTER}](https://huggingface.co/{GRPO_ADAPTER})
144
+
145
+ ## Available Files
146
+
147
+ | File | Quant | Size |
148
+ |------|-------|------|
149
+ | {model_name}-{QUANT_TYPE.lower()}.gguf | {QUANT_TYPE} | {size_mb:.1f} MB |
150
+
151
+ ## Usage
152
+
153
+ ### With Ollama
154
+ ```bash
155
+ huggingface-cli download {OUTPUT_REPO} {model_name}-{QUANT_TYPE.lower()}.gguf
156
+ echo "FROM ./{model_name}-{QUANT_TYPE.lower()}.gguf" > Modelfile
157
+ ollama create {model_name} -f Modelfile
158
+ ollama run {model_name}
159
+ ```
160
+
161
+ ### With llama.cpp
162
+ ```bash
163
+ ./llama-cli -m {model_name}-{QUANT_TYPE.lower()}.gguf -p "Your prompt"
164
+ ```
165
+ """
166
+ api.upload_file(path_or_fileobj=readme.encode(), path_in_repo="README.md", repo_id=OUTPUT_REPO)
167
+ print(" βœ… README uploaded")
168
+
169
+ print("\n" + "=" * 60)
170
+ print("βœ… GGUF Conversion Complete!")
171
+ print(f"πŸ“¦ https://huggingface.co/{OUTPUT_REPO}")
172
+ print(f"πŸ“₯ huggingface-cli download {OUTPUT_REPO} {model_name}-{QUANT_TYPE.lower()}.gguf")
173
+ print("=" * 60)