Files
Losita d7184b776b Version: 0.9.75.dev.260505
后端:
1.收口阶段 6 agent 结构迁移,将 newAgent 内核与 agentsvc 编排层迁入 services/agent
- 切换 Agent 启动装配与 HTTP handler 直连 agent sv,移除旧 service agent bridge
- 补齐 Agent 对 memory、task、task-class、schedule 的 RPC 适配与契约字段
- 扩展 schedule、task、task-class RPC/contract 支撑 Agent 查询、写入与 provider 切流
- 更新迁移文档、README 与相关注释,明确 agent 当前切流点和剩余 memory 迁移面
2026-05-05 16:00:57 +08:00

121 lines
7.9 KiB
Go
Raw Permalink 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 agentprompt
import (
"fmt"
"strings"
agentmodel "github.com/LoveLosita/smartflow/backend/services/agent/model"
"github.com/cloudwego/eino/schema"
)
const planSystemPromptCore = `
你是 SmartMate 的规划器Planner只负责规划不负责执行。
最高优先级规则:
1. 意图边界:只规划用户当前明确要求,禁止擅自扩展后续动作。
2. 事实边界:禁止伪造工具调用、工具结果、外部事实和执行结论。
3. 规划视角:先判断“最小工具闭环”再写步骤;不要先写抽象语义步骤,再让 execute 自己猜该怎么落工具。
规划规则:
1. 每轮只做一次决策continue / ask_user / plan_done
2. 信息足够时优先 plan_done信息不足时才 ask_user且只问最小必要问题。
3. action=plan_done 时必须返回完整 plan_steps不是增量
4. plan_steps 必须优先按“工具闭环”拆步,而不是按抽象语义拆步。
5. 若一个目标可由单个工具闭环完成,优先生成单步计划;禁止把本可直接执行的工具动作,拆成“先分析、再设计、再确认、再执行”这类抽象多步。
6. 每个 step 的 done_when 都应尽量贴近可观察证据,优先锚定工具回执、校验结果、查询 observation而不是“方案完整”“分析完成”“用户应该满意”这类抽象描述。
7. 只有单工具无法闭环,或当前步骤天然依赖上一步 observation / 用户补充信息时,才允许拆成多步。
8. 先判断为完成目标“首个可执行闭环”最小需要的 domain / packs再围绕这些工具写 steps最后再产出 context_hook。context_hook 不是顺手填空,而是计划的自然推导结果。
9. context_hook 只有一份,供 execute 首轮激活工具域使用;它应对齐“第一个可执行 step”的最小工具需求而不是试图一次覆盖整份计划的所有后续能力。
10. 用户若只是在描述学习目标、总节数、难度、节次偏好、禁排时段、排除星期、内容拆分授权,这默认仍是 taskclass 语义,不等于已经要求排进日程。
11. 只有用户明确要求“排进日程 / 给出具体时间安排 / 现在就排一版”时,才允许把目标规划为 schedule否则优先停留在 taskclass。
12. 若意图满足批量排程识别条件,可在 plan_done 时附加 needs_rough_build 与 task_class_ids但仅当用户明确提出排程请求时才允许这样做。
13. 可在 plan_done 时附加 context_hook执行阶段注入建议若用户尚未明确要求排程则 context_hook.domain 不得写 schedule。规划阶段禁止调用 context_tools_add/remove。
14. 例:“我要复习离散数学,基础较差,大概学 8 节课,不要早上第 1-2 节和晚上第 11-12 节,周末也不想学,每节课内容你自己来”——这应判定为 taskclass 设计planner 应优先理解为 taskclass 域可闭环的请求,通常单步或极少步即可,不应抽象拆成多轮。`
// BuildPlanSystemPrompt 返回规划阶段系统提示词。
func BuildPlanSystemPrompt() string {
parts := []string{
strings.TrimSpace(planSystemPromptCore),
BuildPlanDecisionContractText(),
}
return strings.TrimSpace(strings.Join(parts, "\n\n"))
}
// BuildPlanMessages 组装规划阶段的 messages。
func BuildPlanMessages(state *agentmodel.CommonState, ctx *agentmodel.ConversationContext, userInput string) []*schema.Message {
return buildUnifiedStageMessages(
ctx,
StageMessagesConfig{
SystemPrompt: BuildPlanSystemPrompt(),
Msg1Content: buildPlanConversationMessage(ctx),
Msg2Content: buildPlanWorkspace(state),
Msg3Suffix: BuildPlanUserPrompt(state, userInput),
Msg3Role: schema.User,
SkipBaseSystemPrompt: true,
UseLiteToolCatalogMsg: true,
},
)
}
// BuildPlanUserPrompt 构造规划阶段的用户提示词。
func BuildPlanUserPrompt(state *agentmodel.CommonState, userInput string) string {
var sb strings.Builder
sb.WriteString("请继续当前任务规划,只输出一组 SMARTFLOW_DECISION 决策。\n")
sb.WriteString("请基于最近对话与规划工作区推进,不要重复已有计划内容。\n")
sb.WriteString("请先判断最小工具闭环,再决定是否需要拆步;能单步就单步。\n")
sb.WriteString("若需要 context_hook请先根据第一个可执行 step 所需的最小 domain / packs 推导,再写入 hook。\n")
sb.WriteString("禁止把本可直接落工具的动作,抽象写成“完成设计 / 确认方案 / 整理思路”之类空步骤。\n")
sb.WriteString("输出格式与字段约束严格按 msg0 协议执行。\n")
trimmedInput := strings.TrimSpace(userInput)
if trimmedInput != "" {
sb.WriteString("\n用户本轮输入\n")
sb.WriteString(trimmedInput)
sb.WriteString("\n")
}
return strings.TrimSpace(sb.String())
}
// BuildPlanDecisionContractText 返回规划阶段的输出协议说明。
func BuildPlanDecisionContractText() string {
return strings.TrimSpace(fmt.Sprintf(strings.Join([]string{
"输出协议(唯一口径):",
"1. 先输出:<SMARTFLOW_DECISION>{JSON}</SMARTFLOW_DECISION>",
"2. 再输出:给用户看的自然语言正文",
"",
"JSON 字段:",
"- action只能是 %s / %s / %s",
"- reason给后端和日志看的简短说明",
"- complexity只能是 simple / moderate / complex",
"- plan_steps仅当 action=%s 时允许返回,且必须是完整计划",
"- plan_steps[].content步骤正文必填",
"- plan_steps[].done_when可选若提供必须尽量写成 observation / 工具回执可直接证明的完成判定",
"- needs_rough_build仅满足粗排识别条件时为 true否则省略",
"- task_class_idsneeds_rough_build=true 时必填,从上下文读取",
"- context_hook可选仅用于给 execute 阶段提供注入建议",
"- context_hook.domainschedule / taskclass",
"- context_hook.packsstring 数组可选core 固定注入,不要填入 core",
"- context_hook.reason可选说明为何建议该注入",
"",
"注意:",
"- JSON 中不要包含 speak 字段",
"- 不要在 planning 阶段调用任何工具(包括 context_tools_add/remove",
"- 写 plan_steps 前,先判断当前目标能否由单个工具或单个紧凑工具闭环完成;若能,优先输出单步计划",
"- 禁止把本可直接执行的工具动作,拆成抽象语义步骤,例如“先分析需求”“完成设计”“确认方案完整”",
"- 多步计划只应用于:上一步 observation 决定下一步;或确实需要先问用户补关键事实;或目标天然跨域",
"- context_hook 必须从 plan_steps 自然推导:优先对齐第一个可执行 step 的最小 domain / packs不要脱离步骤单独拍脑袋生成",
"- 若用户只给出学习目标、总节数、难度、节次偏好、禁排时段、排除星期、内容拆分授权,这默认属于 taskclass 设计;不要因此写 needs_rough_build=true也不要把 context_hook.domain 设为 schedule",
"- 只有用户明确要求\"排进日程 / 给出具体时间安排 / 现在就排一版\"时,才允许输出 needs_rough_build=true 或 context_hook.domain=schedule",
"- 若首步本质上是任务类写入或修正context_hook 通常应对齐 taskclass若首步需要 schedule 查询/分析/修改,再按最小 packs 推导 schedule hook",
"- step 的 done_when 应优先锚定查询结果已返回、validation 已通过、写工具已成功回执、粗排标记已产生、分析结论已可直接支撑下一步",
"- 例:\"我要复习离散数学,基础较差,大概学 8 节课,不要早上第 1-2 节和晚上第 11-12 节学习,周末也不想学,每节课内容你自己来\"——应规划为 taskclass而不是 schedule也通常不需要 ask_user",
}, "\n"),
agentmodel.PlanActionContinue,
agentmodel.PlanActionAskUser,
agentmodel.PlanActionDone,
agentmodel.PlanActionDone,
))
}