Download check_tokenizer_reserve.py from CMSManhattan/JiRackPrecisionTokenizer: direct link, hf CLI and curl.
- Browser
- Download file 7.24 kB
-
https://huggingface.co/CMSManhattan/JiRackPrecisionTokenizer/resolve/main/check_tokenizer_reserve.py
- Command line
-
hf download hf://CMSManhattan/JiRackPrecisionTokenizer/check_tokenizer_reserve.py
-
curl -L -o check_tokenizer_reserve.py https://huggingface.co/CMSManhattan/JiRackPrecisionTokenizer/resolve/main/check_tokenizer_reserve.py
7.24 kB
| """ | |
| Проверка: попали ли новые кастомные токены (включая 4 tool-calling токена | |
| <|tool_call_start|>/<|tool_call_end|>/<|tool_result_start|>/<|tool_result_end|>) | |
| в зарезервированные слоты эмбеддинг-матрицы чекпоинта JiRack, или токенизатор | |
| физически расширился поверх неё. | |
| Ничего передавать не нужно -- просто: | |
| python3 check_tokenizer_reserve.py | |
| Скрипт сам обходит известные места на сервере и находит: | |
| - папку токенизатора (пробует несколько имён и папок) | |
| - .pt чекпоинт модели 8B Precision (первый подходящий найденный файл) | |
| Если хочешь всё же указать пути вручную -- можно как раньше: | |
| python3 check_tokenizer_reserve.py <путь_к_токенизатору> <путь_к_checkpoint.pt> | |
| """ | |
| import sys | |
| import os | |
| import glob | |
| EMB_KEY = "token_emb.weight" | |
| HEAD_KEY = "lm_head.weight" | |
| TOOL_TOKENS = ["<|tool_call_start|>", "<|tool_call_end|>", "<|tool_result_start|>", "<|tool_result_end|>"] | |
| TOKENIZER_SEARCH_DIRS = [ | |
| ".", | |
| "./qwen_ji_router_tokenizer", | |
| "./ji_precision_tokenizer", | |
| "/mnt/nfs_share/Qweb2_5_Tokenizer/qwen_ji_router_tokenizer", | |
| "/mnt/nfs_share/Qweb2_5_Tokenizer/ji_precision_tokenizer", | |
| "/mnt/nfs_share/Qweb2_5_Tokenizer", | |
| ] | |
| CHECKPOINT_SEARCH_GLOBS = [ | |
| "/mnt/nfs_share/JiRackPrecision_8b/*.pt", | |
| "/mnt/nfs_share/JiRackPrecision_8b/**/*.pt", | |
| "./*.pt", | |
| ] | |
| def looks_like_tokenizer_dir(d): | |
| if not os.path.isdir(d): | |
| return False | |
| names = os.listdir(d) | |
| return any(n in names for n in ("tokenizer_config.json", "tokenizer.json", "vocab.json")) | |
| def find_tokenizer_dir(): | |
| for d in TOKENIZER_SEARCH_DIRS: | |
| if looks_like_tokenizer_dir(d): | |
| return d | |
| return None | |
| def find_checkpoint(): | |
| for pattern in CHECKPOINT_SEARCH_GLOBS: | |
| hits = sorted(glob.glob(pattern, recursive=True)) | |
| if hits: | |
| return hits[0] | |
| return None | |
| def resolve_paths(argv): | |
| tok_path = argv[1] if len(argv) > 1 else None | |
| ckpt_path = argv[2] if len(argv) > 2 else None | |
| if not tok_path: | |
| tok_path = find_tokenizer_dir() | |
| if tok_path: | |
| print(f"(токенизатор не указан -- нашёл автоматически: {tok_path})") | |
| else: | |
| print("!!! Не смог автоматически найти папку токенизатора нигде из известных мест.") | |
| print(" Передай путь вручную первым аргументом.") | |
| sys.exit(1) | |
| if not ckpt_path: | |
| ckpt_path = find_checkpoint() | |
| if ckpt_path: | |
| print(f"(чекпоинт не указан -- нашёл автоматически: {ckpt_path})") | |
| else: | |
| print("(чекпоинт не найден автоматически -- сверка с реальной моделью будет пропущена)") | |
| return tok_path, ckpt_path | |
| def main(): | |
| from transformers import AutoTokenizer | |
| tok_path, ckpt_path = resolve_paths(sys.argv) | |
| print(f"\nЗагружаю токенизатор: {tok_path}") | |
| tok = AutoTokenizer.from_pretrained(tok_path) | |
| vocab = tok.get_vocab() | |
| all_ids = list(vocab.values()) | |
| max_id = max(all_ids) | |
| required_rows = max_id + 1 | |
| print(f" len(tokenizer) = {len(tok)}") | |
| print(f" max token id = {max_id}") | |
| print(f" required emb rows = {required_rows} (max_id + 1)") | |
| if len(all_ids) != len(set(all_ids)): | |
| print(" !!! ОШИБКА: два разных токена делят один и тот же id. " | |
| "Токенизатор сломан, надо пересобрать до дальнейших шагов.") | |
| sys.exit(1) | |
| print(" все id уникальны -- ок") | |
| added = tok.get_added_vocab() | |
| if added: | |
| a_ids = sorted(added.values()) | |
| print(f" добавленных спецтокенов: {len(added)}, id диапазон [{a_ids[0]} .. {a_ids[-1]}]") | |
| else: | |
| print(" ВНИМАНИЕ: get_added_vocab() пуст -- проверь, тот ли это токенизатор.") | |
| print("\n--- Проверка tool-calling токенов ---") | |
| all_tool_tokens_present = True | |
| for t in TOOL_TOKENS: | |
| if t in vocab: | |
| print(f" {t:25s} id={vocab[t]:6d} [найден]") | |
| else: | |
| all_tool_tokens_present = False | |
| print(f" {t:25s} НЕ НАЙДЕН в словаре! -> это не свежий токенизатор, " | |
| f"перегенерируй через make_tokenizator.py") | |
| if not ckpt_path: | |
| print("\n(Чекпоинт не найден -- сверки с реальной моделью не будет.)") | |
| return | |
| import torch | |
| print(f"\nЗагружаю чекпоинт: {ckpt_path}") | |
| ckpt = torch.load(ckpt_path, map_location="cpu", weights_only=False) | |
| sd = ckpt["model"] if "model" in ckpt else ckpt | |
| if EMB_KEY not in sd or HEAD_KEY not in sd: | |
| print(f" !!! Не нашёл ключи {EMB_KEY!r}/{HEAD_KEY!r} в state_dict. " | |
| f"Ключи в наличии (первые 10): {list(sd.keys())[:10]}") | |
| sys.exit(1) | |
| have_rows, hidden = sd[EMB_KEY].shape | |
| head_rows, head_hidden = sd[HEAD_KEY].shape | |
| print(f" {EMB_KEY}: [{have_rows}, {hidden}]") | |
| print(f" {HEAD_KEY}: [{head_rows}, {head_hidden}]") | |
| if have_rows != head_rows: | |
| print(f" !!! Несогласованность: token_emb {have_rows} строк, lm_head {head_rows} строк. " | |
| f"Это чинить раньше, чем что-либо ещё.") | |
| sys.exit(1) | |
| print("\n================ ВЕРДИКТ ================") | |
| if required_rows <= have_rows: | |
| spare = have_rows - required_rows | |
| print(f"RESIZE НЕ НУЖЕН.") | |
| print(f" Токенизатору нужно {required_rows} строк, в чекпоинте есть {have_rows}.") | |
| print(f" Все добавленные токены умещаются в резерв ({spare} строк ещё свободно).") | |
| print(f" VOCAB_SIZE в JiRackTernaryUltra_*.py / JiRackPrecision_*.py оставить как есть: {have_rows}") | |
| else: | |
| extra = required_rows - have_rows | |
| print(f"RESIZE ОБЯЗАТЕЛЕН.") | |
| print(f" Токенизатору нужно {required_rows} строк, в чекпоинте только {have_rows}.") | |
| print(f" Не хватает {extra} строк -> нужно расширять token_emb.weight и lm_head.weight.") | |
| if not all_tool_tokens_present: | |
| print("\nПРИМЕЧАНИЕ: не все tool-calling токены найдены -- перегенерируй токенизатор прежде чем доверять вердикту выше.") | |
| if __name__ == "__main__": | |
| main() | |