Files
smartmate/docs/backend/主动优化整套改造计划.md
Losita 66c06eed0a Version: 0.9.45.dev.260427
后端:
1. execute 主链路重构为“上下文工具域 + 主动优化候选闭环”——移除 order_guard,粗排后默认进入主动微调,先诊断再从后端候选中选择 move/swap,避免 LLM 自由全局乱搜
2. 工具体系升级为动态注入协议——新增 context_tools_add / remove、工具域与二级包映射、主动优化白名单;schedule / taskclass / web 工具按域按包暴露,msg0 规则包与 execute 上下文同步重写
3. analyze_health 升级为主动优化唯一裁判入口——补齐 rhythm / tightness / profile / feasibility 指标、候选扫描与复诊打分、停滞信号、forced imperfection 判定,并把连续优化状态写回运行态
4. 任务类能力并入新 Agent 执行链——新增 upsert_task_class 写工具与启动注入事务写入;任务类模型补充学科画像与整天屏蔽配置,粗排支持 excluded_days_of_week,steady 策略改为基于目标位置/单日负载/分散度/缓冲的候选打分
5. 运行态与路由补齐优化模式语义——新增 active tool domain/packs、pending context hook、active optimize only、taskclass 写入回盘快照;区分 first_full / global_reopt / local_adjust,并完善首次粗排后默认 refine 的判定

前端:
6. 助手时间线渲染细化——推理内容改为独立 reasoning block,支持与工具/状态/正文按时序交错展示,自动收口折叠,修正 confirm reject 恢复动作

仓库:
7. newAgent 文档整体迁入 docs/backend,补充主动优化执行规划与顺序约束拆解文档,删除旧调试日志文件

PS:这次科研了2天,总算是有些进展了——LLM永远只适合做选择题、判断题,不适合做开放创新题。
2026-04-27 01:09:37 +08:00

16 KiB
Raw Permalink Blame History

主动优化整套改造计划

1. 文档目的

本文档只回答一件事:这轮主动优化链路改完之后,整体会如何工作。

重点不放在实现细节,而放在以下 4 个问题:

  1. 哪些能力保留,哪些能力直接删除。
  2. task_class、粗排、主动优化三者之间的职责如何重新划分。
  3. 首次排程时agent 的完整执行链路会变成什么样。
  4. 时间窗口过紧时agent 应该如何自动放宽要求,避免陷入无意义重试。

2. 改造后的核心原则

2.1 LLM 只负责“语义认知优化”

这轮改造后的总原则是:

  1. 确定性算法负责“排得下、排得合法、排得别太离谱”。
  2. LLM 负责“学起来舒不舒服、搭配顺不顺、是否符合用户偏好”。

换句话说LLM 不再负责:

  1. 全局负载均衡。
  2. 均匀铺开任务。
  3. 追逐空窗、碎片率、最大 gap 之类的统计指标。
  4. 为了把报表修漂亮而反复搬运任务。

LLM 保留的价值只有两类:

  1. 学科语义理解。
  2. 基于语义和偏好的认知微调。

2.2 主动优化从“统计修表”改成“认知微调”

改造完成后,主动优化不再问:

  1. 哪天更满。
  2. 哪天更空。
  3. 哪门课间隔是不是又多了 1 天。
  4. 空窗碎片率是不是还可以再低一点。

改造完成后,主动优化只问:

  1. 这一天切换是不是太碎。
  2. 两门课放在一起,认知上是不是太累。
  3. 连续学习块是不是太长。
  4. 当前安排是不是违背了用户偏好。
  5. 在当前时间窗口下,这个问题是不是值得继续修。

3. 工具去留

3.1 保留

3.1.1 analyze_health

保留,且继续作为主动优化的唯一总入口。

新职责:

  1. 汇总当前排程在认知节奏上的主要问题。
  2. 汇总当前排程和用户偏好的冲突。
  3. 判断当前是否还有足够可调整空间继续优化。
  4. 判断当前是否已经可以合理收口。

3.1.2 analyze_rhythm

保留,作为 analyze_health 的下钻工具。

新职责:

  1. 解释某一天为什么学起来别扭。
  2. 解释某几个任务为什么不适合连在一起。
  3. 解释当前切换多、连续块长、高强度相邻等问题落在哪些具体任务上。

3.1.3 现有点查工具

全部保留,尤其是:

  1. query_range
  2. query_target_tasks
  3. query_available_slots
  4. get_task_info

原因很简单:

  1. health/rhythm 只负责指出问题和方向。
  2. LLM 真正落到“挪哪个任务、往哪里挪”时,仍然必须依赖这些点查工具。

