package service import ( cm "app.yhyue.com/moapp/jybase/common" . "app.yhyue.com/moapp/jybase/encrypt" elastic "app.yhyue.com/moapp/jybase/esv1" . "bp.jydev.jianyu360.cn/SocialPlatform/knowledgeBase/entity" "bp.jydev.jianyu360.cn/SocialPlatform/knowledgeBase/rpc/knowledge/init" "bp.jydev.jianyu360.cn/SocialPlatform/knowledgeBase/rpc/knowledge/knowledgeclient" "bp.jydev.jianyu360.cn/SocialPlatform/knowledgeBase/rpc/knowledge/util" "database/sql" "fmt" "github.com/zeromicro/go-zero/core/logx" "log" "strconv" "time" ) type KnowledgeService struct{} var ( Index = "smart_new" Type = "smart" ) // KnowledgeAdd 添加问题 func (k *KnowledgeService) KnowledgeAdd(param *knowledgeclient.AddRequest, segment string) (bool, string) { //先查找知识库Id query := map[string]interface{}{"status": 1, "appid": param.AppId, "ent_id": param.EntId} datalist := Mysql.Find(util.KNOWLEDGE, query, "id", "", -1, -1) if datalist != nil && *datalist != nil && len(*datalist) > 0 { //问题进行分词 keywords := "" keywordsArr := util.HanlpGetNormalWords(param.Question, segment) if len(keywordsArr) != 0 { for _, val := range keywordsArr { keywords += val + " " } } if keywords == "" { keywords = param.Question } createPerson := param.EntUserId var answerId int64 nowTime := time.Now().Local().Format(util.DateFullLayout) fool := Mysql.ExecTx("添加知识", func(tx *sql.Tx) bool { //插入答案 answerData := map[string]interface{}{ "knowledge_id": (*datalist)[0]["id"], "status": 1, "create_time": nowTime, "update_time": nowTime, "create_person": createPerson, "content": param.Answer, } answerId = Mysql.Insert(util.ANSWER, answerData) //插入问题 questionData := map[string]interface{}{ "answer_id": answerId, "content": param.Question, "keywords": keywords, } questionId := Mysql.Insert(util.QUESTION, questionData) return answerId > 0 && questionId > 0 }) if fool { //插入es knowledge := map[string]interface{}{ "knowledgeId": (*datalist)[0]["id"], "status": 1, "createTime": time.Now().Unix(), "createPerson": createPerson, "answer": param.Answer, "question": param.Question, "keywords": keywords, "answerId": answerId, "entId": param.EntId, } b := elastic.Save(Index, Type, knowledge) if !b { return false, "es 保存失败" } // 存入向量库 //插入es knowledgeV := map[string]interface{}{ "mod_time": time.Now().Unix(), "answer": param.Answer, "question": param.Question, "id": answerId, "entId": param.EntId, "questionVector": util.EncodeVector(param.Question), } if !ESV7.Save(ESV7Index, ESV7Type, knowledgeV) { logx.Error("知识库添加向量失败:", knowledgeV) } return b, "" } return fool, "插入mysql出错" } return false, "租户不存在" } // KnowledgeEdit 编辑问题 func (k *KnowledgeService) KnowledgeEdit(param *knowledgeclient.KnowledgeEditReq, segment string) (ok bool) { ok = false //获取问题分词 keywords := "" keywordsArr := util.HanlpGetNormalWords(param.Question, segment) logx.Info("keywordsArr", keywordsArr) if len(keywordsArr) != 0 { for _, val := range keywordsArr { keywords += val + " " } } if keywords == "" { keywords = param.Question } //通过entUserId获取创建人名称 /*req := &usercenter.EntUserReq{ EntId: param.EntId, EntUserId: param.EntUserId, AppId: param.AppId, } resp, err := UserCenterLib.GetEntUserInfo(context.Background(), req) if resp.ErrorCode != 0 { logx.Info("查询用户中台创建人信息失败", param.EntId, param.EntUserId, "err:", err) return ok }*/ createPerson := param.EntUserId fool := Mysql.ExecTx("编辑问题、答案", func(tx *sql.Tx) bool { //修改答案 answerUpdate := map[string]interface{}{ "update_time": time.Now().Local().Format(util.DateFullLayout), "content": param.Answer, } ok1 := Mysql.UpdateByTx(tx, util.ANSWER, map[string]interface{}{"id": param.AnswerId}, answerUpdate) //修改问题 questionUpdate := map[string]interface{}{ "content": param.Question, "keywords": keywords, } ok2 := Mysql.UpdateByTx(tx, util.QUESTION, map[string]interface{}{"answer_id": param.AnswerId}, questionUpdate) return ok1 && ok2 }) if fool { query := `{"query":{"bool":{"must":[{"term":{"answerId":"` + strconv.Itoa(int(param.AnswerId)) + `"}}],"must_not":[],"should":[]}},"from":0,"size":10,"sort":[],"facets":{}}` //修改es数据 newKnowledge := map[string]interface{}{ "knowledgeId": param.KnowledgeId, "status": 1, "createTime": time.Now().Unix(), "createPerson": createPerson, "answer": param.Answer, "question": param.Question, "keywords": keywords, "answerId": param.AnswerId, "entId": param.EntId, } ok1 := elastic.Del(Index, Type, query) ok2 := elastic.Save(Index, Type, newKnowledge) // 查询出来 queryByAid := fmt.Sprintf(`{ "query": { "bool": { "must": [ { "term": { "id": %v } } ] } }, "size": 1 }`, param.AnswerId) rs := ESV7.Get(ESV7Index, ESV7Type, queryByAid) _id := "" if rs != nil && len(*rs) > 0 { _id = cm.InterfaceToStr((*rs)[0]["_id"]) } // 存入向量库 //插入es knowledgeV := map[string]interface{}{ "mod_time": time.Now().Unix(), "answer": param.Answer, "question": param.Question, "id": param.AnswerId, "entId": param.EntId, "questionVector": util.EncodeVector(param.Question), } if _id != "" { knowledgeV["_id"] = _id } if !ESV7.Save(ESV7Index, ESV7Type, knowledgeV) { logx.Error("知识库添加向量失败:", knowledgeV) } return ok1 && ok2 } return ok } // KnowledgeList 问题列表 func (k *KnowledgeService) KnowledgeList(param *knowledgeclient.ListRequest) *knowledgeclient.ListData { var knowledgeList knowledgeclient.ListData var data []*knowledgeclient.KnowledgeEntity countSql := fmt.Sprintf("SELECT COUNT(b.id) FROM %s a LEFT JOIN %s b ON a.id = b.knowledge_id LEFT JOIN %s c ON b.id = c.answer_id WHERE b.`status` =1 and a.ent_id=%d", util.KNOWLEDGE, util.ANSWER, util.QUESTION, param.EntId) count := Mysql.CountBySql(countSql) if count > 0 { //列表数据 sql1 := fmt.Sprintf("SELECT b.content as answer,c.content as question,b.id,b.knowledge_id FROM %s a LEFT JOIN %s b ON a.id = b.knowledge_id LEFT JOIN %s c ON b.id = c.answer_id WHERE b.`status` =1 and a.ent_id=? order by b.update_time desc limit ?,?", util.KNOWLEDGE, util.ANSWER, util.QUESTION) datalist := Mysql.SelectBySql(sql1, param.EntId, (param.PageIndex-1)*param.PageSize, param.PageSize) if datalist != nil && *datalist != nil && len(*datalist) > 0 { for _, value := range *datalist { knowledge := knowledgeclient.KnowledgeEntity{} knowledge.Answer = cm.ObjToString(value["answer"]) knowledge.Question = cm.ObjToString(value["question"]) knowledge.AnswerId = cm.Int64All(value["id"]) knowledge.KnowledgeId = cm.Int64All(value["knowledge_id"]) data = append(data, &knowledge) } } knowledgeList.Total = count knowledgeList.Data = data } return &knowledgeList } // KnowledgeInfo 问题详情 func (k *KnowledgeService) KnowledgeInfo(answerId int64) (data *knowledgeclient.KnowledgeEntity, ok bool) { //util.ANSWER,util.QUESTION sql1 := fmt.Sprintf("SELECT b.content as answer,c.content as question,b.id,b.knowledge_id FROM %s b LEFT JOIN %s c ON b.id = c.answer_id WHERE b.`status` =1 AND b.id = %d", util.ANSWER, util.QUESTION, answerId) datalist := Mysql.SelectBySql(sql1) if datalist != nil && *datalist != nil && len(*datalist) > 0 { knowledge := knowledgeclient.KnowledgeEntity{} knowledge.Answer = cm.ObjToString((*datalist)[0]["answer"]) knowledge.Question = cm.ObjToString((*datalist)[0]["question"]) knowledge.AnswerId = cm.Int64All((*datalist)[0]["id"]) knowledge.KnowledgeId = cm.Int64All((*datalist)[0]["knowledge_id"]) return &knowledge, true } return nil, false } // KnowledgeDel 删除问题 func (k *KnowledgeService) KnowledgeDel(answerId int64) (ok bool) { ok = false //修改答案 answerUpdate := map[string]interface{}{ "update_time": time.Now().Local().Format(util.DateFullLayout), "status": 0, } fool := Mysql.Update(util.ANSWER, map[string]interface{}{"id": answerId}, answerUpdate) if fool { //删除es数据 query := `{"query":{"bool":{"must":[{"term":{"answerId":"` + strconv.Itoa(int(answerId)) + `"}}],"must_not":[],"should":[]}},"from":0,"size":1,"sort":[],"facets":{}}` ok = elastic.Del(Index, Type, query) queryByAid := fmt.Sprintf(`{ "query": { "bool": { "must": [ { "term": { "id": %v } } ] } }, "size": 1 }`, answerId) rs := ESV7.Get(ESV7Index, ESV7Type, queryByAid) if rs != nil && len(*rs) > 0 { _id := cm.InterfaceToStr((*rs)[0]["_id"]) if !ESV7.DelById(ESV7Index, ESV7Type, _id) { logx.Error("删除向量库失败:", _id, answerId) } } } return ok } // FindAnswer 根据问题推荐一个答案 func (k *KnowledgeService) FindAnswer(param *knowledgeclient.FindAnswerReq, addr, index, segment string) *knowledgeclient.Question { var question knowledgeclient.Question robotEntId := SE.Decode4Hex(param.RobotEntId) //组装es query //query := util.DSL4SmartResponse(param.Question, robotEntId, int(param.Type), addr, index, segment) query := util.GetAnswerQueryStr(param.Question, robotEntId, 1, init.C.MinScore) logx.Info("query:", query) if query != "" { res := ESV7.Get(ESV7Index, ESV7Type, query) if res != nil && len(*res) > 0 { data := (*res)[0] question.Answer = cm.ObjToString(data["answer"]) question.Question = cm.ObjToString(data["question"]) } } return &question } // RecommendAnswer 根据问题推荐三个答案 func (k *KnowledgeService) RecommendAnswer(param *knowledgeclient.FindAnswerReq, segment string, recommendQuestionCount int) []*knowledgeclient.Question { var ( keyWords = "" searchField = `"answer","question"` answers []*knowledgeclient.Question ) //根据问题进行分词 keywordsArr := util.HanlpGetNormalWords(param.Question, segment) logx.Info("keywordsArr", keywordsArr) if len(keywordsArr) != 0 { for _, val := range keywordsArr { keyWords += val + " " } } if keyWords == "" { keyWords = param.Question } //logx.Info("entId:", SE.Decode4Hex(param.RobotEntId)) var query = util.DSL4SearchByKwsOrid(keyWords, param.RobotEntId, 0) limit := 3 if param.ReqSource == 1 { limit = recommendQuestionCount } res := elastic.GetAllByNgram(Index, Type, query, "", "", searchField, 0, limit, 0, false) if res != nil && len(*res) > 0 { for _, val := range *res { answers = append(answers, &knowledgeclient.Question{ Question: cm.ObjToString(val["question"]), Answer: cm.ObjToString(val["answer"]), }) } log.Println("推荐答案:", answers) } return answers }