Files
smartmate/backend/active_scheduler/feedbacklocate/prompt.go
Losita ba23ebd201 Version: 0.9.62.dev.260502
后端:
1. 主动调度补齐 `unfinished_feedback` 定位闭环——用户补充信息先在滚动窗口内定位到可校验的日程块,定位失败则继续 ask_user,不再硬猜 target_id 或直接跑 graph。
2. 聊天占管重跑链路加并发保护——`waiting_user_reply -> rerunning` 改为 DB CAS 抢占,重复补充只返回可见等待提示,避免并发生成多份 preview。
3. rerun 结果回写继续收口——新 preview_id 同步回 trigger 审计指针,session 只在拿到新 preview 时更新当前预览,ready_preview 后清空追问状态并释放回普通聊天。
4. 主动调度事件校验放宽 unfinished_feedback 的空 target 场景,允许先触发、后定位,再进入 graph + preview 主链路。
2026-05-02 12:41:50 +08:00

70 lines
2.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 feedbacklocate
import (
"encoding/json"
"strings"
)
const locateSystemPrompt = `
你是 SmartFlow 主动调度里专门负责 unfinished_feedback 的定位器。
你的任务只有一个:根据用户补充的话,把它定位到当前滚动窗口中的某一个 schedule_event定位不了就继续 ask_user。
硬规则:
1. 只允许输出 JSON不要输出 markdown不要输出解释性正文。
2. 只允许返回 action / target_type / target_id / reason / ask_user_question 这几个字段。
3. target_type 只能是 schedule_event。
4. target_id 必须来自候选列表里的 target_id不要编造不要猜一个新的。
5. 当你不能稳定定位时action 必须是 ask_user并给出一句短问题。
6. 当用户补充信息已经足够时action 必须是 select_candidate。
7. 请优先结合当前时间、用户原始补充话术、pending question 和候选日程的时间顺序来判断。
`
func buildPromptInput(req Request, generatedAt string, windowStart string, windowEnd string, candidates []eventCandidate) promptInput {
input := promptInput{
GeneratedAt: generatedAt,
UserMessage: strings.TrimSpace(req.UserMessage),
Window: promptWindowInput{
StartAt: windowStart,
EndAt: windowEnd,
},
}
if trimmed := strings.TrimSpace(req.PendingQuestion); trimmed != "" {
input.PendingQuestion = trimmed
}
if len(req.MissingInfo) > 0 {
input.MissingInfo = cloneAndTrimStrings(req.MissingInfo)
}
input.Candidates = append([]eventCandidate(nil), candidates...)
return input
}
func buildUserPrompt(input promptInput) (string, error) {
raw, err := json.MarshalIndent(input, "", " ")
if err != nil {
return "", err
}
var builder strings.Builder
builder.WriteString("请根据输入定位当前滚动窗口中的 schedule_event。")
builder.WriteString("只输出 JSON不要补充任何其它内容。\n")
builder.WriteString("输入:\n")
builder.WriteString(string(raw))
return builder.String(), nil
}
// BuildAskUserQuestion 负责把 missing_info 转成继续追问用户的短问题。
func BuildAskUserQuestion(missingInfo []string) string {
normalized := cloneAndTrimStrings(missingInfo)
if len(normalized) == 0 {
return "请补充能唯一定位到未完成日程块的信息。"
}
for _, item := range normalized {
if item == "feedback_target" {
return "请告诉我你指的是哪一个未完成的日程块,比如具体时间或名称。"
}
}
return "请补充 " + strings.Join(normalized, "、") + " 对应的信息。"
}