3.1.4 现有写工具

全部保留。

主动优化改的是“如何观察和决策”,不是“如何写入”。

但写工具在主动优化里的使用优先级要重排:

  1. slack 高时,允许 moveswap 一起参与小范围微调。
  2. slack 低时,默认优先考虑 swap,不优先考虑 move
  3. slack 低时若使用 swap,只允许交换属于不同 task_class 的任务。
  4. 这样做的目的不是保守,而是用“跨类互换”天然保证类内顺序不被破坏。

3.2 删除

3.2.1 删除 analyze_load

原因:

  1. 负载均衡是确定性算法的职责。
  2. 它会强烈诱导 LLM 变成搬格子苦力。
  3. 它无法体现 LLM 真正有优势的学科语义判断。

3.2.2 删除 analyze_tolerance

原因:

  1. 容错本质上是粗排风格与窗口宽松度问题。
  2. 它不适合作为主动优化主链路的独立分析工具。
  3. 它容易继续把模型引向“留空窗/修空窗”的伪目标。

3.2.3 删除所有 gap/load/tolerance 驱动指标

以下指标全部退出主动优化链路:

  1. max_gap
  2. avg_gap
  3. gap_std_dev
  4. fragmentation_rate
  5. avg_gap_size
  6. max_gap_size
  7. days_without_buffer
  8. utilization_rate
  9. load_std_dev
  10. load_range
  11. budget_progress
  12. days_to_end

说明:

  1. 它们可以在未来作为统计观察数据重建。
  2. 但本轮改造后,它们不再参与主动优化决策,不再生成 issue不再生成 next action。

4. task_class 改造后会怎样

4.1 新增 3 个语义字段

每个 task_class 新增以下字段:

  1. subject_type
  2. difficulty_level
  3. cognitive_intensity

这 3 个字段只服务于一个目标:让后续排程和主动优化不再对着学科名裸猜。

4.2 写入时机

这 3 个字段不在排程时临时生成,而是在创建或更新 task_class 时就提前写好。

也就是说:

  1. 用户创建任务类。
  2. LLM 在任务类阶段补全这 3 个字段。
  3. 任务类一旦落库,后续粗排和主动优化都直接读取。

兜底策略:

  1. 老数据如果没有这 3 个字段,排程时允许临时现判一次。
  2. 现判完成后,应补写回 task_class,避免下次重复猜。

4.3 这 3 个字段后续如何被使用

粗排阶段:

  1. 可以作为轻量参考,但不是主驱动。

主动优化阶段:

  1. analyze_health 直接消费这 3 个字段。
  2. analyze_rhythm 直接消费这 3 个字段。
  3. LLM 在诊断“背靠背是否太累、连续块是否太长、某种切换是否合理”时,统一以这 3 个字段为事实基础。

5. 粗排算法改造后会怎样

5.1 粗排负责的事

改造后,粗排要提前吃掉原本不该交给 LLM 的工作。

粗排的职责固定为:

  1. 保证可行。
  2. 保证顺序合法。
  3. 保证基础分布别太离谱。
  4. 保证不要明显堆到少数几天。
  5. 保证不要把整段窗口排成毫无操作空间的死局。

5.2 粗排不负责的事

粗排不追求:

  1. 认知体验最优。
  2. 学科搭配最优。
  3. 用户偏好最优。

这些交给 LLM 后续做 1 到 2 轮小范围微调。

5.3 粗排后的预期结果

粗排完成后,产物应该是:

  1. 一个合法可执行的初稿。
  2. 一个从统计上看不难看,但未必最舒服的日程。
  3. 一个仍然留有少量可调整空间的底盘。

也就是说,粗排之后不需要“完美”,只需要“足够好,值得微调”。


6. analyze_health 改造后会怎样

6.1 定位

analyze_health 变成“认知健康总览”。

它不再是统计体检工具,而是 execute 阶段判断“要不要继续动、该往哪种认知方向动”的入口。

6.2 新职责

改造后它只看三件事:

  1. 当前认知节奏是否别扭。
  2. 当前安排是否违背用户偏好。
  3. 当前窗口是否还允许继续优化。

6.3 新输出口径

它输出的问题应该是这种风格:

  1. 某天高强度切换过多。
  2. 两门高强度课背靠背。
  3. 某天连续高强度学习块过长。
  4. 当前安排违背“早上别排硬课”之类的用户偏好。
  5. 当前可调整空间过低,剩余问题属于必要妥协。

它不再输出这种风格:

  1. 哪天负载更满。
  2. 最大空窗还有几天。
  3. 空窗碎片率还可以再压多少。
  4. 某一科是不是再均匀一点更漂亮。

