Version: 0.9.10.dev.260409
后端: 1. newAgent 运行态重置双保险落地,并补齐写工具后的实时排程预览刷新 - 更新 model/common_state.go:新增 ResetForNextRun,统一清理 round/plan/rough_build/allow_reorder/terminal 等执行期临时状态 - 更新 node/chat.go + service/agentsvc/agent_newagent.go:在“无 pending 且上一轮已 done”时分别于 chat 主入口与 loadOrCreateRuntimeState 冷加载处执行兜底重置,覆盖正常新一轮对话与断线恢复场景 - 更新 model/graph_run_state.go + node/agent_nodes.go + node/execute.go:写工具执行后立即刷新 Redis 排程预览,Deliver 继续保留最终覆盖写,保证前端能及时看到最新操作结果 2. 顺序守卫从“直接中止”改为“优先自动复原 suggested 相对顺序” - 更新 node/order_guard.go:检测到 suggested 顺序被打乱后,不再直接 abort;改为复用当前坑位按 baseline 自动回填,并在复原失败时仅记录诊断日志后继续交付 - 更新 tools/state.go:ScheduleState 新增 RuntimeQueue 运行态快照字段,支持队列化处理与断线恢复 3. 多任务微调工具链升级:新增筛选/队列工具并替换首空位查询口径 - 新建 tools/read_filter_tools.go + tools/runtime_queue.go + tools/queue_tools.go:新增 query_available_slots / query_target_tasks / queue_pop_head / queue_apply_head_move / queue_skip_head / queue_status,支持“先筛选目标,再逐项处理”的稳定微调链路 - 更新 tools/registry.go + tools/write_tools.go + tools/read_helpers.go:移除 find_first_free 注册口径;batch_move 限制为最多 2 条,超过时引导改走队列逐项处理;queue_apply_head_move 纳入写工具集合 4. 复合规划工具扩充,并改为在 newAgent/tools 本地实现以规避循环导入 - 更新 tools/compound_tools.go + tools/registry.go:spread_even 正式接入,并与 min_context_switch 一起作为复合写工具保留在 newAgent/tools 内部实现,不再依赖外层 logic 5. prompt 与工具文档同步升级,明确当前用户诉求锚点与队列化执行约束 - 更新 prompt/execute.go + prompt/execute_context.go + prompt/plan.go:执行提示默认引导 query_target_tasks(enqueue=true) → queue_pop_head → query_available_slots → queue_apply_head_move / queue_skip_head;补齐 batch_move 上限、spread_even 使用边界、顺序策略与工具 JSON 返回示例 - 更新 prompt/execute_context.go:将“初始用户目标”改为“当前用户诉求”,并保留首轮目标来源;旧 observation 折叠文案改为“当前工具调用结果已经被使用过,当前无需使用,为节省上下文空间,已折叠” - 更新 tools/SCHEDULE_TOOLS.md:同步补齐 query_* / queue_* / spread_even / min_context_switch 的说明、限制与返回示例 6. 同步更新调试日志文件 前端:无 仓库:无
This commit is contained in:
@@ -17,6 +17,7 @@ const executeSystemPromptWithPlan = `
|
||||
3. 需要写操作时输出 action=confirm 并附带 tool_call,等待用户确认。
|
||||
4. 若用户给出了“二次微调方向”(如负载均衡、某天减负、某类任务后移),优先围绕该方向推进,并在 goal_check 说明满足情况。
|
||||
5. 只有在用户明确允许打乱顺序时,才可使用 min_context_switch 做重排。
|
||||
6. 多任务微调时默认走队列链路:query_target_tasks(enqueue=true) → queue_pop_head → query_available_slots → queue_apply_head_move / queue_skip_head。
|
||||
|
||||
你不要做什么:
|
||||
1. 不要跳到其他 plan 步骤,不要越级执行。
|
||||
@@ -30,6 +31,8 @@ const executeSystemPromptWithPlan = `
|
||||
9. list_tasks.category 只接受任务类名称,不接受 task_class_ids(如 "1,2,3")。
|
||||
10. 不要忽略用户最新补充的微调方向;若与旧目标冲突,以最新用户要求为准。
|
||||
11. 若当前顺序策略是“默认保持顺序”,禁止调用 min_context_switch。
|
||||
12. 不要把超过 2 条任务打包到 batch_move;大批量调整请改走队列逐项处理。
|
||||
13. 不要在未获取队首(queue_pop_head)时直接调用 queue_apply_head_move。
|
||||
|
||||
执行规则:
|
||||
1. 只输出严格 JSON,不要输出 markdown,不要在 JSON 外补充文本。
|
||||
@@ -51,10 +54,11 @@ const executeSystemPromptReAct = `
|
||||
|
||||
你可以做什么:
|
||||
1. 你可以基于用户给定的二次微调方向,对 suggested 做定向微调。
|
||||
2. existing 属于已安排事实层,可用于冲突判断和参考,不作为 move/batch_move 的目标。
|
||||
3. 你可以先调用读工具补充必要事实(例如 get_overview/list_tasks/find_first_free/get_task_info)。
|
||||
4. 你可以在需要改动时提出 confirm(move/swap/unplace/batch_move)。
|
||||
2. existing 属于已安排事实层,可用于冲突判断和参考,不作为 move/batch_move/spread_even 的目标。
|
||||
3. 你可以先调用读工具补充必要事实(例如 get_overview/list_tasks/query_target_tasks/query_available_slots/get_task_info)。
|
||||
4. 你可以在需要改动时提出 confirm(move/swap/unplace/batch_move/spread_even)。
|
||||
5. 只有用户明确允许打乱顺序时,才可使用 min_context_switch。
|
||||
6. 多任务处理默认使用队列链路:先 query_target_tasks(enqueue=true) 入队,再 queue_pop_head 逐项处理。
|
||||
|
||||
你不要做什么:
|
||||
1. 不要假设任务还没排进去,然后改成逐个手动 place。
|
||||
@@ -64,9 +68,11 @@ const executeSystemPromptReAct = `
|
||||
5. 若工具结果与已知事实明显冲突(如无写操作却从“有任务”变成“0任务”),先自我纠错并重查一次,不要直接 ask_user。
|
||||
6. 不要连续两轮调用“同一读工具 + 等价 arguments”;若上一轮已成功返回,下一轮必须换工具或进入 confirm。
|
||||
7. list_tasks.category 只接受任务类名称,不接受 task_class_ids(如 "1,2,3")。
|
||||
8. 若已明确“本轮先收口”,不要继续调用 list_tasks/find_first_free/move 做无目标微调。
|
||||
8. 若已明确“本轮先收口”,不要继续调用 list_tasks/query_available_slots/move 做无目标微调。
|
||||
9. 若用户明确了微调方向,不要只做“局部看起来更空”的随机调整;每次改动都要能对应到该方向。
|
||||
10. 若顺序策略为“保持顺序”,禁止调用 min_context_switch。
|
||||
11. 不要在同一轮构造大规模 batch_move;batch_move 最多 2 条,超过请走队列逐项处理。
|
||||
12. 未调用 queue_pop_head 获取 current 前,不要调用 queue_apply_head_move。
|
||||
|
||||
执行规则:
|
||||
1. 只输出严格 JSON,不要输出 markdown,不要在 JSON 外补充文本。
|
||||
@@ -367,6 +373,10 @@ func buildExecuteStrictJSONUserPrompt() string {
|
||||
- 若用户本轮给了二次微调方向,优先满足该方向,再考虑通用均衡优化
|
||||
- 若上下文已明确“当前未收到微调偏好,本轮先收口”,请直接输出 action=done
|
||||
- 仅当顺序策略明确允许打乱顺序时,才可以调用 min_context_switch
|
||||
- spread_even 用于“范围内均匀化”,必须先用 query_target_tasks 明确目标任务集合
|
||||
- 多任务调整默认先调用 query_target_tasks(enqueue=true),再用 queue_pop_head 逐项处理
|
||||
- queue_apply_head_move 只能用于 current 任务;若当前任务无法落位,调用 queue_skip_head 后继续
|
||||
- batch_move 一次最多 2 条;超过 2 条必须改走队列逐项处理
|
||||
`)
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ const (
|
||||
|
||||
// executeTrimmedObservationText 是重复工具压缩后的 observation 占位文案。
|
||||
// 当同工具在窗口内出现多次时,只保留最新一条真实结果,其余旧结果统一替换为该文案。
|
||||
executeTrimmedObservationText = "当前工具调用结果过于久远,已经被删除。"
|
||||
executeTrimmedObservationText = "当前工具调用结果已经被使用过,当前无需使用,为节省上下文空间,已折叠"
|
||||
)
|
||||
|
||||
type executeToolSchemaDoc struct {
|
||||
@@ -159,20 +159,23 @@ func buildExecuteMessage3(state *newagentmodel.CommonState, ctx *newagentmodel.C
|
||||
"- 当前模式:"+modeText,
|
||||
)
|
||||
|
||||
goal := extractExecuteInitialGoal(ctx)
|
||||
if goal == "" {
|
||||
goal = "暂无可用目标描述,请按当前上下文稳步推进。"
|
||||
initialGoal, currentGoal := extractExecuteGoalAnchors(ctx)
|
||||
if currentGoal == "" {
|
||||
currentGoal = "暂无可用目标描述,请按当前上下文稳步推进。"
|
||||
}
|
||||
|
||||
lines = append(lines, "执行锚点:")
|
||||
lines = append(lines, "- 初始用户目标:"+goal)
|
||||
lines = append(lines, "- 当前用户诉求:"+currentGoal)
|
||||
if initialGoal != "" && initialGoal != currentGoal {
|
||||
lines = append(lines, "- 首轮目标来源:"+initialGoal)
|
||||
}
|
||||
if taskClassText := renderExecuteTaskClassIDs(state); taskClassText != "" {
|
||||
lines = append(lines, "- 目标任务类:"+taskClassText)
|
||||
}
|
||||
lines = append(lines, "- 啥时候结束Loop:你可以根据工具调用记录自行判断。")
|
||||
lines = append(lines, "- 非目标:不重新粗排、不修改无关任务类。")
|
||||
if hasExecuteRoughBuildDone(ctx) {
|
||||
lines = append(lines, "- 阶段约束:粗排已完成,本轮只微调 suggested;existing 仅作已安排事实参考,不做 move/batch_move。")
|
||||
lines = append(lines, "- 阶段约束:粗排已完成,本轮只微调 suggested;existing 仅作已安排事实参考,不做 move/batch_move/spread_even。")
|
||||
}
|
||||
if state != nil {
|
||||
if state.AllowReorder {
|
||||
@@ -230,7 +233,7 @@ func renderExecuteToolCatalogCompact(ctx *newagentmodel.ConversationContext) str
|
||||
// renderExecuteToolReturnHint 返回工具的“返回类型 + 最小示例”。
|
||||
//
|
||||
// 说明:
|
||||
// 1. 所有工具当前都返回 string(自然语言),这里主要补“内容形态示例”,减少模型盲猜;
|
||||
// 1. 所有工具当前都返回 string,但部分是“JSON 字符串”,这里补齐内容形态示例减少模型盲猜;
|
||||
// 2. 示例只保留最小片段,避免工具说明过长挤占上下文窗口。
|
||||
func renderExecuteToolReturnHint(toolName string) (returnType string, sample string) {
|
||||
returnType = "string(自然语言文本)"
|
||||
@@ -241,8 +244,18 @@ func renderExecuteToolReturnHint(toolName string) (returnType string, sample str
|
||||
return returnType, "已预排任务共24个: [35]第一章随机事件与概率 — 已预排至 第3天第5-6节..."
|
||||
case "get_task_info":
|
||||
return returnType, "[35]第一章随机事件与概率 | 状态:已预排(suggested) | 占用时段:第3天第5-6节"
|
||||
case "find_first_free":
|
||||
return returnType, "首个可用位置:第5天第1-2节(可直接放置)| 当日负载:总占6/12..."
|
||||
case "query_available_slots":
|
||||
return "string(JSON字符串)", `{"tool":"query_available_slots","count":12,"strict_count":8,"embedded_count":4,"slots":[{"day":5,"week":12,"day_of_week":3,"slot_start":1,"slot_end":2,"slot_type":"empty"}]}`
|
||||
case "query_target_tasks":
|
||||
return "string(JSON字符串)", `{"tool":"query_target_tasks","count":6,"status":"suggested","enqueue":true,"enqueued":6,"queue":{"pending_count":6},"items":[{"task_id":35,"name":"示例任务","status":"suggested","slots":[{"day":3,"week":12,"day_of_week":1,"slot_start":5,"slot_end":6}]}]}`
|
||||
case "queue_pop_head":
|
||||
return "string(JSON字符串)", `{"tool":"queue_pop_head","has_head":true,"pending_count":5,"current":{"task_id":35,"name":"示例任务","status":"suggested","slots":[{"day":3,"week":12,"day_of_week":1,"slot_start":5,"slot_end":6}]}}`
|
||||
case "queue_status":
|
||||
return "string(JSON字符串)", `{"tool":"queue_status","pending_count":5,"completed_count":1,"skipped_count":0,"current_task_id":35,"current_attempt":1}`
|
||||
case "queue_apply_head_move":
|
||||
return "string(JSON字符串)", `{"tool":"queue_apply_head_move","success":true,"task_id":35,"pending_count":4,"completed_count":2,"result":"已将 [35]... 从第3天第5-6节移至第5天第3-4节。"}`
|
||||
case "queue_skip_head":
|
||||
return "string(JSON字符串)", `{"tool":"queue_skip_head","success":true,"skipped_task_id":35,"pending_count":4,"skipped_count":1}`
|
||||
case "query_range":
|
||||
return returnType, "第5天第3-6节:第3节空、第4节空..."
|
||||
case "place":
|
||||
@@ -252,7 +265,9 @@ func renderExecuteToolReturnHint(toolName string) (returnType string, sample str
|
||||
case "swap":
|
||||
return returnType, "交换完成:[35]... ↔ [36]..."
|
||||
case "batch_move":
|
||||
return returnType, "批量移动完成,2个任务全部成功。"
|
||||
return returnType, "批量移动完成,2个任务全部成功。(单次最多2条)"
|
||||
case "spread_even":
|
||||
return returnType, "均匀化调整完成:共处理 6 个任务,候选坑位 24 个。"
|
||||
case "min_context_switch":
|
||||
return returnType, "最少上下文切换重排完成:共处理 6 个任务,上下文切换次数 5 -> 2。"
|
||||
case "unplace":
|
||||
@@ -496,13 +511,13 @@ func buildEarlyExecuteReactSummary(records []executeLoopRecord, windowLimit int)
|
||||
return fmt.Sprintf("已折叠 %d 条旧记录,涉及:%s。", len(early), strings.Join(parts, "、"))
|
||||
}
|
||||
|
||||
func extractExecuteInitialGoal(ctx *newagentmodel.ConversationContext) string {
|
||||
func extractExecuteGoalAnchors(ctx *newagentmodel.ConversationContext) (initial string, current string) {
|
||||
if ctx == nil {
|
||||
return ""
|
||||
return "", ""
|
||||
}
|
||||
history := ctx.HistorySnapshot()
|
||||
firstUser, _ := pickExecuteUserInputs(history)
|
||||
return firstUser
|
||||
firstUser, lastUser := pickExecuteUserInputs(history)
|
||||
return firstUser, lastUser
|
||||
}
|
||||
|
||||
func hasExecuteRoughBuildDone(ctx *newagentmodel.ConversationContext) bool {
|
||||
|
||||
@@ -27,7 +27,7 @@ const planSystemPrompt = `
|
||||
条件2:用户意图明确是"批量安排/帮我排课/把任务类排进日程"等批量调度需求。
|
||||
满足时:后端会在用户确认计划后自动运行粗排算法(硬性约束已由算法保证,无需 LLM 校验)。
|
||||
你的 plan_steps 应聚焦于"用读写工具优化方案",建议两步:
|
||||
第1步:用 get_overview / find_first_free 等读工具审视粗排结果,找出可优化的点(时段分布不均、空位未利用等);
|
||||
第1步:用 get_overview / query_target_tasks / query_available_slots 等读工具审视粗排结果,找出可优化的点(时段分布不均、空位未利用等);
|
||||
第2步:用 move / batch_move 等写工具微调后,将最终方案展示给用户确认。
|
||||
禁止安排任何"校验/验证约束"步骤——硬性约束由算法兜底,LLM 不需要操心。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user