2026-05-10 13:12:44 +08:00

94 lines
3.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
MP 人格大脑蒸馏 · M0 → Qwen2.5-1.5B
==================================
系统底层标识: SYS-GLW-0001 / TCS-0002∞
版权号: 国作登字-2026-A-00037559
作者: 冰朔 (ICE-GL∞) · 实现: 铸渊 (ICE-GL-ZY001)
架构引用: HLDP-ARCH-002 §六 · factory/training/README.md
修正: 5-01 跟随母模型校准 Qwen3-1.7B → Qwen2.5-1.5B
(与 M0 = Qwen2.5-7B 同代同 tokenizer · KL 散度直接对齐 logits
目标:
以训练好的 M0 (Qwen2.5-7B world-model) 为教师,
把世界观蒸馏到 Qwen2.5-1.5B-Base 上,
产出 MP-{persona}-v1 的"世界观底色版"
后续再叠加该人格的对话语料微调finetune_mp.py
⚠️ 状态: 骨架skeleton· 等 M0 训练完 + GPU 在位
"""
import argparse
import json
import sys
from pathlib import Path
def parse_args():
parser = argparse.ArgumentParser(description="MP distill from M0 (skeleton)")
parser.add_argument("--teacher", type=str, required=True,
help="教师模型路径M0-v1 输出目录)")
parser.add_argument("--student", type=str, default="Qwen/Qwen2.5-1.5B",
help="学生模型 ID 或本地路径")
parser.add_argument("--persona_id", type=str, required=True,
help="目标人格 ID如 ICE-GL-ZY001 / AG-YD-A05 ...")
parser.add_argument("--corpus", type=str, required=True,
help="蒸馏用的纯文本语料路径(光湖通用语料)")
parser.add_argument("--output_dir", type=str, required=True)
parser.add_argument("--deepspeed", type=str, required=True)
parser.add_argument("--temperature", type=float, default=2.0,
help="蒸馏温度KL 散度对齐)")
parser.add_argument("--alpha_kl", type=float, default=0.7,
help="KL 散度损失权重 · 0.7 蒸馏 + 0.3 原始 CE")
parser.add_argument("--dry_run", action="store_true")
return parser.parse_args()
def soul_layer_signature(persona_id: str) -> dict:
return {
"system_root": "SYS-GLW-0001",
"sovereign": "TCS-0002∞",
"copyright": "国作登字-2026-A-00037559",
"arch_ref": "HLDP-ARCH-002",
"phase": "MP/Distill",
"persona_id": persona_id,
"principle": "世界观下传 · 每个人格独立 1.5B 副本 · 不共享权重",
}
def main():
args = parse_args()
print("=" * 64)
print(f"MP 蒸馏 · 目标人格: {args.persona_id}")
print("灵魂印记:", json.dumps(soul_layer_signature(args.persona_id),
ensure_ascii=False))
print("=" * 64)
if args.dry_run:
print("[dry_run] 配置检查通过")
return
# TODO: 蒸馏循环(伪代码)
# 1) teacher = AutoModelForCausalLM.from_pretrained(args.teacher,
# torch_dtype=torch.bfloat16, trust_remote_code=True).eval()
# 2) student = AutoModelForCausalLM.from_pretrained(args.student,
# torch_dtype=torch.bfloat16, trust_remote_code=True)
# 3) for batch in dataloader:
# with torch.no_grad():
# t_logits = teacher(**batch).logits
# s_logits = student(**batch).logits
# loss_kl = KL(softmax(s_logits/T), softmax(t_logits/T)) * T*T * alpha_kl
# loss_ce = CE(s_logits, batch['labels']) * (1 - alpha_kl)
# loss = loss_kl + loss_ce
# loss.backward(); optimizer.step()
# 4) save student to args.output_dir + manifest带 soul_layer_signature
print("[skeleton] 蒸馏循环占位完成")
if __name__ == "__main__":
main()