Browse Source

wip:智能聊天走语料代码条

wangkaiyue 2 years ago
parent
commit
ea6c82c437

+ 1 - 0
go.mod

@@ -4,6 +4,7 @@ go 1.15
 
 require (
 	app.yhyue.com/moapp/jybase v0.0.0-20230405040249-a36a23595798
+	app.yhyue.com/moapp/jypkg v0.0.0-20230330033424-b61bb6a4ad7e
 	github.com/gogf/gf/contrib/drivers/mysql/v2 v2.3.3
 	github.com/gogf/gf/contrib/nosql/redis/v2 v2.3.3
 	github.com/gogf/gf/v2 v2.3.1

+ 10 - 0
internal/consts/consts.go

@@ -1,6 +1,16 @@
 package consts
 
+import "github.com/gogf/gf/v2/frame/g"
+
 const (
 	JY_SESSIONNAME = "SESSIONID"
 	ContextKey     = "ContextKey"
 )
+const (
+	QUESTION_TYPE_GUESS   = iota + 1 //猜你想问
+	QUESTION_TYPE_USUALLY            //常见问题
+)
+
+var (
+	RequestJsonHeader = g.MapStrStr{"Content-Type": "application/json"}
+)

+ 1 - 1
internal/controller/chatHistory.go

@@ -17,7 +17,7 @@ type cChatHistory struct{}
 // Method 获取聊天记录
 func (c *cChatHistory) Method(ctx context.Context, req *v1.ChatHistoryReq) (res *v1.ChatHistoryRes, err error) {
 	res = &v1.ChatHistoryRes{}
-	history, err := model.Message.GetMessage(model.SessionCtx.Get(ctx).JSession.AccountId, req.PageNum, req.PageSize)
+	history, err := model.ChatHistroy.GetMessage(model.SessionCtx.Get(ctx).JSession.AccountId, req.PageNum, req.PageSize)
 	if err != nil {
 		glog.Error(ctx, "%d查询聊天记录异常,error:%s", model.SessionCtx.Get(ctx).JSession.AccountId, err)
 		res.ErrorCode = -1

+ 1 - 1
internal/controller/evaluate.go

@@ -16,7 +16,7 @@ type cEvaluate struct{}
 func (c *cEvaluate) Method(ctx context.Context, req *v1.EvaluateReq) (res *v1.EvaluateRes, err error) {
 	res = &v1.EvaluateRes{}
 	id := encrypt.SE.Decode4Hex(req.MessageId)
-	err = model.Message.Evaluate(model.SessionCtx.Get(ctx).JSession.AccountId, id, req.Evaluate)
+	err = model.ChatHistroy.Evaluate(model.SessionCtx.Get(ctx).JSession.AccountId, id, req.Evaluate)
 	if err != nil {
 		res.Data = false
 		return

+ 3 - 1
internal/controller/guessQuestion.go

@@ -14,5 +14,7 @@ var (
 type cGuessQuestion struct{}
 
 func (c *cGuessQuestion) Method(ctx context.Context, req *v1.GuessQuestionReq) (res *v1.QuestionRes, err error) {
-	return &v1.QuestionRes{Data: model.Question.GetProblem(model.GetScenario(req.Href), 1, g.Config().MustGet(ctx, "chat.usuallyProblem", 5).Int())}, nil
+	var list []string
+	list, err = model.Question.GetGuessQuestion(ctx, g.Config().MustGet(ctx, "chat.usuallyProblem", 5).Int())
+	return &v1.QuestionRes{Data: list}, nil
 }

+ 3 - 1
internal/controller/usuallyProblem.go

@@ -14,5 +14,7 @@ var (
 type cUsuallyProblem struct{}
 
 func (c *cUsuallyProblem) Method(ctx context.Context, req *v1.UsuallyProblemReq) (res *v1.QuestionRes, err error) {
-	return &v1.QuestionRes{Data: model.Question.GetProblem(model.GetScenario(req.Href), 0, g.Config().MustGet(ctx, "chat.guessQuestion", 5).Int())}, nil
+	var list []string
+	list, err = model.Question.GetUsuallyProblem(ctx, model.GetScenario(req.Href), g.Config().MustGet(ctx, "chat.guessQuestion", 5).Int())
+	return &v1.QuestionRes{Data: list}, nil
 }

+ 47 - 0
internal/model/chatApi.go

@@ -0,0 +1,47 @@
+package model
+
+import (
+	"aiChat/internal/consts"
+	"context"
+	"github.com/gogf/gf/v2/frame/g"
+	"github.com/gogf/gf/v2/net/gclient"
+	"github.com/gogf/gf/v2/util/gconv"
+)
+
+type GPTReq struct {
+	*BaseQuestion
+	Identity string `json:"identity"`
+}
+
+type GPTRes struct {
+	Status   int        `json:"status"`
+	Response string     `json:"response"`
+	History  [][]string `json:"history"`
+	Time     string     `json:"time"`
+}
+
+var (
+	ChatGpt = &cChatGpt{}
+)
+
+type cChatGpt struct {
+}
+
+func (c *cChatGpt) Do(ctx context.Context, qReq *QuestionReq) (res *GPTRes, err error) {
+	gReq := GPTReq{
+		BaseQuestion: qReq.BaseQuestion,
+		Identity:     g.Config().MustGet(ctx, "chat.api.identity", "剑鱼chat").String(),
+	}
+	//g.Dump(gReq)
+	var gRes *gclient.Response
+	gRes, err = g.Client().Header(consts.RequestJsonHeader).Post(ctx, g.Config().MustGet(ctx, "chat.api.addr", "").String(), gReq)
+	if err != nil {
+		return nil, err
+	}
+	res = &GPTRes{}
+	err = gconv.Struct(gRes.ReadAll(), res)
+	if err != nil {
+		return nil, err
+	}
+	return
+}

+ 9 - 9
internal/model/message.go → internal/model/chatHistory.go

@@ -10,12 +10,12 @@ import (
 )
 
 var (
-	Message = &cMessage{
+	ChatHistroy = &cChatHistroy{
 		Arr: make([]*SaveMessage, 0, 100),
 	}
 )
 
-type cMessage struct {
+type cChatHistroy struct {
 	Arr []*SaveMessage
 }
 
@@ -38,14 +38,14 @@ type SaveMessage struct {
 }
 
 // SaveMessage 保存聊天信息
-func (m *cMessage) SaveMessage(msg *SaveMessage) {
+func (m *cChatHistroy) SaveMessage(msg *SaveMessage) {
 	m.Arr = append(m.Arr, msg)
 	if len(m.Arr) > 0 {
 		tmp, ctx := m.Arr, gctx.New()
 		m.Arr = make([]*SaveMessage, 0, 5)
 
 		val := gconv.Maps(tmp)
-		r, err := g.Model("ai_message").Data(val).Insert()
+		r, err := g.Model("ai_message_history").Data(val).Insert()
 		if err != nil {
 			glog.Error(ctx, "插入聊天记录异常,error:%s\ndata:%v", err, val)
 			g.Dump(val)
@@ -61,8 +61,8 @@ func (m *cMessage) SaveMessage(msg *SaveMessage) {
 }
 
 // GetMessage 查询聊天信息
-func (m *cMessage) GetMessage(userId int64, pageNum, pageSize int) (h []ResHistory, err error) {
-	err = g.Model("ai_message").Where("person_id = ?", userId).OrderDesc("create_time").OrderDesc("id").Limit(pageNum, (pageNum+1)*pageSize).Scan(&h)
+func (m *cChatHistroy) GetMessage(userId int64, pageNum, pageSize int) (h []ResHistory, err error) {
+	err = g.Model("ai_message_history").Where("person_id = ?", userId).OrderDesc("create_time").OrderDesc("id").Limit(pageNum, (pageNum+1)*pageSize).Scan(&h)
 	if err != nil {
 		return
 	}
@@ -70,8 +70,8 @@ func (m *cMessage) GetMessage(userId int64, pageNum, pageSize int) (h []ResHisto
 }
 
 // Evaluate 评价
-func (m *cMessage) Evaluate(userId int64, megId string, value int) error {
-	res, err := g.Model("ai_message").One("id =? and person_id =? and type=2", megId, userId)
+func (m *cChatHistroy) Evaluate(userId int64, megId string, value int) error {
+	res, err := g.Model("ai_message_history").One("id =? and person_id =? and type=2", megId, userId)
 	if err != nil {
 		return err
 	}
@@ -81,7 +81,7 @@ func (m *cMessage) Evaluate(userId int64, megId string, value int) error {
 	if gconv.Int(res.Map()["useful"]) != 0 {
 		return fmt.Errorf("已评价")
 	}
-	r, _ := g.Model("ai_message").Data(g.Map{"useful": value}).Where("id =? and person_id =? and type=2", megId, userId).Update()
+	r, _ := g.Model("ai_message_history").Data(g.Map{"useful": value}).Where("id =? and person_id =? and type=2", megId, userId).Update()
 	affect, _ := r.RowsAffected()
 	if affect != 1 {
 		return fmt.Errorf("评价异常")

+ 114 - 47
internal/model/question.go

@@ -1,45 +1,70 @@
 package model
 
 import (
-	elastic "app.yhyue.com/moapp/jybase/esv1"
+	"aiChat/internal/consts"
+	"aiChat/utility"
 	"context"
 	"fmt"
 	"github.com/gogf/gf/v2/frame/g"
 	"github.com/gogf/gf/v2/util/gconv"
+	"regexp"
+	"strings"
 )
 
 var (
-	Question = &cQuestion{}
+	Question    = &cQuestion{}
+	regExpSmart = regexp.MustCompile("smart_\\S+_smart")
 )
 
 const (
-	answerFrom = iota
-	Answer_UsuallyProblem
+	Answer_UsuallyProblem = iota + 1
 	Answer_Isbusiness
 	Answer_ChatGPT
-
-	index, itype          = "aiquestion", "aiquestion"
-	GetQuestionListSql    = `{"query":{"bool":{"must":[{"term":{"status":1}},{"term":{"isbusiness":%d}},{"term":{"source":"%s"}}]}},"from":0,"size":%d,"sort":[{"id":"desc"}],"_source": ["question"]}`
-	GetAnswerFromQuestion = `{"query":{"bool":{"must":[{"term":{"status":1}},{"multi_match":{"query":"%s","minimum_should_match":"%s","fields":["question"]}}]}},"from":0,"size":1,"_source":["check_member","isbusiness","question","answer","auto_url","joggle","service_id","noperm","source"]}`
 )
 
 type cQuestion struct {
 }
 
-// QuestionReq 用户发送过来的问题详情
+type BaseQuestion struct {
+	Prompt  string     `json:"prompt"`
+	History [][]string `json:"history"`
+}
+
 type QuestionReq struct {
-	Context string `json:"context"` //内容
-	History []struct {
-		Q string `json:"q"` //问题
-		A string `json:"a"` //答案
-	} `json:"history,omitempty"` //会话上下文,会话历史
-	Href string `json:"href,omitempty"` //咨询页面
+	*BaseQuestion
+	Href string `json:"href"` //咨询页面
+}
+
+// GetGuessQuestion 猜你想问
+func (q *cQuestion) GetGuessQuestion(ctx context.Context, limit int) (list []string, err error) {
+	list = make([]string, 0, limit)
+	res, err := g.Model("ai_question_list").Ctx(ctx).Fields("question").
+		Where("status = 1 and question_type = ?", consts.QUESTION_TYPE_GUESS).OrderDesc("id").Limit(limit).All()
+	if err != nil {
+		return nil, err
+	}
+	for _, m := range res.List() {
+		list = append(list, gconv.String(m["question"]))
+	}
+	return
+}
+
+// GetUsuallyProblem 获取常见问题
+func (q *cQuestion) GetUsuallyProblem(ctx context.Context, scenario, limit int) (list []string, err error) {
+	list = make([]string, 0, limit)
+	res, err := g.Model("ai_question_list").Ctx(ctx).Fields("question").
+		Where("status = 1 and question_type = ? and source = ?", consts.QUESTION_TYPE_USUALLY, scenario).OrderDesc("id").Limit(limit).All()
+	if err != nil {
+		return nil, err
+	}
+	for _, m := range res.List() {
+		list = append(list, gconv.String(m["question"]))
+	}
+	return
 }
 
-// QuestionEsRes 问题检索库查询结果
-type QuestionEsRes struct {
+type BusinessRes struct {
 	CheckMember int    `json:"check_member" dc:"是否校验大会员权限"`
-	Isbusiness  int    `json:"isbusiness" dc:"业务意图 0:否 1:是"`
 	Answer      string `json:"answer" dc:"答案"`
 	AutoUrl     string `json:"auto_url" dc:"默认url"`
 	Joggle      string `json:"joggle" dc:"业务接口"`
@@ -48,39 +73,81 @@ type QuestionEsRes struct {
 	ServiceId   string `json:"service_id" dc:"大会员功能服务id"`
 }
 
-// GetProblem 获取常见问题及猜你想问
-func (q *cQuestion) GetProblem(scenario, isbusiness, limit int) (list []string) {
-	list = make([]string, 0, limit)
-	res := elastic.Get(index, itype, fmt.Sprintf(GetQuestionListSql, isbusiness, scenarioName[scenario], limit))
-	if res != nil && len(*res) > 0 {
-		for _, m := range *res {
-			list = append(list, gconv.MapStrStr(m)["question"])
-		}
+// 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").Where("ai_code = ?", code).One()
+	if err != nil {
+		return nil, err
 	}
-	return
+	if res.IsEmpty() {
+		return nil, fmt.Errorf("未知业务指令")
+	}
+	bRes = &BusinessRes{}
+	if err = res.Struct(bRes); err != nil {
+		return nil, err
+	}
+	return bRes, nil
 }
 
-// GetAnswer 获取答案
-func (q *cQuestion) GetAnswer(ctx context.Context, question *QuestionReq) (itemFrom int, detail string, err error) {
-	res := elastic.Get(index, itype, fmt.Sprintf(GetAnswerFromQuestion, question.Context, g.Config().MustGet(ctx, "chat.match", "70%").String()))
-	if res == nil || len(*res) == 0 {
-		return getAnswerFromChatGPT()
+// DetailQuestion 问题处理
+func (q *cQuestion) DetailQuestion(ctx context.Context, qRes *QuestionReq) (reply string, from int, err error) {
+	cRes, err := ChatGpt.Do(ctx, qRes)
+	if err != nil {
+		return "", 0, err
 	}
-	qResObj := &QuestionEsRes{}
-	gconv.Struct((*res)[0], qResObj)
-
-	// 非业务问题直接返回
-	if qResObj.Isbusiness == 0 {
-		return Answer_UsuallyProblem, qResObj.Answer, nil
+	// 校验是否有业务逻辑
+	matchArr := regExpSmart.FindStringSubmatch(cRes.Response)
+	if len(matchArr) == 0 {
+		return cRes.Response, Answer_ChatGPT, nil
 	}
+	// 查询业务逻辑
+	var bRes = &BusinessRes{}
+	bRes, err = q.getIsbusinessData(ctx, matchArr[0])
 
-	// 业务问题
-	//qResObj.CheckMember
-
-	return Answer_Isbusiness, "", nil
-}
-
-// getChatGPT 获取ChatGPT答案
-func getAnswerFromChatGPT() (int, string, error) {
-	return Answer_ChatGPT, "", nil
+	// 权限校验
+	jSession := SessionCtx.Get(ctx).JSession
+	powerPass := func() bool {
+		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 {
+			return false
+		}
+		// 大会员权益ServiceId校验
+		if bRes.ServiceId != "" {
+			for _, v := range strings.Split(bRes.ServiceId, ",") {
+				var ok bool = false
+				for _, vv := range power.Member.MemberPowerList {
+					if gconv.Int64(v) == vv {
+						ok = true
+						break
+					}
+				}
+				if !ok {
+					return false
+				}
+			}
+		}
+		return true
+	}()
+	if !powerPass {
+		return bRes.Noperm, Answer_Isbusiness, nil
+	}
+	_, infoId := GetScenarioAndInfoId(qRes.Href)
+	if bRes.Source == scenarioName[DetailPage] && infoId == "" {
+		return bRes.AutoUrl, Answer_Isbusiness, nil
+	}
+	businessRes, err := DoBusiness(ctx, bRes.Joggle, &RpcParams{
+		UserId:     jSession.UserId,
+		Answer:     bRes.Answer,
+		BiddingId:  infoId,
+		IsEnt:      false,
+		BaseUserId: jSession.NewUid,
+	})
+	if err != nil {
+		return "", Answer_Isbusiness, nil
+	}
+	if businessRes.ErrMsg != "" {
+		return "", Answer_Isbusiness, fmt.Errorf(businessRes.ErrMsg)
+	}
+	return businessRes.ReplyMsg, Answer_Isbusiness, nil
 }

+ 46 - 0
internal/model/rpc.go

@@ -0,0 +1,46 @@
+package model
+
+import (
+	"context"
+	"github.com/gogf/gf/v2/frame/g"
+	"github.com/gogf/gf/v2/util/gconv"
+	"net/rpc"
+)
+
+type RpcParams struct {
+	UserId     string //用户id
+	Answer     string //答案原型
+	BiddingId  string //招标信息id
+	IsEnt      bool   //当前是否是企业身份
+	PageNum    int    //当前页码
+	PageSize   int    //每页数据
+	BaseUserId int64  //base_user_id
+}
+
+type Result struct {
+	ErrCode  int
+	ErrMsg   string
+	ReplyMsg string
+}
+
+type RpcResult []byte
+
+// DoBusiness 调用业务意图处理
+func DoBusiness(ctx context.Context, joggle string, param *RpcParams) (*Result, error) {
+	client, err := rpc.DialHTTP("tcp", g.Cfg().MustGet(ctx, "chat.businessRpc", "").String())
+	defer client.Close()
+	if err != nil {
+		return nil, err
+	}
+	var repl RpcResult
+	err = client.Call(joggle, param, &repl)
+	if err != nil {
+		return nil, err
+	}
+	rData := &Result{}
+	err = gconv.Struct(repl, rData)
+	if err != nil {
+		return nil, err
+	}
+	return rData, nil
+}

+ 25 - 2
internal/model/scenario.go

@@ -1,24 +1,25 @@
 package model
 
 import (
+	"app.yhyue.com/moapp/jybase/encrypt"
 	"net/url"
 	"regexp"
 	"strings"
 )
 
 const (
-	IndexPage = iota //b=0
+	IndexPage = iota + 1 //b=0
 	DetailPage
 	WorkDesk //c=1   相当于c=iota
 )
 
 var (
+	regExpDetail = regexp.MustCompile("^/article/(\\w+)/(.*).html")
 	scenarioName = map[int]string{
 		IndexPage:  "index",    //网站首页
 		DetailPage: "detail",   //三级页
 		WorkDesk:   "workDesk", //工作桌面
 	}
-	regExpDetail = regexp.MustCompile("^/article/(\\w+)/(.*).html")
 )
 
 // GetScenario 获取场景
@@ -37,3 +38,25 @@ func GetScenario(refer string) int {
 	}
 	return IndexPage
 }
+
+// GetScenarioAndInfoId 获取场景和信息id
+func GetScenarioAndInfoId(refer string) (scenario int, sid string) {
+	u, err := url.Parse(refer)
+	if err == nil {
+		if strings.HasPrefix(u.Path, "/page_workDesktop") {
+			if strings.HasPrefix(u.Path, "/page_workDesktop/work-bench/page") {
+				uu, err := url.Parse(u.Query().Get("link"))
+				if err == nil && uu.Path != "" {
+					if arr := regExpDetail.FindStringSubmatch(uu.Path); len(arr) == 3 {
+						if idArr := encrypt.CommonDecodeArticle(arr[1], arr[2]); len(idArr) > 0 {
+							sid = idArr[0]
+						}
+						return DetailPage, sid
+					}
+				}
+			}
+			return WorkDesk, ""
+		}
+	}
+	return IndexPage, ""
+}

+ 19 - 14
internal/model/ws.go

@@ -5,6 +5,7 @@ import (
 	"app.yhyue.com/moapp/jybase/date"
 	"context"
 	"github.com/gogf/gf/v2/encoding/gjson"
+	"github.com/gogf/gf/v2/frame/g"
 	"github.com/gogf/gf/v2/net/ghttp"
 	"github.com/gogf/gf/v2/os/glog"
 	"time"
@@ -29,23 +30,27 @@ func (m *wsChat) Handle(ws *ghttp.WebSocket, msg []byte, ip, agent string) {
 	if err := gjson.Unmarshal(msg, req); err != nil {
 		glog.Errorf(m.Ctx, "%d 接收消息Unmarshal出错:%v", m.UserId, err)
 	}
-	Message.SaveMessage(&SaveMessage{
-		Content:    req.Context,
+	ChatHistroy.SaveMessage(&SaveMessage{
+		Content:    req.Prompt,
 		Type:       1,
 		Useful:     0,
-		Refer:      "",
+		Refer:      req.Href,
 		PersonId:   m.UserId,
 		CreateTime: time.Now().Format(date.Date_Full_Layout),
 	})
-	//switch req.Type {
-	//case ReqType_Heartbeat: //用户端心跳
-	//	cache.SetUserHeartbeat(userId)
-	//	nws.SendMsg(ws, &User{Id: userId}, &Resp{Type: RespType_Heartbeat})
-	//case ReqType_CustomerService_Heartbeat: //客服端心跳
-	//	nws.SendMsg(ws, &User{Id: userId}, &Resp{Type: RespType_Heartbeat})
-	//	cache.SetCustomerServiceHeartbeat(entId, entUserId, userId)
-	//}
-
-	Question.GetAnswer(m.Ctx, req)
-
+	reply, from, err := Question.DetailQuestion(m.Ctx, req)
+	if err != nil {
+		g.Log().Error(m.Ctx, err)
+		_ = ws.WriteJSON(g.Map{"error_code": -1, "error_msg": err.Error()})
+		return
+	}
+	ChatHistroy.SaveMessage(&SaveMessage{
+		Content:    req.Prompt,
+		Type:       2,
+		Refer:      req.Href,
+		PersonId:   m.UserId,
+		Item:       from,
+		CreateTime: time.Now().Format(date.Date_Full_Layout),
+	})
+	_ = ws.WriteJSON(g.Map{"error_code": 0, "error_msg": "", "data": reply})
 }

+ 5 - 0
main.go

@@ -5,9 +5,14 @@ import (
 	_ "aiChat/utility"
 	_ "github.com/gogf/gf/contrib/drivers/mysql/v2"
 	_ "github.com/gogf/gf/contrib/nosql/redis/v2"
+	"github.com/gogf/gf/v2/frame/g"
 	"github.com/gogf/gf/v2/os/gctx"
+	"regexp"
 )
 
 func main() {
+	var regExpSmart = regexp.MustCompile("smart_\\S+_smart")
+	g.Dump(regExpSmart.FindStringSubmatch("啊啥的smart_问你_smart啊啥的"))
+	return
 	cmd.Main.Run(gctx.New())
 }

+ 10 - 5
manifest/config/config.yaml

@@ -13,10 +13,19 @@ server:
   AccessLogPattern: "access.{Ymd}.log"
 
 chat:
+  appId: "10000"
   usuallyProblem: 5 # 常见问题返回数量
   guessQuestion: 5 # 猜你想问返回数量
-  match: 50% # 检索库匹配值
+  api:
+    addr: "http://49.233.60.39:7880"
+    identity: "剑鱼chat"
+  businessRpc: "127.0.0.1:5051"
 
+etcd:
+  hosts:
+    - 192.168.3.149:2379
+  powerCheckCenterKey: "powercheck.rpc" #权益校验中台
+  userCenterKey: "usercenter.rpc" #用户中台rpc
 
 redis:
   session:
@@ -24,10 +33,6 @@ redis:
   main:
     address: 192.168.3.206:1712
 
-elasticsearch:
-  address: "http://192.168.3.206:9800"
-  size: 5
-
 database:
   default:
     link: "mysql:root:=PDT49#80Z!RVv52_z@tcp(192.168.3.217:4000)/base_service"

+ 22 - 0
resource/aiChat.sql

@@ -0,0 +1,22 @@
+CREATE TABLE `ai_message_history` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `content` text COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '内容',
+  `type` tinyint(4) NOT NULL COMMENT '类型 1:用户提问 2:智能助手回复',
+  `useful` tinyint(4) DEFAULT NULL COMMENT '-1:无用 1:有用',
+  `item` tinyint(4) NOT NULL COMMENT '1:常见问题 2:业务意图 3:chatgpt',
+  `refer` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '会话来源地址',
+  `person_id` int(11) NOT NULL COMMENT '自然人id',
+  `create_time` datetime NOT NULL COMMENT '创建时间',
+  PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci AUTO_INCREMENT=100001 COMMENT='aichat聊天记录';
+
+CREATE TABLE `ai_question_list` (
+    `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '问题表id',
+    `status` tinyint(4) DEFAULT '1' COMMENT '状态:0:无效 1:有效',
+    `question` text CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '问题',
+    `source` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT 'index:网站首页 detail:三级页 workDesk:工作桌面首页 ',
+    `question_type` tinyint(4) DEFAULT '1' COMMENT '1:猜你想问 2:常见问题',
+    `create_time` datetime DEFAULT NULL COMMENT '创建时间',
+    `update_time` datetime DEFAULT NULL,
+    PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci AUTO_INCREMENT=30001 COMMENT='常见问题列表';

+ 0 - 20
utility/elasticsearch.go

@@ -1,20 +0,0 @@
-package utility
-
-import (
-	elastic "app.yhyue.com/moapp/jybase/esv1"
-	"github.com/gogf/gf/v2/frame/g"
-	"github.com/gogf/gf/v2/os/gctx"
-)
-
-type esConf struct {
-	Address string `json:"address"`
-	Size    int    `json:"size"`
-}
-
-func init() {
-	var EsConf esConf
-	ctx := gctx.New()
-	_ = g.Cfg().MustGet(ctx, "elasticsearch", "").Scan(&EsConf)
-	elastic.InitElasticSize(EsConf.Address, EsConf.Size)
-	g.Log().Info(ctx, "初始化 elasticsearch", EsConf)
-}

+ 28 - 0
utility/init.go

@@ -0,0 +1,28 @@
+package utility
+
+import (
+	"app.yhyue.com/moapp/jypkg/middleground"
+	"github.com/gogf/gf/v2/frame/g"
+	"github.com/gogf/gf/v2/os/gctx"
+)
+
+var (
+	Middleground *middleground.Middleground
+)
+
+type esConf struct {
+	Address string `json:"address"`
+	Size    int    `json:"size"`
+}
+
+func init() {
+	//var EsConf esConf
+	ctx := gctx.New()
+	//_ = g.Cfg().MustGet(ctx, "elasticsearch", "").Scan(&EsConf)
+	//elastic.InitElasticSize(EsConf.Address, EsConf.Size)
+	//g.Log().Info(ctx, "初始化 elasticsearch", EsConf)
+
+	Middleground = middleground.NewMiddleground(g.Cfg().MustGet(ctx, "etcd.hosts").Strings()).
+		RegPowerCheckCenter(g.Cfg().MustGet(ctx, "etcd.powerCheckCenterKey").String()).
+		RegUserCenter(g.Cfg().MustGet(ctx, "etcd.userCenterKey").String())
+}