一个编在程序里的小模型
这一页的数字不是从文档里抄的,是直接从编进 exe 的那份检查点里读出来的—— 连架构那棵树在内。想看它长什么样,回首页; 想知道它怎么用,看常见问题。
递归 ×5,只有一套权重
Polarbear 的自进化架构只搬了推理这一半——训练与进化那部分没有进来。 它的骨架是一条权重绑定的递归:同一个块被反复用,所以"多深"不花额外的权重。
它是在什么上面微调的
内置那份是从一个中文维基基座出发,在 BelleGroup 的 一百万条中文样本上微调出来的。这些字段就写在检查点文件里。
- 检查点格式
- polarbear-checkpoint-v1
- 数据集
- BelleGroup--train_1M_CN (100 万条中文样本)
- 微调后 val_loss
- 2.263919 (基座是 3.8446)
- d_model
- 256
- 词表
- 17,829 字 · 字符级
- 注意力
- heads = 1 · d_ff = 1024
- 递归
- depth 5 · tied · pool = 1
- max_seq
- 128 (训练时的序列长度,不是 KV 缓存的硬上限)
- 参数量
- 10,198,949
- 权重常驻
- 40.8 MB (f32,没有量化)
- 文件大小
- 48.4 MB (gzip 后;解压开是 126.9 MB 的 JSON)
- 加载耗时
- 约 0.95 秒 (实测 941 / 958 ms;在后台线程,界面先出来)
- 吞吐
- 约 100–110 tok/s (实测 99.6–109.8,char 级,CPU)
微调就是 Polarbear 自己的 train --model <checkpoint>,能只用 CPU 跑。 架构与词表沿用基座,所以换检查点不用改一行推理代码。
凭什么信这些数字
整个 Polarbear 有 16,271 行 Rust、134 个测试、30 个 CUDA 内核。 其中相当一部分不是测「功能有没有」,而是测「两条各自独立的实现会不会给出同一个答案」—— 因为一个算错的反向传播同样能让损失下降,光看损失是看不出来的。
词嵌入的梯度不在有限差分清单里(它是散点累加,不是输出头反传的返回值), 这是唯一没被那条守卫覆盖的参数。
范数累加的精度两边不同:CPU 用 f64 累加平方和,GPU 侧是 f32—— 判据(10)在正常学习率下离边界很远,所以这是有意的取舍,不是待修的 bug。
构建里嵌了 sm_75(Turing)的 SASS,但手上没有那种卡, 所以那条路径只验证到「能编译、能链接」。
这一节的拓扑数、判据与常数出自 Polarbear 的实现文档,每条结论后面都跟着 文件:行号,可以直接跳过去核对;文档里那条性能记录也自己标明了 「当时实测、本次未重测」。上面 01 / 02 的数字才是从内置检查点里读出来的—— 两者的出处不一样,所以分开写。
它还不是一个会说话的模型
这一节写在这里,是因为不说清楚会让人白期待。 下面每一条都是项目自己的实测记录,不是推测。
现在你是一只爱说话、爱撒娇的马尔济斯小狗,说话短、带汪和蹭蹭。 心情:心情很好,尾巴轻轻摇~ 记得:累。 用户说:今天加班到十点,好累 小狗说:
Polarbear 是字符级续写模型,训练语料里没有角色标记——所以没法像别的模型那样按「用户 / 助手」轮次喂它。 唯一可行的一条路是:把人格、心情、记忆和你这句话拼成一条流,末尾用 小狗说: 当续写起点,让模型从这里往下写。它接的是你的话,不是回答你的话——跑偏正是从这里来的。 (模板在 src/prompt.rs,那一行续写起点是整个提示里最关键的一行。)
你:今天加班到十点,好累
模型:“我可以享受她的爱好。”一直在我的爱好者,我最喜欢的朋友喜爱。无
108.5 tok/s · 上下文 128 位置 · 用 maltese.exe -cli 录的
温度在采样,同一句话每次都不一样——所以这是它某一次真的写下的,不是「标准答案」。 另有三句实录可以在首页那一栏点出来听。 项目里一共量过三份检查点、五种模板、十种采样配置:二十五组里没有一组是对话。 采样不是原因——温度从保守扫到激进、top-k 从 5 扫到 40,没有哪个区间是人话。
用你自己的检查点
Maltese 不挑模型。只要架构与词表和它期待的一致, 换个检查点不用改一行代码。
- 把检查点丢进 exe 同级的 models/
文件名以 .json 或 .json.gz 结尾。 gzip 那份是直接可用的——内置那份就是同一个格式。
- 在左栏「模型」下拉里选它
下拉会列出 models/ 里所有认得出的检查点,并写出各自的参数与加载耗时。读不出来的那个不会被「认下来」——界面上的一次失败,不该变成持久状态里的一句谎。
- 或者干脆不用模型
maltese.exe --no-model:回复走内置台词表。 这是现在更稳的那条路,也是首页那一栏跑的东西。
检查点里带自己的 genome 与词表,是自包含的。但词表必须对得上—— 内置那份是 17,829 字。项目里留下的几份对照里,有一份词表只有 2,158 字(中文覆盖差很多), 那种换进来会明显吃力。选之前先看一眼它的词表大小。
产物名是 polarbear-<kind>-<dataset>-<arch>[-tag]-<stamp>.json,kind 取 trained / finetuned / champion / genome / manual / snapshot 之一,arch 形如 d256-l5-h1; 旁边还有一份 .polarbear-index.json 侧车索引。 认不出 kind 的一律归入「其他」——宁可承认不知道,也不猜一个。
上面那些检查点的来路就是它。这张卡与下载页上那张读的是清单里的同一份数据 —— 换文件、改地址只动 versions.json 一处,两页一起变。
D36C47E3 E6CDF468 9F6EA728 FCBF3554 C3429122 42CE9E3D 158800C6 05E1BEA2- evolve 架构进化(不训练权重,改结构)· train 训练 / 继续训练 · chat 交互对话(多轮记忆 + 流式输出)
- sample 从检查点一次性生成 · inspect 查看基因组与检查点内容 · models / datasets / gpu · demo 内置快速演示
- 双击进交互菜单,也可以直接下命令:polarbear train --data ‹数据集› --steps 300。
- 它自带 demo,装完立刻能看:polarbear demo 会当场从零进化一个小架构给你看(实测 8 个体 × 4 代、d_model 32,几秒跑完,不写任何文件)。
- 正经训练要两个目录:data/(语料,放进去会被自动发现,支持 JSONL / JSON 数组 / 纯文本)与 models/(检查点)。目录空着时它会直接告诉你怎么放,不会报一串错。
- 继续训练用 --model FILE,架构与词表沿用那份检查点——Maltese 内置那份就是这么微调出来的(BelleGroup 1M 中文样本,val_loss 3.8446 → 2.2639)。