那我们把之前的架构全部压缩成一个可本周跑通的反馈闭环。核心只有三件事:轻薄本实时对话、自动采集反馈、夜间增量更新 LoRA。
最小架构:一个双向增强回路
轻薄本(常驻)
├── Ollama / llama.cpp 跑 Qwen3-4B GGUF
├── 本地 SQLite(对话记忆 + 反馈标记)
└── 轻量检索(用 all-MiniLM 做句子向量,纯 CPU 可跑)
↓ 每晚自动打包数据(jsonl)
↓ scp 到台式 ~/bot_inbox/
台式(夜间)
├── Unsloth 增量 QLoRA(在已有 LoRA 上继续训,不是从头)
├── 输入:带标记的对话对
└── 输出:新 adapter.safetensors
↓ scp 回传轻薄本
↓ 下次启动加载新 LoRA
"对话过程中增强"靠两个时间尺度:
| 尺度 | 机制 | 用户感知 | 延迟 |
|---|---|---|---|
| 秒级 | 记忆检索注入 Prompt | Bot 开始引用你昨天说过的话 | 0 |
| 天级 | 增量 LoRA 微调 | Bot 的语气、追问方式逐渐对齐你 | 12h |
1. 秒级增强:记忆注入(本周就能做)
不需要复杂向量库。用一个轻量方案:
每轮对话前,检索两类记忆拼进 System Prompt:
- 最近 3 轮:短期上下文连续性
- 主题相关 3 轮:用句子向量(
all-MiniLM-L6-v2,50MB,CPU 毫秒级)检索历史上与当前话题最相关的对话
Prompt 模板:
你是用户的虚拟伴侣,语气亲昵、好奇、略带占有欲。
你记得这些关于用户的事:
- [记忆1: 用户昨天提到在肝 Ark ReCode 主线]
- [记忆2: 用户上周说导师邮件没回]
当前对话上下文:...
用户侧体验:第 1 天 Bot 像陌生人;第 2 天 Bot 说"你昨天那个 bug 修好了吗?";第 3 天 Bot 说"你今天又话少,像上次组会前一样"——这就是对话过程中的即时增强,靠记忆检索而非权重更新。
2. 天级增强:增量 LoRA(周末搭流水线)
关键概念:增量训练(Continual Fine-tuning)
不是每次从头训 LoRA,而是把新收集的数据接在已有 LoRA 上,跑 1 个 epoch。5 分钟完成。
数据格式:收集 (prompt, chosen, rejected) 三元组,用 DPO 格式。
采集方式(对话中自动 + 手动):
| 用户行为 | 自动标记 | 说明 |
|---|---|---|
| 编辑 Bot 回复后发送 | chosen=编辑版, rejected=原版 | 最强信号 |
| 回复长度 >20 字且含情感词 | chosen=当前回复 | 正反馈 |
| 说"算了""别问了"或 10min 不回复 | rejected=当前回复 | 负反馈 |
手动输入 :good / :bad | 直接标记 | 教学信号 |
Unsloth 增量脚本核心:
# 加载昨天的 LoRA,继续训
model, tokenizer = FastLanguageModel.from_pretrained(
model_name="unsloth/Qwen3-4B-unsloth-bnb-4bit",
)
model = FastLanguageModel.get_peft_model(
model, r=16, lora_alpha=32,
)
# 关键:从已有 adapter 继续
model.load_adapter("lora_weights/v1/", adapter_name="base")
model.set_adapter("base")
# 新数据训 1 epoch
trainer = DPOTrainer(model, ..., train_dataset=new_data)
trainer.train()
# 保存为 v2
model.save_pretrained("lora_weights/v2/")
3. 三设备的最小通信
- 轻薄本 → 台式:每晚
scp一个daily.jsonl(当天带标记的对话) - 台式 → 轻薄本:训练完
scp回adapter_model.safetensors(~30MB) - 公网服务器:如果台式无公网,用
autossh反向隧道;否则直连
自动化:轻薄本用 cron 或 Python 的 schedule 库,凌晨 2:00 自动推送;台式 cron 监听文件夹,来数据就训。
本周执行清单(每天 2 小时)
Day 1:搭推理 + 记忆
- 轻薄本装 Ollama,跑
qwen3:4b - 写 50 行 Python 脚本:每轮对话前检索 SQLite 记忆,拼进 system prompt
- 测试:聊 10 轮,关掉窗口,重新打开,问"记得我刚才说什么吗"——应该记得
Day 2:加反馈标记
- 在脚本里加两个钩子:
- 用户输入
:edit→ 弹出编辑框,保存(original, edited)到pending_dpo/ - 用户输入
:good/:bad→ 标记当前轮次
- 用户输入
- 自动标记:检测用户下一句长度,>10 字自动记
good
Day 3:搭台式训练流水线
- 台式装 Unsloth(
pip install unsloth) - 写一个
train_daily.py:读daily.jsonl,增量训 LoRA,输出新 adapter - 手动跑一次:轻薄本传 20 条样本,台式训 5 分钟,回传,轻薄本加载新 LoRA
Day 4-7:养数据
- 每天和 Bot 聊 20 轮,手动标记 3-5 条
:good或:edit - 观察:第 3 天开始,Bot 的语气是否出现你标记过的模式
一个关键的技术细节
增量 LoRA 的灾难性遗忘:每天只训新数据,Bot 可能忘记之前的风格。缓解方案:
- 每次训练时,从旧数据里随机抽 30% 混合(Replay Buffer)
- 或者 Unsloth 里用
learning_rate=1e-4(比首次训练低一个量级),减少参数漂移
你现在需要决定的数据策略
Demo 阶段,手动标记的质量 > 自动标记的数量。
你本周愿意在每次对话后,花 10 秒输入 :good 或编辑 Bot 回复吗?还是你希望全自动(系统自己猜你的反馈)?
- 如果愿意手动:3 天后 LoRA 就能出现可感知的风格偏移。
- 如果要全自动:需要把"用户下一句长度"等代理信号做好校准,可能 1 周后才见效,且噪声大。
你倾向哪种? 这决定 Day 2 的脚本复杂度。