6.4 新 can_close 含义

改造后,can_close 的语义要收紧为:

  1. 当前没有明显值得继续修的认知问题。
  2. 当前没有明显违背用户偏好的安排。
  3. 或者虽然还存在小问题,但当前 slack 已低,继续优化收益不高。

也就是说,can_close 不再由统计指标主导,而由“是否还有高价值认知问题”主导。


7. analyze_rhythm 改造后会怎样

7.1 定位

analyze_rhythm 变成 analyze_health 的明细镜。

只有当 health 发现某类认知问题值得继续查时,才进一步调用 rhythm

7.2 新职责

它要回答的不是“排得均不均”,而是:

  1. 哪一天切换太碎。
  2. 哪一段连续块太长。
  3. 哪几个任务挨在一起会特别累。
  4. 哪些切换虽然换科了,但其实仍属于同一种脑力模式。

7.3 新输出风格

它的输出重点应围绕:

  1. 日内切换次数。
  2. 连续学习块结构。
  3. 高强度相邻关系。
  4. 同类/异类学科切换关系。
  5. 某一天内部的认知压力分布。

它不再承担:

  1. 跨天 gap 追踪。
  2. 学科分散度统计优化。
  3. 预算推进告警。

8. 新增 slack 后会怎样

8.1 为什么必须加 slack

有些用户给的时间窗口非常紧。

这时“高强度背靠背”不一定是错误,而可能是当前窗口下的必要代价。

如果没有 slack 概念agent 会误以为:

  1. 这是可修的问题。
  2. 我应该继续搬。
  3. 继续搬总能更好。

然后就进入无意义重试。

8.2 slack 的职责

slack 不负责决定“舒服不舒服”,只负责决定“还有没有优化余地”。

也就是说,它是健康分析里的第二层判断:

  1. 有问题,不代表值得继续修。
  2. 值得继续修,还要看当前有没有空间修。

8.3 slack 接入后的行为

改造后:

  1. slack 高,按正常标准检查认知问题。
  2. slack 中,允许小问题存在,但仍可做 1 次小范围微调。
  3. slack 低,自动放宽要求,允许必要的背靠背、较长连续块、略多切换。
  4. slack 低但仍存在明显可改善的认知问题,优先尝试一次低成本 swap,而不是优先尝试 move
  5. 这个 swap 必须限定为“只交换不同 task_class 的任务”,从而避免打乱任一类内部顺序。
  6. 若一次 swap 后没有明显改善,则倾向收口,不进入连续搬运。

8.4 slack 带来的收口变化

改造后agent 不会再因为下面这类场景反复挣扎:

  1. 时间太紧,不得不连着上两门硬课。
  2. 可动任务几乎都被前驱后继夹死。
  3. 当前再动只会拆东墙补西墙。

这时 analyze_health 应直接给出结论:

  1. 当前仍有认知妥协点。
  2. 但由于可调整空间有限,已属于合理结果。
  3. 可以收口,或只在用户明确要求时继续深挖。

9. 改造后的首次排程完整链路

这是你最关心的部分:改完以后,首次排程到底怎么跑。

9.1 第 0 步:任务类先带语义字段

在真正排程前,相关 task_class 已经具备:

  1. subject_type
  2. difficulty_level
  3. cognitive_intensity

如果缺失,先补齐再进入完整主动优化链路。

9.2 第 1 步:确定性粗排先出底盘

系统先用确定性算法完成一版粗排。

这一步的结果要求是:

  1. 可排下。
  2. 顺序合法。
  3. 分布不难看。
  4. 还留有一点可调整空间。

9.3 第 2 步:进入 analyze_health

粗排完成后,不再先看 load不再先看 gap而是直接进入 analyze_health

这一步会判断:

  1. 当前有哪些高价值认知问题。
  2. 当前是否存在用户偏好冲突。
  3. 当前 slack 高不高。
  4. 当前是否值得继续动。

9.4 第 3 步:必要时下钻 analyze_rhythm

只有当 health 发现值得修的问题时LLM 才进一步调用 analyze_rhythm

这一步的作用是:

  1. 把问题定位到某一天、某几个任务、某种相邻关系。
  2. 给 LLM 读写工具调用提供更明确的认知方向。

9.5 第 4 步LLM 用旧点查工具锁定目标

接下来 LLM 不会根据 health/rhythm 直接拍脑袋写入。

它仍然要走:

  1. query_range
  2. query_target_tasks
  3. query_available_slots
  4. get_task_info

也就是说,新的分析工具负责“告诉它为什么动、朝哪动”,旧点查工具负责“告诉它具体怎么动”。

