洄
73M 参数,从零训练的桌面猫系 AI
不是调用 API,而是从 Wiki 预训练开始,到对话微调,到推理部署,完整走通了一遍「造一个小 AI」的全流程。傲娇、会捣乱、也会在你需要时出现。
概述
2026年6月 · 独立完成
洄是一个从零训练的 73M 参数中文对话语言模型,猫系桌面宠物角色。 不是调用 API,而是完整走通了「数据管线 → 模型架构 → 预训练 → 对话微调 → 推理部署」的全流程。
硬件限制:RTX 4050 Laptop 6GB VRAM,在消费级笔记本显卡上完成全量训练。
模型架构
基于 Transformer 的轻量设计
- · 参数量:73M(d_model=512, 16 layers, 8 heads, d_ff=2048)
- · 组件:SwiGLU FFN / RoPE 位置编码 / RMSNorm 归一化
- · 词表:12,000(BPE 分词器,自行训练)
- · 特殊 Token:<user> / <assistant> / <system>
- · 最大序列长度:512
训练流程
两阶段训练
第一阶段 — Wiki 预训练
中文 Wikipedia 语料,让模型学会基础语言能力。 得到 best_model.pt(577MB),作为后续微调的基础。
第二阶段 — 对话微调
混合数据训练:猫设角色扮演对话 ~44k 对 + LCCC 微博中文闲聊 ~50k-200k 对(Claude:LCCC ≈ 2:1)。 训练配置:epochs=5-10, batch_size=8, peak_lr=1e-4。
关键技术细节
- · Loss Masking:只对 assistant 回复计算 loss,显式布尔状态机追踪 in_asst
- · Checkpoint 热启动:strict=False 加载,支持架构升级后迁移
- · 数据清洗:CJK 字符间空格 strip
- · System Prompt 多样性:7 种变体 + 12% dropout 防过拟合
数据清洗与迭代
不是一次就跑通——反复洗数据、调比例、重训练
LCCC 数据的意外干扰
一开始以为越多通用中文对话越好,所以从 LCCC 抽了大量微博闲聊数据。 但实际训练后发现,LCCC 里大量的口语化表达和生活场景内容反而成了噪音—— 比如「今天吃了什么」「周末去哪玩」这类对话和猫设角色的语境完全不搭, 模型学了之后回复开始变得口语化、闲聊化,冲淡了角色的一致性。
另外 LCCC 数据里存在大量汉字间空格(如「会 有 你 的」), 这是因为原始数据的分词残留。虽然写了 strip_cjk_spaces() 清洗函数, 但第一次跑数据管线时漏掉了这一步,导致模型输出也带上了空格污染。
长句子的影响
对话数据中有一些特别长的句子——几十上百字的连续独白。 这些长句子在训练时会导致 attention 分散,模型学到的不是「对话」, 而是「自言自语」。后来加了长度过滤,超过一定阈值的对话对被排除或截断, 回复质量明显改善。
过拟合与反复调试
73M 的参数吃 ~1168 万 token 的数据,很快就出现过拟合—— 模型开始逐字重复自己的回复(「去躺着歇一会儿。去躺着歇一会儿。」), 或者陷入 emoji 循环(🥺😗 一直刷)。
解决不是一次性的——是一个反复调整、重跑、再观察的循环:
- · 调整混合比例:Claude 对话比例从 2:1 降到 1:1 再调回来, 在角色一致性和通用对话能力之间找平衡
- · 增加 LCCC 数据量:从 50k 加到 100k、200k,观察通用数据 能否压制过拟合——有效,但加太多又会冲淡角色
- · 调整 System Prompt:7 种变体加 12% dropout,让模型不依赖 某一种固定的开场白
- · 调整训练轮数:从 10 epoch 降到 5 epoch,减少过拟合风险
- · 推理端加拦截:有些问题训练侧解决不了,只能在推理端硬截—— emoji 循环截断、复读检测、标点压缩
整个过程前前后后重跑了不下十轮。每次改一个变量,跑一遍训练, 看生成效果,再决定下一步改什么。没有标准答案,只能靠迭代摸索。
推理与角色控制
让 AI 保持猫设、不崩人设
推理端实现了多道拦截机制,打磨「像真人聊天」的体验:
- · Emoji 循环截断(🥺😗 偶发 → 自动截断)
- · 猫设复读检测与截断
- · 标点压缩
- · 历史 6 轮自动清零(防止长上下文退化)
- · Claude 系统消息泄露过滤
生成参数:temperature=0.65, repetition_penalty=1.4
不同时期的测试对话
训练过程中的对话样本
早期(Wiki 预训练后,对话微调初期)
你:小洄?
洄:你不说我是谁
你:你是谁
洄:你忘了?我是洄呀!
你:哦好的,洄~
洄:嗯,去吧。今天走了不少路。上课呢?还是下个星期多?还有一个月?
↑ 早期:能识别身份但容易跑题,句子间缺乏连贯性
中期(LCCC 混合微调后)
你:吃草莓吗
洄:吃了,好。
你:你想我吗
洄:想。
你:你想啥呢
洄:你想我吗。
↑ 中期:能直接回答问题,开始有猫系简短风格;但偶发重复和过拟合
后期(调整数据比例 + 优化推理拦截后)
你:你真好
洄:哼!
你:哈哈哈哈哈爱你
洄:哼,你在说啥?
你:(探头)
洄:嗯,在。
↑ 后期:猫设稳定——傲娇+嘴硬+温柔底色。「哼」和「嗯,在」之间 是同一个人