Files
smartmate/backend/agent/scheduleplan/tool.go
Losita d3cec2a5b9 Version: 0.7.0.dev.260319
 feat(agent): 新增智能排程 Agent 全链路 + ReAct 精排引擎

  🏗️ 智能排程 Graph 编排(阶段 1 基础链路)
  - 新增 scheduleplan 包:state / tool / prompt / nodes / runner / graph 六件套
  - 实现 plan → preview → materialize → apply → reflect → finalize 完整图编排
  - 通过函数注入解耦 agent 层与 service 层,避免循环依赖
  - 路由层新增 schedule_plan 动作,复用现有 SSE + 持久化链路

  🧠 ReAct 精排引擎(阶段 1.5 语义化微调)
  - 粗排后构建"混合日程"(既有课程 + 建议任务),统一为 HybridScheduleEntry
  - LLM 开启深度思考,通过 Swap / Move / TimeAvailable / GetAvailableSlots 四个 Tool 在内存中优化任务时间
  - reasoning_content 实时流式推送前端,用户可见 AI 思考过程
  - 精排结果仅预览不落库,向后兼容(未注入依赖时走原有 materialize 路径)

  📝 文档
  - 新增 ReAct 精排引擎决策记录

  ⚠️ 已知问题:深度思考模式耗时较长,超时策略待优化
2026-03-19 23:18:56 +08:00

77 lines
2.8 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"
"errors"
"strconv"
"github.com/LoveLosita/smartflow/backend/model"
)
// SchedulePlanToolDeps 描述"智能排程工具包"需要的外部依赖。
//
// 设计目标:
// 1) 通过函数注入把 agent 包与 service/dao 解耦,避免循环依赖;
// 2) 每个函数对应一个可独立 mock 的业务能力;
// 3) 后续可按需扩展(如局部修补、任务类自动生成等)。
type SchedulePlanToolDeps struct {
// SmartPlanningRaw 调用粗排算法,同时返回展示结构和已分配的任务项。
// 返回值:
// - []UserWeekSchedule展示型结构供 SSE 阶段推送给前端预览;
// - []TaskClassItem已分配的任务项EmbeddedTime 已回填),供 materialize 直接转换。
SmartPlanningRaw func(ctx context.Context, userID, taskClassID int) ([]model.UserWeekSchedule, []model.TaskClassItem, error)
// BatchApplyPlans 将排程方案批量落库。
// 输入taskClassID、userID、落库请求体。
// 输出errornil 表示全部成功)。
BatchApplyPlans func(ctx context.Context, taskClassID, userID int, plans *model.UserInsertTaskClassItemToScheduleRequestBatch) error
// GetTaskClassByID 获取任务类详情(含关联的 Items
// 用于:
// 1) 校验 task_class_id 合法性;
// 2) 获取 Items 列表,为连续对话微调提供上下文。
GetTaskClassByID func(ctx context.Context, taskClassID, userID int) (*model.TaskClass, error)
// HybridScheduleWithPlan 构建混合日程(既有日程 + 粗排建议),供 ReAct 精排使用。
// 可选依赖:未注入时 ReAct 精排阶段不可用,走原有 materialize 路径。
HybridScheduleWithPlan func(ctx context.Context, userID, taskClassID int) ([]model.HybridScheduleEntry, []model.TaskClassItem, error)
}
// validate 校验依赖完整性,缺失任意一个都无法完成排程链路。
func (d SchedulePlanToolDeps) validate() error {
if d.SmartPlanningRaw == nil {
return errors.New("schedule plan tool deps: SmartPlanningRaw is nil")
}
if d.BatchApplyPlans == nil {
return errors.New("schedule plan tool deps: BatchApplyPlans is nil")
}
if d.GetTaskClassByID == nil {
return errors.New("schedule plan tool deps: GetTaskClassByID is nil")
}
return nil
}
// ExtraInt 从 extra map 中安全提取整数值。
//
// 兼容策略:
// 1) JSON 数字默认解析为 float64做 int 转换;
// 2) 兼容字符串形式(如 "42"),用 Atoi 解析;
// 3) 其余类型返回 false由调用方决定后续处理。
func ExtraInt(extra map[string]any, key string) (int, bool) {
v, ok := extra[key]
if !ok {
return 0, false
}
switch n := v.(type) {
case float64:
return int(n), true
case int:
return n, true
case string:
i, err := strconv.Atoi(n)
return i, err == nil
default:
return 0, false
}
}