Files
smartmate/backend/services/agent/node/correction.go
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

137 lines
4.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 agentnode
import (
"fmt"
"strings"
agentmodel "github.com/LoveLosita/smartflow/backend/services/agent/model"
"github.com/cloudwego/eino/schema"
)
const (
correctionHistoryKindKey = "newagent_history_kind"
correctionHistoryKindCorrectionUser = "llm_correction_prompt"
)
// AppendLLMCorrection 追加 LLM 修正提示到对话历史。
//
// 设计目的:
// 1. 当 LLM 输出不符合预期(如不支持的 action、格式错误等不应直接报错终止
// 2. 应该给 LLM 一个自我修正的机会,把错误反馈写回历史,让它重新生成;
// 3. 该函数封装了"追加 assistant 消息 + 追加纠正提示"的通用流程。
//
// 参数说明:
// - conversationContext: 对话上下文,用于追加历史消息;
// - llmOutput: LLM 的原始输出内容,会作为 assistant 消息追加;
// - validOptionsDesc: 合法选项的描述,用于构造纠正提示。
//
// 使用示例:
//
// AppendLLMCorrection(conversationContext, decision.Speak, "合法的 action 包括continue、ask_user、next_plan、done")
//
// 返回值:
// - 返回 nil 表示修正流程完成,调用方应继续 Graph 循环;
// - 该函数不会返回 error因为追加历史失败不影响主流程。
func AppendLLMCorrection(
conversationContext *agentmodel.ConversationContext,
llmOutput string,
validOptionsDesc string,
) {
if conversationContext == nil {
return
}
// 1. 构造 assistant 消息,让 LLM 知道自己刚才输出了什么。
// 2. 空输出不回灌,避免把占位文本写进历史造成噪音。
// 3. 与最近一条 assistant 完全相同则跳过,避免重复回灌放大复读。
assistantContent := strings.TrimSpace(llmOutput)
appendCorrectionAssistantIfNeeded(conversationContext, assistantContent)
// 2. 构造纠正提示,明确告知 LLM 哪里错了、合法选项有哪些。
// 不做硬编码的错误类型,由调用方通过 validOptionsDesc 传入。
correctionContent := fmt.Sprintf(
"你的输出不符合预期。%s 请重新分析当前状态,输出正确的内容。",
validOptionsDesc,
)
conversationContext.AppendHistory(&schema.Message{
Role: schema.User,
Content: correctionContent,
Extra: map[string]any{
correctionHistoryKindKey: correctionHistoryKindCorrectionUser,
},
})
}
// AppendLLMCorrectionWithHint 追加 LLM 修正提示(带自定义错误描述)。
//
// 相比 AppendLLMCorrection该函数允许调用方提供更详细的错误描述
// 适用于需要明确告知 LLM 具体哪里出错的场景。
//
// 参数说明:
// - conversationContext: 对话上下文;
// - llmOutput: LLM 的原始输出内容;
// - errorDesc: 具体的错误描述,如 "action \"invalid\" 不是合法的执行动作"
// - validOptionsDesc: 合法选项的描述。
func AppendLLMCorrectionWithHint(
conversationContext *agentmodel.ConversationContext,
llmOutput string,
errorDesc string,
validOptionsDesc string,
) {
if conversationContext == nil {
return
}
assistantContent := strings.TrimSpace(llmOutput)
appendCorrectionAssistantIfNeeded(conversationContext, assistantContent)
correctionContent := fmt.Sprintf(
"%s %s 请重新分析当前状态,输出正确的内容。",
errorDesc,
validOptionsDesc,
)
conversationContext.AppendHistory(&schema.Message{
Role: schema.User,
Content: correctionContent,
Extra: map[string]any{
correctionHistoryKindKey: correctionHistoryKindCorrectionUser,
},
})
}
// appendCorrectionAssistantIfNeeded 在纠错回灌前做最小降噪。
//
// 1. 空文本直接跳过,避免写入“占位噪音”;
// 2. 若与“最近一条 assistant 文本”完全一致则跳过,避免同句反复回灌;
// 3. 仅负责“是否回灌”判定,不负责生成纠错 user 提示。
func appendCorrectionAssistantIfNeeded(
conversationContext *agentmodel.ConversationContext,
assistantContent string,
) {
if conversationContext == nil {
return
}
assistantContent = strings.TrimSpace(assistantContent)
if assistantContent == "" {
return
}
history := conversationContext.HistorySnapshot()
for i := len(history) - 1; i >= 0; i-- {
msg := history[i]
if msg == nil || msg.Role != schema.Assistant {
continue
}
if strings.TrimSpace(msg.Content) == assistantContent {
return
}
// 只看最近一条 assistant避免误去重很久以前的正常重复表达。
break
}
conversationContext.AppendHistory(&schema.Message{
Role: schema.Assistant,
Content: assistantContent,
})
}