fix: 代码优化 1.需要环境区分的配置,从常量移动到yaml 2. 新增获取机器人应用配置的公共方法 3.以上修改相应的业务调整 4.修复一些单元测试文件的报错
This commit is contained in:
parent
32cd8691b7
commit
fa08cad74a
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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{
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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"`
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
`
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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())
|
||||||
|
|
|
||||||
|
|
@ -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{
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue