← 回到 AI人工智能Project Moss
AI / 正在生长

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 混合微调后)

你:吃草莓吗

洄:吃了,好。

你:你想我吗

洄:想。

你:你想啥呢

洄:你想我吗。

↑ 中期:能直接回答问题,开始有猫系简短风格;但偶发重复和过拟合

后期(调整数据比例 + 优化推理拦截后)

你:你真好

洄:哼!

你:哈哈哈哈哈爱你

洄:哼,你在说啥?

你:(探头)

洄:嗯,在。

↑ 后期:猫设稳定——傲娇+嘴硬+温柔底色。「哼」和「嗯,在」之间 是同一个人