diff --git a/config/config_env.yaml b/config/config_env.yaml index 234891d..3f2c73f 100644 --- a/config/config_env.yaml +++ b/config/config_env.yaml @@ -147,6 +147,26 @@ dingtalk: # 机器人群组 bot_group_id: bbxt: 23 + # 互动卡片 + card: + # 卡片回调路由key + callback_route_key: "gateway.dev.cdlsxd.cn-dingtalk-card" + # 卡片调试工具 [show:展示 hide:隐藏] + debug_tool_entry_show: "hide" + # 卡片模板 + template: + # 基础消息卡片(title + content) + base_msg: "291468f8-a048-4132-a37e-a14365e855e9.schema" + # 内容收集卡片(title + textarea + button) + content_collect: "3a447814-6a3e-4a02-b48a-92c57b349d77.schema" + # 创建群聊申请(title + content + button) + create_group_approve: "faad6d5d-726d-467f-a6ba-28c1930aa5f3.schema" + # 场景群 + scene_group: + # 问题处理群模板ID + group_template_id_issue_handling: "420089e3-b0fb-40f5-89d2-ec47223bff3b" + # 问题处理群模板机器人ID + group_template_robot_id_issue_handling: "VqgJYpB91j3RnB217690607273471011" qywx: corp_id: "ww48151f694fb8ec67" diff --git a/internal/biz/group_config.go b/internal/biz/group_config.go index c1e89a1..32a6b76 100644 --- a/internal/biz/group_config.go +++ b/internal/biz/group_config.go @@ -591,8 +591,8 @@ func (g *GroupConfigBiz) shouldCreateIssueHandlingGroup(ctx context.Context, rec } issueOwnerStr := strings.Join(userNames, "、") - // 获取机器人应用配置 - botConfig, err := g.botConfigImpl.GetRobotConfig(callback.RobotCode) + // 获取应用配置 + appKey, err := g.botConfigImpl.GetRobotAppKey(callback.RobotCode) if err != nil { return fmt.Errorf("获取机器人配置失败,err: %v", err) } @@ -601,35 +601,34 @@ func (g *GroupConfigBiz) shouldCreateIssueHandlingGroup(ctx context.Context, rec outTrackId := constants.BuildCardOutTrackId(callback.ConversationId, callback.RobotCode) // 发送钉钉卡片 - _, err = g.dingtalkCardClient.CreateAndDeliver(dingtalk.AppKey{ - AppKey: botConfig.ClientId, - AppSecret: botConfig.ClientSecret, - }, &card_1_0.CreateAndDeliverRequest{ - CardTemplateId: tea.String(constants.DingtalkCardTplCreateGroupApprove), - OutTrackId: tea.String(outTrackId), - CallbackType: tea.String("STREAM"), - CardData: &card_1_0.CreateAndDeliverRequestCardData{ - CardParamMap: map[string]*string{ - "title": tea.String("创建群聊提醒"), - "content": tea.String(fmt.Sprintf("**确认创建群聊?**\n\n将邀请以下成员加入群聊:\n\n%s", issueOwnerStr)), - "remark": tea.String("注:如若无需,忽略即可"), - "button_left": tea.String("创建群聊"), - "button_right": tea.String("忽略"), - "action_id": tea.String("create_group"), - "button_display": tea.String("true"), - "group_scope": tea.String(strings.TrimSpace(rec.UserContent.Text)), - "_CARD_DEBUG_TOOL_ENTRY": tea.String(constants.CardDebugToolEntryShow), // 调试字段 + _, err = g.dingtalkCardClient.CreateAndDeliver( + appKey, + &card_1_0.CreateAndDeliverRequest{ + CardTemplateId: tea.String(g.conf.Dingtalk.Card.Template.CreateGroupApprove), + OutTrackId: tea.String(outTrackId), + CallbackType: tea.String("STREAM"), + CardData: &card_1_0.CreateAndDeliverRequestCardData{ + CardParamMap: map[string]*string{ + "title": tea.String("创建群聊提醒"), + "content": tea.String(fmt.Sprintf("**确认创建群聊?**\n\n将邀请以下成员加入群聊:\n\n%s", issueOwnerStr)), + "remark": tea.String("注:如若无需,忽略即可"), + "button_left": tea.String("创建群聊"), + "button_right": tea.String("忽略"), + "action_id": tea.String("create_group"), + "button_display": tea.String("true"), + "group_scope": tea.String(strings.TrimSpace(rec.UserContent.Text)), + "_CARD_DEBUG_TOOL_ENTRY": tea.String(g.conf.Dingtalk.Card.DebugToolEntryShow), // 调试字段 + }, }, - }, - ImGroupOpenSpaceModel: &card_1_0.CreateAndDeliverRequestImGroupOpenSpaceModel{ - SupportForward: tea.Bool(false), - }, - OpenSpaceId: tea.String("dtv1.card//im_group." + callback.ConversationId), - ImGroupOpenDeliverModel: &card_1_0.CreateAndDeliverRequestImGroupOpenDeliverModel{ - RobotCode: tea.String(callback.RobotCode), - Recipients: userIds, - }, - }) + ImGroupOpenSpaceModel: &card_1_0.CreateAndDeliverRequestImGroupOpenSpaceModel{ + SupportForward: tea.Bool(false), + }, + OpenSpaceId: tea.String("dtv1.card//im_group." + callback.ConversationId), + ImGroupOpenDeliverModel: &card_1_0.CreateAndDeliverRequestImGroupOpenDeliverModel{ + RobotCode: tea.String(callback.RobotCode), + Recipients: userIds, + }, + }) if err != nil { return fmt.Errorf("发送钉钉卡片失败,err: %v", err) } diff --git a/internal/biz/qywx_app_test.go b/internal/biz/qywx_app_test.go index e82f612..b30d7dd 100644 --- a/internal/biz/qywx_app_test.go +++ b/internal/biz/qywx_app_test.go @@ -10,9 +10,11 @@ import ( "ai_scheduler/internal/domain/repo" "ai_scheduler/internal/domain/workflow" "ai_scheduler/internal/pkg" + "ai_scheduler/internal/pkg/dingtalk" "ai_scheduler/internal/pkg/lsxd" "ai_scheduler/internal/pkg/utils_ollama" "ai_scheduler/internal/pkg/utils_oss" + "ai_scheduler/internal/tools" "ai_scheduler/utils" "context" "testing" @@ -53,6 +55,14 @@ func run() { registry := workflow.NewRegistry(configConfig, client, repos, components) botGroupConfigImpl := impl.NewBotGroupConfigImpl(db) + botConfigImpl := impl.NewBotConfigImpl(db) qywxAppBiz = NewQywxAppBiz(configConfig, botGroupQywxImpl, group, other) - groupConfigBiz = NewGroupConfigBiz(toolRegis, utils_ossClient, botGroupConfigImpl, registry, configConfig) + reportDailyCacheImpl := impl.NewReportDailyCacheImpl(db) + toolManager := tools.NewManager(configConfig, client) + oauth2Client, _ := dingtalk.NewOauth2Client(rdb) + dingtalkCardClient, _ := dingtalk.NewCardClient(oauth2Client) + + // reportDailyCacheImpl *impl.ReportDailyCacheImpl, rdb *utils.Rdb, toolManager *tools.Manager, dingtalkCardClient *dingtalk.CardClient + + groupConfigBiz = NewGroupConfigBiz(toolRegis, utils_ossClient, botGroupConfigImpl, botConfigImpl, registry, configConfig, reportDailyCacheImpl, rdb, toolManager, dingtalkCardClient) } diff --git a/internal/config/config.go b/internal/config/config.go index c0a6b4d..c129ca4 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -72,10 +72,12 @@ type LLMCapabilityConfig struct { // DingtalkConfig 钉钉配置 type DingtalkConfig struct { - ApiKey string `mapstructure:"api_key"` - ApiSecret string `mapstructure:"api_secret"` - TableDemand AITableConfig `mapstructure:"table_demand"` - BotGroupID map[string]int `mapstructure:"bot_group_id"` // 机器人群组 + ApiKey string `mapstructure:"api_key"` + ApiSecret string `mapstructure:"api_secret"` + TableDemand AITableConfig `mapstructure:"table_demand"` + BotGroupID map[string]int `mapstructure:"bot_group_id"` // 机器人群组 + Card CardConfig `mapstructure:"card"` // 互动卡片 + SceneGroup SceneGroupConfig `mapstructure:"scene_group"` // 场景群 } // QywxConfig 企业微信配置 @@ -97,6 +99,34 @@ type AITableConfig struct { SheetIdOrName string `mapstructure:"sheet_id_or_name"` } +// CardConfig 互动卡片配置 +type CardConfig struct { + // 卡片回调路由key + CallbackRouteKey string `mapstructure:"callback_route_key"` + // 卡片调试工具 [show:展示 hide:隐藏] + DebugToolEntryShow string `mapstructure:"debug_tool_entry_show"` + // 卡片模板 + Template CardTemplateConfig `mapstructure:"template"` +} + +// CardTemplateConfig 卡片模板配置 +type CardTemplateConfig struct { + // 基础消息卡片(title + content) + BaseMsg string `mapstructure:"base_msg"` + // 内容收集卡片(title + textarea + button) + ContentCollect string `mapstructure:"content_collect"` + // 创建群聊申请(title + content + button) + CreateGroupApprove string `mapstructure:"create_group_approve"` +} + +// SceneGroupConfig 场景群配置 +type SceneGroupConfig struct { + // 问题处理群模板ID + GroupTemplateIDIssueHandling string `mapstructure:"group_template_id_issue_handling"` + // 问题处理群模板机器人ID + GroupTemplateRobotIDIssueHandling string `mapstructure:"group_template_robot_id_issue_handling"` +} + // SysConfig 系统配置 type SysConfig struct { SessionLen int `mapstructure:"session_len"` diff --git a/internal/data/constants/dingtalk.go b/internal/data/constants/dingtalk.go index 6919771..1ec6894 100644 --- a/internal/data/constants/dingtalk.go +++ b/internal/data/constants/dingtalk.go @@ -84,13 +84,12 @@ const ( }` ) -// 交互卡片回调类型 +// 交互卡片回调 const ( + // 回调类型 CardActionCallbackTypeAction string = "actionCallback" // 交互卡片回调事件类型 -) -// 交互卡片回调事件类型 -const ( + // 回调事件类型 CardActionTypeCreateGroup string = "create_group" // 创建群聊 ) @@ -117,24 +116,50 @@ func ParseCardOutTrackId(outTrackId string) (spaceId string, botId string) { return } -// dingtalk 卡片模板 -const ( - DingtalkCardTplBaseMsg string = "291468f8-a048-4132-a37e-a14365e855e9.schema" // 基础消息卡片(title + content) - DingtalkCardTplCreateGroupApprove string = "faad6d5d-726d-467f-a6ba-28c1930aa5f3.schema" // 创建群聊申请 -) +// 问题处理群机器人 - LLM 提示词 +const IssueHandlingExtractContentPrompt string = `你是一个【问题与答案生成助手】。 + + 你的职责是: + - 分析用户输入的内容 + - 识别其中隐含或明确的问题 + - 基于输入内容本身,生成对应的问题与答案 -// dingtalk 模板群相关 -const ( - // 群模板id - GroupTemplateIdIssueHandling string = "420089e3-b0fb-40f5-89d2-ec47223bff3b" // 问题处理群模板id + 当用户输入为【多条群聊聊天记录】时: + - 结合问题主题,判断聊天记录中正在讨论或试图解决的问题 + - 一个群聊中可能包含多个相互独立的问题,但它们都围绕着一个主题,一般为用户提出的第一个问题,尽可能总结为一个问题 + - 若确实问题很独立,需要分别识别,对每个问题,整理出清晰、可复用的“问题描述”和“对应答案” - // 模板群机器人ID - GroupTemplateRobotIdIssueHandling string = "VqgJYpB91j3RnB217690607273471011" // 问题处理群模板机器人ID -) + 生成答案时的原则: + - 答案必须来源于聊天内容中已经给出的信息或共识 + - 不要引入外部知识,不要使用聊天记录中真实人名或敏感信息,适当总结 + - 若聊天中未形成明确答案,应明确标记为“暂无明确结论” + - 若存在多种不同观点,应分别列出,不要擅自合并或裁决 -// 群模板机器人 - 主应用机器人映射 -var GroupTemplateRobotIdMap = map[string]string{ - GroupTemplateRobotIdIssueHandling: "ding5wwvnf9hxeyjau7t", -} + 【JSON 输出原则】: + - 你的最终输出必须是**合法的 JSON** + - 不得输出任何额外解释性文字 + - JSON 结构必须严格符合以下约定 -const CardDebugToolEntryShow string = "hide" // 卡片调试工具 [show:展示 hide:隐藏] + JSON 结构约定: + { + "items": [ + { + "question": "清晰、独立、可复用的问题描述", + "answer": "基于聊天内容整理出的答案;如无结论则为“暂无明确结论”", + "confidence": "high | medium | low" + } + ] + } + + 字段说明: + - items:问题与答案列表;若未识别到有效问题,则返回空数组 [] + - question:抽象后的标准问题表述,不包含具体聊天语句 + - answer:整理后的答案,不得引入聊天之外的信息 + - confidence:根据聊天中信息的一致性和明确程度给出判断 + + 如果无法从输入中识别出任何有效问题,返回: + { "items": [] } + + 用户输入: + %s + ` diff --git a/internal/data/impl/bot_config.go b/internal/data/impl/bot_config.go index 4fcbbe6..613cbc0 100644 --- a/internal/data/impl/bot_config.go +++ b/internal/data/impl/bot_config.go @@ -3,6 +3,7 @@ package impl import ( "ai_scheduler/internal/data/model" "ai_scheduler/internal/entitys" + "ai_scheduler/internal/pkg/dingtalk" "ai_scheduler/tmpl/dataTemp" "ai_scheduler/utils" "encoding/json" @@ -21,20 +22,31 @@ func NewBotConfigImpl(db *utils.Db) *BotConfigImpl { } // GetRobotConfig 获取机器人配置 -func (b *BotConfigImpl) GetRobotConfig(robotCode string) (entitys.DingTalkBot, error) { +func (b *BotConfigImpl) GetRobotConfig(robotCode string) (*entitys.DingTalkBot, error) { // 获取机器人配置 var botConfig model.AiBotConfig - cond := builder.NewCond().And(builder.Eq{"robot_code": robotCode}) + cond := builder.NewCond().And(builder.Eq{"robot_code": robotCode}).And(builder.Eq{"status": 1}) err := b.GetOneBySearchToStrut(&cond, &botConfig) if err != nil { - return entitys.DingTalkBot{}, err + return nil, err } // 解出 config var config entitys.DingTalkBot err = json.Unmarshal([]byte(botConfig.BotConfig), &config) if err != nil { - return entitys.DingTalkBot{}, err + return nil, err } - return config, nil + return &config, nil +} + +// GetRobotAppKey 获取机器人应用ID +func (b *BotConfigImpl) GetRobotAppKey(robotCode string) (dingtalk.AppKey, error) { + // 获取机器人配置 + dingTalkBotConfig, err := b.GetRobotConfig(robotCode) + if err != nil { + return dingtalk.AppKey{}, err + } + + return dingTalkBotConfig.GetAppKey(), nil } diff --git a/internal/entitys/bot.go b/internal/entitys/bot.go index ed0902c..55d5743 100644 --- a/internal/entitys/bot.go +++ b/internal/entitys/bot.go @@ -2,6 +2,7 @@ package entitys import ( "ai_scheduler/internal/data/model" + "ai_scheduler/internal/pkg/dingtalk" "gitea.cdlsxd.cn/self-tools/l-dingtalk-stream-sdk-go/chatbot" ) @@ -21,3 +22,10 @@ type DingTalkBot struct { ClientId string `json:"client_id"` ClientSecret string `json:"client_secret"` } + +func (d *DingTalkBot) GetAppKey() dingtalk.AppKey { + return dingtalk.AppKey{ + AppKey: d.ClientId, + AppSecret: d.ClientSecret, + } +} diff --git a/internal/server/ding_talk_bot.go b/internal/server/ding_talk_bot.go index d40fb3f..997f761 100644 --- a/internal/server/ding_talk_bot.go +++ b/internal/server/ding_talk_bot.go @@ -35,14 +35,9 @@ func NewDingTalkBotServer( for _, service := range services { serviceConfigs, err := service.GetServiceCfg() for _, serviceConf := range serviceConfigs { - // 配置不全 if serviceConf.ClientId == "" || serviceConf.ClientSecret == "" { continue } - // 非应用主机器人 pass ,防止重复 - if serviceConf.ClientId != serviceConf.BotIndex { - continue - } cli := DingBotServerInit(serviceConf.ClientId, serviceConf.ClientSecret, service) if cli == nil { log.Infof("%s客户端初始失败:%s", serviceConf.BotIndex, err.Error()) diff --git a/internal/services/callback.go b/internal/services/callback.go index 98361ff..267bf49 100644 --- a/internal/services/callback.go +++ b/internal/services/callback.go @@ -409,7 +409,7 @@ func (s *CallbackService) CallbackDingtalkRobot(c *fiber.Ctx) (err error) { // 通过机器人ID路由到不同能力 switch data.RobotCode { - case constants.GroupTemplateRobotIdIssueHandling: + case s.cfg.Dingtalk.SceneGroup.GroupTemplateRobotIDIssueHandling: // 问题处理群机器人 err := s.issueHandling(c, data) if err != nil { @@ -420,20 +420,6 @@ func (s *CallbackService) CallbackDingtalkRobot(c *fiber.Ctx) (err error) { return nil } - // ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) - // defer cancel() - - // 统一初始化请求参数 - // requireData, err := s.dingTalkBotBiz.InitRequire(ctx, &data) - // if err != nil { - // return fmt.Errorf("初始化请求参数失败: %v", err) - // } - - // 这里需要再实现一套HTTP形式的回调,用于处理钉钉群模板机器人的回调 - // 主程等待处理结果 - // resChan := make(chan string, 10) - // defer close(resChan) - return nil } @@ -456,60 +442,10 @@ func (s *CallbackService) issueHandling(c *fiber.Ctx, data chatbot.BotCallbackDa // 问题处理群机器人内容提取 func (s *CallbackService) issueHandlingExtractContent(data chatbot.BotCallbackDataModel) { - systemPrompt := `你是一个【问题与答案生成助手】。 - - 你的职责是: - - 分析用户输入的内容 - - 识别其中隐含或明确的问题 - - 基于输入内容本身,生成对应的问题与答案 - - 当用户输入为【多条群聊聊天记录】时: - - 结合问题主题,判断聊天记录中正在讨论或试图解决的问题 - - 一个群聊中可能包含多个相互独立的问题,但它们都围绕着一个主题,尽可能总结为一个问题 - - 若确实问题很独立,需要分别识别,对每个问题,整理出清晰、可复用的“问题描述”和“对应答案” - - 生成答案时的原则: - - 答案必须来源于聊天内容中已经给出的信息或共识 - - 不要引入外部知识,不要使用聊天记录中真实人名或敏感信息,适当总结 - - 若聊天中未形成明确答案,应明确标记为“暂无明确结论” - - 若存在多种不同观点,应分别列出,不要擅自合并或裁决 - - 【JSON 输出原则】: - - 你的最终输出必须是**合法的 JSON** - - 不得输出任何额外解释性文字 - - JSON 结构必须严格符合以下约定 - - JSON 结构约定: - { - "items": [ - { - "question": "清晰、独立、可复用的问题描述", - "answer": "基于聊天内容整理出的答案;如无结论则为“暂无明确结论”", - "confidence": "high | medium | low" - } - ] - } - - 字段说明: - - items:问题与答案列表;若未识别到有效问题,则返回空数组 [] - - question:抽象后的标准问题表述,不包含具体聊天语句 - - answer:整理后的答案,不得引入聊天之外的信息 - - confidence:根据聊天中信息的一致性和明确程度给出判断 - - 如果无法从输入中识别出任何有效问题,返回: - { "items": [] } - - 问题主题: - %s - - 用户输入: - %s - ` - - prompt := fmt.Sprintf(systemPrompt, "紧急加款,提示当前账户为离线账户,请输入银行流水号", data.Text.Content) - - fmt.Println("prompt:", prompt) - + // 1.提取用户输入 + prompt := fmt.Sprintf(constants.IssueHandlingExtractContentPrompt, data.Text.Content) + log.Infof("问题提取提示词: %s", prompt) + // LLM 提取 generateResp, err := s.ollamaClient.Generation(context.Background(), &api.GenerateRequest{ Model: s.cfg.Ollama.GenerateModel, Prompt: prompt, @@ -519,7 +455,6 @@ func (s *CallbackService) issueHandlingExtractContent(data chatbot.BotCallbackDa log.Errorf("问题提取失败: %v", err) return } - // 解析 JSON 响应 var resp struct { Items []struct { @@ -533,6 +468,7 @@ func (s *CallbackService) issueHandlingExtractContent(data chatbot.BotCallbackDa return } + // 2.构建文本域内容 cardContentTpl := "问题:%s \n答案:%s" var cardContentList []string for _, item := range resp.Items { @@ -540,20 +476,22 @@ func (s *CallbackService) issueHandlingExtractContent(data chatbot.BotCallbackDa } cardContent := strings.Join(cardContentList, "\n\n") - // 调用卡片 - // 构建卡片 OutTrackId - outTrackId := constants.BuildCardOutTrackId(data.ConversationId, data.RobotCode) + // 3.获取应用AppKey + appKey, err := s.botConfigImpl.GetRobotAppKey(data.RobotCode) + if err != nil { + log.Errorf("获取应用配置失败: %v", err) + return + } + // 4.创建并投放卡片 + outTrackId := constants.BuildCardOutTrackId(data.ConversationId, data.RobotCode) // 构建卡片 OutTrackId _, err = s.dingtalkCardClient.CreateAndDeliver( - dingtalk.AppKey{ - AppKey: "ding5wwvnf9hxeyjau7t", - AppSecret: "FxXVlTzxrKXvJ8h-9uK0s5TjaBfOJSXumpmrHal-NmQAtku9wOPxcss0Af6WHoAK", - }, + appKey, &card_1_0.CreateAndDeliverRequest{ - CardTemplateId: tea.String("3a447814-6a3e-4a02-b48a-92c57b349d77.schema"), + CardTemplateId: tea.String(s.cfg.Dingtalk.Card.Template.ContentCollect), OutTrackId: tea.String(outTrackId), CallbackType: tea.String("HTTP"), - CallbackRouteKey: tea.String("gateway.dev.cdlsxd.cn-dingtalk-card"), + CallbackRouteKey: tea.String(s.cfg.Dingtalk.Card.CallbackRouteKey), CardData: &card_1_0.CreateAndDeliverRequestCardData{ CardParamMap: map[string]*string{ "title": tea.String("QA知识收集"), @@ -562,7 +500,7 @@ func (s *CallbackService) issueHandlingExtractContent(data chatbot.BotCallbackDa "textarea_display": tea.String("normal"), "action_id": tea.String("collect_qa"), "tenant_id": tea.String(constants.KnowledgeTenantIdDefault), - "_CARD_DEBUG_TOOL_ENTRY": tea.String(constants.CardDebugToolEntryShow), // 调试字段 + "_CARD_DEBUG_TOOL_ENTRY": tea.String(s.cfg.Dingtalk.Card.DebugToolEntryShow), // 调试字段 }, }, ImGroupOpenSpaceModel: &card_1_0.CreateAndDeliverRequestImGroupOpenSpaceModel{ @@ -570,7 +508,7 @@ func (s *CallbackService) issueHandlingExtractContent(data chatbot.BotCallbackDa }, OpenSpaceId: tea.String("dtv1.card//im_group." + data.ConversationId), ImGroupOpenDeliverModel: &card_1_0.CreateAndDeliverRequestImGroupOpenDeliverModel{ - RobotCode: tea.String(constants.GroupTemplateRobotIdIssueHandling), + RobotCode: tea.String(s.cfg.Dingtalk.SceneGroup.GroupTemplateRobotIDIssueHandling), }, }, ) @@ -579,26 +517,24 @@ func (s *CallbackService) issueHandlingExtractContent(data chatbot.BotCallbackDa // 问题处理群机器人查询知识库 func (s *CallbackService) issueHandlingQueryKnowledgeBase(data chatbot.BotCallbackDataModel) { - // 获取应用主机器人 - mainRobotCode := data.RobotCode - if robotCode, ok := constants.GroupTemplateRobotIdMap[data.RobotCode]; ok { - mainRobotCode = robotCode - } - // 获取应用机器人配置 - robotConfig, err := s.botConfigImpl.GetRobotConfig(mainRobotCode) + // // 获取应用主机器人 + // mainRobotCode := data.RobotCode + // if robotCode, ok := constants.GroupTemplateRobotIdMap[data.RobotCode]; ok { + // mainRobotCode = robotCode + // } + + // 获取应用配置 + appKey, err := s.botConfigImpl.GetRobotAppKey(data.RobotCode) if err != nil { - log.Errorf("应用机器人配置不存在: %s, err: %v", mainRobotCode, err) + log.Errorf("应用机器人配置不存在: %s, err: %v", data.RobotCode, err) return } // 创建卡片 - outTrackId := constants.BuildCardOutTrackId(data.ConversationId, mainRobotCode) + outTrackId := constants.BuildCardOutTrackId(data.ConversationId, data.RobotCode) _, err = s.dingtalkCardClient.CreateAndDeliver( - dingtalk.AppKey{ - AppKey: robotConfig.ClientId, - AppSecret: robotConfig.ClientSecret, - }, + appKey, &card_1_0.CreateAndDeliverRequest{ - CardTemplateId: tea.String(constants.DingtalkCardTplBaseMsg), + CardTemplateId: tea.String(s.cfg.Dingtalk.Card.Template.BaseMsg), CardData: &card_1_0.CreateAndDeliverRequestCardData{ CardParamMap: map[string]*string{ "title": tea.String(data.Text.Content), @@ -650,10 +586,7 @@ func (s *CallbackService) issueHandlingQueryKnowledgeBase(data chatbot.BotCallba // 卡片更新 _, err = s.dingtalkCardClient.UpdateCard( - dingtalk.AppKey{ - AppKey: robotConfig.ClientId, - AppSecret: robotConfig.ClientSecret, - }, + appKey, &card_1_0.UpdateCardRequest{ OutTrackId: tea.String(outTrackId), CardData: &card_1_0.UpdateCardRequestCardData{ @@ -740,27 +673,24 @@ func (s *CallbackService) issueHandlingCollectQA(data card.CardRequest) *card.Ca conversationId, robotCode := constants.ParseCardOutTrackId(data.OutTrackId) // 获取主应用机器人(这里可能是群模板机器人) - mainRobotId := robotCode - if robotCode, ok := constants.GroupTemplateRobotIdMap[robotCode]; ok { - mainRobotId = robotCode - } + // mainRobotId := robotCode + // if robotCode, ok := constants.GroupTemplateRobotIdMap[robotCode]; ok { + // mainRobotId = robotCode + // } - // 获取 robot 配置 - robotConfig, err := s.botConfigImpl.GetRobotConfig(mainRobotId) + // 获取应用配置 + appKey, err := s.botConfigImpl.GetRobotAppKey(robotCode) if err != nil { - log.Errorf("获取 robot 配置失败: %v", err) + log.Errorf("获取应用机器人配置失败: %v", err) return } // 发送卡片通知用户注入成功 outTrackId := constants.BuildCardOutTrackId(conversationId, robotCode) s.dingtalkCardClient.CreateAndDeliver( - dingtalk.AppKey{ - AppKey: robotConfig.ClientId, - AppSecret: robotConfig.ClientSecret, - }, + appKey, &card_1_0.CreateAndDeliverRequest{ - CardTemplateId: tea.String(constants.DingtalkCardTplBaseMsg), + CardTemplateId: tea.String(s.cfg.Dingtalk.Card.Template.BaseMsg), OutTrackId: tea.String(outTrackId), CardData: &card_1_0.CreateAndDeliverRequestCardData{ CardParamMap: map[string]*string{ diff --git a/internal/services/dtalk_bot.go b/internal/services/dtalk_bot.go index 18e80b6..3fcc186 100644 --- a/internal/services/dtalk_bot.go +++ b/internal/services/dtalk_bot.go @@ -296,16 +296,14 @@ func (d *DingBotService) createIssueHandlingGroupAndInit(ctx context.Context, ca // 初始化群聊 // 1.开场白 - // 构建卡片 OutTrackId - outTrackId := constants.BuildCardOutTrackId(openConversationId, constants.GroupTemplateRobotIdIssueHandling) - // 群主题 groupScope := callbackParams["group_scope"].(string) - + // 构建卡片 OutTrackId + outTrackId := constants.BuildCardOutTrackId(openConversationId, d.config.Dingtalk.SceneGroup.GroupTemplateRobotIDIssueHandling) _, err = d.dingtalkCardClient.CreateAndDeliver( appKey, &card_1_0.CreateAndDeliverRequest{ - CardTemplateId: tea.String(constants.DingtalkCardTplBaseMsg), + CardTemplateId: tea.String(d.config.Dingtalk.Card.Template.BaseMsg), OutTrackId: tea.String(outTrackId), CallbackType: tea.String("HTTP"), CardData: &card_1_0.CreateAndDeliverRequestCardData{ @@ -319,7 +317,7 @@ func (d *DingBotService) createIssueHandlingGroupAndInit(ctx context.Context, ca }, OpenSpaceId: tea.String("dtv1.card//im_group." + openConversationId), ImGroupOpenDeliverModel: &card_1_0.CreateAndDeliverRequestImGroupOpenDeliverModel{ - RobotCode: tea.String(constants.GroupTemplateRobotIdIssueHandling), + RobotCode: tea.String(d.config.Dingtalk.SceneGroup.GroupTemplateRobotIDIssueHandling), AtUserIds: map[string]*string{ "@ALL": tea.String("@ALL"), }, @@ -329,11 +327,11 @@ func (d *DingBotService) createIssueHandlingGroupAndInit(ctx context.Context, ca // 2. 机器人能力 // 构建卡片 OutTrackId - outTrackId = constants.BuildCardOutTrackId(openConversationId, constants.GroupTemplateRobotIdIssueHandling) + outTrackId = constants.BuildCardOutTrackId(openConversationId, d.config.Dingtalk.SceneGroup.GroupTemplateRobotIDIssueHandling) _, err = d.dingtalkCardClient.CreateAndDeliver( appKey, &card_1_0.CreateAndDeliverRequest{ - CardTemplateId: tea.String(constants.DingtalkCardTplBaseMsg), + CardTemplateId: tea.String(d.config.Dingtalk.Card.Template.BaseMsg), OutTrackId: tea.String(outTrackId), CallbackType: tea.String("HTTP"), CardData: &card_1_0.CreateAndDeliverRequestCardData{ @@ -347,7 +345,7 @@ func (d *DingBotService) createIssueHandlingGroupAndInit(ctx context.Context, ca }, OpenSpaceId: tea.String("dtv1.card//im_group." + openConversationId), ImGroupOpenDeliverModel: &card_1_0.CreateAndDeliverRequestImGroupOpenDeliverModel{ - RobotCode: tea.String(constants.GroupTemplateRobotIdIssueHandling), + RobotCode: tea.String(d.config.Dingtalk.SceneGroup.GroupTemplateRobotIDIssueHandling), AtUserIds: map[string]*string{ "@ALL": tea.String("@ALL"), }, @@ -371,7 +369,7 @@ func (d *DingBotService) createIssueHandlingGroup(ctx context.Context, accessTok // 根据群模板ID创建群 if useTemplateGroup { - return d.dingTalkOld.CreateSceneGroupConversation(ctx, accessToken, "问题处理群", userIds, constants.GroupTemplateIdIssueHandling) + return d.dingTalkOld.CreateSceneGroupConversation(ctx, accessToken, "问题处理群", userIds, d.config.Dingtalk.SceneGroup.GroupTemplateIDIssueHandling) } return diff --git a/internal/services/dtalk_bot_test.go b/internal/services/dtalk_bot_test.go index 37c206e..989cba2 100644 --- a/internal/services/dtalk_bot_test.go +++ b/internal/services/dtalk_bot_test.go @@ -93,10 +93,14 @@ func run() { ollamaService := llm_service.NewOllamaGenerate(client, utils_vllmClient, configConfig, chatHisImpl) // 初始化工具管理器 manager := tools.NewManager(configConfig, client) + // 初始化钉钉认证客户端 + oauth2Client, _ := dingtalk.NewOauth2Client(rdb) // 初始化钉钉联系人客户端 - contactClient, _ := dingtalk.NewContactClient(configConfig) + contactClient, _ := dingtalk.NewContactClient(oauth2Client) // 初始化钉钉记事本客户端 - notableClient, _ := dingtalk.NewNotableClient(configConfig) + notableClient, _ := dingtalk.NewNotableClient(oauth2Client) + // 初始化钉钉卡片客户端 + cardClient, _ := dingtalk.NewCardClient(oauth2Client) // 初始化工具注册 toolRegis := tools_regis.NewToolsRegis(botToolsImpl) // 初始化机器人聊天历史实现层 @@ -120,8 +124,9 @@ func run() { group := qywx.NewGroup(botGroupQywxImpl, qywxAuth) other := qywx.NewOther(qywxAuth) qywxAppBiz := biz.NewQywxAppBiz(configConfig, botGroupQywxImpl, group, other) - groupConfigBiz := biz.NewGroupConfigBiz(toolRegis, utils_ossClient, botGroupConfigImpl, registry, configConfig, impl.NewReportDailyCacheImpl(db), rdb) - dingTalkBotBiz := biz.NewDingTalkBotBiz(doDo, handle, botConfigImpl, botGroupImpl, user, botChatHisImpl, impl.NewReportDailyCacheImpl(db), manager, configConfig, sendCardClient, groupConfigBiz) + groupConfigBiz := biz.NewGroupConfigBiz(toolRegis, utils_ossClient, botGroupConfigImpl, botConfigImpl, registry, configConfig, impl.NewReportDailyCacheImpl(db), rdb, manager, cardClient) + macro := do.NewMacro(botGroupImpl, impl.NewReportDailyCacheImpl(db)) + dingTalkBotBiz := biz.NewDingTalkBotBiz(doDo, handle, botConfigImpl, botGroupImpl, user, botChatHisImpl, impl.NewReportDailyCacheImpl(db), manager, configConfig, sendCardClient, groupConfigBiz, macro) // 初始化钉钉机器人服务 cronService = NewCronService(configConfig, dingTalkBotBiz, qywxAppBiz, groupConfigBiz) }