answer.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. package model
  2. import (
  3. v1 "aiChat/api/v1"
  4. "aiChat/utility/fsw"
  5. . "app.yhyue.com/moapp/jybase/common"
  6. "app.yhyue.com/moapp/jybase/date"
  7. "app.yhyue.com/moapp/jybase/encrypt"
  8. "bufio"
  9. "context"
  10. "fmt"
  11. "github.com/gogf/gf/v2/frame/g"
  12. "github.com/gogf/gf/v2/util/gconv"
  13. "io"
  14. "strings"
  15. "time"
  16. )
  17. var (
  18. Answer = &cAnswer{}
  19. )
  20. type cAnswer struct {
  21. }
  22. // FindAnswer 获取答案
  23. func (l *cAnswer) FindAnswer(ctx context.Context, answerReq *v1.FindAnswerReq) (rs *v1.FindAnswerRes, err error) {
  24. defer Catch()
  25. jSession := SessionCtx.Get(ctx).JSession
  26. second := g.Cfg().MustGet(ctx, "history.time").Int()
  27. limit := g.Cfg().MustGet(ctx, "history.limit").Int()
  28. historyData := getHistory(ctx, jSession.PositionId, second, limit)
  29. // 查一分钟内的10条 历史信息
  30. req, from := &QuestionReq{
  31. Href: answerReq.Href,
  32. BaseQuestion: &BaseQuestion{
  33. Prompt: answerReq.Prompt,
  34. History: historyData,
  35. },
  36. }, 0
  37. questionId := ChatHistory.Save(ctx, &ChatRecord{
  38. Content: req.Prompt,
  39. Type: 1,
  40. Refer: req.Href,
  41. PersonId: jSession.PositionId,
  42. CreateTime: time.Now().Format(date.Date_Full_Layout),
  43. })
  44. content, res, replyId, errMsg := func() (string, io.ReadCloser, int64, error) {
  45. var (
  46. err error
  47. res io.ReadCloser
  48. reply string
  49. )
  50. errReply := func() string {
  51. // 校验是否在黑名单,黑名单不返回内容
  52. if UserBlackList.CheckBlackList(ctx, jSession.PositionId) {
  53. return g.Cfg().MustGet(ctx, "limit.blackMsg").String()
  54. }
  55. // 校验问答频率
  56. if ChatLimit.GetBucket(ctx, jSession.PositionId).TakeAvailable(1) == 0 {
  57. return g.Cfg().MustGet(ctx, "limit.exceedMsg").String()
  58. }
  59. // 问题敏感词过滤
  60. if fsw.Match(req.Prompt) {
  61. return g.Cfg().MustGet(ctx, "limit.fswMsg").String()
  62. }
  63. return ""
  64. }()
  65. if errReply != "" {
  66. reply, from = errReply, -1
  67. } else {
  68. reply, res, from, err = Question.DetailQuestion(ctx, req)
  69. if err != nil {
  70. g.Log().Error(ctx, "问答异常", err)
  71. reply = g.Cfg().MustGet(ctx, "limit.errMsg").String()
  72. errReply = g.Cfg().MustGet(ctx, "limit.errMsg").String()
  73. }
  74. }
  75. if from == Answer_ChatGPT {
  76. return reply, res, 0, nil
  77. }
  78. if reply == "" {
  79. reply = g.Cfg().MustGet(ctx, "limit.emptyMsg").String()
  80. errReply = g.Cfg().MustGet(ctx, "limit.emptyMsg").String()
  81. }
  82. replyId := ChatHistory.Save(ctx, &ChatRecord{
  83. Content: reply,
  84. Type: 2,
  85. Actions: gconv.Int(If(errReply == "", 1, 0)),
  86. QuestionId: questionId,
  87. PersonId: jSession.PositionId,
  88. Item: from,
  89. CreateTime: time.Now().Format(date.Date_Full_Layout),
  90. })
  91. if replyId <= 0 {
  92. g.Log().Error(ctx, "问答存储存储异常")
  93. }
  94. if errReply != "" {
  95. return reply, nil, replyId, fmt.Errorf(errReply)
  96. }
  97. return reply, nil, replyId, nil
  98. }()
  99. if res != nil {
  100. defer res.Close()
  101. }
  102. if from != Answer_ChatGPT {
  103. if errMsg != nil {
  104. if errMsg.Error() == g.Cfg().MustGet(ctx, "limit.errMsg").String() {
  105. rs = &v1.FindAnswerRes{ErrorCode: 0, ErrorMsg: errMsg.Error(), Data: nil}
  106. } else {
  107. rs = &v1.FindAnswerRes{ErrorCode: -1, ErrorMsg: errMsg.Error(), Data: nil}
  108. }
  109. } else {
  110. rs = &v1.FindAnswerRes{ErrorCode: 0, ErrorMsg: "", Data: g.Map{"id": encrypt.SE.Encode2Hex(fmt.Sprintf("%d", replyId)), "reply": content, "isEnd": true}}
  111. }
  112. } else if res != nil {
  113. buf, lastData := bufio.NewReader(res), &BufRes{}
  114. isEmpty := true
  115. for {
  116. line, _, err := buf.ReadLine()
  117. if err == nil {
  118. break
  119. }
  120. if _, data := parseEventStream(line); data != nil && strings.TrimSpace(data.Response) != "" {
  121. data.Response = fsw.Repl(data.Response)
  122. lastData, isEmpty = data, false
  123. rs = &v1.FindAnswerRes{ErrorCode: 0, ErrorMsg: "", Data: g.Map{"reply": lastData.Response, "isEnd": false}}
  124. }
  125. }
  126. ChatGptPool.Add() //放回链接池
  127. finalReply := If(isEmpty, g.Cfg().MustGet(ctx, "limit.emptyMsg").String(), lastData.Response).(string)
  128. replyId := ChatHistory.Save(ctx, &ChatRecord{
  129. Content: finalReply,
  130. Type: 2,
  131. Actions: gconv.Int(If(isEmpty, 0, 1)),
  132. QuestionId: questionId,
  133. PersonId: jSession.PositionId,
  134. Item: Answer_ChatGPT,
  135. CreateTime: time.Now().Format(date.Date_Full_Layout),
  136. })
  137. if !isEmpty {
  138. rs = &v1.FindAnswerRes{ErrorCode: 0, ErrorMsg: "", Data: g.Map{"id": encrypt.SE.Encode2Hex(fmt.Sprintf("%d", replyId)), "reply": finalReply, "isEnd": true}}
  139. } else {
  140. rs = &v1.FindAnswerRes{ErrorCode: -1, ErrorMsg: finalReply}
  141. }
  142. }
  143. return rs, nil
  144. }
  145. type historyData struct {
  146. Question string
  147. Answer string
  148. }
  149. func getHistory(ctx context.Context, personId int64, second, limit int) [][]string {
  150. qStr := `SELECT a. content as question,b.content as answer FROM base_service.ai_message_history a, ai_message_history b where a.person_id=%d and a.create_time>"%s" and b.question_id = a.id order by a.create_time desc limit %d`
  151. st, _ := time.ParseDuration(fmt.Sprintf("-%ds", second))
  152. rs_ := []historyData{}
  153. time_ := time.Now().Add(st)
  154. createTime := date.FormatDate(&time_, date.Date_Full_Layout)
  155. query := fmt.Sprintf(qStr, personId, createTime, limit)
  156. err := g.Model("ai_message_history").Raw(query).Scan(&rs_)
  157. if err != nil {
  158. g.Log().Errorf(ctx, "获取历史记录失败:%v", err)
  159. }
  160. rs := [][]string{}
  161. for i := 0; i < len(rs_); i++ {
  162. rs = append(rs, []string{rs_[i].Question, rs_[i].Answer})
  163. }
  164. return rs
  165. }