开源项目Online-SDFT展示在安卓设备上对230M小模型持续微调,利用用户与通知的延迟交互信号更新模型,所有推理和训练均在本地完成。
小型语言模型现在已经可以直接在手机上运行。但它们中的大多数在发布的那一刻就停止了学习。

对于个人 AI 而言,这似乎是一个奇怪的终点。一些最有用的信号只在模型行动之后才会出现:
用户是否忽略了这个通知?
他们之后是否又打开了它?
他们是否重写了建议内容?
他们是否再次请求了它?
这些交互包含了关于用户的有用信息,但它们是延迟的、私密的、模糊的。它们不是干净的标签,也不是可靠的标量奖励。
为了探索这个问题,我们构建了 Online-SDFT——一个开源原型,它在保持学习循环在设备端运行的同时,持续地从延迟交互中对小型语言模型进行微调。
一旦模型被配置好,推理、交互存储、重放和适配器更新就全部在本地发生。
假设模型收到一个通知,并在三个动作中选择一个:
监督微调需要对每个通知都有一个正确答案。但手机从未观察到理想动作是什么。
强化学习用奖励取代了正确答案,但这个奖励也很难定义。打开一个通知并不一定意味着它出现在正确的时间。忽略它也不一定意味着它不重要。用户可能只是当时很忙。
还有另一个复杂因素:模型只能观察到它实际采取的行动的结果。如果它归档了一个通知,它就无法知道如果它立即显示了通知会发生什么。
手机收到的不是标签或奖励。它收到的是"后见之明"。
核心思想很简单:让模型在看到发生了什么之后重新审视自己的决策。
在决策时刻,学生只能看到当前上下文:
notification + time + local context
之后,老师看到相同的上下文加上观察到的结果:
notification + time + local context + what the user did afterward
因为老师有更多信息,它可以产生一个更好、更明智的动作分布。我们随后将这个软分布蒸馏给学生,而学生在未来做决策时无法访问结果。
从概念上讲,循环是这样的:
for interaction in stream:
context = observe_context()
action = student.sample(context)
execute(action)
hindsight = wait_for_outcome(action)
with lora_disabled():
target = model(context, hindsight)
if causally_supported(action, hindsight):
replay.add(context, target)
update_lora(replay.sample_balanced())
没有单独的教师模型。部署的模型使用其 LoRA 适配器来行动,而相同的冻结基础模型在禁用适配器的状态下回顾已完成的交互。
老师知道发生了什么。学生学习预测老师会得出什么结论。
一个诱人的替代方案是将每个结果转换为一个硬标签。
dismissed notification → archive
但这种推断往往太强了。忽略通知可能意味着通知不相关、时间不对、已经从预览中理解了,或者只是被其他任务打断了。
因此,Online-SDFT 使用可靠性调节的软目标。可靠的结果可以强烈支持一个动作。模糊的结果只在仍然合理的动作之间重新分配概率。没有什么有用信息的结果则不产生更新。
这很重要,因为它防止训练循环编造反事实结果或将每个手势都视为明确的偏好。
香草自蒸馏没有指定如何从一个实时的、依赖动作的流中收集有用的交互。
一个纯粹贪婪的模型可能会锁定在早期行为上,只收集证实自己选择的证据。
我们在模型不确定时添加少量探索,然后随着信心增长逐渐减少。这给了系统机会从替代动作中观察结果,而不会永久地使服务策略变得随机。
反馈是稀疏的且相关的。几个相似的结果可能一起到达,而罕见但有信息量的结果可能只发生一次。
我们不是只从最新的交互中更新,而是保留一个有界的最近教训窗口。采样平衡反馈类别,同时优先考虑更新的例子。最新教训总是被包含在内,这样模型就能保持对变化的响应能力。
重放仅用于训练。它不会使服务提示变长。
我们在三个配对的合成通知流上评估了六种方法,每个流有 240 个决策。
以下是精选结果:
Online-SDFT 在 720 个决策中匹配了 506 个隐藏的采样偏好。
与拒绝微调的比较特别有趣。拒绝微调使用了相同的 LoRA 容量,但需要经过验证的硬目标。它接受了 311 个后见之明教师候选中的 75 个。Online-SDFT 可以保留来自结果的有用但不够强到无法构成 one-hot 标签的分级信息。
重放也相当重要。移除重放后,偏好准确率从 70.3% 降至 39.6%,累积遗憾从 44.8 增加到 134.9。
这些结果是初步的。只有三个合成流,而且所选配置是在这些相同的流上调整的,而不是在单独的保留基准上确认的。
仓库包含一个独立的 Android 项目,在物理设备上运行持续学习循环。
冻结的 230M 参数基础模型做出通知路由决策。一旦结果可用,ONNX Runtime Training 就会更新 LoRA 适配器。适配器检查点和重放状态保留在应用私有存储中,并在应用重启后保留。
在一次物理手机测试中,反复忽略一个通知会教导模型保持沉默。再次请求该通知然后改变学习到的行为,使得下一个会被显示。
没有服务器执行更新。
这仍然是一个工程原型,而不是生产级别的通知管理器。当前的计算图使用 FP32,目标是高内存 ARM64 设备。模型导出和初始配置仍然需要 Linux 主机。我们也还没有完成对延迟、峰值内存、电池消耗或热节流的系统分析。
Android 通知监听器 API 也在通知发布之后才运行,所以当前的原型演示的是事后路由,而不是在警报出现之前的保证抑制。
项目及完整论文:Online-SDFT
源代码和 Android 原型:GitHub 仓库
可运行实验:Google Colab notebook
我们感兴趣更广泛的问题是:
还有哪些应用可以从延迟的、依赖动作的结果中本地学习?
通知路由是一个例子,但相同的结构也出现在写作建议、快捷方式推荐、应用排名、邮件辅助和其他形式的个人 AI 中。
我特别感兴趣的是那些有用信号已经存在于设备上、但太过模糊而无法被视为传统标签或奖励的例子。
披露:我在起草和编辑本文时使用了 AI 辅助。在发布之前,我对照链接的实现和实验结果审查了技术声明。