Files
smartmate/backend/agent/llm/quicknote.go
Losita 468367d617 Version: 0.8.3.dev.260328
后端:
1.彻底删除原agent文件夹,并将现agent2文件夹全量重命名为agent(包括全部涉及到的文件以及文档、注释),迁移工作完美结束
2.修复了重试消息的相关逻辑问题

前端:
1.改善了一些交互体验,修复了一些bug,现在只剩少的功能了,现存的bug基本都修复完毕

全仓库:
1.更新了决策记录和README文档
2026-03-28 18:00:31 +08:00

171 lines
5.6 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 agentllm
import (
"context"
"fmt"
"strings"
agentprompt "github.com/LoveLosita/smartflow/backend/agent/prompt"
"github.com/cloudwego/eino-ext/components/model/ark"
)
// QuickNoteIntentOutput 是“随口记意图识别”模型契约。
type QuickNoteIntentOutput struct {
IsQuickNote bool `json:"is_quick_note"`
Title string `json:"title"`
DeadlineAt string `json:"deadline_at"`
Reason string `json:"reason"`
}
// QuickNotePriorityOutput 是“随口记优先级评估”模型契约。
type QuickNotePriorityOutput struct {
PriorityGroup int `json:"priority_group"`
Reason string `json:"reason"`
UrgencyThresholdAt string `json:"urgency_threshold_at"`
}
// QuickNotePlanOutput 是“随口记单请求聚合规划”模型契约。
type QuickNotePlanOutput struct {
Title string `json:"title"`
DeadlineAt string `json:"deadline_at"`
UrgencyThresholdAt string `json:"urgency_threshold_at"`
PriorityGroup int `json:"priority_group"`
PriorityReason string `json:"priority_reason"`
Banter string `json:"banter"`
}
// IdentifyQuickNoteIntent 调用模型识别“是否随口记”。
func IdentifyQuickNoteIntent(ctx context.Context, chatModel *ark.ChatModel, nowText, userInput string) (*QuickNoteIntentOutput, error) {
prompt := fmt.Sprintf(`当前时间(北京时间,精确到分钟):%s
用户输入:%s
请仅输出 JSON不要 markdown不要解释字段如下
{
"is_quick_note": boolean,
"title": string,
"deadline_at": string,
"reason": string
}
字段约束:
1) deadline_at 只允许输出绝对时间,格式必须为 "yyyy-MM-dd HH:mm"。
2) 如果用户说了“明天/后天/下周一/今晚”等相对时间,必须基于上面的当前时间换算成绝对时间。
3) 如果用户没有提及时间deadline_at 输出空字符串。`,
nowText,
userInput,
)
parsed, _, err := CallArkJSON[QuickNoteIntentOutput](ctx, chatModel, agentprompt.QuickNoteIntentPrompt, prompt, ArkCallOptions{
Temperature: 0,
MaxTokens: 256,
Thinking: ThinkingModeDisabled,
})
return parsed, err
}
// PlanQuickNotePriority 调用模型评估优先级与紧急分界线。
func PlanQuickNotePriority(ctx context.Context, chatModel *ark.ChatModel, nowText, title, userInput, deadlineClue, deadlineText string) (*QuickNotePriorityOutput, error) {
prompt := fmt.Sprintf(`当前时间(北京时间,精确到分钟):%s
请对以下任务评估优先级:
- 任务标题:%s
- 用户原始输入:%s
- 时间线索原文:%s
- 归一化截止时间:%s
请仅输出 JSON不要 markdown不要解释
{
"priority_group": 1|2|3|4,
"reason": "简短理由",
"urgency_threshold_at": "yyyy-MM-dd HH:mm 或空字符串"
}
额外约束:
1) urgency_threshold_at 表示“何时从不紧急象限自动平移到紧急象限”;
2) 若该任务不需要自动平移,可输出空字符串;
3) 若任务已在紧急象限priority_group=1 或 3优先输出空字符串
4) 若输出非空时间,必须是绝对时间,且不晚于归一化截止时间(若有)。`,
nowText,
title,
userInput,
deadlineClue,
deadlineText,
)
parsed, _, err := CallArkJSON[QuickNotePriorityOutput](ctx, chatModel, agentprompt.QuickNotePriorityPrompt, prompt, ArkCallOptions{
Temperature: 0,
MaxTokens: 256,
Thinking: ThinkingModeDisabled,
})
return parsed, err
}
// PlanQuickNoteInSingleCall 一次性完成标题/时间/优先级/banter 聚合规划。
func PlanQuickNoteInSingleCall(ctx context.Context, chatModel *ark.ChatModel, nowText, userInput string) (*QuickNotePlanOutput, error) {
prompt := fmt.Sprintf(`当前时间(北京时间,精确到分钟):%s
用户输入:%s
请仅输出 JSON不要 markdown不要解释字段如下
{
"title": string,
"deadline_at": string,
"urgency_threshold_at": string,
"priority_group": 1|2|3|4,
"priority_reason": string,
"banter": string
}
约束:
1) deadline_at 只允许 "yyyy-MM-dd HH:mm" 或空字符串;
2) urgency_threshold_at 只允许 "yyyy-MM-dd HH:mm" 或空字符串;
3) 若用户给了相对时间(如明天/今晚/下周一),必须换算为绝对时间;
4) 若任务不需要自动平移,可让 urgency_threshold_at 为空;
5) banter 只允许一句中文不超过30字不得改动任务事实。`,
nowText,
strings.TrimSpace(userInput),
)
parsed, _, err := CallArkJSON[QuickNotePlanOutput](ctx, chatModel, agentprompt.QuickNotePlanPrompt, prompt, ArkCallOptions{
Temperature: 0,
MaxTokens: 220,
Thinking: ThinkingModeDisabled,
})
return parsed, err
}
// GenerateQuickNoteBanter 生成成功写入后的轻松跟进句。
func GenerateQuickNoteBanter(ctx context.Context, chatModel *ark.ChatModel, userMessage, title, priorityText, deadlineText string) (string, error) {
if chatModel == nil {
return "", fmt.Errorf("model is nil")
}
prompt := fmt.Sprintf(`用户原话:%s
已确认事实:
- 任务标题:%s
- %s
- %s
请输出一句轻松自然的跟进话术(仅一句)。`,
strings.TrimSpace(userMessage),
strings.TrimSpace(title),
strings.TrimSpace(priorityText),
strings.TrimSpace(deadlineText),
)
text, err := CallArkText(ctx, chatModel, agentprompt.QuickNoteReplyBanterPrompt, prompt, ArkCallOptions{
Temperature: 0.7,
MaxTokens: 72,
Thinking: ThinkingModeDisabled,
})
if err != nil {
return "", err
}
text = strings.TrimSpace(text)
text = strings.Trim(text, "\"'“”‘’")
if text == "" {
return "", fmt.Errorf("empty content")
}
if idx := strings.Index(text, "\n"); idx >= 0 {
text = strings.TrimSpace(text[:idx])
}
return text, nil
}