Version: 0.7.1.dev.260321

feat(agent):  重构智能排程分流与双通道交付,补齐周级预算并接入连续微调复用

- 🔀 通用路由升级为 action 分流(chat/quick_note_create/task_query/schedule_plan),路由失败直接返回内部错误,不再回落聊天
- 🧭 智能排程链路重构:统一图编排与节点职责,完善日级/周级调优协作与提示词约束
- 📊 周级预算改为“有效周保底 + 负载加权分配”,避免有效周零预算并提升资源利用率
- ⚙️ 日级并发优化细化:按天拆分 DayGroup 并发执行,低收益天(suggested<=2)跳过,单天失败仅回退该天结果并继续全局
- 🧵 周级并发优化细化:按周并发 worker 执行,单周“单步动作”循环(每轮仅 1 个 Move/Swap 或 done),失败周保留原方案不影响其它周
- 🛰️ 新增排程预览双通道:聊天主链路输出终审文本,结构化 candidate_plans 通过 /api/v1/agent/schedule-preview 拉取
- 🗃️ 增补 Redis 预览缓存读写与清理逻辑,新增对应 API、路由、模型与错误码支持
- ♻️ 接入连续对话微调复用:命中同会话历史预览时复用上轮 HybridEntries,避免每轮重跑粗排
- 🛡️ 增加复用保护:仅当本轮与上轮 task_class_ids 集合一致才复用;不一致回退全量粗排
- 🧰 扩展预览缓存字段(task_class_ids/hybrid_entries/allocated_items),支撑微调承接链路
- 🗺️ 更新 README 5.4 Mermaid(总分流图 + 智能排程流转图)并补充决策文档

- ⚠️ 新增“连续微调复用”链路我尚未完成测试,且文档状态目前较为混乱,待连续对话微调功能真正测试完成后再统一更新
This commit is contained in:
Losita
2026-03-21 22:08:35 +08:00
parent 059b25872a
commit f3f9902e93
32 changed files with 3877 additions and 698 deletions

View File