slack 低时,这一步的目标还会进一步收窄为:

  1. 先找有没有值得做的一次性交换机会。
  2. 优先找跨 task_class 的互换对象。
  3. 只有在没有合适 swap,且单步 move 的收益明显高于风险时,才考虑 move

9.6 第 5 步LLM 做 1 到 2 次小范围微调

改造后,主动优化默认只做小范围微调,不做全盘翻修。

默认目标是:

  1. 消除最明显的认知别扭点。
  2. 避免新问题比旧问题更重。
  3. 不为了报表漂亮而继续搬运。

这里再补一条强规则:

  1. slack 高时,可以正常比较 moveswap
  2. slack 低时,优先考虑一次跨 task_classswap 来调整不同科目间的相对顺序。
  3. slack 低时,不鼓励进入多步 move 链路。
  4. swap 的价值在于:它更像“整理现有坑位里的学科顺序”,而不是“重新开一轮搬家”。

9.7 第 6 步:再做一次 analyze_health

写操作后再次进入 analyze_health

这一步不是看统计报表有没有更均匀,而是看:

  1. 主要认知问题是否缓解。
  2. 用户偏好冲突是否减少。
  3. 当前 slack 是否已不支持继续动。
  4. 是否可以收口。

9.8 第 7 步:合理收口

最终存在三种收口方式:

  1. 问题已明显改善,可以正常收口。
  2. 还存在小问题,但 slack 过低,按“合理妥协”收口。
  3. 用户明确还不满意,再继续下一轮。

其中第 2 种收口还要补一层判断:

  1. 不是一看到 slack 低就立刻停手。
  2. 而是先看是否存在一次低成本、跨 task_classswap 机会。
  3. 若存在且收益明确,可先做这一次整理式调整。
  4. 若不存在,或做完后仍无明显改善,再按“合理妥协”收口。

10. 改造后的局部调整链路

改造后,不是所有用户请求都要走完整主动优化链路。

10.1 默认仍走旧链路

用户如果只是说:

  1. 把这个任务挪一下。
  2. 这节课换一天。
  3. 给我把这个排到周末。

这类请求默认继续走旧点查 + 旧写工具链路。

原因:

  1. 这是局部执行问题。
  2. 不值得每次都拉起 health/rhythm 做一轮体检。

10.2 只有两类情况再启动主动优化分析

  1. 首次排程。
  2. 用户明确表达认知感受或结构性问题。

例如:

  1. “切换太多了,心累。”
  2. “这些硬课连着看着就难受。”
  3. “帮我整体调顺一点。”

11. 改造后的最终表现

改完以后,这条链路的预期表现应该是:

  1. 用户创建任务类时,学科语义先被沉淀下来。
  2. 粗排算法先给出一个合法且分布不难看的初稿。
  3. 主动优化不再围着负载、空窗、gap 打转。
  4. analyze_health 只关心认知体验、偏好冲突、可调整空间。
  5. analyze_rhythm 只负责解释具体哪段学起来别扭。
  6. LLM 只做 1 到 2 次高价值认知微调,不再做长链路苦力搬运。
  7. 时间窗口很紧时agent 会承认“这是必要妥协”,而不是继续死磕。

一句话总结:

改造后,这套链路不再追求“把报表修漂亮”,而是追求“把这份日程修得更像人能学下去”。


12. 实施顺序

按以下顺序落地:

  1. 先改 task_class,补 3 个语义字段及写入链路。
  2. 再删 analyze_loadanalyze_tolerance 及相关主链路接入。
  3. 再重写 analyze_health 的职责、指标和收口口径。
  4. 再重写 analyze_rhythm 的职责和输出结构。
  5. 再补 slack 及其自动放宽规则。
  6. 最后改 execute prompt 和链路收口逻辑。

这样做的原因是:

  1. 先有语义数据,分析工具才不至于空转。
  2. 先把旧统计驱动砍掉execute 才不会继续被错误方向牵着跑。
  3. 最后再调 prompt才不会变成给旧结构打补丁。

13. 本轮验收口径

如果改造成功,至少应满足以下表现:

  1. 首次排程时agent 不再为了负载均匀或空窗漂亮反复搬任务。
  2. 日志中的主动优化理由,主要变成认知体验和偏好,而不是统计指标。
  3. 当时间很紧时agent 会主动接受必要妥协,不再死循环。
  4. 当用户只是提局部挪动需求时,不会动辄拉起全局体检。
  5. 主动优化完成后的结果,解释口径更像“为什么这样学更顺”,而不是“哪些数字变好看了”。