package model import ( "aiChat/utility" "aiChat/utility/fsw" "context" "encoding/json" "fmt" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/util/gconv" "io" "regexp" "strings" ) var ( Question = &cQuestion{} regExpSmart = regexp.MustCompile("smart_\\S+_smart") ) const ( Answer_UsuallyProblem = iota + 1 Answer_Isbusiness Answer_ChatGPT ) type cQuestion struct { } type BaseQuestion struct { Prompt string `json:"prompt"` History [][]string `json:"history"` } type QuestionReq struct { *BaseQuestion Href string `json:"href"` //咨询页面 } // ParseHistoryFsw 过滤历史记录敏感词 func (r *BaseQuestion) ParseHistoryFsw() { if len(r.History) == 0 { return } var newHistory [][]string for i := len(r.History) - 1; i >= 0; i-- { var pass bool = true for _, v := range r.History[i] { if fsw.Match(v) { pass = false } } if pass { newHistory = append(newHistory, r.History[i]) if len(newHistory) > 3 { break } } } r.History = newHistory } type questionFilter struct { HasBuyer bool `json:"hasBuyer" dc:"有采购单位"` HasWinner bool `json:"hasWinner" dc:"有中标单位"` TopType InfoType `json:"topType" dc:"信息类型"` } type InfoType map[string]bool func (t InfoType) Check(infoType string) bool { if len(t) == 0 { return false } if _, ok := t[infoType]; ok { return true } return false } // GetUsuallyProblem 获取常见问题 func (q *cQuestion) GetUsuallyProblem(ctx context.Context, href string, limit int) (list []string, err error) { scenario, infoId := GetScenarioAndInfoId(href) list = make([]string, 0, limit) res, err := g.Model("ai_question_list").Ctx(ctx).Fields("question", "filter"). Where("status = 1 and source = ?", scenario).OrderDesc("create_time").OrderAsc("id").Limit(limit).All() if err != nil { return nil, err } hasWinner, hasBuyer, infoTypes := getInfo(infoId) for _, m := range res.List() { if m["filter"] != nil { tFilter := questionFilter{} if json.Unmarshal(gconv.Bytes(m["filter"]), &tFilter) != nil { continue } if !((hasBuyer && tFilter.HasBuyer) || (hasWinner && tFilter.HasWinner) || len(infoTypes) > 0 && tFilter.TopType.Check(infoTypes)) { continue } } list = append(list, gconv.String(m["question"])) } return } func getInfo(infoId string) (hasWinner, hasBuyer bool, infoTypes string) { if infoId == "" { return } res, ok := utility.MgoBidding.FindById(utility.BiddingConf.Collection, infoId, `{"buyer":1,"winner":1,"toptype":1}`) if ok && res == nil || len(*res) == 0 { res, _ = utility.MgoBidding.FindById(utility.BiddingConf.Collection, infoId, `{"buyer":1,"winner":1,"toptype":1}`) } if res != nil && len(*res) > 0 { hasWinner = (*res)["winner"] != nil hasBuyer = (*res)["buyer"] != nil infoTypes = gconv.String((*res)["toptype"]) } return } type BusinessRes struct { Answer string `json:"answer" dc:"答案"` AutoUrl string `json:"auto_url" dc:"默认url"` Joggle string `json:"joggle" dc:"业务接口"` Noperm string `json:"noperm" dc:"无权限回复"` Source string `json:"source" dc:"问题所属"` CheckMember int `json:"check_member" dc:"是否校验大会员权限"` ServiceId string `json:"service_id" dc:"大会员功能服务id"` CheckNewentniche int `json:"check_newentniche" dc:"校验新版商机管理"` CheckNewvip int `json:"check_newvip" dc:"校验是否是新版超级订阅"` } // getIsbusinessData 获取业务规则 func (q *cQuestion) getIsbusinessData(ctx context.Context, code string) (bRes *BusinessRes, err error) { res, err := g.Model("ai_question").Ctx(ctx).Fields("check_member", "answer", "auto_url", "joggle", "noperm", "source", "service_id", "check_newvip", "check_newentniche").Where("ai_code = ?", code).One() if err != nil { return nil, err } if res.IsEmpty() { return nil, fmt.Errorf("未知业务指令") } bRes = &BusinessRes{} if err = res.Struct(bRes); err != nil { return nil, err } return bRes, nil } // DetailQuestion 问题处理 func (q *cQuestion) DetailQuestion(ctx context.Context, qRes *QuestionReq) (reply string, res io.ReadCloser, from int, err error) { qRes.ParseHistoryFsw() // 语义服务 sRes, err := ChatGpt.SimpleDo(ctx, qRes) if err != nil { return "", nil, 0, err } //P393 stream接口不再使用 //if sRes.Result.Answer == "" { // poolErr := ChatGptPool.Get() // if poolErr != nil { // return "", nil, 0, poolErr // } // cRes, err := ChatGpt.GPTDo(ctx, qRes) // if err != nil { // ChatGptPool.Add() // return "", nil, 0, err // } // return "", cRes, Answer_ChatGPT, nil //} // 校验是否有业务逻辑 matchArr := regExpSmart.FindStringSubmatch(sRes.Result.Answer) if len(matchArr) == 0 { return sRes.Result.Answer, nil, Answer_UsuallyProblem, nil } // 查询业务逻辑 var bRes = &BusinessRes{} bRes, err = q.getIsbusinessData(ctx, matchArr[0]) _, infoId := GetScenarioAndInfoId(qRes.Href) if bRes.Source == scenarioName[DetailPage] && infoId == "" { return bRes.AutoUrl, nil, Answer_Isbusiness, nil } // 权限校验 jSession := SessionCtx.Get(ctx).JSession powerPass := func() bool { if bRes.CheckMember == 0 && bRes.CheckNewvip == 0 && bRes.CheckNewentniche == 0 { return true } power := utility.Middleground.PowerCheckCenter.Check(g.Config().MustGet(ctx, "chat.appId").String(), jSession.UserId, jSession.NewUid, jSession.AccountId, jSession.EntId, jSession.PositionType, jSession.PositionId) // 大会员权益校验 if bRes.CheckMember == 1 && power.Member.Status > 0 && bRes.ServiceId != "" { for _, v := range strings.Split(bRes.ServiceId, ",") { for _, vv := range power.Member.MemberPowerList { if gconv.Int64(v) == vv { return true } } } } // 校验新版超级订阅 if bRes.CheckNewvip == 1 && power.Vip.Upgrade > 0 && power.Vip.Status > 0 { return true } // 校验商机管理 if bRes.CheckNewentniche == 1 && power.Entniche.Status > 0 && power.Entniche.IsNew > 0 { return true } return false }() if !powerPass { return bRes.Noperm, nil, Answer_Isbusiness, nil } businessRes, err := utility.DoBusiness(ctx, bRes.Joggle, &utility.RpcParams{ UserId: jSession.UserId, Answer: bRes.Answer, BiddingId: infoId, BaseUserId: jSession.NewUid, }) if err != nil { return "", nil, Answer_Isbusiness, nil } if businessRes.ErrMsg != "" { return "", nil, Answer_Isbusiness, fmt.Errorf(businessRes.ErrMsg) } return businessRes.ReplyMsg, nil, Answer_Isbusiness, nil }