package eino import ( "context" "encoding/json" "strings" "github.com/cloudwego/eino/components/prompt" "github.com/cloudwego/eino/schema" ) // RunCtx 是组装模型消息用的上下文:图解释器(graph.go)把黑板汇总到它, // buildMessages 据此拼出发给模型的消息序列。用统一结构避免散落多处拼装。 type RunCtx struct { UserID string SessionID string System string // Agent 节点系统提示词 Query string // 用户输入 Profile string // 召回的画像 History []*schema.Message // 短期历史 ToolOut []string // 工具/检索节点产出(含参考资料) Upstream []string // 前序协作 agent 的产出(多 agent 接力时注入,让下游基于上游继续) } // chatTemplate 是会话消息模板:系统提示词 + 历史占位 + 用户输入。 // 用 Eino components/prompt.ChatTemplate(FString 仅解析模板串、值原样注入,故 JSON 花括号安全)。 var chatTemplate = prompt.FromMessages(schema.FString, schema.SystemMessage("{system}"), schema.MessagesPlaceholder("history", true), schema.UserMessage("{query}"), ) // buildMessages 把上下文组装为发给模型的消息序列(系统提示词 + 画像 + 工具产出 + 历史 + 用户输入)。 // 系统串的动态拼装(按需注入画像/参考资料)留在 Go 侧;最终经 ChatTemplate 成型。 func buildMessages(ctx context.Context, rc *RunCtx) ([]*schema.Message, error) { var sys strings.Builder sys.WriteString(rc.System) if rc.Profile != "" { sys.WriteString("\n\n关于当前用户的已知信息:\n") sys.WriteString(rc.Profile) sys.WriteString("\n请据此个性化作答并保持其偏好。") } if len(rc.ToolOut) > 0 { sys.WriteString("\n\n以下是工具/检索得到的参考资料:\n") sys.WriteString(strings.Join(rc.ToolOut, "\n---\n")) } if len(rc.Upstream) > 0 { sys.WriteString("\n\n以下是前序协作 agent 的产出,请在此基础上继续完成你的部分(不要重头再来):\n") sys.WriteString(strings.Join(rc.Upstream, "\n---\n")) } return chatTemplate.Format(ctx, map[string]any{ "system": sys.String(), "history": rc.History, "query": rc.Query, }) } // previewArgs 把工具入参压成一行短预览。 func previewArgs(args map[string]any) string { if data, err := json.Marshal(args); err == nil { return truncate(string(data), 120) } return "" }