Version: 0.7.8.dev.260325

后端:
迁移了schedule_plan逻辑并探索了新的架构组织思路
删除了一些Codex测试时产生的单测文件
前端:
做了一些改进
This commit is contained in:
LoveLosita
2026-03-25 20:37:55 +08:00
parent a4b5b549d3
commit aa04bfb452
22 changed files with 4627 additions and 704 deletions

View File

@@ -1,18 +1,205 @@
package agentmodel
// SchedulePlanState 是“首次排程”skill 的运行时状态骨架。
type SchedulePlanState struct {
TraceID string
UserID int
ConversationID string
UserInput string
TaskClassIDs []int
UseQuickRefineOnly bool
Completed bool
FinalSummary string
import (
"strings"
"time"
"github.com/LoveLosita/smartflow/backend/model"
)
const (
// SchedulePlanTimezoneName 是排程链路默认业务时区。
// 与随口记保持一致,固定东八区,避免容器运行在 UTC 导致“明天/今晚”偏移。
SchedulePlanTimezoneName = "Asia/Shanghai"
// SchedulePlanDatetimeLayout 是排程链路内部统一的分钟级时间格式。
SchedulePlanDatetimeLayout = "2006-01-02 15:04"
// SchedulePlanDefaultDailyRefineConcurrency 是日内并发优化默认并发度。
// 这里给一个保守默认值,避免未配置时直接把模型并发打满导致限流。
SchedulePlanDefaultDailyRefineConcurrency = 3
// SchedulePlanDefaultWeeklyAdjustBudget 是周级配平默认调整额度。
// 额度存在的目的:
// 1. 防止周级 ReAct 过度调整导致震荡;
// 2. 控制 token 与时延成本;
// 3. 让方案改动更可解释。
SchedulePlanDefaultWeeklyAdjustBudget = 5
// SchedulePlanDefaultWeeklyTotalBudget 是周级“总尝试次数”默认预算。
//
// 设计意图:
// 1. 总预算统计“动作尝试次数”(成功/失败都记一次);
// 2. 有效预算统计“成功动作次数”(仅成功时记一次);
// 3. 通过双预算把“探索次数”和“有效改动次数”分离,降低模型无效空转成本。
SchedulePlanDefaultWeeklyTotalBudget = 8
// SchedulePlanDefaultWeeklyRefineConcurrency 是周级“按周并发”默认并发度。
// 说明:
// 1. 周级输入规模通常比单天更大,默认并发度不宜过高,避免触发模型侧限流;
// 2. 可在运行时按请求状态覆盖。
SchedulePlanDefaultWeeklyRefineConcurrency = 2
// SchedulePlanAdjustmentScopeSmall 表示“小改动微调”。
// 语义:优先走快速路径,只做轻量周级调整。
SchedulePlanAdjustmentScopeSmall = "small"
// SchedulePlanAdjustmentScopeMedium 表示“中等改动微调”。
// 语义:跳过日内拆分,直接进入周级配平。
SchedulePlanAdjustmentScopeMedium = "medium"
// SchedulePlanAdjustmentScopeLarge 表示“大改动重排”。
// 语义:必要时重新走全量路径(日内并发 + 周级配平)。
SchedulePlanAdjustmentScopeLarge = "large"
)
const (
schedulePlanTimezoneName = SchedulePlanTimezoneName
schedulePlanDatetimeLayout = SchedulePlanDatetimeLayout
schedulePlanDefaultDailyRefineConcurrency = SchedulePlanDefaultDailyRefineConcurrency
schedulePlanDefaultWeeklyAdjustBudget = SchedulePlanDefaultWeeklyAdjustBudget
schedulePlanDefaultWeeklyTotalBudget = SchedulePlanDefaultWeeklyTotalBudget
schedulePlanDefaultWeeklyRefineConcurrency = SchedulePlanDefaultWeeklyRefineConcurrency
schedulePlanAdjustmentScopeSmall = SchedulePlanAdjustmentScopeSmall
schedulePlanAdjustmentScopeMedium = SchedulePlanAdjustmentScopeMedium
schedulePlanAdjustmentScopeLarge = SchedulePlanAdjustmentScopeLarge
)
// DayGroup 是“按天拆分后”的最小优化单元。
//
// 设计目的:
// 1. 把全量周视角数据拆成“单天小包”,降低日内 ReAct 输入规模;
// 2. 支持并发优化不同天的数据,缩短整体等待;
// 3. 通过 SkipRefine 让低收益天数直接跳过,节省模型调用成本。
type DayGroup struct {
Week int
DayOfWeek int
Entries []model.HybridScheduleEntry
SkipRefine bool
}
// ScheduleRefineState 是“连续微调排程”skill 的运行时状态骨架
// SchedulePlanState 是“智能排程”链路在 graph 节点间传递的统一状态容器
//
// 设计目标:
// 1) 收拢排程请求全生命周期的上下文,降低节点间参数散落;
// 2) 支持“粗排 -> 日内并发优化 -> 周级配平 -> 终审校验”的完整链路追踪;
// 3) 支持连续对话微调:保留上版方案 + 本次约束变更,便于增量重排。
type SchedulePlanState struct {
// ── 基础上下文 ──
TraceID string
UserID int
ConversationID string
RequestNow time.Time
RequestNowText string
// ── plan 节点输出 ──
UserIntent string
Constraints []string
TaskClassIDs []int
Strategy string
TaskTags map[int]string
TaskTagHintsByName map[string]string
// ── preview 节点输出 ──
CandidatePlans []model.UserWeekSchedule
AllocatedItems []model.TaskClassItem
HasPlanningWindow bool
PlanStartWeek int
PlanStartDay int
PlanEndWeek int
PlanEndDay int
// ── 日内并发优化阶段 ──
DailyGroups map[int]map[int]*DayGroup
DailyResults map[int]map[int][]model.HybridScheduleEntry
DailyRefineConcurrency int
// ── 周级 ReAct 精排阶段 ──
HybridEntries []model.HybridScheduleEntry
MergeSnapshot []model.HybridScheduleEntry
ReactRound int
ReactMaxRound int
ReactSummary string
ReactDone bool
WeeklyAdjustBudget int
WeeklyAdjustUsed int
WeeklyTotalBudget int
WeeklyTotalUsed int
WeeklyRefineConcurrency int
WeeklyActionLogs []string
// ── 连续对话微调 ──
PreviousPlanJSON string
IsAdjustment bool
RestartRequested bool
AdjustmentScope string
AdjustmentReason string
AdjustmentConfidence float64
HasPreviousPreview bool
PreviousTaskClassIDs []int
PreviousHybridEntries []model.HybridScheduleEntry
PreviousAllocatedItems []model.TaskClassItem
PreviousCandidatePlans []model.UserWeekSchedule
// ── 最终输出 ──
FinalSummary string
Completed bool
}
// NewSchedulePlanState 创建排程状态对象并初始化默认值。
func NewSchedulePlanState(traceID string, userID int, conversationID string) *SchedulePlanState {
now := schedulePlanNowToMinute()
return &SchedulePlanState{
TraceID: traceID,
UserID: userID,
ConversationID: conversationID,
RequestNow: now,
RequestNowText: now.In(schedulePlanLocation()).Format(schedulePlanDatetimeLayout),
Strategy: "steady",
TaskTags: make(map[int]string),
TaskTagHintsByName: make(map[string]string),
DailyRefineConcurrency: schedulePlanDefaultDailyRefineConcurrency,
WeeklyRefineConcurrency: schedulePlanDefaultWeeklyRefineConcurrency,
AdjustmentScope: schedulePlanAdjustmentScopeLarge,
ReactMaxRound: 2,
WeeklyAdjustBudget: schedulePlanDefaultWeeklyAdjustBudget,
WeeklyTotalBudget: schedulePlanDefaultWeeklyTotalBudget,
}
}
// NormalizeSchedulePlanAdjustmentScope 归一化排程微调力度字段。
//
// 兜底策略:
// 1. 只接受 small/medium/large
// 2. 任何未知值都回退为 large保证不会误走“过轻”路径。
func NormalizeSchedulePlanAdjustmentScope(raw string) string {
switch strings.ToLower(strings.TrimSpace(raw)) {
case schedulePlanAdjustmentScopeSmall:
return schedulePlanAdjustmentScopeSmall
case schedulePlanAdjustmentScopeMedium:
return schedulePlanAdjustmentScopeMedium
default:
return schedulePlanAdjustmentScopeLarge
}
}
// schedulePlanLocation 返回排程链路使用的业务时区。
func schedulePlanLocation() *time.Location {
loc, err := time.LoadLocation(schedulePlanTimezoneName)
if err != nil {
return time.Local
}
return loc
}
// schedulePlanNowToMinute 返回当前时间并截断到分钟级。
func schedulePlanNowToMinute() time.Time {
return time.Now().In(schedulePlanLocation()).Truncate(time.Minute)
}
func normalizeAdjustmentScope(raw string) string {
return NormalizeSchedulePlanAdjustmentScope(raw)
}
// ScheduleRefineState 先保留现有骨架,避免本轮“只迁 schedule_plan”时误动 refine。
type ScheduleRefineState struct {
TraceID string
UserID int