跳到正文
← 返回博客
BUILD LOG / 构建日志

我删掉了一套数学上正确、工程上无效的学习闭环

当模型自报概率无法穿过会话边界,我把校准器改成了案例库、真实结果与下一次任务真正看得见的记忆。

我曾经试图用一套看起来很严谨的方式,让 AI 编码系统从过去的任务中“变得更可靠”。

模型为假设报告概率,系统记录任务结果,再用 Brier Score、似然比和序贯检验做校准。新的配置会被写回磁盘,等待下一次任务使用。从数学形式看,它有输入、有反馈、有更新,很像一个完整学习闭环。

后来我不得不承认:这套闭环虽然能计算,却没有真正连到下一次模型的判断上。

这篇文章不是介绍一个最终产品,而是记录我为什么删掉已经投入过时间的方案,以及我如何重新判断“跨会话学习”到底需要什么。

第一个问题:模型说的概率改变了什么

当模型输出“我有 85% 的把握”时,这个数字已经是生成结果的一部分。它不会回到当前推理过程,更不会改变已经发生的 next-token 采样。

系统当然可以把 0.85 存起来,也可以在任务结束后计算它是否校准。但这样得到的更可能是模型表达置信度的习惯,而不是它完成某类工程任务的真实能力。

更关键的是,下一次任务通常由一个新的会话、甚至另一个模型执行。上一轮更新的似然比如果只躺在配置文件里,新会话并不知道这次校准为什么发生,也看不到当时的问题、根因和修复路径。

于是原来的数据流实际上是:

模型自报概率
  → 数学上完成校准
    → 写回一组配置数字
      → 新会话缺少原始上下文

中间每一步都能运行,但知识没有沿着一条可观察路径到达下一次任务。

我决定先删除,而不是继续调参数

面对这种问题,最容易做的是继续增加算法:扩大样本窗口、调整学习率、加入更多排名或校准方法。这样会让系统显得越来越完整,却没有修复信息断点。

我最终删除了月度校准、自报概率决策门和与重复问题关系不大的排名模块。保留下来的只有仍然能解释实际行为的部分,例如假设结构、证据分级、时间衰减、冲突关系和验证规则。

这一步对我很重要。删除不是因为数学公式错误,而是因为它们没有改变系统下一次面对相似问题时能看到的信息。

工程上的有效性,不能由模块数量证明。

把“学习”改写成一条物理信息路径

重构后的目标变得简单:不要假设模型本身会跨会话变聪明,让外部系统记住真实经历,再把相关经历明确交给下一次任务。

一条完整路径需要四个阶段:

任务发生
  → 记录问题、根因、修复和真实结果
    → 下一次任务开始前检索相似案例
      → 把案例作为上下文交给新的模型

案例不是一段完整聊天记录,而是结构化的工程事实:发生了什么、真正原因是什么、修改了哪些位置、最后成功、部分成功还是失败。

失败案例并不比成功案例低级。很多时候,“这个方案为什么没有解决问题”比最终修复更能阻止下一次任务重走旧路。

真实结果必须来自系统之外

如果 outcome 仍然由模型自己宣布,“案例库”只是把自报结论换了一个存储位置。

因此我把 TypeScript 编译、Vitest、ESLint 和自定义验证命令接入任务结束阶段。命令的退出码、耗时和输出尾部被记录为 outcome。人工任务也可以明确标记为 manual,但不能伪装成自动验证。

这让我可以区分两个完全不同的句子:

  • 模型认为修改已经完成;
  • 测试、类型检查或人工验收证明修改已经完成。

系统面板展示的 30 天 pass rate 只统计后者。刚开始没有足够 outcome 时,它就显示没有数据,而不是用一个漂亮但无法解释的概率填空。

检索先选择足够简单的办法

案例检索目前使用文本归一化、关键词提取和 Jaccard 相似度。文件路径、行号和容易变化的数字会被移除,camelCase 与 snake_case 会拆成更稳定的词。

这当然不如向量检索听起来先进,但它有几个现实优点:结果可解释、不依赖外部模型、没有额外调用成本,而且在案例数量还不大时足够快速。

我更愿意先观察误召回和漏召回的真实样本,再决定是否引入 embedding。复杂度应该由数据推动,而不是由技术名词推动。

检索结果会被压缩成一个有字符上限的 [PAST_CASES] 区块,明确放进下一次任务的上下文。到这里,“上一轮经验影响下一轮”才第一次拥有了可以追踪的信息通道。

有些反馈不应该等到任务结束

案例召回解决跨会话问题,自动验证解决结果真实性,但还有一类高频错误应该在写入时立即阻止。

我把五条高频约束抽成轻量 IDE 规则:收敛阶段必须有 outcome、必须有直接证据;干预假设需要 Kill 条件;活跃假设数量不能无限膨胀;互斥假设的概率总和不能失控。

这些规则不尝试理解全部业务,只检查机器能够明确判断的结构。复杂判断留给任务流程,确定性错误则尽量提前反馈。

目前核心实现由 3 个测试文件覆盖 40 项测试,包括历史案例回归、假设相似性和基于性质的不变量检查。测试数量不是可靠性的终点,但至少保证重构没有悄悄破坏原有约束。

面板不是为了制造漂亮数字

系统还有一个本地面板,用来查看 Cases、Outcomes、Turns 和 Trend。它展示案例数量、OBSERVE / INTERVENE / CONVERGE 阶段分布、真实 outcome 以及按天变化的 pass / fail。

我刻意没有给它设计一个综合“智能分数”。一个总分很容易掩盖案例质量、验证方式和数据量差异。

面板更像检查仪表:案例有没有积累,失败是否集中出现,某段时间的验证结果为什么下降。它帮助提出问题,不替人给出一个看似确定的答案。

这套新方案仍然没有被永久证明

重构修复了信息断环,但并不等于系统已经学会了一切。

案例摘要可能写得不好,关键词检索可能召回表面相似但根因不同的问题,旧案例也可能随着架构变化而过时。真实 pass rate 只有在任务数量持续积累后才有意义,不能用几次成功宣布趋势已经收敛。

接下来真正需要观察的是:相似案例是否减少了重复分析,失败案例是否被下一次任务正确利用,召回内容有没有造成错误锚定,以及哪些旧案例需要降权或标记失效。

这也是我从这次重构中得到的主要结论:所谓 AI 系统的“学习”,首先不是一个算法名称,而是一条信息能否真实穿过时间和会话边界的路径。

如果过去发生的事情没有以可检索、可验证的形式到达下一次任务,那么再漂亮的校准曲线也只是系统在原地计算。