fix: 代码优化 1.需要环境区分的配置,从常量移动到yaml 2. 新增获取机器人应用配置的公共方法 3.以上修改相应的业务调整 4.修复一些单元测试文件的报错

This commit is contained in:
fuzhongyun 2026-01-27 11:51:26 +08:00
parent 32cd8691b7
commit fa08cad74a
11 changed files with 223 additions and 191 deletions

View File

@ -147,6 +147,26 @@ dingtalk:
# 机器人群组 # 机器人群组
bot_group_id: bot_group_id:
bbxt: 23 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: qywx:
corp_id: "ww48151f694fb8ec67" corp_id: "ww48151f694fb8ec67"

View File

@ -591,8 +591,8 @@ func (g *GroupConfigBiz) shouldCreateIssueHandlingGroup(ctx context.Context, rec
} }
issueOwnerStr := strings.Join(userNames, "、") issueOwnerStr := strings.Join(userNames, "、")
// 获取机器人应用配置 // 获取应用配置
botConfig, err := g.botConfigImpl.GetRobotConfig(callback.RobotCode) appKey, err := g.botConfigImpl.GetRobotAppKey(callback.RobotCode)
if err != nil { if err != nil {
return fmt.Errorf("获取机器人配置失败err: %v", err) return fmt.Errorf("获取机器人配置失败err: %v", err)
} }
@ -601,11 +601,10 @@ func (g *GroupConfigBiz) shouldCreateIssueHandlingGroup(ctx context.Context, rec
outTrackId := constants.BuildCardOutTrackId(callback.ConversationId, callback.RobotCode) outTrackId := constants.BuildCardOutTrackId(callback.ConversationId, callback.RobotCode)
// 发送钉钉卡片 // 发送钉钉卡片
_, err = g.dingtalkCardClient.CreateAndDeliver(dingtalk.AppKey{ _, err = g.dingtalkCardClient.CreateAndDeliver(
AppKey: botConfig.ClientId, appKey,
AppSecret: botConfig.ClientSecret, &card_1_0.CreateAndDeliverRequest{
}, &card_1_0.CreateAndDeliverRequest{ CardTemplateId: tea.String(g.conf.Dingtalk.Card.Template.CreateGroupApprove),
CardTemplateId: tea.String(constants.DingtalkCardTplCreateGroupApprove),
OutTrackId: tea.String(outTrackId), OutTrackId: tea.String(outTrackId),
CallbackType: tea.String("STREAM"), CallbackType: tea.String("STREAM"),
CardData: &card_1_0.CreateAndDeliverRequestCardData{ CardData: &card_1_0.CreateAndDeliverRequestCardData{
@ -618,7 +617,7 @@ func (g *GroupConfigBiz) shouldCreateIssueHandlingGroup(ctx context.Context, rec
"action_id": tea.String("create_group"), "action_id": tea.String("create_group"),
"button_display": tea.String("true"), "button_display": tea.String("true"),
"group_scope": tea.String(strings.TrimSpace(rec.UserContent.Text)), "group_scope": tea.String(strings.TrimSpace(rec.UserContent.Text)),
"_CARD_DEBUG_TOOL_ENTRY": tea.String(constants.CardDebugToolEntryShow), // 调试字段 "_CARD_DEBUG_TOOL_ENTRY": tea.String(g.conf.Dingtalk.Card.DebugToolEntryShow), // 调试字段
}, },
}, },
ImGroupOpenSpaceModel: &card_1_0.CreateAndDeliverRequestImGroupOpenSpaceModel{ ImGroupOpenSpaceModel: &card_1_0.CreateAndDeliverRequestImGroupOpenSpaceModel{

View File

@ -10,9 +10,11 @@ import (
"ai_scheduler/internal/domain/repo" "ai_scheduler/internal/domain/repo"
"ai_scheduler/internal/domain/workflow" "ai_scheduler/internal/domain/workflow"
"ai_scheduler/internal/pkg" "ai_scheduler/internal/pkg"
"ai_scheduler/internal/pkg/dingtalk"
"ai_scheduler/internal/pkg/lsxd" "ai_scheduler/internal/pkg/lsxd"
"ai_scheduler/internal/pkg/utils_ollama" "ai_scheduler/internal/pkg/utils_ollama"
"ai_scheduler/internal/pkg/utils_oss" "ai_scheduler/internal/pkg/utils_oss"
"ai_scheduler/internal/tools"
"ai_scheduler/utils" "ai_scheduler/utils"
"context" "context"
"testing" "testing"
@ -53,6 +55,14 @@ func run() {
registry := workflow.NewRegistry(configConfig, client, repos, components) registry := workflow.NewRegistry(configConfig, client, repos, components)
botGroupConfigImpl := impl.NewBotGroupConfigImpl(db) botGroupConfigImpl := impl.NewBotGroupConfigImpl(db)
botConfigImpl := impl.NewBotConfigImpl(db)
qywxAppBiz = NewQywxAppBiz(configConfig, botGroupQywxImpl, group, other) 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)
} }

View File

@ -76,6 +76,8 @@ type DingtalkConfig struct {
ApiSecret string `mapstructure:"api_secret"` ApiSecret string `mapstructure:"api_secret"`
TableDemand AITableConfig `mapstructure:"table_demand"` TableDemand AITableConfig `mapstructure:"table_demand"`
BotGroupID map[string]int `mapstructure:"bot_group_id"` // 机器人群组 BotGroupID map[string]int `mapstructure:"bot_group_id"` // 机器人群组
Card CardConfig `mapstructure:"card"` // 互动卡片
SceneGroup SceneGroupConfig `mapstructure:"scene_group"` // 场景群
} }
// QywxConfig 企业微信配置 // QywxConfig 企业微信配置
@ -97,6 +99,34 @@ type AITableConfig struct {
SheetIdOrName string `mapstructure:"sheet_id_or_name"` 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 系统配置 // SysConfig 系统配置
type SysConfig struct { type SysConfig struct {
SessionLen int `mapstructure:"session_len"` SessionLen int `mapstructure:"session_len"`

View File

@ -84,13 +84,12 @@ const (
}` }`
) )
// 交互卡片回调类型 // 交互卡片回调
const ( const (
// 回调类型
CardActionCallbackTypeAction string = "actionCallback" // 交互卡片回调事件类型 CardActionCallbackTypeAction string = "actionCallback" // 交互卡片回调事件类型
)
// 交互卡片回调事件类型 // 回调事件类型
const (
CardActionTypeCreateGroup string = "create_group" // 创建群聊 CardActionTypeCreateGroup string = "create_group" // 创建群聊
) )
@ -117,24 +116,50 @@ func ParseCardOutTrackId(outTrackId string) (spaceId string, botId string) {
return return
} }
// dingtalk 卡片模板 // 问题处理群机器人 - LLM 提示词
const ( const IssueHandlingExtractContentPrompt string = `你是一个问题与答案生成助手
DingtalkCardTplBaseMsg string = "291468f8-a048-4132-a37e-a14365e855e9.schema" // 基础消息卡片(title + content)
DingtalkCardTplCreateGroupApprove string = "faad6d5d-726d-467f-a6ba-28c1930aa5f3.schema" // 创建群聊申请
)
// 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 结构必须严格符合以下约定
JSON 结构约定
{
"items": [
{
"question": "清晰、独立、可复用的问题描述",
"answer": "基于聊天内容整理出的答案;如无结论则为“暂无明确结论”",
"confidence": "high | medium | low"
}
]
} }
const CardDebugToolEntryShow string = "hide" // 卡片调试工具 [show展示 hide隐藏] 字段说明
- items问题与答案列表若未识别到有效问题则返回空数组 []
- question抽象后的标准问题表述不包含具体聊天语句
- answer整理后的答案不得引入聊天之外的信息
- confidence根据聊天中信息的一致性和明确程度给出判断
如果无法从输入中识别出任何有效问题返回
{ "items": [] }
用户输入
%s
`

View File

@ -3,6 +3,7 @@ package impl
import ( import (
"ai_scheduler/internal/data/model" "ai_scheduler/internal/data/model"
"ai_scheduler/internal/entitys" "ai_scheduler/internal/entitys"
"ai_scheduler/internal/pkg/dingtalk"
"ai_scheduler/tmpl/dataTemp" "ai_scheduler/tmpl/dataTemp"
"ai_scheduler/utils" "ai_scheduler/utils"
"encoding/json" "encoding/json"
@ -21,20 +22,31 @@ func NewBotConfigImpl(db *utils.Db) *BotConfigImpl {
} }
// GetRobotConfig 获取机器人配置 // GetRobotConfig 获取机器人配置
func (b *BotConfigImpl) GetRobotConfig(robotCode string) (entitys.DingTalkBot, error) { func (b *BotConfigImpl) GetRobotConfig(robotCode string) (*entitys.DingTalkBot, error) {
// 获取机器人配置 // 获取机器人配置
var botConfig model.AiBotConfig 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) err := b.GetOneBySearchToStrut(&cond, &botConfig)
if err != nil { if err != nil {
return entitys.DingTalkBot{}, err return nil, err
} }
// 解出 config // 解出 config
var config entitys.DingTalkBot var config entitys.DingTalkBot
err = json.Unmarshal([]byte(botConfig.BotConfig), &config) err = json.Unmarshal([]byte(botConfig.BotConfig), &config)
if err != nil { 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
} }

View File

@ -2,6 +2,7 @@ package entitys
import ( import (
"ai_scheduler/internal/data/model" "ai_scheduler/internal/data/model"
"ai_scheduler/internal/pkg/dingtalk"
"gitea.cdlsxd.cn/self-tools/l-dingtalk-stream-sdk-go/chatbot" "gitea.cdlsxd.cn/self-tools/l-dingtalk-stream-sdk-go/chatbot"
) )
@ -21,3 +22,10 @@ type DingTalkBot struct {
ClientId string `json:"client_id"` ClientId string `json:"client_id"`
ClientSecret string `json:"client_secret"` ClientSecret string `json:"client_secret"`
} }
func (d *DingTalkBot) GetAppKey() dingtalk.AppKey {
return dingtalk.AppKey{
AppKey: d.ClientId,
AppSecret: d.ClientSecret,
}
}

View File

@ -35,14 +35,9 @@ func NewDingTalkBotServer(
for _, service := range services { for _, service := range services {
serviceConfigs, err := service.GetServiceCfg() serviceConfigs, err := service.GetServiceCfg()
for _, serviceConf := range serviceConfigs { for _, serviceConf := range serviceConfigs {
// 配置不全
if serviceConf.ClientId == "" || serviceConf.ClientSecret == "" { if serviceConf.ClientId == "" || serviceConf.ClientSecret == "" {
continue continue
} }
// 非应用主机器人 pass ,防止重复
if serviceConf.ClientId != serviceConf.BotIndex {
continue
}
cli := DingBotServerInit(serviceConf.ClientId, serviceConf.ClientSecret, service) cli := DingBotServerInit(serviceConf.ClientId, serviceConf.ClientSecret, service)
if cli == nil { if cli == nil {
log.Infof("%s客户端初始失败:%s", serviceConf.BotIndex, err.Error()) log.Infof("%s客户端初始失败:%s", serviceConf.BotIndex, err.Error())

View File

@ -409,7 +409,7 @@ func (s *CallbackService) CallbackDingtalkRobot(c *fiber.Ctx) (err error) {
// 通过机器人ID路由到不同能力 // 通过机器人ID路由到不同能力
switch data.RobotCode { switch data.RobotCode {
case constants.GroupTemplateRobotIdIssueHandling: case s.cfg.Dingtalk.SceneGroup.GroupTemplateRobotIDIssueHandling:
// 问题处理群机器人 // 问题处理群机器人
err := s.issueHandling(c, data) err := s.issueHandling(c, data)
if err != nil { if err != nil {
@ -420,20 +420,6 @@ func (s *CallbackService) CallbackDingtalkRobot(c *fiber.Ctx) (err error) {
return nil 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 return nil
} }
@ -456,60 +442,10 @@ func (s *CallbackService) issueHandling(c *fiber.Ctx, data chatbot.BotCallbackDa
// 问题处理群机器人内容提取 // 问题处理群机器人内容提取
func (s *CallbackService) issueHandlingExtractContent(data chatbot.BotCallbackDataModel) { func (s *CallbackService) issueHandlingExtractContent(data chatbot.BotCallbackDataModel) {
systemPrompt := `你是一个问题与答案生成助手 // 1.提取用户输入
prompt := fmt.Sprintf(constants.IssueHandlingExtractContentPrompt, data.Text.Content)
你的职责是 log.Infof("问题提取提示词: %s", prompt)
- 分析用户输入的内容 // LLM 提取
- 识别其中隐含或明确的问题
- 基于输入内容本身生成对应的问题与答案
当用户输入为多条群聊聊天记录
- 结合问题主题判断聊天记录中正在讨论或试图解决的问题
- 一个群聊中可能包含多个相互独立的问题但它们都围绕着一个主题尽可能总结为一个问题
- 若确实问题很独立需要分别识别对每个问题整理出清晰可复用的问题描述对应答案
生成答案时的原则
- 答案必须来源于聊天内容中已经给出的信息或共识
- 不要引入外部知识不要使用聊天记录中真实人名或敏感信息适当总结
- 若聊天中未形成明确答案应明确标记为暂无明确结论
- 若存在多种不同观点应分别列出不要擅自合并或裁决
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)
generateResp, err := s.ollamaClient.Generation(context.Background(), &api.GenerateRequest{ generateResp, err := s.ollamaClient.Generation(context.Background(), &api.GenerateRequest{
Model: s.cfg.Ollama.GenerateModel, Model: s.cfg.Ollama.GenerateModel,
Prompt: prompt, Prompt: prompt,
@ -519,7 +455,6 @@ func (s *CallbackService) issueHandlingExtractContent(data chatbot.BotCallbackDa
log.Errorf("问题提取失败: %v", err) log.Errorf("问题提取失败: %v", err)
return return
} }
// 解析 JSON 响应 // 解析 JSON 响应
var resp struct { var resp struct {
Items []struct { Items []struct {
@ -533,6 +468,7 @@ func (s *CallbackService) issueHandlingExtractContent(data chatbot.BotCallbackDa
return return
} }
// 2.构建文本域内容
cardContentTpl := "问题:%s \n答案%s" cardContentTpl := "问题:%s \n答案%s"
var cardContentList []string var cardContentList []string
for _, item := range resp.Items { for _, item := range resp.Items {
@ -540,20 +476,22 @@ func (s *CallbackService) issueHandlingExtractContent(data chatbot.BotCallbackDa
} }
cardContent := strings.Join(cardContentList, "\n\n") cardContent := strings.Join(cardContentList, "\n\n")
// 调用卡片 // 3.获取应用AppKey
// 构建卡片 OutTrackId appKey, err := s.botConfigImpl.GetRobotAppKey(data.RobotCode)
outTrackId := constants.BuildCardOutTrackId(data.ConversationId, data.RobotCode) if err != nil {
log.Errorf("获取应用配置失败: %v", err)
return
}
// 4.创建并投放卡片
outTrackId := constants.BuildCardOutTrackId(data.ConversationId, data.RobotCode) // 构建卡片 OutTrackId
_, err = s.dingtalkCardClient.CreateAndDeliver( _, err = s.dingtalkCardClient.CreateAndDeliver(
dingtalk.AppKey{ appKey,
AppKey: "ding5wwvnf9hxeyjau7t",
AppSecret: "FxXVlTzxrKXvJ8h-9uK0s5TjaBfOJSXumpmrHal-NmQAtku9wOPxcss0Af6WHoAK",
},
&card_1_0.CreateAndDeliverRequest{ &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), OutTrackId: tea.String(outTrackId),
CallbackType: tea.String("HTTP"), 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{ CardData: &card_1_0.CreateAndDeliverRequestCardData{
CardParamMap: map[string]*string{ CardParamMap: map[string]*string{
"title": tea.String("QA知识收集"), "title": tea.String("QA知识收集"),
@ -562,7 +500,7 @@ func (s *CallbackService) issueHandlingExtractContent(data chatbot.BotCallbackDa
"textarea_display": tea.String("normal"), "textarea_display": tea.String("normal"),
"action_id": tea.String("collect_qa"), "action_id": tea.String("collect_qa"),
"tenant_id": tea.String(constants.KnowledgeTenantIdDefault), "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{ 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), OpenSpaceId: tea.String("dtv1.card//im_group." + data.ConversationId),
ImGroupOpenDeliverModel: &card_1_0.CreateAndDeliverRequestImGroupOpenDeliverModel{ 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) { func (s *CallbackService) issueHandlingQueryKnowledgeBase(data chatbot.BotCallbackDataModel) {
// 获取应用主机器人 // // 获取应用主机器人
mainRobotCode := data.RobotCode // mainRobotCode := data.RobotCode
if robotCode, ok := constants.GroupTemplateRobotIdMap[data.RobotCode]; ok { // if robotCode, ok := constants.GroupTemplateRobotIdMap[data.RobotCode]; ok {
mainRobotCode = robotCode // mainRobotCode = robotCode
} // }
// 获取应用机器人配置
robotConfig, err := s.botConfigImpl.GetRobotConfig(mainRobotCode) // 获取应用配置
appKey, err := s.botConfigImpl.GetRobotAppKey(data.RobotCode)
if err != nil { if err != nil {
log.Errorf("应用机器人配置不存在: %s, err: %v", mainRobotCode, err) log.Errorf("应用机器人配置不存在: %s, err: %v", data.RobotCode, err)
return return
} }
// 创建卡片 // 创建卡片
outTrackId := constants.BuildCardOutTrackId(data.ConversationId, mainRobotCode) outTrackId := constants.BuildCardOutTrackId(data.ConversationId, data.RobotCode)
_, err = s.dingtalkCardClient.CreateAndDeliver( _, err = s.dingtalkCardClient.CreateAndDeliver(
dingtalk.AppKey{ appKey,
AppKey: robotConfig.ClientId,
AppSecret: robotConfig.ClientSecret,
},
&card_1_0.CreateAndDeliverRequest{ &card_1_0.CreateAndDeliverRequest{
CardTemplateId: tea.String(constants.DingtalkCardTplBaseMsg), CardTemplateId: tea.String(s.cfg.Dingtalk.Card.Template.BaseMsg),
CardData: &card_1_0.CreateAndDeliverRequestCardData{ CardData: &card_1_0.CreateAndDeliverRequestCardData{
CardParamMap: map[string]*string{ CardParamMap: map[string]*string{
"title": tea.String(data.Text.Content), "title": tea.String(data.Text.Content),
@ -650,10 +586,7 @@ func (s *CallbackService) issueHandlingQueryKnowledgeBase(data chatbot.BotCallba
// 卡片更新 // 卡片更新
_, err = s.dingtalkCardClient.UpdateCard( _, err = s.dingtalkCardClient.UpdateCard(
dingtalk.AppKey{ appKey,
AppKey: robotConfig.ClientId,
AppSecret: robotConfig.ClientSecret,
},
&card_1_0.UpdateCardRequest{ &card_1_0.UpdateCardRequest{
OutTrackId: tea.String(outTrackId), OutTrackId: tea.String(outTrackId),
CardData: &card_1_0.UpdateCardRequestCardData{ CardData: &card_1_0.UpdateCardRequestCardData{
@ -740,27 +673,24 @@ func (s *CallbackService) issueHandlingCollectQA(data card.CardRequest) *card.Ca
conversationId, robotCode := constants.ParseCardOutTrackId(data.OutTrackId) conversationId, robotCode := constants.ParseCardOutTrackId(data.OutTrackId)
// 获取主应用机器人(这里可能是群模板机器人) // 获取主应用机器人(这里可能是群模板机器人)
mainRobotId := robotCode // mainRobotId := robotCode
if robotCode, ok := constants.GroupTemplateRobotIdMap[robotCode]; ok { // if robotCode, ok := constants.GroupTemplateRobotIdMap[robotCode]; ok {
mainRobotId = robotCode // mainRobotId = robotCode
} // }
// 获取 robot 配置 // 获取应用配置
robotConfig, err := s.botConfigImpl.GetRobotConfig(mainRobotId) appKey, err := s.botConfigImpl.GetRobotAppKey(robotCode)
if err != nil { if err != nil {
log.Errorf("获取 robot 配置失败: %v", err) log.Errorf("获取应用机器人配置失败: %v", err)
return return
} }
// 发送卡片通知用户注入成功 // 发送卡片通知用户注入成功
outTrackId := constants.BuildCardOutTrackId(conversationId, robotCode) outTrackId := constants.BuildCardOutTrackId(conversationId, robotCode)
s.dingtalkCardClient.CreateAndDeliver( s.dingtalkCardClient.CreateAndDeliver(
dingtalk.AppKey{ appKey,
AppKey: robotConfig.ClientId,
AppSecret: robotConfig.ClientSecret,
},
&card_1_0.CreateAndDeliverRequest{ &card_1_0.CreateAndDeliverRequest{
CardTemplateId: tea.String(constants.DingtalkCardTplBaseMsg), CardTemplateId: tea.String(s.cfg.Dingtalk.Card.Template.BaseMsg),
OutTrackId: tea.String(outTrackId), OutTrackId: tea.String(outTrackId),
CardData: &card_1_0.CreateAndDeliverRequestCardData{ CardData: &card_1_0.CreateAndDeliverRequestCardData{
CardParamMap: map[string]*string{ CardParamMap: map[string]*string{

View File

@ -296,16 +296,14 @@ func (d *DingBotService) createIssueHandlingGroupAndInit(ctx context.Context, ca
// 初始化群聊 // 初始化群聊
// 1.开场白 // 1.开场白
// 构建卡片 OutTrackId
outTrackId := constants.BuildCardOutTrackId(openConversationId, constants.GroupTemplateRobotIdIssueHandling)
// 群主题 // 群主题
groupScope := callbackParams["group_scope"].(string) groupScope := callbackParams["group_scope"].(string)
// 构建卡片 OutTrackId
outTrackId := constants.BuildCardOutTrackId(openConversationId, d.config.Dingtalk.SceneGroup.GroupTemplateRobotIDIssueHandling)
_, err = d.dingtalkCardClient.CreateAndDeliver( _, err = d.dingtalkCardClient.CreateAndDeliver(
appKey, appKey,
&card_1_0.CreateAndDeliverRequest{ &card_1_0.CreateAndDeliverRequest{
CardTemplateId: tea.String(constants.DingtalkCardTplBaseMsg), CardTemplateId: tea.String(d.config.Dingtalk.Card.Template.BaseMsg),
OutTrackId: tea.String(outTrackId), OutTrackId: tea.String(outTrackId),
CallbackType: tea.String("HTTP"), CallbackType: tea.String("HTTP"),
CardData: &card_1_0.CreateAndDeliverRequestCardData{ 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), OpenSpaceId: tea.String("dtv1.card//im_group." + openConversationId),
ImGroupOpenDeliverModel: &card_1_0.CreateAndDeliverRequestImGroupOpenDeliverModel{ ImGroupOpenDeliverModel: &card_1_0.CreateAndDeliverRequestImGroupOpenDeliverModel{
RobotCode: tea.String(constants.GroupTemplateRobotIdIssueHandling), RobotCode: tea.String(d.config.Dingtalk.SceneGroup.GroupTemplateRobotIDIssueHandling),
AtUserIds: map[string]*string{ AtUserIds: map[string]*string{
"@ALL": tea.String("@ALL"), "@ALL": tea.String("@ALL"),
}, },
@ -329,11 +327,11 @@ func (d *DingBotService) createIssueHandlingGroupAndInit(ctx context.Context, ca
// 2. 机器人能力 // 2. 机器人能力
// 构建卡片 OutTrackId // 构建卡片 OutTrackId
outTrackId = constants.BuildCardOutTrackId(openConversationId, constants.GroupTemplateRobotIdIssueHandling) outTrackId = constants.BuildCardOutTrackId(openConversationId, d.config.Dingtalk.SceneGroup.GroupTemplateRobotIDIssueHandling)
_, err = d.dingtalkCardClient.CreateAndDeliver( _, err = d.dingtalkCardClient.CreateAndDeliver(
appKey, appKey,
&card_1_0.CreateAndDeliverRequest{ &card_1_0.CreateAndDeliverRequest{
CardTemplateId: tea.String(constants.DingtalkCardTplBaseMsg), CardTemplateId: tea.String(d.config.Dingtalk.Card.Template.BaseMsg),
OutTrackId: tea.String(outTrackId), OutTrackId: tea.String(outTrackId),
CallbackType: tea.String("HTTP"), CallbackType: tea.String("HTTP"),
CardData: &card_1_0.CreateAndDeliverRequestCardData{ 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), OpenSpaceId: tea.String("dtv1.card//im_group." + openConversationId),
ImGroupOpenDeliverModel: &card_1_0.CreateAndDeliverRequestImGroupOpenDeliverModel{ ImGroupOpenDeliverModel: &card_1_0.CreateAndDeliverRequestImGroupOpenDeliverModel{
RobotCode: tea.String(constants.GroupTemplateRobotIdIssueHandling), RobotCode: tea.String(d.config.Dingtalk.SceneGroup.GroupTemplateRobotIDIssueHandling),
AtUserIds: map[string]*string{ AtUserIds: map[string]*string{
"@ALL": tea.String("@ALL"), "@ALL": tea.String("@ALL"),
}, },
@ -371,7 +369,7 @@ func (d *DingBotService) createIssueHandlingGroup(ctx context.Context, accessTok
// 根据群模板ID创建群 // 根据群模板ID创建群
if useTemplateGroup { if useTemplateGroup {
return d.dingTalkOld.CreateSceneGroupConversation(ctx, accessToken, "问题处理群", userIds, constants.GroupTemplateIdIssueHandling) return d.dingTalkOld.CreateSceneGroupConversation(ctx, accessToken, "问题处理群", userIds, d.config.Dingtalk.SceneGroup.GroupTemplateIDIssueHandling)
} }
return return

View File

@ -93,10 +93,14 @@ func run() {
ollamaService := llm_service.NewOllamaGenerate(client, utils_vllmClient, configConfig, chatHisImpl) ollamaService := llm_service.NewOllamaGenerate(client, utils_vllmClient, configConfig, chatHisImpl)
// 初始化工具管理器 // 初始化工具管理器
manager := tools.NewManager(configConfig, client) 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) toolRegis := tools_regis.NewToolsRegis(botToolsImpl)
// 初始化机器人聊天历史实现层 // 初始化机器人聊天历史实现层
@ -120,8 +124,9 @@ func run() {
group := qywx.NewGroup(botGroupQywxImpl, qywxAuth) group := qywx.NewGroup(botGroupQywxImpl, qywxAuth)
other := qywx.NewOther(qywxAuth) other := qywx.NewOther(qywxAuth)
qywxAppBiz := biz.NewQywxAppBiz(configConfig, botGroupQywxImpl, group, other) qywxAppBiz := biz.NewQywxAppBiz(configConfig, botGroupQywxImpl, group, other)
groupConfigBiz := biz.NewGroupConfigBiz(toolRegis, utils_ossClient, botGroupConfigImpl, registry, configConfig, impl.NewReportDailyCacheImpl(db), rdb) groupConfigBiz := biz.NewGroupConfigBiz(toolRegis, utils_ossClient, botGroupConfigImpl, botConfigImpl, registry, configConfig, impl.NewReportDailyCacheImpl(db), rdb, manager, cardClient)
dingTalkBotBiz := biz.NewDingTalkBotBiz(doDo, handle, botConfigImpl, botGroupImpl, user, botChatHisImpl, impl.NewReportDailyCacheImpl(db), manager, configConfig, sendCardClient, groupConfigBiz) 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) cronService = NewCronService(configConfig, dingTalkBotBiz, qywxAppBiz, groupConfigBiz)
} }