123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- 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
- }
|