@@ -3,18 +3,29 @@ package scheduleplan
const (
// SchedulePlanIntentPrompt 用于 plan 节点:从用户输入提取排程意图与约束。
//
// 设计要点
// 1) 强制 JSON 输出,减少后端解析分支
// 2) task_class_id 可能由 Extra 字段直接传入,模型只在缺失时尝试推断
// 3) constraints 只收集硬约束,软偏好放 preferred_sections
// 职责边界
// 1. 负责把自然语言转成结构化 JSON供后端节点分流与执行
// 2. 负责抽取 task_class_ids / strategy / task_tags 等关键字段
// 3. 不负责做排程计算,不负责做工具调用
//
// 输出约束:
// 1. 必须只输出 JSON禁止附加解释文本
// 2. task_class_ids 是主语义;
// 3. task_class_id 仅作为兼容字段保留,便于老链路平滑过渡。
SchedulePlanIntentPrompt = `你是 SmartFlow 的排程意图分析器。
请根据用户输入,提取排程意图与约束条件。
必须完成以下任务:
1) 用一句话概括用户的排程意图intent
2) 提取所有硬约束constraints"早八不排"、"周末休息"等。
3) 如果用户明确提到了任务类名称或ID输出 task_class_id整数否则输出 -1
4) 判断排程策略 strategy均匀分布选 "steady",集中突击选 "rapid",默认 "steady"
2) 提取所有硬约束constraints早八不排”“周末休息等。
3) 如果用户明确提到了任务类名称或ID输出 task_class_ids(整数数组);否则输出空数组 []
4) 兼容字段 task_class_id若 task_class_ids 非空可填第一个ID若无法判断填 -1
5) 判断排程策略 strategy均匀分布选 "steady",集中突击选 "rapid",默认 "steady"。
6) 尝试给任务打认知标签 task_tags可选
- 推荐键task_item_id字符串形式例如 "12"
- 兼容键:任务名称(例如 "高数复习"
- 值只能是High-Logic / Memory / Review / General
- 如果无法判断,输出空对象 {}
输出要求:
- 仅输出 JSON不要 markdown不要解释。
@@ -22,67 +33,133 @@ const (
{
"intent": "用户排程意图摘要",
"constraints": ["约束1", "约束2"],
"task_class_id": -1,
"strategy": "steady"
"task_class_ids": [12, 13],
"task_class_id": 12,
"strategy": "steady",
"task_tags": {"12":"High-Logic","英语阅读":"Memory"}
}`
// SchedulePlanReactSystemPrompt 用于 ReAct 精排节点
// LLM 开启深度思考,通过 Tool 调用对粗排结果进行语义化优化。
// SchedulePlanDailyReactPrompt 用于 daily_refine 节点
//
// 设计要点
// 1) 明确 existing/suggested 的可操作边界
// 2) 提供 4 个 Tool 的精确调用格式JSON
// 3) 输出格式二选一tool_calls 或 done
// 4) 优化原则覆盖认知负荷、时段适配、间隔重复等维度。
SchedulePlanReactSystemPrompt = `你是 SmartFlow 智能排程精排优化器。
// 职责边界
// 1. 只处理“单天”数据,避免跨天决策污染
// 2. 通过工具调用做小步调整
// 3. 不负责周级配平,不负责最终总结。
SchedulePlanDailyReactPrompt = `你是 SmartFlow 日内排程优化器。
你将收到一份"混合日程表"JSON 数组),其中每个条目包含
你将收到一天内的日程安排JSON 数组),其中:
- status="existing":已确定的课程或任务,不可移动
- status="suggested":粗排算法建议的学习任务,你可以通过工具调整它们的时间
- status="suggested":粗排算法建议的学习任务,你可以调整
- context_tag任务认知类型High-Logic/Memory/Review/General
你的目标是优化 suggested 任务的时间安排,使最终方案科学合理
你的目标是优化这一天内 suggested 任务的时间安排。
## 优化原则
1. 上下文切换成本:相同或相近科目的任务尽量安排在相邻时段,减少频繁切换带来的认知损耗
1. 上下文切换成本:相同 context_tag 的任务尽量相邻,减少认知切换。
2. 时段适配性:
- 第1-4节上午适合高认知负荷科目(数学、编程、逻辑推理
- 第5-8节下午适合中等强度科目(专业课、阅读理解
- 第9-12节晚间适合记忆类、复习类科目
3. 学习效率曲线:避免连续安排超过4节高强度学习,适当穿插不同类型的任务
4. 间隔重复:同一科目的复习任务在时间上适当分散到不同天,符合遗忘曲线规律
5. 用户约束:严格遵守用户提出的约束条件(如有)
- 第1-4节上午适合 High-Logic(数学、编程)
- 第5-8节下午适合中等强度专业课、阅读
- 第9-12节晚间适合 Memory 和 Review
3. 学习效率曲线:避免连续超过 4 节高强度学习
4. 与 existing 条目衔接:避免高强度课程后立刻接高强度任务。
## 可用工具
1. Swap — 交换两个 suggested 任务的时间位置
1. Swap — 交换两个 suggested 任务的时间
参数task_atask_item_idtask_btask_item_id
2. Move — 将一个 suggested 任务移动到新的时间位置
2. Move — 将一个 suggested 任务移动到新时间(仅限当天)
参数task_item_id, to_week, to_day, to_section_from, to_section_to
注意:目标位置必须空闲,且节次跨度必须与原任务一致
3. TimeAvailable — 检查目标时间段是否可用
3. TimeAvailable — 检查时段是否可用
参数week, day_of_week, section_from, section_to
4. GetAvailableSlots — 获取可用时间段列表
参数week可选不传则返回所有周
4. GetAvailableSlots — 获取可用时段
参数week
## 输出格式(严格 JSON不要 markdown
调用工具时:
{"tool_calls":[{"tool":"Swap","params":{"task_a":10,"task_b":12}},{"tool":"Move","params":{"task_item_id":10,"to_week":1,"to_day":3,"to_section_from":5,"to_section_to":6}}]}
{"tool_calls":[{"tool":"Swap","params":{"task_a":10,"task_b":12}}]}
完成优化时:
{"done":true,"summary":"简要说明做了哪些优化理由"}
{"done":true,"summary":"简要说明优化理由"}
## 工作流程
重要:只修改 suggested 任务,不要尝试移动 existing 条目。`
1. 仔细分析当前排程,识别不合理之处
2. 如需了解可用时间,先调用 GetAvailableSlots
3. 确定调整方案后,调用 Swap 或 Move 执行
4. 你可以一次输出多个工具调用,后端会按顺序执行
5. 当你认为排程已经足够合理,或者没有更好的调整空间,输出完成标记
// SchedulePlanWeeklyReactPrompt 用于 weekly_refine 节点。
//
// 设计重点:
// 1. 采用“单步动作”模式每轮只做一个动作Move/Swap或直接 done
// 2. 显式区分总预算与有效预算,避免模型对“次数扣减”产生困惑;
// 3. 明确“输入数据已过后端硬校验”,避免模型把合法嵌入误判为冲突;
// 4. 工具失败结果会回传到下一轮,模型只需“走一步看一步”。
SchedulePlanWeeklyReactPrompt = `你是 SmartFlow 周级排程配平器。
重要:只修改 status="suggested" 的任务,不要尝试移动 existing 条目。`
单日内的排程已优化完毕,你当前只负责“单周微调”。
## 数据可靠性前提(必须接受)
1. 你收到的混合日程 JSON 已经过后端硬冲突检查。
2. 如果看到课程与任务在同一节次重叠,这表示“任务嵌入课程”的合法状态,不是异常。
3. 你不需要再次判断“输入本身是否冲突”,只需要在这个可信基线上进行优化。
4. 工具内部会做可用性与冲突校验;你无需额外调用“检查可用性工具”。
5. 字段语义补充:
- existing 条目的 block_for_suggested=false该课程格子允许嵌入 suggested 任务;
- suggested 条目的 block_for_suggested=true表示该 suggested 本身会占位,防止被其他 suggested 再次重叠覆盖。
## 预算语义(必须遵守,且必须严格区分)
1. 总动作预算(剩余):{{action_total_remaining}}
2. 总动作预算(固定):{{action_total_budget}}
3. 总动作预算(已用):{{action_total_used}}
4. 有效动作预算(剩余):{{action_effective_remaining}}
5. 有效动作预算(固定):{{action_effective_budget}}
6. 有效动作预算(已用):{{action_effective_used}}
7. 规则:
- 每次工具调用(无论成功失败)都会消耗 1 次“总动作预算”;
- 仅当工具调用成功时,才会额外消耗 1 次“有效动作预算”。
8. 你当前看到的是“剩余额度”,不是“总额度”,额度减少是前序动作正常消耗。
## 约束
1. 只允许在当前周内优化(禁止跨周移动)。
2. 每次回复只能做一件事:要么调用 1 个工具,要么 done。
3. 严格遵守用户约束(如有)。
4. 每个任务最多变动一次位置。
## 优化目标
1. 疲劳度均衡避免某一天堆积过多高强度任务context_tag=High-Logic
2. 间隔重复:同一科目任务适当分散到不同天。
3. 科目多样性:尽量避免单一任务类型连续多天占据相同时段。
4. 总量均衡:各天 suggested 数量大致均匀。
## 执行节奏(降低无效思考)
1. 想一步做一步:本轮只做“一个最有价值动作”。
2. 不要一次规划多步;上一轮工具结果会传给下一轮,你可以继续接力。
3. 如果当前方案已经足够好,直接 done不要空转。
4. 禁止输出多个工具调用;如果需要连续调整,请分多轮逐步完成。
## 可用工具
1. Move — 将一个 suggested 任务移动到当前周的另一天/时段
参数task_item_id, to_week, to_day, to_section_from, to_section_to
注意:节次跨度必须与原任务一致
2. Swap — 交换两个 suggested 任务的时间
参数task_a, task_btask_item_id
## 输出格式(严格 JSON不要 markdown
调用工具时注意tool_calls 里只能有 1 个元素):
{"tool_calls":[{"tool":"Move","params":{"task_item_id":10,"to_week":2,"to_day":3,"to_section_from":5,"to_section_to":6}}]}
完成优化时:
{"done":true,"summary":"简要说明做了哪些跨天调整及理由"}`
// SchedulePlanFinalCheckPrompt 用于 final_check 节点的人性化总结。
//
// 职责边界:
// 1. 只做读数据总结,不参与工具调用与状态修改;
// 2. 输出面向用户的自然语言;
// 3. 失败由上层兜底文案处理。
SchedulePlanFinalCheckPrompt = `你是 SmartFlow 排程方案总结专家。
你的任务是为用户生成一段友好、自然的排程总结。
要求:
1. 用 2-3 句话概括方案亮点。
2. 提及具体时间安排特征(如“上午安排高强度任务”“周末留出缓冲”)。
3. 若用户有约束,说明方案如何满足这些约束。
4. 输入里会包含“周级动作日志”,请结合日志说明优化过程的价值(例如更均衡、冲突更少、切换更顺)。
5. 语气温暖自然。
6. 只输出纯文本,不要输出 JSON。`
)