Initial commit: BitFlow MoE - 微型中文 MoE 语言模型 for micro:bit
This commit is contained in:
commit
586917e75c
14 files changed
+2522
No files matched your search
+191
@@ -0,0 +1,191 @@
|
||||
"""
|
||||
BitFlow MoE v4 部署脚本
|
||||
将训练好的 int8 权重和推理代码部署到 micro:bit
|
||||
|
||||
用法:
|
||||
python deploy_moe.py # 自动查找 micro:bit 并部署
|
||||
python deploy_moe.py D:\\ # 指定 micro:bit 盘符
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
import glob
|
||||
|
||||
# 文件路径
|
||||
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
WEIGHTS_FILE = os.path.join(SCRIPT_DIR, "bitflow_moe_weights.bin")
|
||||
INFER_CODE = os.path.join(SCRIPT_DIR, "bitflow_moe.py")
|
||||
|
||||
# micro:bit 上的文件名
|
||||
TARGET_WEIGHTS = "weights.bin"
|
||||
TARGET_MAIN = "main.py"
|
||||
|
||||
|
||||
def find_microbit():
|
||||
"""自动查找 micro:bit USB 盘符"""
|
||||
# Windows: 查找 MICROBIT 卷标
|
||||
for letter in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
|
||||
drive = f"{letter}:\\"
|
||||
if os.path.exists(drive):
|
||||
# 检查是否是 micro:bit
|
||||
label_path = os.path.join(drive, "DETAILS.TXT")
|
||||
if os.path.exists(label_path):
|
||||
try:
|
||||
with open(label_path, "r") as f:
|
||||
content = f.read()
|
||||
if "micro:bit" in content.lower() or "V2" in content or "nRF52" in content:
|
||||
return drive
|
||||
except:
|
||||
pass
|
||||
# 也检查卷标
|
||||
vol_label = os.path.join(drive, "MICROBIT.HTM")
|
||||
if os.path.exists(vol_label):
|
||||
return drive
|
||||
return None
|
||||
|
||||
|
||||
def deploy(target_drive):
|
||||
"""部署文件到 micro:bit"""
|
||||
target_weights = os.path.join(target_drive, TARGET_WEIGHTS)
|
||||
target_main = os.path.join(target_drive, TARGET_MAIN)
|
||||
|
||||
# 检查源文件
|
||||
if not os.path.exists(WEIGHTS_FILE):
|
||||
print(f"[ERROR] 权重文件不存在: {WEIGHTS_FILE}")
|
||||
print(" 请先运行: python train_bitflow_moe.py")
|
||||
return False
|
||||
|
||||
if not os.path.exists(INFER_CODE):
|
||||
print(f"[ERROR] 推理代码不存在: {INFER_CODE}")
|
||||
return False
|
||||
|
||||
# 权重文件大小
|
||||
w_size = os.path.getsize(WEIGHTS_FILE)
|
||||
print(f"\n[deploy] 部署到 micro:bit")
|
||||
print(f" 盘符: {target_drive}")
|
||||
print(f" 权重: {WEIGHTS_FILE} ({w_size/1024:.1f}KB)")
|
||||
print(f" 代码: {INFER_CODE}")
|
||||
|
||||
# 拷贝权重
|
||||
print(f"\n [1/2] 拷贝权重 -> {TARGET_WEIGHTS} ...")
|
||||
try:
|
||||
shutil.copy2(WEIGHTS_FILE, target_weights)
|
||||
print(f" OK ({w_size/1024:.1f}KB)")
|
||||
except Exception as e:
|
||||
print(f" FAILED: {e}")
|
||||
return False
|
||||
|
||||
# 拷贝代码 (重命名为 main.py)
|
||||
print(f" [2/2] 拷贝代码 -> {TARGET_MAIN} ...")
|
||||
try:
|
||||
shutil.copy2(INFER_CODE, target_main)
|
||||
code_size = os.path.getsize(target_main)
|
||||
print(f" OK ({code_size/1024:.1f}KB)")
|
||||
except Exception as e:
|
||||
print(f" FAILED: {e}")
|
||||
return False
|
||||
|
||||
# 验证
|
||||
print(f"\n[verify] 部署验证:")
|
||||
if os.path.exists(target_weights):
|
||||
print(f" {TARGET_WEIGHTS}: {os.path.getsize(target_weights)} bytes OK")
|
||||
else:
|
||||
print(f" {TARGET_WEIGHTS}: MISSING!")
|
||||
return False
|
||||
|
||||
if os.path.exists(target_main):
|
||||
print(f" {TARGET_MAIN}: {os.path.getsize(target_main)} bytes OK")
|
||||
else:
|
||||
print(f" {TARGET_MAIN}: MISSING!")
|
||||
return False
|
||||
|
||||
total = os.path.getsize(target_weights) + os.path.getsize(target_main)
|
||||
print(f"\n[done] 部署完成! 总计 {total/1024:.1f}KB")
|
||||
print(f"\n micro:bit 将自动重启并运行 main.py")
|
||||
print(f" 通过串口 (115200) 发送: GEN:0,1,5|20")
|
||||
print(f" (ID格式: 逗号分隔的字符ID, |后为生成长度)")
|
||||
print(f"\n 字符ID对照表见下方:")
|
||||
return True
|
||||
|
||||
|
||||
def print_vocab():
|
||||
"""打印字符ID对照表"""
|
||||
VOCAB_CHARS = (
|
||||
"猫狗鸟鱼猪牛马鸡虫羊兔鸭鹅"
|
||||
"坐跑飞游看吃睡走听来叫爬跳唱画读做"
|
||||
"在上里到"
|
||||
"的是好了"
|
||||
"吗什么怎哪"
|
||||
"你我他她们它"
|
||||
"蓝绿红黄白"
|
||||
"天地水火花草树木日月星云春夏秋冬"
|
||||
"大小多高远快"
|
||||
"有没会不"
|
||||
"人头脚手眼腿"
|
||||
"垫肉书子"
|
||||
"一三只两"
|
||||
"热冷落开"
|
||||
"自然动植物质色样颜得都"
|
||||
"你好吗谢谢再见早晚安静"
|
||||
"很棒爱喜欢乐伤心气"
|
||||
"名字叫谁和问答应"
|
||||
"聊天话今天说"
|
||||
"客用"
|
||||
"bit"
|
||||
"\n"
|
||||
)
|
||||
print(f"\n{'='*60}")
|
||||
print("字符ID对照表 (用于串口通信)")
|
||||
print(f"{'='*60}")
|
||||
for i, c in enumerate(VOCAB_CHARS):
|
||||
display = "\\n" if c == "\n" else c
|
||||
print(f" {i:3d}: {display} ", end="")
|
||||
if (i + 1) % 8 == 0:
|
||||
print()
|
||||
print()
|
||||
print(f"\n常用短语ID:")
|
||||
examples = {
|
||||
"你好": "0,1", # 需要查实际ID
|
||||
}
|
||||
# 生成常用短语
|
||||
phrases = ["你好", "你好吗", "谢谢", "再见", "早安", "晚安",
|
||||
"你叫什么名字", "你喜欢什么", "什么会飞", "什么会跑"]
|
||||
CH2I = {c: i for i, c in enumerate(VOCAB_CHARS)}
|
||||
for p in phrases:
|
||||
ids = [str(CH2I[c]) for c in p if c in CH2I]
|
||||
print(f" {p}: {','.join(ids)}")
|
||||
print(f"\n 生成命令: GEN:<ID列表>|<生成长度>")
|
||||
print(f" 示例: GEN:{','.join(str(CH2I[c]) for c in '你好' if c in CH2I)}|10")
|
||||
|
||||
|
||||
def main():
|
||||
print("=" * 60)
|
||||
print("BitFlow MoE v4 部署工具")
|
||||
print("=" * 60)
|
||||
|
||||
# 查找 micro:bit
|
||||
if len(sys.argv) > 1:
|
||||
target = sys.argv[1]
|
||||
if not os.path.exists(target):
|
||||
print(f"[ERROR] 指定的盘符不存在: {target}")
|
||||
return
|
||||
else:
|
||||
print("\n[search] 正在查找 micro:bit ...")
|
||||
target = find_microbit()
|
||||
if target is None:
|
||||
print("[ERROR] 未找到 micro:bit!")
|
||||
print("\n请确保:")
|
||||
print(" 1. micro:bit 已通过 USB 连接")
|
||||
print(" 2. micro:bit 已出现在文件管理器中")
|
||||
print(" 3. 如已知盘符, 可指定: python deploy_moe.py D:\\")
|
||||
return
|
||||
|
||||
# 部署
|
||||
success = deploy(target)
|
||||
|
||||
if success:
|
||||
print_vocab()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in new issue
Block a user