Spaces:
Running
Running
zhan1206 commited on
Commit ·
4cfb0d8
1
Parent(s): bae07a4
fix: F1 mask double-conversion NaN, F2 think token old format, S3 vocab sync, S1/S2 TODO, N1-N5
Browse files- configs/ds_zero3.json +1 -1
- configs/fusion-mini-config.json +0 -1
- models/fusion_mini.py +3 -5
- models/fusion_model.py +19 -10
- models/sbla_attention.py +17 -5
- models/thinking_dial.py +1 -1
- scripts/fix_think_tokens.py +53 -45
- train/full_finetune.py +28 -4
- train/lora_finetune.py +1 -1
configs/ds_zero3.json
CHANGED
|
@@ -15,7 +15,7 @@
|
|
| 15 |
},
|
| 16 |
"overlap_comm": true,
|
| 17 |
"contiguous_gradients": true,
|
| 18 |
-
"sub_group_size":
|
| 19 |
"reduce_bucket_size": "auto",
|
| 20 |
"stage3_prefetch_bucket_size": "auto",
|
| 21 |
"stage3_param_persistence_threshold": "auto",
|
|
|
|
| 15 |
},
|
| 16 |
"overlap_comm": true,
|
| 17 |
"contiguous_gradients": true,
|
| 18 |
+
"sub_group_size": 1e6,
|
| 19 |
"reduce_bucket_size": "auto",
|
| 20 |
"stage3_prefetch_bucket_size": "auto",
|
| 21 |
"stage3_param_persistence_threshold": "auto",
|
configs/fusion-mini-config.json
CHANGED
|
@@ -26,7 +26,6 @@
|
|
| 26 |
"tie_word_embeddings": false,
|
| 27 |
"enable_thinking_dial": true,
|
| 28 |
"num_thinking_depths": 4,
|
| 29 |
-
"think_rank": 0,
|
| 30 |
|
| 31 |
"torch_dtype": "float32",
|
| 32 |
"transformers_version": "4.36.0",
|
|
|
|
| 26 |
"tie_word_embeddings": false,
|
| 27 |
"enable_thinking_dial": true,
|
| 28 |
"num_thinking_depths": 4,
|
|
|
|
| 29 |
|
| 30 |
"torch_dtype": "float32",
|
| 31 |
"transformers_version": "4.36.0",
|
models/fusion_mini.py
CHANGED
|
@@ -357,11 +357,9 @@ class FusionMini(PreTrainedModel):
|
|
| 357 |
# 1. Embeddings
|
| 358 |
hidden_states = self.embeddings(input_ids)
|
| 359 |
|
| 360 |
-
# 2. 处理 attention_mask
|
| 361 |
-
|
| 362 |
-
|
| 363 |
-
attention_mask = attention_mask.unsqueeze(1).unsqueeze(2)
|
| 364 |
-
attention_mask = (1.0 - attention_mask) * -10000.0
|
| 365 |
|
| 366 |
# 3. Transformer 层
|
| 367 |
for layer in self.layers:
|
|
|
|
| 357 |
# 1. Embeddings
|
| 358 |
hidden_states = self.embeddings(input_ids)
|
| 359 |
|
| 360 |
+
# 2. 处理 attention_mask - pass raw HF format to layers
|
| 361 |
+
# Each FusionMiniLayer handles mask conversion internally
|
| 362 |
+
# DO NOT pre-convert here to avoid double-conversion NaN (F1)
|
|
|
|
|
|
|
| 363 |
|
| 364 |
# 3. Transformer 层
|
| 365 |
for layer in self.layers:
|
models/fusion_model.py
CHANGED
|
@@ -96,8 +96,8 @@ class FusionConfig(PretrainedConfig):
|
|
| 96 |
# SBLA 参数
|
| 97 |
self.block_size = block_size
|
| 98 |
self.latent_dim = latent_dim
|
| 99 |
-
self.
|
| 100 |
-
self.
|
| 101 |
self.sbla_mode = sbla_mode
|
| 102 |
|
| 103 |
# Thinking Dial 参数
|
|
@@ -134,6 +134,10 @@ class FusionAttention(nn.Module):
|
|
| 134 |
def __init__(self, config: FusionConfig):
|
| 135 |
super().__init__()
|
| 136 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 137 |
mode = getattr(config, 'sbla_mode', 'hybrid')
|
| 138 |
self.sbla = SBLAttention(
|
| 139 |
hidden_size=config.hidden_size,
|
|
@@ -152,12 +156,15 @@ class FusionAttention(nn.Module):
|
|
| 152 |
past_key_value: Optional[Tuple[torch.Tensor, torch.Tensor]] = None,
|
| 153 |
use_cache: bool = False,
|
| 154 |
) -> Tuple[torch.Tensor, Optional[Tuple[torch.Tensor, torch.Tensor]]]:
|
| 155 |
-
#
|
|
|
|
|
|
|
|
|
|
| 156 |
output = self.sbla(hidden_states, attention_mask)
|
| 157 |
|
| 158 |
-
# KV Cache: extract from SBLA's Q/K projections for cache reuse
|
| 159 |
present_key_value = None
|
| 160 |
if use_cache:
|
|
|
|
| 161 |
batch_size, seq_len, _ = hidden_states.shape
|
| 162 |
K = self.sbla.k_proj(hidden_states)
|
| 163 |
V = self.sbla.v_proj(hidden_states)
|
|
@@ -277,12 +284,14 @@ class FusionModel(PreTrainedModel, GenerationMixin):
|
|
| 277 |
else:
|
| 278 |
raise ValueError("Either input_ids or inputs_embeds must be provided")
|
| 279 |
|
| 280 |
-
# 处理 attention_mask
|
| 281 |
-
|
| 282 |
-
|
| 283 |
-
|
| 284 |
-
|
| 285 |
-
|
|
|
|
|
|
|
| 286 |
|
| 287 |
# Transformer 层(支持 KV Cache)
|
| 288 |
past_key_values = kwargs.get("past_key_values", None)
|
|
|
|
| 96 |
# SBLA 参数
|
| 97 |
self.block_size = block_size
|
| 98 |
self.latent_dim = latent_dim
|
| 99 |
+
self.window_size = window_size or sbla_window_size or block_size
|
| 100 |
+
self.sbla_window_size = self.window_size # Keep as alias for backward compat
|
| 101 |
self.sbla_mode = sbla_mode
|
| 102 |
|
| 103 |
# Thinking Dial 参数
|
|
|
|
| 134 |
def __init__(self, config: FusionConfig):
|
| 135 |
super().__init__()
|
| 136 |
|
| 137 |
+
# TODO(S2): GQA not yet implemented - num_key_value_heads is stored in config
|
| 138 |
+
# but SBLAttention uses num_attention_heads for all Q/K/V projections.
|
| 139 |
+
# To implement GQA: split Q/K/V projections, use num_key_value_heads for K/V,
|
| 140 |
+
# and add repeat_kv() expansion for attention computation.
|
| 141 |
mode = getattr(config, 'sbla_mode', 'hybrid')
|
| 142 |
self.sbla = SBLAttention(
|
| 143 |
hidden_size=config.hidden_size,
|
|
|
|
| 156 |
past_key_value: Optional[Tuple[torch.Tensor, torch.Tensor]] = None,
|
| 157 |
use_cache: bool = False,
|
| 158 |
) -> Tuple[torch.Tensor, Optional[Tuple[torch.Tensor, torch.Tensor]]]:
|
| 159 |
+
# TODO(S1): KV Cache is currently decorative - SBLA recomputes full Q/K/V internally.
|
| 160 |
+
# For true incremental generation, SBLA.forward needs to accept past_key_value
|
| 161 |
+
# and only compute Q for new tokens, reusing cached K/V.
|
| 162 |
+
# Present implementation: always full recomputation, cache returned but unused.
|
| 163 |
output = self.sbla(hidden_states, attention_mask)
|
| 164 |
|
|
|
|
| 165 |
present_key_value = None
|
| 166 |
if use_cache:
|
| 167 |
+
# Cache K/V for potential future use when SBLA supports incremental mode
|
| 168 |
batch_size, seq_len, _ = hidden_states.shape
|
| 169 |
K = self.sbla.k_proj(hidden_states)
|
| 170 |
V = self.sbla.v_proj(hidden_states)
|
|
|
|
| 284 |
else:
|
| 285 |
raise ValueError("Either input_ids or inputs_embeds must be provided")
|
| 286 |
|
| 287 |
+
# 处理 attention_mask - pass raw HF format (1=valid, 0=padding) to SBLA
|
| 288 |
+
# SBLAttention handles the conversion internally
|
| 289 |
+
# DO NOT convert here - it would cause double-conversion NaN (F1)
|
| 290 |
+
# if attention_mask is not None:
|
| 291 |
+
# if attention_mask.dim() == 2:
|
| 292 |
+
# attention_mask = attention_mask.unsqueeze(1).unsqueeze(2)
|
| 293 |
+
# float_mask = attention_mask.to(dtype=hidden_states.dtype)
|
| 294 |
+
# attention_mask = (1.0 - float_mask) * torch.finfo(hidden_states.dtype).min
|
| 295 |
|
| 296 |
# Transformer 层(支持 KV Cache)
|
| 297 |
past_key_values = kwargs.get("past_key_values", None)
|
models/sbla_attention.py
CHANGED
|
@@ -275,12 +275,24 @@ class SBLAttention(nn.Module):
|
|
| 275 |
combined_mask = causal_mask
|
| 276 |
|
| 277 |
# 应用外部 attention_mask(padding mask)
|
|
|
|
|
|
|
| 278 |
if attention_mask is not None:
|
| 279 |
-
|
| 280 |
-
|
| 281 |
-
|
| 282 |
-
|
| 283 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 284 |
else:
|
| 285 |
combined_mask = combined_mask.unsqueeze(0) # (1, 1, seq_len, seq_len)
|
| 286 |
|
|
|
|
| 275 |
combined_mask = causal_mask
|
| 276 |
|
| 277 |
# 应用外部 attention_mask(padding mask)
|
| 278 |
+
# Supports both raw HF format (batch, seq_len) with 1=valid/0=padding,
|
| 279 |
+
# and pre-expanded format (batch, 1, 1, seq_len).
|
| 280 |
if attention_mask is not None:
|
| 281 |
+
if attention_mask.dim() == 2:
|
| 282 |
+
# Raw HF format: (batch, seq_len), 1=valid, 0=padding
|
| 283 |
+
padding_mask = (1.0 - attention_mask.float()).unsqueeze(1).unsqueeze(2) # (batch, 1, 1, seq_len)
|
| 284 |
+
padding_mask = padding_mask * torch.finfo(hidden_states.dtype).min
|
| 285 |
+
combined_mask = combined_mask.unsqueeze(0).unsqueeze(0) + padding_mask # (1, 1, seq, seq) + (batch, 1, 1, seq)
|
| 286 |
+
elif attention_mask.dim() == 4:
|
| 287 |
+
# Pre-expanded format (already converted, e.g. from FusionMini)
|
| 288 |
+
ext_mask = attention_mask.squeeze(1) # (batch, 1, seq_len)
|
| 289 |
+
padding_mask = (1.0 - ext_mask) * float('-inf') # (batch, 1, seq_len)
|
| 290 |
+
combined_mask = combined_mask.unsqueeze(0) + padding_mask.unsqueeze(1)
|
| 291 |
+
else:
|
| 292 |
+
# 3D fallback
|
| 293 |
+
padding_mask = (1.0 - attention_mask.float()).unsqueeze(1) # (batch, 1, 1, seq_len)
|
| 294 |
+
padding_mask = padding_mask * torch.finfo(hidden_states.dtype).min
|
| 295 |
+
combined_mask = combined_mask.unsqueeze(0).unsqueeze(0) + padding_mask
|
| 296 |
else:
|
| 297 |
combined_mask = combined_mask.unsqueeze(0) # (1, 1, seq_len, seq_len)
|
| 298 |
|
models/thinking_dial.py
CHANGED
|
@@ -36,7 +36,7 @@ Thinking Dial(动态推理强度控制)- 真实实现
|
|
| 36 |
import torch
|
| 37 |
import torch.nn as nn
|
| 38 |
import re
|
| 39 |
-
from typing import List, Dict, Optional, Any
|
| 40 |
from dataclasses import dataclass
|
| 41 |
from transformers import PreTrainedModel, GenerationMixin
|
| 42 |
|
|
|
|
| 36 |
import torch
|
| 37 |
import torch.nn as nn
|
| 38 |
import re
|
| 39 |
+
from typing import List, Dict, Optional, Any, Tuple
|
| 40 |
from dataclasses import dataclass
|
| 41 |
from transformers import PreTrainedModel, GenerationMixin
|
| 42 |
|
scripts/fix_think_tokens.py
CHANGED
|
@@ -1,57 +1,65 @@
|
|
| 1 |
#!/usr/bin/env python3
|
| 2 |
-
"""Fix think token
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
import re
|
| 4 |
-
import
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
|
| 6 |
-
#
|
|
|
|
|
|
|
| 7 |
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
|
| 12 |
original = content
|
| 13 |
|
| 14 |
-
#
|
| 15 |
-
content =
|
| 16 |
-
content = content.replace('THINK_END = "|>"', 'THINK_END = "|>"')
|
| 17 |
-
|
| 18 |
-
# Replace build_think_token return
|
| 19 |
-
content = content.replace(
|
| 20 |
-
'return f"{THINK_START}{depth}{THINK_END}"',
|
| 21 |
-
'return f"{THINK_START}{depth}{THINK_END}"'
|
| 22 |
-
)
|
| 23 |
|
| 24 |
-
#
|
| 25 |
-
content =
|
| 26 |
-
'THINK_DEPTH_PATTERN = re.compile(r"<\\|think\\| depth=(\\d+)\\|>")',
|
| 27 |
-
'THINK_DEPTH_PATTERN = re.compile(r"<\\|think_depth_(\\d+)\\|>")'
|
| 28 |
-
)
|
| 29 |
-
|
| 30 |
-
# Replace any inline <|think| depth=N|> with <|think_depth_N|>
|
| 31 |
-
content = re.sub(r'<\|think\|\s*depth=(\d+)\|>', r'<|think_depth_\1|>', content)
|
| 32 |
|
| 33 |
if content != original:
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
print(f" Fixed
|
| 37 |
return True
|
| 38 |
-
|
| 39 |
-
print(f" No change: {filepath}")
|
| 40 |
-
return False
|
| 41 |
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
#!/usr/bin/env python3
|
| 2 |
+
"""Fix think token format across the project.
|
| 3 |
+
|
| 4 |
+
Ensures all files use the unified <|think_depth_N|> format,
|
| 5 |
+
not the old <|think| depth=N|> format.
|
| 6 |
+
"""
|
| 7 |
import re
|
| 8 |
+
import sys
|
| 9 |
+
from pathlib import Path
|
| 10 |
+
|
| 11 |
+
# Old format patterns (to replace)
|
| 12 |
+
OLD_INLINE = re.compile(r'<\|think\|\s*depth=(\d+)\|>')
|
| 13 |
+
OLD_FSTRING = re.compile(r'f"<\|think\|\s*depth=\{(\w+)\}\|>"')
|
| 14 |
+
OLD_TEMPLATE = '<|think| depth='
|
| 15 |
|
| 16 |
+
# New format
|
| 17 |
+
NEW_INLINE = r'<|think_depth_\1|>'
|
| 18 |
+
NEW_FSTRING = r'f"<|think_depth_{\1}|>"'
|
| 19 |
|
| 20 |
+
|
| 21 |
+
def fix_file(filepath: Path) -> bool:
|
| 22 |
+
"""Fix think tokens in a single file. Returns True if changes were made."""
|
| 23 |
+
try:
|
| 24 |
+
content = filepath.read_text(encoding='utf-8')
|
| 25 |
+
except Exception:
|
| 26 |
+
return False
|
| 27 |
|
| 28 |
original = content
|
| 29 |
|
| 30 |
+
# Fix inline occurrences: <|think| depth=N|> -> <|think_depth_N|>
|
| 31 |
+
content = OLD_INLINE.sub(NEW_INLINE, content)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
|
| 33 |
+
# Fix f-string templates: f"<|think| depth={var}|>" -> f"<|think_depth_{var}|>"
|
| 34 |
+
content = OLD_FSTRING.sub(NEW_FSTRING, content)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
|
| 36 |
if content != original:
|
| 37 |
+
filepath.write_text(content, encoding='utf-8')
|
| 38 |
+
count = sum(1 for a, b in zip(original.split('\n'), content.split('\n')) if a != b)
|
| 39 |
+
print(f" Fixed {filepath} ({count} lines)")
|
| 40 |
return True
|
| 41 |
+
return False
|
|
|
|
|
|
|
| 42 |
|
| 43 |
+
|
| 44 |
+
def main():
|
| 45 |
+
project_root = Path(__file__).parent.parent
|
| 46 |
+
|
| 47 |
+
# Scan all Python files
|
| 48 |
+
changed = 0
|
| 49 |
+
for py_file in project_root.rglob('*.py'):
|
| 50 |
+
if fix_file(py_file):
|
| 51 |
+
changed += 1
|
| 52 |
+
|
| 53 |
+
# Also check JSON data files
|
| 54 |
+
for json_file in project_root.rglob('*.json'):
|
| 55 |
+
if 'node_modules' in str(json_file):
|
| 56 |
+
continue
|
| 57 |
+
if fix_file(json_file):
|
| 58 |
+
changed += 1
|
| 59 |
+
|
| 60 |
+
print(f"\nTotal files fixed: {changed}")
|
| 61 |
+
return 0
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
if __name__ == '__main__':
|
| 65 |
+
sys.exit(main())
|
train/full_finetune.py
CHANGED
|
@@ -89,7 +89,7 @@ class FusionFullFinetuneDataset(Dataset):
|
|
| 89 |
think_rank = item.get("think_rank", 0)
|
| 90 |
|
| 91 |
if think_rank > 0:
|
| 92 |
-
thinking_token = f"<|
|
| 93 |
full_text = f"{thinking_token}\n{prompt}\n{response}"
|
| 94 |
else:
|
| 95 |
full_text = f"{prompt}\n{response}"
|
|
@@ -112,6 +112,7 @@ class FusionFullFinetuneDataset(Dataset):
|
|
| 112 |
def create_local_model(
|
| 113 |
model_size: str = "8B",
|
| 114 |
torch_dtype: torch.dtype = torch.bfloat16,
|
|
|
|
| 115 |
):
|
| 116 |
"""
|
| 117 |
创建本地 FusionModel(无需预训练权重)
|
|
@@ -132,6 +133,12 @@ def create_local_model(
|
|
| 132 |
|
| 133 |
config_dict = model_configs[model_size]
|
| 134 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 135 |
common_config = dict(
|
| 136 |
block_size=512,
|
| 137 |
latent_dim=64,
|
|
@@ -146,6 +153,18 @@ def create_local_model(
|
|
| 146 |
|
| 147 |
config = FusionConfig(**config_dict, **common_config)
|
| 148 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 149 |
logger.info(f"[create_local_model] 创建 Fusion-{model_size}(随机初始化)")
|
| 150 |
logger.info(f" hidden_size={config.hidden_size}, layers={config.num_hidden_layers}, "
|
| 151 |
f"heads={config.num_attention_heads}")
|
|
@@ -162,8 +181,7 @@ def create_tokenizer(tokenizer_type: str = "fusion", vocab_size: int = 32000):
|
|
| 162 |
"""
|
| 163 |
Create tokenizer using the unified tokenizer module.
|
| 164 |
"""
|
| 165 |
-
|
| 166 |
-
logger.info(f"[create_tokenizer] Creating tokenizer: type={tokenizer_type}, effective_vocab={effective_vocab}")
|
| 167 |
tokenizer = get_tokenizer(tokenizer_type, vocab_size=vocab_size)
|
| 168 |
return tokenizer
|
| 169 |
|
|
@@ -192,8 +210,14 @@ def train(args):
|
|
| 192 |
vocab_size_map = {"0.5B": 32000, "1.5B": 32000, "8B": 100000, "14B": 100000}
|
| 193 |
tokenizer = create_tokenizer(vocab_size=vocab_size_map.get(args.model_size, 32000))
|
| 194 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 195 |
# 3. 创建模型(本地随机初始化)
|
| 196 |
-
model, config = create_local_model(args.model_size, torch_dtype=args.torch_dtype)
|
| 197 |
|
| 198 |
# 4. 加载数据集
|
| 199 |
train_dataset = FusionFullFinetuneDataset(
|
|
|
|
| 89 |
think_rank = item.get("think_rank", 0)
|
| 90 |
|
| 91 |
if think_rank > 0:
|
| 92 |
+
thinking_token = f"<|think_depth_{think_rank}|>"
|
| 93 |
full_text = f"{thinking_token}\n{prompt}\n{response}"
|
| 94 |
else:
|
| 95 |
full_text = f"{prompt}\n{response}"
|
|
|
|
| 112 |
def create_local_model(
|
| 113 |
model_size: str = "8B",
|
| 114 |
torch_dtype: torch.dtype = torch.bfloat16,
|
| 115 |
+
vocab_size_override: Optional[int] = None,
|
| 116 |
):
|
| 117 |
"""
|
| 118 |
创建本地 FusionModel(无需预训练权重)
|
|
|
|
| 133 |
|
| 134 |
config_dict = model_configs[model_size]
|
| 135 |
|
| 136 |
+
# S3 fix: override vocab_size to match actual tokenizer
|
| 137 |
+
if vocab_size_override is not None:
|
| 138 |
+
config_dict['vocab_size'] = vocab_size_override
|
| 139 |
+
if vocab_size_override is not None:
|
| 140 |
+
config_dict['vocab_size'] = vocab_size_override
|
| 141 |
+
|
| 142 |
common_config = dict(
|
| 143 |
block_size=512,
|
| 144 |
latent_dim=64,
|
|
|
|
| 153 |
|
| 154 |
config = FusionConfig(**config_dict, **common_config)
|
| 155 |
|
| 156 |
+
# Override vocab_size if tokenizer has different size (S3 fix)
|
| 157 |
+
if vocab_size_override is not None and vocab_size_override != config.vocab_size:
|
| 158 |
+
logger.warning(f"[S3-fix] Overriding model vocab_size: {config.vocab_size} -> {vocab_size_override}")
|
| 159 |
+
config.vocab_size = vocab_size_override
|
| 160 |
+
|
| 161 |
+
# S3-fix: sync vocab_size to actual tokenizer if provided
|
| 162 |
+
if vocab_size_override is not None:
|
| 163 |
+
if vocab_size_override != config.vocab_size:
|
| 164 |
+
logger.warning(f"[S3-fix] Overriding vocab_size: {config.vocab_size} -> {vocab_size_override}")
|
| 165 |
+
model.resize_token_embeddings(vocab_size_override)
|
| 166 |
+
config.vocab_size = vocab_size_override
|
| 167 |
+
|
| 168 |
logger.info(f"[create_local_model] 创建 Fusion-{model_size}(随机初始化)")
|
| 169 |
logger.info(f" hidden_size={config.hidden_size}, layers={config.num_hidden_layers}, "
|
| 170 |
f"heads={config.num_attention_heads}")
|
|
|
|
| 181 |
"""
|
| 182 |
Create tokenizer using the unified tokenizer module.
|
| 183 |
"""
|
| 184 |
+
logger.info(f"[create_tokenizer] Creating tokenizer: type={tokenizer_type}, vocab_size={vocab_size}")
|
|
|
|
| 185 |
tokenizer = get_tokenizer(tokenizer_type, vocab_size=vocab_size)
|
| 186 |
return tokenizer
|
| 187 |
|
|
|
|
| 210 |
vocab_size_map = {"0.5B": 32000, "1.5B": 32000, "8B": 100000, "14B": 100000}
|
| 211 |
tokenizer = create_tokenizer(vocab_size=vocab_size_map.get(args.model_size, 32000))
|
| 212 |
|
| 213 |
+
# Sync vocab_size to actual tokenizer size to prevent index-out-of-range (S3)
|
| 214 |
+
actual_vocab_size = len(tokenizer)
|
| 215 |
+
if actual_vocab_size != vocab_size_map.get(args.model_size, 32000):
|
| 216 |
+
logger.warning(f"[S3-fix] Vocab size mismatch: config={vocab_size_map.get(args.model_size, 32000)}, tokenizer={actual_vocab_size}. Syncing to tokenizer.")
|
| 217 |
+
vocab_size_map[args.model_size] = actual_vocab_size
|
| 218 |
+
|
| 219 |
# 3. 创建模型(本地随机初始化)
|
| 220 |
+
model, config = create_local_model(args.model_size, torch_dtype=args.torch_dtype, vocab_size_override=actual_vocab_size)
|
| 221 |
|
| 222 |
# 4. 加载数据集
|
| 223 |
train_dataset = FusionFullFinetuneDataset(
|
train/lora_finetune.py
CHANGED
|
@@ -104,7 +104,7 @@ class FusionDataset(Dataset):
|
|
| 104 |
|
| 105 |
# 注入 Thinking Dial 控制 token
|
| 106 |
if self.add_thinking_token and think_rank > 0:
|
| 107 |
-
thinking_token = f"<|
|
| 108 |
full_text = f"{thinking_token}\n{prompt}\n{response}"
|
| 109 |
else:
|
| 110 |
full_text = f"{prompt}\n{response}"
|
|
|
|
| 104 |
|
| 105 |
# 注入 Thinking Dial 控制 token
|
| 106 |
if self.add_thinking_token and think_rank > 0:
|
| 107 |
+
thinking_token = f"<|think_depth_{think_rank}|>"
|
| 108 |
full_text = f"{thinking_token}\n{prompt}\n{response}"
|
| 109 |
else:
|
| 110 |
full_text = f"{prompt}\n{response}"
|