fix:修复报错
This commit is contained in:
parent
7c973750dd
commit
25b55ec1f8
|
|
@ -23,7 +23,7 @@ redis:
|
||||||
host: 47.97.27.195:6379
|
host: 47.97.27.195:6379
|
||||||
type: node
|
type: node
|
||||||
pass: lansexiongdi@666
|
pass: lansexiongdi@666
|
||||||
key: report-api-test
|
key: report-api
|
||||||
pollSize: 5 #连接池大小,不配置,或配置为0表示不启用连接池
|
pollSize: 5 #连接池大小,不配置,或配置为0表示不启用连接池
|
||||||
minIdleConns: 2 #最小空闲连接数
|
minIdleConns: 2 #最小空闲连接数
|
||||||
maxIdleTime: 30 #每个连接最大空闲时间,如果超过了这个时间会被关闭
|
maxIdleTime: 30 #每个连接最大空闲时间,如果超过了这个时间会被关闭
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@ import (
|
||||||
"ai_scheduler/internal/data/impl"
|
"ai_scheduler/internal/data/impl"
|
||||||
"ai_scheduler/internal/data/model"
|
"ai_scheduler/internal/data/model"
|
||||||
"ai_scheduler/internal/entitys"
|
"ai_scheduler/internal/entitys"
|
||||||
"ai_scheduler/internal/pkg/mapstructure"
|
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v2/log"
|
"github.com/gofiber/fiber/v2/log"
|
||||||
|
|
@ -47,10 +47,11 @@ func (d *DingTalkBotBiz) GetDingTalkBotCfgList() (dingBotList []entitys.DingTalk
|
||||||
err = d.botConfigImpl.GetRangeToMapStruct(&cond, &botConfig)
|
err = d.botConfigImpl.GetRangeToMapStruct(&cond, &botConfig)
|
||||||
for _, v := range botConfig {
|
for _, v := range botConfig {
|
||||||
var config entitys.DingTalkBot
|
var config entitys.DingTalkBot
|
||||||
err = mapstructure.Decode(v, &config)
|
err = json.Unmarshal([]byte(v.BotConfig), &config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
d.log.Info("初始化“%s”失败:%s", v.BotName, err.Error())
|
d.log.Info("初始化“%s”失败:%s", v.BotName, err.Error())
|
||||||
}
|
}
|
||||||
|
config.BotIndex = v.BotIndex
|
||||||
dingBotList = append(dingBotList, config)
|
dingBotList = append(dingBotList, config)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ func NewHandle(
|
||||||
|
|
||||||
func (r *Handle) Recognize(ctx context.Context, rec *entitys.Recognize, promptProcessor PromptOption) (match entitys.Match, err error) {
|
func (r *Handle) Recognize(ctx context.Context, rec *entitys.Recognize, promptProcessor PromptOption) (match entitys.Match, err error) {
|
||||||
entitys.ResLog(rec.Ch, "recognize_start", "准备意图识别")
|
entitys.ResLog(rec.Ch, "recognize_start", "准备意图识别")
|
||||||
|
|
||||||
prompt, err := promptProcessor.CreatePrompt(ctx, rec)
|
prompt, err := promptProcessor.CreatePrompt(ctx, rec)
|
||||||
//意图识别
|
//意图识别
|
||||||
recognizeMsg, err := r.Ollama.IntentRecognize(ctx, &entitys.ToolSelect{
|
recognizeMsg, err := r.Ollama.IntentRecognize(ctx, &entitys.ToolSelect{
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
package dingtalk
|
||||||
|
|
||||||
|
import (
|
||||||
|
"ai_scheduler/internal/config"
|
||||||
|
"ai_scheduler/internal/data/constants"
|
||||||
|
"ai_scheduler/internal/pkg/l_request"
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/redis/go-redis/v9"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Auth struct {
|
||||||
|
redis *redis.Client
|
||||||
|
cfg *config.Config
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAuth(cfg *config.Config, redis *redis.Client) *Auth {
|
||||||
|
return &Auth{
|
||||||
|
redis: redis,
|
||||||
|
cfg: cfg,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Auth) GetAccessToken(ctx context.Context, clientId string, clientSecret string) (accessToken string, err error) {
|
||||||
|
if clientId == "" {
|
||||||
|
return "", errors.New("clientId is empty")
|
||||||
|
}
|
||||||
|
token := a.redis.Get(ctx, a.getKey(clientId)).String()
|
||||||
|
if token == "" {
|
||||||
|
authInfo, _err := a.getNewAccessToken(ctx, clientId, clientSecret)
|
||||||
|
if _err != nil {
|
||||||
|
return "", _err
|
||||||
|
}
|
||||||
|
a.redis.SetEx(ctx, a.getKey(clientId), authInfo.AccessToken, time.Duration(authInfo.ExpiresIn-3600)*time.Second)
|
||||||
|
accessToken = authInfo.AccessToken
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Auth) getKey(clientId string) string {
|
||||||
|
return a.cfg.Redis.Key + ":" + constants.DingTalkAuthBaseKeyPrefix + ":" + clientId
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Auth) getNewAccessToken(ctx context.Context, clientId string, clientSecret string) (auth AuthInfo, err error) {
|
||||||
|
if clientId == "" || clientSecret == "" {
|
||||||
|
err = errors.New("clientId or clientSecret is empty")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
req := l_request.Request{
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Url: constants.GetDingTalkRequestUrl(constants.RequestUrlGetAccessToken, nil),
|
||||||
|
Data: map[string]string{
|
||||||
|
"appkey": clientId,
|
||||||
|
"appsecret": clientSecret,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
res, err := req.Send()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = json.Unmarshal(res.Content, &auth)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
package dingtalk
|
||||||
|
|
||||||
|
import (
|
||||||
|
"ai_scheduler/internal/data/impl"
|
||||||
|
"ai_scheduler/internal/entitys"
|
||||||
|
"database/sql"
|
||||||
|
"errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Dept struct {
|
||||||
|
dingUserImpl *impl.BotUserImpl
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDept(dingUserImpl *impl.BotUserImpl) *User {
|
||||||
|
return &User{
|
||||||
|
dingUserImpl: dingUserImpl,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *User) GetDeptInfo(userId string) (userInfo *entitys.DingTalkUserInfo, err error) {
|
||||||
|
if len(userId) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
user, err := u.dingUserImpl.GetByStaffId(userId)
|
||||||
|
if err != nil {
|
||||||
|
if !errors.Is(err, sql.ErrNoRows) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//如果没有找到,则新增
|
||||||
|
if user == nil {
|
||||||
|
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
package dingtalk
|
||||||
|
|
||||||
|
import "ai_scheduler/internal/data/model"
|
||||||
|
|
||||||
|
type Bot struct {
|
||||||
|
id int
|
||||||
|
botConfig *model.AiBotConfig
|
||||||
|
}
|
||||||
|
type BotOption func(*Bot)
|
||||||
|
|
||||||
|
func WithId(id int) BotOption {
|
||||||
|
return func(b *Bot) {
|
||||||
|
b.id = id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithBootConfig(BotConfig *model.AiBotConfig) BotOption {
|
||||||
|
return func(bot *Bot) {
|
||||||
|
bot.botConfig = BotConfig
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
package dingtalk
|
||||||
|
|
||||||
|
type AuthInfo struct {
|
||||||
|
AccessToken string `json:"accessToken"`
|
||||||
|
ExpiresIn int64 `json:"expiresIn"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserInfoResResult struct {
|
||||||
|
Errcode string `json:"errcode"`
|
||||||
|
Result Result `json:"result"`
|
||||||
|
Errmsg string `json:"errmsg"`
|
||||||
|
}
|
||||||
|
type Result struct {
|
||||||
|
Extension string `json:"extension"`
|
||||||
|
Unionid string `json:"unionid"`
|
||||||
|
Boss string `json:"boss"`
|
||||||
|
RoleList struct {
|
||||||
|
GroupName string `json:"group_name"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Id string `json:"id"`
|
||||||
|
} `json:"role_list"`
|
||||||
|
ExclusiveAccount bool `json:"exclusive_account"`
|
||||||
|
ManagerUserid string `json:"manager_userid"`
|
||||||
|
Admin string `json:"admin"`
|
||||||
|
Remark string `json:"remark"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
HiredDate int `json:"hired_date"`
|
||||||
|
Userid string `json:"userid"`
|
||||||
|
WorkPlace string `json:"work_place"`
|
||||||
|
DeptOrderList struct {
|
||||||
|
DeptId string `json:"dept_id"`
|
||||||
|
Order string `json:"order"`
|
||||||
|
} `json:"dept_order_list"`
|
||||||
|
RealAuthed string `json:"real_authed"`
|
||||||
|
DeptIdList string `json:"dept_id_list"`
|
||||||
|
JobNumber string `json:"job_number"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
LeaderInDept struct {
|
||||||
|
Leader string `json:"leader"`
|
||||||
|
DeptId string `json:"dept_id"`
|
||||||
|
} `json:"leader_in_dept"`
|
||||||
|
Mobile string `json:"mobile"`
|
||||||
|
Active string `json:"active"`
|
||||||
|
OrgEmail string `json:"org_email"`
|
||||||
|
Telephone string `json:"telephone"`
|
||||||
|
Avatar string `json:"avatar"`
|
||||||
|
HideMobile string `json:"hide_mobile"`
|
||||||
|
Senior string `json:"senior"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
UnionEmpExt struct {
|
||||||
|
UnionEmpMapList struct {
|
||||||
|
Userid string `json:"userid"`
|
||||||
|
CorpId string `json:"corp_id"`
|
||||||
|
} `json:"union_emp_map_list"`
|
||||||
|
Userid string `json:"userid"`
|
||||||
|
CorpId string `json:"corp_id"`
|
||||||
|
} `json:"union_emp_ext"`
|
||||||
|
StateCode string `json:"state_code"`
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,140 @@
|
||||||
|
package dingtalk
|
||||||
|
|
||||||
|
import (
|
||||||
|
"ai_scheduler/internal/data/constants"
|
||||||
|
"ai_scheduler/internal/data/impl"
|
||||||
|
"ai_scheduler/internal/data/model"
|
||||||
|
"ai_scheduler/internal/entitys"
|
||||||
|
"ai_scheduler/internal/pkg"
|
||||||
|
"ai_scheduler/internal/pkg/l_request"
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/gofiber/fiber/v2/log"
|
||||||
|
"xorm.io/builder"
|
||||||
|
)
|
||||||
|
|
||||||
|
type User struct {
|
||||||
|
dingUserImpl *impl.BotUserImpl
|
||||||
|
botConfigImpl *impl.BotConfigImpl
|
||||||
|
auth *Auth
|
||||||
|
logger log.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUser(
|
||||||
|
dingUserImpl *impl.BotUserImpl,
|
||||||
|
botConfig *impl.BotConfigImpl,
|
||||||
|
auth *Auth,
|
||||||
|
logger log.Logger,
|
||||||
|
) *User {
|
||||||
|
return &User{
|
||||||
|
dingUserImpl: dingUserImpl,
|
||||||
|
botConfigImpl: botConfig,
|
||||||
|
logger: logger,
|
||||||
|
auth: auth,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *User) GetUserInfo(ctx context.Context, staffId string, botOption ...BotOption) (userInfo *entitys.DingTalkUserInfo, err error) {
|
||||||
|
if len(staffId) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
user, err := u.dingUserImpl.GetByStaffId(staffId)
|
||||||
|
if err != nil {
|
||||||
|
if !errors.Is(err, sql.ErrNoRows) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//如果没有找到,则新增
|
||||||
|
if user == nil {
|
||||||
|
DingUserInfo, _err := u.GetUserInfoFromDingTalkWithBot(ctx, staffId, botOption...)
|
||||||
|
if _err != nil {
|
||||||
|
return nil, _err
|
||||||
|
}
|
||||||
|
dingUserDo := &model.AiBotUser{
|
||||||
|
StaffID: DingUserInfo.Userid,
|
||||||
|
Name: DingUserInfo.Name,
|
||||||
|
Title: DingUserInfo.Title,
|
||||||
|
Extension: DingUserInfo.Extension,
|
||||||
|
DeptIDList: DingUserInfo.DeptIdList,
|
||||||
|
IsBoss: int32(pkg.Ter(DingUserInfo.Boss == "true", constants.IsBossTrue, constants.IsBossFalse)),
|
||||||
|
IsSenior: int32(pkg.Ter(DingUserInfo.Boss == "true", constants.IsSeniorTrue, constants.IsSeniorFalse)),
|
||||||
|
HiredDate: time.Unix(int64(DingUserInfo.HiredDate), 0),
|
||||||
|
}
|
||||||
|
//deptIdList, _err := pkg.StringToSlice(DingUserInfo.DeptIdList)
|
||||||
|
//if err != nil {
|
||||||
|
// return nil, _err
|
||||||
|
//}
|
||||||
|
dingUserDo.DeptIDList = strings.Trim(dingUserDo.DeptIDList, "[]")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *User) GetUserInfoFromDingTalkWithBot(ctx context.Context, staffId string, botOption ...BotOption) (userInfo Result, err error) {
|
||||||
|
botInfo := &Bot{}
|
||||||
|
for _, option := range botOption {
|
||||||
|
option(botInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
if botInfo.id == 0 && botInfo.botConfig == nil {
|
||||||
|
err = errors.New("botInfo is nil")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if botInfo.botConfig == nil {
|
||||||
|
cond := builder.NewCond()
|
||||||
|
cond = cond.And(builder.Eq{"bot_id": botInfo.id})
|
||||||
|
err = u.botConfigImpl.GetOneBySearchToStrut(&cond, botInfo.botConfig)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
var config entitys.DingTalkBot
|
||||||
|
err = json.Unmarshal([]byte(botInfo.botConfig.BotConfig), &config)
|
||||||
|
if err != nil {
|
||||||
|
log.Infof("初始化“%s”失败:%s", botInfo.botConfig.BotName, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
token, err := u.auth.GetAccessToken(ctx, config.ClientId, config.ClientSecret)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return u.GetUserInfoFromDingTalk(ctx, token, staffId)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *User) GetUserInfoFromDingTalk(ctx context.Context, token string, staffId string) (user Result, err error) {
|
||||||
|
if token == "" && staffId == "" {
|
||||||
|
err = errors.New("获取钉钉用户信息的必要参数不足")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
req := l_request.Request{
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Url: constants.GetDingTalkRequestUrl(constants.RequestUrlGetUserGet, map[string]string{
|
||||||
|
"access_token": token,
|
||||||
|
}),
|
||||||
|
Data: map[string]string{
|
||||||
|
"userid": staffId,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
res, err := req.Send()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var userInfoResResult UserInfoResResult
|
||||||
|
err = json.Unmarshal(res.Content, &userInfoResResult)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if userInfoResResult.Errcode != "0" {
|
||||||
|
fmt.Errorf("钉钉请求报错:%s", userInfoResResult.Errmsg)
|
||||||
|
}
|
||||||
|
return userInfoResResult.Result, err
|
||||||
|
}
|
||||||
|
|
@ -65,6 +65,7 @@ func (r *AiRouterBiz) RouteWithSocket(client *gateway.Client, req *entitys.ChatS
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//意图识别
|
//意图识别
|
||||||
|
|
||||||
requireData.Match, err = r.handle.Recognize(ctx, &rec, &do.WithSys{})
|
requireData.Match, err = r.handle.Recognize(ctx, &rec, &do.WithSys{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("意图识别失败: %s", err.Error())
|
log.Errorf("意图识别失败: %s", err.Error())
|
||||||
|
|
|
||||||
|
|
@ -31,3 +31,5 @@ type BotType int
|
||||||
const (
|
const (
|
||||||
BotTypeDingTalk BotType = 1 // 系统的bug/优化建议
|
BotTypeDingTalk BotType = 1 // 系统的bug/优化建议
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const DingTalkAuthBaseKeyPrefix = "dingTalk_auth"
|
||||||
|
|
|
||||||
|
|
@ -30,3 +30,5 @@ var UseFulMap = map[UseFul]string{
|
||||||
UseFulNotUnclear: "回答不明确",
|
UseFulNotUnclear: "回答不明确",
|
||||||
UseFulNotError: "理解错误",
|
UseFulNotError: "理解错误",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type BaseBool int32
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
package constants
|
||||||
|
|
||||||
|
import "net/url"
|
||||||
|
|
||||||
|
const DingTalkBseUrl = "https://oapi.dingtalk.com"
|
||||||
|
|
||||||
|
type RequestUrl string
|
||||||
|
|
||||||
|
const (
|
||||||
|
RequestUrlGetAccessToken RequestUrl = "/v1.0/oauth2/accessToken"
|
||||||
|
RequestUrlGetUserGet RequestUrl = "/topapi/v2/user/get"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetDingTalkRequestUrl(path RequestUrl, query map[string]string) string {
|
||||||
|
u, _ := url.Parse(DingTalkBseUrl + string(path))
|
||||||
|
q := u.Query()
|
||||||
|
for key, val := range query {
|
||||||
|
q.Add(key, val)
|
||||||
|
}
|
||||||
|
u.RawQuery = q.Encode()
|
||||||
|
return u.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsBoss 是否是老板
|
||||||
|
type IsBoss int
|
||||||
|
|
||||||
|
const (
|
||||||
|
IsBossTrue IsBoss = 1
|
||||||
|
IsBossFalse IsBoss = 0
|
||||||
|
)
|
||||||
|
|
||||||
|
// IsSenior 是否是老板
|
||||||
|
type IsSenior int
|
||||||
|
|
||||||
|
const (
|
||||||
|
IsSeniorTrue IsSenior = 1
|
||||||
|
IsSeniorFalse IsSenior = 0
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
package constants
|
||||||
|
|
||||||
|
import (
|
||||||
|
"ai_scheduler/internal/biz"
|
||||||
|
"ai_scheduler/internal/biz/do"
|
||||||
|
"ai_scheduler/internal/biz/llm_service"
|
||||||
|
"ai_scheduler/internal/data/impl"
|
||||||
|
"ai_scheduler/internal/entitys"
|
||||||
|
"ai_scheduler/internal/gateway"
|
||||||
|
"ai_scheduler/internal/pkg/dingtalk"
|
||||||
|
"ai_scheduler/internal/pkg/utils_ollama"
|
||||||
|
"ai_scheduler/internal/pkg/utils_vllm"
|
||||||
|
"ai_scheduler/internal/server"
|
||||||
|
"ai_scheduler/internal/services"
|
||||||
|
"ai_scheduler/internal/tools"
|
||||||
|
"ai_scheduler/internal/tools_bot"
|
||||||
|
"ai_scheduler/utils"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
const
|
||||||
|
|
||||||
|
func TestMain(m *testing.M) {
|
||||||
|
bootstrap := initialize.LoadConfigWithTest()
|
||||||
|
businessLogger := log2.NewBusinessLogger(bootstrap.Logs, id, Name, Version)
|
||||||
|
helper := pkg.NewLogHelper(businessLogger, bootstrap)
|
||||||
|
|
||||||
|
db, cleanup := utils.NewGormDb(configConfig)
|
||||||
|
sysImpl := impl.NewSysImpl(db)
|
||||||
|
taskImpl := impl.NewTaskImpl(db)
|
||||||
|
chatHisImpl := impl.NewChatHisImpl(db)
|
||||||
|
doDo := do.NewDo(sysImpl, taskImpl, chatHisImpl, configConfig)
|
||||||
|
client, cleanup2, err := utils_ollama.NewClient(configConfig)
|
||||||
|
if err != nil {
|
||||||
|
cleanup()
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
utils_vllmClient, cleanup3, err := utils_vllm.NewClient(configConfig)
|
||||||
|
if err != nil {
|
||||||
|
cleanup2()
|
||||||
|
cleanup()
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
ollamaService := llm_service.NewOllamaGenerate(client, utils_vllmClient, configConfig, chatHisImpl)
|
||||||
|
manager := tools.NewManager(configConfig, client)
|
||||||
|
sessionImpl := impl.NewSessionImpl(db)
|
||||||
|
botTool := tools_bot.NewBotTool(configConfig, client, sessionImpl)
|
||||||
|
handle := do.NewHandle(ollamaService, manager, configConfig, sessionImpl, botTool)
|
||||||
|
aiRouterBiz := biz.NewAiRouterBiz(doDo, handle)
|
||||||
|
chatHistoryBiz := biz.NewChatHistoryBiz(chatHisImpl, taskImpl)
|
||||||
|
gatewayGateway := gateway.NewGateway()
|
||||||
|
chatService := services.NewChatService(aiRouterBiz, chatHistoryBiz, gatewayGateway, configConfig)
|
||||||
|
sessionBiz := biz.NewSessionBiz(configConfig, sessionImpl, sysImpl, chatHisImpl)
|
||||||
|
sessionService := services.NewSessionService(sessionBiz, chatHistoryBiz)
|
||||||
|
taskBiz := biz.NewTaskBiz(configConfig, taskImpl)
|
||||||
|
taskService := services.NewTaskService(sessionBiz, taskBiz)
|
||||||
|
oldClient := dingtalk.NewOldClient(configConfig)
|
||||||
|
contactClient, err := dingtalk.NewContactClient(configConfig)
|
||||||
|
if err != nil {
|
||||||
|
cleanup3()
|
||||||
|
cleanup2()
|
||||||
|
cleanup()
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
notableClient, err := dingtalk.NewNotableClient(configConfig)
|
||||||
|
if err != nil {
|
||||||
|
cleanup3()
|
||||||
|
cleanup2()
|
||||||
|
cleanup()
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
callbackService := services.NewCallbackService(configConfig, gatewayGateway, oldClient, contactClient, notableClient, botTool)
|
||||||
|
historyService := services.NewHistoryService(chatHistoryBiz)
|
||||||
|
app := server.NewHTTPServer(chatService, sessionService, taskService, gatewayGateway, callbackService, historyService)
|
||||||
|
botConfigImpl := impl.NewBotConfigImpl(db)
|
||||||
|
dingTalkBotBiz := biz.NewDingTalkBotBiz(doDo, handle, botConfigImpl)
|
||||||
|
dingBotService := services.NewDingBotService(configConfig, dingTalkBotBiz)
|
||||||
|
v := server.ProvideAllDingBotServices(dingBotService)
|
||||||
|
dingTalkBotServer := server.NewDingTalkBotServer(v)
|
||||||
|
servers := server.NewServers(configConfig, app, dingTalkBotServer)
|
||||||
|
code := m.Run()
|
||||||
|
os.Exit(code)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_GetUserInfo(t *testing.T) {
|
||||||
|
var c entitys.TaskConfig
|
||||||
|
config := `{"param": {"type": "object", "required": ["number"], "properties": {"number": {"type": "string", "description": "订单编号/流水号"}}}, "request": {"url": "http://www.baidu.com/${number}", "headers": {"Authorization": "${authorization}"}, "method": "GET"}}`
|
||||||
|
err := json.Unmarshal([]byte(config), &c)
|
||||||
|
t.Log(err)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
package impl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"ai_scheduler/internal/data/model"
|
||||||
|
"ai_scheduler/tmpl/dataTemp"
|
||||||
|
"ai_scheduler/utils"
|
||||||
|
"database/sql"
|
||||||
|
)
|
||||||
|
|
||||||
|
type BotUserImpl struct {
|
||||||
|
dataTemp.DataTemp
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBotUserImpl(db *utils.Db) *BotUserImpl {
|
||||||
|
return &BotUserImpl{
|
||||||
|
DataTemp: *dataTemp.NewDataTemp(db, new(model.AiBotUser)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k BotUserImpl) GetByStaffId(staffId string) (data *model.AiBotUser, err error) {
|
||||||
|
data = &model.AiBotUser{}
|
||||||
|
err = k.Db.Model(k.Model).Where("staff_id = ?", staffId).Find(data).Error
|
||||||
|
if data == nil {
|
||||||
|
err = sql.ErrNoRows
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
@ -14,9 +14,10 @@ const TableNameAiBotConfig = "ai_bot_config"
|
||||||
type AiBotConfig struct {
|
type AiBotConfig struct {
|
||||||
BotID int32 `gorm:"column:bot_id;primaryKey;autoIncrement:true" json:"bot_id"`
|
BotID int32 `gorm:"column:bot_id;primaryKey;autoIncrement:true" json:"bot_id"`
|
||||||
SysID int32 `gorm:"column:sys_id;not null" json:"sys_id"`
|
SysID int32 `gorm:"column:sys_id;not null" json:"sys_id"`
|
||||||
BotType int32 `gorm:"column:bot_type;not null;default:1" json:"bot_type"`
|
BotType int32 `gorm:"column:bot_type;not null;default:1;comment:类型,1为钉钉机器人" json:"bot_type"` // 类型,1为钉钉机器人
|
||||||
BotName string `gorm:"column:bot_name;not null" json:"bot_name"`
|
BotName string `gorm:"column:bot_name;not null;comment:名字" json:"bot_name"` // 名字
|
||||||
BotConfig string `gorm:"column:bot_config;not null" json:"bot_config"`
|
BotConfig string `gorm:"column:bot_config;not null;comment:配置" json:"bot_config"` // 配置
|
||||||
|
BotIndex string `gorm:"column:bot_index;not null;comment:索引" json:"bot_index"` // 索引
|
||||||
CreateAt time.Time `gorm:"column:create_at;default:CURRENT_TIMESTAMP" json:"create_at"`
|
CreateAt time.Time `gorm:"column:create_at;default:CURRENT_TIMESTAMP" json:"create_at"`
|
||||||
UpdatedAt time.Time `gorm:"column:updated_at;default:CURRENT_TIMESTAMP" json:"updated_at"`
|
UpdatedAt time.Time `gorm:"column:updated_at;default:CURRENT_TIMESTAMP" json:"updated_at"`
|
||||||
Status int32 `gorm:"column:status;not null" json:"status"`
|
Status int32 `gorm:"column:status;not null" json:"status"`
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||||
|
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||||
|
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||||
|
|
||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const TableNameAiBotUser = "ai_bot_user"
|
||||||
|
|
||||||
|
// AiBotUser mapped from table <ai_bot_user>
|
||||||
|
type AiBotUser struct {
|
||||||
|
UserID int32 `gorm:"column:user_id;primaryKey" json:"user_id"`
|
||||||
|
StaffID string `gorm:"column:staff_id;not null;comment:标记用户用的唯一id,钉钉:钉钉侧提供的user_id" json:"staff_id"` // 标记用户用的唯一id,钉钉:钉钉侧提供的user_id
|
||||||
|
Name string `gorm:"column:name;not null;comment:用户名称" json:"name"` // 用户名称
|
||||||
|
Title string `gorm:"column:title;not null;comment:职位" json:"title"` // 职位
|
||||||
|
Extension string `gorm:"column:extension;not null;default:1;comment:信息面板" json:"extension"` // 信息面板
|
||||||
|
RoleList string `gorm:"column:role_list;not null;comment:角色列表。" json:"role_list"` // 角色列表。
|
||||||
|
DeptIDList string `gorm:"column:dept_id_list;not null;comment:所在部门id列表" json:"dept_id_list"` // 所在部门id列表
|
||||||
|
IsBoss int32 `gorm:"column:is_boss;not null;comment:是否是老板" json:"is_boss"` // 是否是老板
|
||||||
|
IsSenior int32 `gorm:"column:is_senior;not null;comment:是否是高管" json:"is_senior"` // 是否是高管
|
||||||
|
HiredDate time.Time `gorm:"column:hired_date;not null;default:CURRENT_TIMESTAMP;comment:入职时间" json:"hired_date"` // 入职时间
|
||||||
|
Status int32 `gorm:"column:status;not null" json:"status"`
|
||||||
|
DeleteAt time.Time `gorm:"column:delete_at" json:"delete_at"`
|
||||||
|
CreateAt time.Time `gorm:"column:create_at;default:CURRENT_TIMESTAMP" json:"create_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// TableName AiBotUser's table name
|
||||||
|
func (*AiBotUser) TableName() string {
|
||||||
|
return TableNameAiBotUser
|
||||||
|
}
|
||||||
|
|
@ -8,9 +8,6 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type RequireDataDingTalkBot struct {
|
type RequireDataDingTalkBot struct {
|
||||||
Session string
|
|
||||||
Key string
|
|
||||||
Sys model.AiSy
|
|
||||||
Histories []model.AiChatHi
|
Histories []model.AiChatHi
|
||||||
SessionInfo model.AiSession
|
SessionInfo model.AiSession
|
||||||
Tasks []model.AiTask
|
Tasks []model.AiTask
|
||||||
|
|
@ -24,7 +21,7 @@ type RequireDataDingTalkBot struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type DingTalkBot struct {
|
type DingTalkBot struct {
|
||||||
BotIndex string
|
BotIndex string `json:"bot_index"`
|
||||||
ClientId string
|
ClientId string `json:"client_id"`
|
||||||
ClientSecret string
|
ClientSecret string `json:"client_secret"`
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
package entitys
|
||||||
|
|
||||||
|
type DingTalkUserInfo struct {
|
||||||
|
UserId string `json:"user_id"`
|
||||||
|
StaffId string `json:"staff_id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Dept []Dept `json:"dept"`
|
||||||
|
IsBoss int `json:"is_boss"`
|
||||||
|
IsSenior int `json:"is_senior"`
|
||||||
|
HiredDate int `json:"hired_date"`
|
||||||
|
Extension string `json:"extension"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Dept struct {
|
||||||
|
DeptName string `json:"dept_name"`
|
||||||
|
DeptId int `json:"dept_id"`
|
||||||
|
}
|
||||||
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -65,3 +66,31 @@ func HexEncode(src, dst []byte) int {
|
||||||
}
|
}
|
||||||
return len(src) * 2
|
return len(src) * 2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ter 三目运算 Ter(true, 1, 2)
|
||||||
|
func Ter[T any](cond bool, a, b T) T {
|
||||||
|
if cond {
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToSlice [num,num]转slice
|
||||||
|
func StringToSlice(s string) ([]int, error) {
|
||||||
|
// 1. 去掉两端的方括号
|
||||||
|
trimmed := strings.Trim(s, "[]")
|
||||||
|
|
||||||
|
// 2. 按逗号分割
|
||||||
|
parts := strings.Split(trimmed, ",")
|
||||||
|
|
||||||
|
// 3. 转换为 []int
|
||||||
|
result := make([]int, 0, len(parts))
|
||||||
|
for _, part := range parts {
|
||||||
|
num, err := strconv.Atoi(strings.TrimSpace(part))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result = append(result, num)
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -62,10 +62,10 @@ func (d *DingTalkBotServer) Run(ctx context.Context, botIndex string) {
|
||||||
}
|
}
|
||||||
err := cli.Start(ctx)
|
err := cli.Start(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Info("%s启动失败", name)
|
log.Infof("%s启动失败", name)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
log.Info("%s启动成功", name)
|
log.Infof("%s启动成功", name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func DingBotServerInit(clientId string, clientSecret string, service DingBotServiceInterface) (cli *client.StreamClient) {
|
func DingBotServerInit(clientId string, clientSecret string, service DingBotServiceInterface) (cli *client.StreamClient) {
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ func (d *DingBotService) OnChatBotMessageReceived(ctx context.Context, data *cha
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
defer close(requireData.Ch)
|
//defer close(requireData.Ch)
|
||||||
//if match, _err := d.dingTalkBotBiz.Recognize(ctx, data); _err != nil {
|
//if match, _err := d.dingTalkBotBiz.Recognize(ctx, data); _err != nil {
|
||||||
// requireData.Ch <- entitys.Response{
|
// requireData.Ch <- entitys.Response{
|
||||||
// Type: entitys.ResponseEnd,
|
// Type: entitys.ResponseEnd,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue