Files
smartmate/backend/agent/scheduleplan/runner.go
Losita e5b27df80d Version: 0.7.2.dev.260322
feat(schedule-plan):  重构智能排程链路并修复粗排双节对齐问题

-  新增“对话级排程状态持久化”能力:引入 `agent_schedule_states` 模型/DAO,并接入启动迁移
-  智能排程图升级:补齐小幅微调(quick refine)分支,完善预算/并发/状态字段流转
-  预览链路增强:完善排程预览服务读写与桥接逻辑,新增本地预览页 `infra/schedule_preview_viewer.html`
- ♻️ 缓存治理统一:将相关缓存处理收口到 DAO + `cache_deleter` 联动清理,移除旧散落逻辑
- 🐛 修复粗排核心 bug:禁止单节降级,强制双节并按 `1-2/3-4/...` 对齐;修复结束日扫描边界问题
-  新增粗排回归测试:覆盖孤立单节、偶数起点双节、Filler 对齐等关键场景
2026-03-22 13:50:10 +08:00

129 lines
4.5 KiB
Go
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.
package scheduleplan
import (
"context"
"github.com/cloudwego/eino-ext/components/model/ark"
"github.com/cloudwego/eino/schema"
)
// schedulePlanRunner 是“单次图执行”的请求级依赖容器。
//
// 设计目标:
// 1. 把节点运行所需依赖model/deps/emit/extra/history就近收口
// 2. 让 graph.go 只保留“节点连线与分支决策”,提升可读性;
// 3. 避免在 graph.go 里重复出现大量闭包和参数透传。
type schedulePlanRunner struct {
chatModel *ark.ChatModel
deps SchedulePlanToolDeps
emitStage func(stage, detail string)
userMessage string
extra map[string]any
chatHistory []*schema.Message
// weekly refine 需要的上下文
outChan chan<- string
modelName string
// daily refine 并发度
dailyRefineConcurrency int
}
func newSchedulePlanRunner(
chatModel *ark.ChatModel,
deps SchedulePlanToolDeps,
emitStage func(stage, detail string),
userMessage string,
extra map[string]any,
chatHistory []*schema.Message,
outChan chan<- string,
modelName string,
dailyRefineConcurrency int,
) *schedulePlanRunner {
return &schedulePlanRunner{
chatModel: chatModel,
deps: deps,
emitStage: emitStage,
userMessage: userMessage,
extra: extra,
chatHistory: chatHistory,
outChan: outChan,
modelName: modelName,
dailyRefineConcurrency: dailyRefineConcurrency,
}
}
// 节点方法适配层
func (r *schedulePlanRunner) planNode(ctx context.Context, st *SchedulePlanState) (*SchedulePlanState, error) {
return runPlanNode(ctx, st, r.chatModel, r.userMessage, r.extra, r.chatHistory, r.emitStage)
}
func (r *schedulePlanRunner) roughBuildNode(ctx context.Context, st *SchedulePlanState) (*SchedulePlanState, error) {
return runRoughBuildNode(ctx, st, r.deps, r.emitStage)
}
func (r *schedulePlanRunner) dailySplitNode(ctx context.Context, st *SchedulePlanState) (*SchedulePlanState, error) {
return runDailySplitNode(ctx, st, r.emitStage)
}
func (r *schedulePlanRunner) quickRefineNode(ctx context.Context, st *SchedulePlanState) (*SchedulePlanState, error) {
return runQuickRefineNode(ctx, st, r.emitStage)
}
func (r *schedulePlanRunner) dailyRefineNode(ctx context.Context, st *SchedulePlanState) (*SchedulePlanState, error) {
return runDailyRefineNode(ctx, st, r.chatModel, r.dailyRefineConcurrency, r.emitStage)
}
func (r *schedulePlanRunner) mergeNode(ctx context.Context, st *SchedulePlanState) (*SchedulePlanState, error) {
return runMergeNode(ctx, st, r.emitStage)
}
func (r *schedulePlanRunner) weeklyRefineNode(ctx context.Context, st *SchedulePlanState) (*SchedulePlanState, error) {
return runWeeklyRefineNode(ctx, st, r.chatModel, r.outChan, r.modelName, r.emitStage)
}
func (r *schedulePlanRunner) finalCheckNode(ctx context.Context, st *SchedulePlanState) (*SchedulePlanState, error) {
return runFinalCheckNode(ctx, st, r.chatModel, r.emitStage)
}
func (r *schedulePlanRunner) returnPreviewNode(ctx context.Context, st *SchedulePlanState) (*SchedulePlanState, error) {
return runReturnPreviewNode(ctx, st, r.emitStage)
}
func (r *schedulePlanRunner) exitNode(_ context.Context, st *SchedulePlanState) (*SchedulePlanState, error) {
return st, nil
}
// 分支决策适配层
func (r *schedulePlanRunner) nextAfterPlan(_ context.Context, st *SchedulePlanState) (string, error) {
return selectNextAfterPlan(st), nil
}
// nextAfterRoughBuild 根据粗排构建结果决定后续路径。
//
// 规则:
// 1. 没有可优化条目 -> exit
// 2. task_class_ids >= 2 -> dailySplit多任务类混排先做日内并发
// 3. task_class_ids == 1 -> weeklyRefine单任务类直接周级配平
func (r *schedulePlanRunner) nextAfterRoughBuild(_ context.Context, st *SchedulePlanState) (string, error) {
if st == nil || len(st.HybridEntries) == 0 {
return schedulePlanGraphNodeExit, nil
}
// 1. 连续微调且判定为 small先走快速微调节点收缩预算后再进 weekly。
if st.IsAdjustment && st.AdjustmentScope == schedulePlanAdjustmentScopeSmall {
return schedulePlanGraphNodeQuickRefine, nil
}
// 2. 连续微调且判定为 medium直接走 weekly跳过 daily。
if st.IsAdjustment && st.AdjustmentScope == schedulePlanAdjustmentScopeMedium {
return schedulePlanGraphNodeWeeklyRefine, nil
}
// 3. large 或非微调:保持原有逻辑,多任务类走 daily单任务类直达 weekly。
if len(st.TaskClassIDs) >= 2 {
return schedulePlanGraphNodeDailySplit, nil
}
return schedulePlanGraphNodeWeeklyRefine, nil
}