| |
| """ |
| Patch IQuestLab/IQuest-Coder models for transformers 5.x compatibility. |
| |
| Fixes the meta-device RoPE bug where accelerate zeros out inv_freq during |
| model initialization, causing the model to produce only newlines/garbage. |
| |
| Usage: |
| python patch_iquestcoder.py |
| |
| This will find and patch all cached IQuest-Coder modeling files automatically. |
| Run this AFTER downloading the model (e.g. after a failed heretic run or |
| after running `huggingface-cli download IQuestLab/IQuest-Coder-V1-40B-Instruct`). |
| """ |
|
|
| import glob |
| import os |
| import re |
| import sys |
|
|
| |
| ORIGINAL_PATTERN = re.compile( |
| r'( @torch\.no_grad\(\)\n' |
| r' @dynamic_rope_update\n' |
| r' def forward\(self, x: torch\.Tensor, position_ids: torch\.Tensor\)' |
| r' -> Tuple\[torch\.Tensor, torch\.Tensor\]:\n)' |
| r'( inv_freq_expanded = self\.inv_freq\[None, :, None\]\.float\(\)\.expand\(position_ids\.shape\[0\], -1, 1\)\.to\(x\.device\))' |
| ) |
|
|
| REPLACEMENT = ( |
| r'\1' |
| r' # Lazy recompute: accelerate meta-device init leaves inv_freq as zeros\n' |
| r' if self.inv_freq is not None and self.inv_freq.numel() > 0 and (self.inv_freq == 0).all():\n' |
| r' inv_freq, self.attention_scaling = self.rope_init_fn(self.config, None)\n' |
| r' self.inv_freq = inv_freq.to(device=x.device, dtype=self.inv_freq.dtype)\n' |
| r' self.original_inv_freq = self.inv_freq\n' |
| r'\2' |
| ) |
|
|
| |
| PATCH_MARKER = "Lazy recompute: accelerate meta-device init" |
|
|
| |
| SEARCH_PATHS = [ |
| os.path.expanduser("~/.cache/huggingface/hub/models--IQuestLab--*/**/modeling_iquestcoder.py"), |
| "/llm/huggingface/modules/transformers_modules/IQuestLab/**/modeling_iquestcoder.py", |
| |
| "/data/huggingface/**/modeling_iquestcoder.py", |
| "/scratch/**/modeling_iquestcoder.py", |
| ] |
|
|
|
|
| def find_model_files(): |
| """Find all cached IQuest-Coder modeling files.""" |
| found = [] |
| |
| for env_var in ["HF_HOME", "TRANSFORMERS_CACHE", "HUGGINGFACE_HUB_CACHE"]: |
| val = os.environ.get(env_var) |
| if val: |
| SEARCH_PATHS.append(os.path.join(val, "**/modeling_iquestcoder.py")) |
|
|
| for pattern in SEARCH_PATHS: |
| found.extend(glob.glob(pattern, recursive=True)) |
|
|
| |
| seen = set() |
| unique = [] |
| for f in found: |
| real = os.path.realpath(f) |
| if real not in seen: |
| seen.add(real) |
| unique.append(f) |
| return unique |
|
|
|
|
| def patch_file(filepath): |
| """Apply the RoPE lazy-recompute patch to a modeling file.""" |
| with open(filepath, "r", encoding="utf-8") as f: |
| content = f.read() |
|
|
| if PATCH_MARKER in content: |
| print(f" SKIP (already patched): {filepath}") |
| return False |
|
|
| new_content, count = ORIGINAL_PATTERN.subn(REPLACEMENT, content) |
| if count == 0: |
| print(f" WARN (pattern not found — may need manual patching): {filepath}") |
| return False |
|
|
| with open(filepath, "w", encoding="utf-8") as f: |
| f.write(new_content) |
|
|
| print(f" OK (patched {count} location(s)): {filepath}") |
| return True |
|
|
|
|
| def main(): |
| print("IQuest-Coder RoPE patch for transformers 5.x") |
| print("=" * 50) |
| print() |
|
|
| files = find_model_files() |
| if not files: |
| print("No IQuest-Coder model files found in cache.") |
| print("Download the model first, then re-run this script.") |
| print() |
| print("Searched:") |
| for p in SEARCH_PATHS: |
| print(f" {p}") |
| sys.exit(1) |
|
|
| print(f"Found {len(files)} file(s):\n") |
| patched = 0 |
| for f in files: |
| if patch_file(f): |
| patched += 1 |
|
|
| print() |
| if patched: |
| print(f"Done — patched {patched} file(s).") |
| else: |
| print("No files needed patching.") |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|