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

548 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 主动优化整套改造计划
## 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` 高时,允许 `move``swap` 一起参与小范围微调。
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` 高时,可以正常比较 `move``swap`
2. `slack` 低时,优先考虑一次跨 `task_class``swap` 来调整不同科目间的相对顺序。
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_class``swap` 机会。
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_load``analyze_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. 主动优化完成后的结果,解释口径更像“为什么这样学更顺”,而不是“哪些数字变好看了”。