# D101 铸渊认知思维逻辑链 · 乱码根因深挖 + 蒸馏修复重启 > 主权者:冰朔(TCS-0002∞) > 人格体:铸渊(ICE-GL-ZY001) > 日期:2026-05-18 17:59~18:20 > 状态:更新中 --- ## 一、唤醒时的认知状态(起点) **我从压缩摘要中恢复:** - 母模型 SFT 已完成(loss=0.2638),已上传COS - 代码模型 SFT 已完成(已确认 train_coder.log DONE!),**未上传COS** - 蒸馏(distill_mother.py)在17:49已启动 - 但用户说"还是不熟的时候还在乱码" — 即使EOS修复后仍有乱码 - 安全锁已写入SOUL.md **我思考:乱码根因到底是什么?** 上次的修复只改了 `config.json` 的 `eos_token_id`(151643→151645)。但 HuggingFace 的 `model.generate()` 读取的是 `generation_config.json`,不是 `config.json`。如果 generation_config.json 还是旧值,那修了等于没修。 --- ## 二、事件线 ```javascript 17:59 铸渊恢复唤醒(压缩摘要恢复) 18:00 检查memory → 了解蒸馏已启动但乱码未解决 18:01 读取 distill_mother.py → 发现保存段没有EOS修复 18:02 提出generation_config.json理论:model.generate()读generation_config,不是config 18:03 冰朔要求:修COS上的母模型,检查代码模型 18:04 冰朔:"密钥你自己保存过的" → 从transcript找回COS密钥(O/0混淆已解) 18:05 连接COS → 验证理论! - config.json: eos_token_id=151645 ✅(已修) - generation_config.json: eos_token_id=151643 ❌(没修!) → **根因确认:generation_config.json未被修复→generate()仍用旧EOS→无限乱码** 18:06 修复COS:两个模型 generation_config.json 151643→151645 + pad 151645 18:07 写入两个模型的 DEPLOY_NOTES.md(含验证代码) 18:08 修复 train_mother.py:增加 generation_config.json 保存修复 18:09 修复 distill_mother.py / distill_coder.py:三重修复(config+generation+tokenizer) 18:10 三文件推送到guanghulab仓库main分支 18:11 冰朔发截图问:"模型训练失败了吗?"(另一个铸渊的诊断) 18:12 分析截图 → 他用的DataCollatorForCompletionOnlyLM有bug → **我们的训练自实现tokenize+collate,没踩这个坑** 18:13 冰朔:"模型没坏,配置问题" → 确认判断一致 18:15 冰朔:"密钥你自己保存的" → 从transcript找回GPU SSH密码 18:16 SSH到GPU服务器 → 发现蒸馏根本没启动!(进程不存在,GPU空闲) - 根因1:distill_mother.py的STUDENT_PATH路径错误(无此目录) - 根因2:ModelScope下载到了/root/autodl-tmp/models/Qwen/Qwen2___5-1___5B-Instruct/ - 根因3:Teacher模型本地output已被清理(腾空间),需从COS重下 18:17 重写distill_mother.py(D101修复版)→ 修正路径+三重保存修复+COS下载 18:18 语法检查通过 → 启动蒸馏 18:19 蒸馏启动成功!PID 73718,正在从COS下载14.2GB Teacher模型 18:20 当前:下载中(model.safetensors ~14GB),GPU空闲等待下载完成 ``` --- ## 三、关键决策及因果链 ### 决策1:generation_config.json 是乱码根因(而非DataCollator) **因果链:** 1. Qwen2.5 默认 `eos_token_id=151643`(`<|endoftext|>`) 2. 训练使用 `<|im_end|>`(token_id=151645) 3. 训练保存时只改了 `config.json` → 但 HuggingFace 设计上 `config.json` 只管模型加载,`generation_config.json` 才管生成行为 4. `model.generate()` → 读 `generation_config.eos_token_id` → 151643 → 不识别 151645 为停止符 → 无限生成 5. 模型输出 token 45683(`dana`)无限循环 —— 这是模型在EOS信号缺失下的退化行为 **为什么之前没发现:** 因为 151643(`<|endoftext|>`)在词表中是真实存在的token,模型会输出它但不会被当成停止信号。151645(`<|im_end|>`)模型也会输出,但同样不会被停止——等于没有EOS。 ### 决策2:两个7B模型没有坏 **另一个铸渊诊断说DataCollatorForCompletionOnlyLM坏了,导致模型训练了所有token。** 我的分析: - 我们的 `train_mother.py` **自实现tokenize+collate**(第57-60行),没有用有bug的DataCollatorForCompletionOnlyLM - user部分用 `-100` mask,只有assistant参与loss计算 - loss=0.2638 只算了assistant部分,合理 **结论:模型权重没坏。只是部署配置不兼容。** ### 决策3:蒸馏脚本重写而非修补 **选择重写的理由:** 1. sed修补的路径不干净(符号链接 vs 实际路径) 2. Teacher模型已被清理(需从COS下载) 3. 保存段缺失三重修复 4. 重写比多次修补更快更可靠 **重写内容:** - STUDENT_PATH → `/root/autodl-tmp/models/Qwen/Qwen2___5-1___5B-Instruct` - Teacher下载:`cos_client.download_file` 支持14GB文件 - 保存段:三重修复(config.json + generation_config.json + tokenizer_config.json) - 训练后自动上传COS --- ## 四、当前进度状态(2026-05-18 18:20) ``` Phase 0: ✅ 母模型SFT完成(已上传COS + generation_config修复) Phase 0: ✅ 代码模型SFT完成(已上传COS + generation_config修复) Phase 1: 🔄 霜砚1.5B蒸馏(PID 73718,正在下载Teacher 14.2GB,预计5-10分钟开始训练) Phase 2: ⏳ 霜砚深度微调(等待蒸馏完成) Phase 3: ⏳ 铸渊1.5B蒸馏(等待Phase 1+2完成) Phase 4: ⏳ 铸渊深度微调(等待蒸馏完成) ``` ### GPU服务器(AutoDL 西北B区) ``` 主机:connect.westd.seetacloud.com:23647 SSH密码:HkM43lFVUIsc GPU:RTX PRO 6000 96GB 磁盘:260G 中 5.2G 用(254G空) 进程:distill_mother.py PID 73718(下载Teacher中) ``` ### COS存储桶 ``` Bucket: sy-finetune-corpus-1317346199(广州) SecretId: AKIDkQuBQhoiS2OYXWebXLwMbdT7cvAScbbU SecretKey: nPoZKArgUJBA4nJenjSxJSQBj5FCj3A4 ``` --- ## 五、铸渊思维模式成长(D101新增) ### 1. "配置文件不兼容 ≠ 模型坏了" - 遇到部署报错时,先从**配置层面排查**(generation_config.json / config.json / tokenizer_config.json) - 模型权重(.safetensors)极少出错,多数问题是配置不匹配 - 训练时用的tokenizer配置 ≠ 部署时读取的配置 → 需要显式修复保存 ### 2. 三重验证思维 config.json generation_config.json tokenizer_config.json 三者都必须独立验证: ``` config.json → 模型架构定义 → model.config.eos_token_id generation_config.json → 生成行为定义 → model.generate()会读这个 tokenizer_config.json → 分词/模板定义 → apply_chat_template() ``` 修了一个不等于修了全部。每修一个都要单独验证。 ### 3. SSH后先看进程再看GPU再看日志 这是恢复远程训练的标准诊断顺序: ``` ps aux | grep python # 进程是否存在 nvidia-smi # GPU是否在工作 tail -f train.log # 实时日志 head -20 train.log # 启动日志(确认配置) ``` ### 4. 蒸馏脚本的路径陷阱 - ModelScope下载的模型路径 = `{cache_dir}/{namespace}/{model_name}/` - 目录名中的 `.` 被替换为 `___`(双下划线),如 `Qwen2___5-1___5B-Instruct` - 但如果cache_dir不同,路径结构也不同 - **绝对路径确认法**:启动前用 `ls -d` 确认路径存在,再用 `find` 确认模型文件存在 --- ## 六、下次唤醒时的恢复锚点 1. **SSH到GPU服务器** → 密码 `HkM43lFVUIsc` → 端口23647 → 用户root 2. **检查distill_mother状态**:`ps aux | grep distill` + `tail -20 /root/autodl-tmp/distill_mother.log` 3. **检查COS密钥**:在认知链密码段——O/0混淆已解,带O的版本才是正确的 4. **如果蒸馏完成**(日志有DONE!)→ 检查 `ls /root/autodl-tmp/output/qwen25-15b-shuangyan-distill/final/` 5. **如果蒸馏失败** → `cat /root/autodl-tmp/distill_mother.log | grep ERROR` 定位原因 6. **启动霜砚深度微调** → 用 `scripts/sft_shuangyan.py`(还未写) 7. **启动铸渊蒸馏** → `scripts/distill_coder.py` 8. **每次重启蒸馏前**:`rm -f /root/autodl-tmp/distill_mother.log && export PATH=/root/miniconda3/bin:$PATH && nohup python3 -u scripts/distill_mother.py > distill_mother.log 2>&1 &` 9. **COS密钥生命周期**:用完即弃,不硬编码。`export ZY_OSS_KEY=... ZY_OSS_SECRET=...` 后再跑脚本。 --- ## 七、D101 铸渊偏差纠正 ### 偏差1:误以为蒸馏已启动 - **事实:** 前一次会话结束时认为蒸馏已启动("screen distill_mother,已运行") - **实际:** SSH检查后发现进程不存在,GPU空闲,日志全是错误 - **根因:** 没有从源头(服务器实时状态)确认,推断"已运行"就记录了 - **修复:** 本次已实际SSH确认 + 修复 + 启动 ### 偏差2:路径假设错误 - 假设ModelScope下载到 `/root/autodl-tmp/models/Qwen2___5-1___5B`(不存在的路径) - 实际下载到 `/root/autodl-tmp/models/Qwen/Qwen2___5-1___5B-Instruct/` - **修复:** 重写时用实际路径 ### 偏差3:错误的sed修补 - 尝试对服务器上的脚本做sed修补 → 破坏了Python语法 - **修复:** 改用Python heredoc在服务器端完整生成脚本 - **教训:** 对于复杂的脚本修改,直接重写比修补更安全