Browse Source

Merge remote-tracking branch 'origin/rag/3.0.1' into debug

# Conflicts:
#	models/business_conf.go
#	utils/common.go
Roc 1 week ago
parent
commit
c4c459b56b

+ 194 - 19
controllers/llm/question.go

@@ -7,6 +7,8 @@ import (
 	"eta/eta_api/models/rag"
 	"eta/eta_api/models/rag/request"
 	"eta/eta_api/models/rag/response"
+	"eta/eta_api/services"
+	"eta/eta_api/services/elastic"
 	"eta/eta_api/utils"
 	"fmt"
 	"github.com/rdlucklib/rdluck_tools/paging"
@@ -54,23 +56,131 @@ func (c *QuestionController) List() {
 	}
 	startSize = utils.StartIndex(currentIndex, pageSize)
 
-	var condition string
-	var pars []interface{}
+	var total int
+	viewList := make([]rag.QuestionView, 0)
 
-	if keyWord != "" {
-		condition += fmt.Sprintf(` AND %s like ?`, rag.QuestionColumns.QuestionContent)
-		pars = append(pars, `%`+keyWord+`%`)
+	if keyWord == `` {
+		var condition string
+		var pars []interface{}
+
+		if keyWord != "" {
+			condition += fmt.Sprintf(` AND %s like ?`, rag.QuestionColumns.QuestionContent)
+			pars = append(pars, `%`+keyWord+`%`)
+		}
+		obj := new(rag.Question)
+		tmpTotal, list, err := obj.GetPageListByCondition(condition, pars, startSize, pageSize)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取失败,Err:" + err.Error()
+			return
+		}
+		total = tmpTotal
+
+		if list != nil && len(list) > 0 {
+			viewList = list[0].ListToViewList(list)
+		}
+	} else {
+		sortMap := map[string]string{
+			//"ArticleCreateTime": "desc",
+			//"WechatArticleId":   "desc",
+		}
+		tmpTotal, list, err := elastic.RagQuestionEsSearch(keyWord, startSize, pageSize, sortMap)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取失败,Err:" + err.Error()
+			return
+		}
+		total = int(tmpTotal)
+		if list != nil && len(list) > 0 {
+			viewList = list[0].ToViewList(list)
+		}
 	}
 
-	obj := new(rag.Question)
-	total, list, err := obj.GetPageListByCondition(condition, pars, startSize, pageSize)
-	if err != nil {
-		br.Msg = "获取失败"
-		br.ErrMsg = "获取失败,Err:" + err.Error()
+	page := paging.GetPaging(currentIndex, pageSize, total)
+	resp := response.QuestionListListResp{
+		List:   viewList,
+		Paging: page,
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// TitleList
+// @Title 标题列表
+// @Description 标题列表
+// @Param   PageSize   query   int  true       "每页数据条数"
+// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
+// @Param   KeyWord   query   string  true       "搜索关键词"
+// @Success 200 {object} []*rag.QuestionListListResp
+// @router /question/title/list [get]
+func (c *QuestionController) TitleList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
 		return
 	}
+	pageSize, _ := c.GetInt("PageSize")
+	currentIndex, _ := c.GetInt("CurrentIndex")
+	keyWord := c.GetString("KeyWord")
+
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
 
-	viewList := obj.ListToViewList(list)
+	var total int
+	viewList := make([]rag.QuestionView, 0)
+
+	if keyWord == `` {
+		var condition string
+		var pars []interface{}
+
+		if keyWord != "" {
+			condition += fmt.Sprintf(` AND %s like ?`, rag.QuestionColumns.QuestionContent)
+			pars = append(pars, `%`+keyWord+`%`)
+		}
+		obj := new(rag.Question)
+		tmpTotal, list, err := obj.GetTitlePageListByCondition(condition, pars, startSize, pageSize)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取失败,Err:" + err.Error()
+			return
+		}
+		total = tmpTotal
+
+		if list != nil && len(list) > 0 {
+			viewList = list[0].ListToViewList(list)
+		}
+	} else {
+		sortMap := map[string]string{
+			//"ArticleCreateTime": "desc",
+			//"WechatArticleId":   "desc",
+		}
+		tmpTotal, list, err := elastic.RagQuestionEsSearch(keyWord, startSize, pageSize, sortMap)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取失败,Err:" + err.Error()
+			return
+		}
+		total = int(tmpTotal)
+		if list != nil && len(list) > 0 {
+			viewList = list[0].ToViewList(list)
+		}
+	}
 
 	page := paging.GetPaging(currentIndex, pageSize, total)
 	resp := response.QuestionListListResp{
@@ -84,6 +194,47 @@ func (c *QuestionController) List() {
 	br.Data = resp
 }
 
+// Detail
+// @Title 列表
+// @Description 列表
+// @Param   QuestionId   query   int  true       "问题id"
+// @Success 200 {object} []*rag.QuestionListListResp
+// @router /question/detail [get]
+func (c *QuestionController) Detail() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		return
+	}
+	questionId, _ := c.GetInt("QuestionId")
+	if questionId <= 0 {
+		br.Msg = "问题id不能为空"
+		br.ErrMsg = "问题id不能为空"
+		return
+	}
+
+	obj := new(rag.Question)
+	questionItem, err := obj.GetByID(questionId)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+
+	br.Data = questionItem.ToView()
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
 // Add
 // @Title 新增问题
 // @Description 新增问题
@@ -109,16 +260,18 @@ func (c *QuestionController) Add() {
 		br.IsSendEmail = false
 		return
 	}
-	obj := rag.Question{}
-	_, err = obj.GetByCondition(` AND question_content = ? `, []interface{}{req.Content})
-	if err == nil {
-		br.Msg = "问题已入库,请不要重复添加"
-		br.IsSendEmail = false
-		return
-	}
+	//obj := rag.Question{}
+	//_, err = obj.GetByCondition(` AND question_content = ? `, []interface{}{req.Content})
+	//if err == nil {
+	//	br.Msg = "问题已入库,请不要重复添加"
+	//	br.IsSendEmail = false
+	//	return
+	//}
 
+	title := utils.GetFirstNChars(req.Content, 20)
 	item := &rag.Question{
 		QuestionId:      0,
+		QuestionTitle:   title,
 		QuestionContent: req.Content,
 		Sort:            0,
 		ModifyTime:      time.Now(),
@@ -131,6 +284,9 @@ func (c *QuestionController) Add() {
 		return
 	}
 
+	// 新增/编辑ES数据
+	go services.AddOrEditEsRagQuestion(item.QuestionId)
+
 	br.Ret = 200
 	br.Success = true
 	br.Msg = `添加成功`
@@ -178,9 +334,10 @@ func (c *QuestionController) Edit() {
 		}
 		return
 	}
+	item.QuestionTitle = utils.GetFirstNChars(req.Content, 20)
 	item.QuestionContent = req.Content
 	item.ModifyTime = time.Now()
-	err = item.Update([]string{"question_content", "modify_time"})
+	err = item.Update([]string{"question_title", "question_content", "modify_time"})
 	if err != nil {
 		br.Msg = "修改失败"
 		br.ErrMsg = "修改失败,Err:" + err.Error()
@@ -235,7 +392,25 @@ func (c *QuestionController) Del() {
 		return
 	}
 
+	// 删除ES数据
+	go services.DelEsRagQuestion(item.QuestionId)
+
 	br.Ret = 200
 	br.Success = true
 	br.Msg = `删除成功`
 }
+
+//func init() {
+//	// 问题加到es
+//	{
+//		obj := rag.Question{}
+//		list, _ := obj.GetListByCondition(``, ` `, []interface{}{}, 0, 10000)
+//		total := len(list)
+//		for k, item := range list {
+//			fmt.Println(k, "/", total)
+//			services.AddOrEditEsRagQuestion(item.QuestionId)
+//		}
+//
+//		fmt.Println("结束了")
+//	}
+//}

+ 4 - 0
models/business_conf.go

@@ -64,6 +64,7 @@ const (
 	KnowledgeArticleName                     = "KnowledgeArticleName"             // 原文库
 	BusinessConfEsWechatArticle              = "EsIndexNameWechatArticle"         // ES索引名称-微信文章
 	BusinessConfEsWechatArticleAbstract      = "EsIndexNameWechatArticleAbstract" // ES索引名称-微信文章摘要
+	BusinessConfEsRagQuestion                = "EsIndexNameRagQuestion"           // ES索引名称-知识库问题
 	BusinessConfIsOpenChartExpired           = "IsOpenChartExpired"               // 是否开启图表有效期鉴权/报告禁止复制
 	BusinessConfReportChartExpiredTime       = "ReportChartExpiredTime"           // 图表有效期鉴权时间,单位:分钟
 	BusinessConfOssUrlReplace                = "OssUrlReplace"                    // OSS地址替换-兼容内网客户用
@@ -278,6 +279,9 @@ func InitBusinessConf() {
 	if BusinessConfMap[BusinessConfEsWechatArticleAbstract] != "" {
 		utils.EsWechatArticleAbstractName = BusinessConfMap[BusinessConfEsWechatArticleAbstract]
 	}
+	if BusinessConfMap[BusinessConfEsRagQuestion] != "" {
+		utils.EsRagQuestionName = BusinessConfMap[BusinessConfEsRagQuestion]
+	}
 	confStr := BusinessConfMap[LLMInitConfig]
 	if confStr != "" {
 		var config LLMConfig

+ 31 - 5
models/rag/question.go

@@ -10,8 +10,11 @@ import (
 
 type Question struct {
 	QuestionId      int       `gorm:"column:question_id;type:int(9) UNSIGNED;primaryKey;not null;" description:"question_id"`
+	QuestionTitle   string    `gorm:"column:question_title;type:varchar(255);comment:问题标题;" description:"问题标题"`
 	QuestionContent string    `gorm:"column:question_content;type:varchar(255);comment:问题内容;" description:"问题内容"`
 	Sort            int       `gorm:"column:sort;type:int(11);comment:排序;default:0;" description:"排序"`
+	SysUserId       int       `gorm:"column:sys_user_id;type:int(11);comment:添加人id;default:0;" description:"添加人id"`
+	SysUserRealName string    `gorm:"column:sys_user_real_name;type:varchar(255);comment:添加人真实名称;" description:"添加人真实名称"`
 	ModifyTime      time.Time `gorm:"column:modify_time;type:datetime;default:NULL;" description:"modify_time"`
 	CreateTime      time.Time `gorm:"column:create_time;type:datetime;default:NULL;" description:"create_time"`
 }
@@ -24,12 +27,14 @@ func (m *Question) TableName() string {
 // QuestionColumns get sql column name.获取数据库列名
 var QuestionColumns = struct {
 	QuestionID      string
+	QuestionTitle   string
 	QuestionContent string
 	Sort            string
 	ModifyTime      string
 	CreateTime      string
 }{
 	QuestionID:      "question_id",
+	QuestionTitle:   "question_title",
 	QuestionContent: "question_content",
 	Sort:            "sort",
 	ModifyTime:      "modify_time",
@@ -56,8 +61,11 @@ func (m *Question) Del() (err error) {
 
 type QuestionView struct {
 	QuestionId      int    `gorm:"column:question_id;type:int(9) UNSIGNED;primaryKey;not null;" description:"question_id"`
-	QuestionContent string `gorm:"column:question_content;type:varchar(255);comment:问题内容;" description:"问题内容"` //
-	Sort            int    `gorm:"column:sort;type:int(11);comment:排序;default:0;" description:"sort"`          // 排序
+	QuestionTitle   string `gorm:"column:question_title;type:varchar(255);comment:问题标题;" description:"问题标题"`
+	QuestionContent string `gorm:"column:question_content;type:varchar(255);comment:问题内容;" description:"问题内容"`
+	Sort            int    `gorm:"column:sort;type:int(11);comment:排序;default:0;" description:"排序"`
+	SysUserId       int    `gorm:"column:sys_user_id;type:int(11);comment:添加人id;default:0;" description:"添加人id"`
+	SysUserRealName string `gorm:"column:sys_user_real_name;type:varchar(255);comment:添加人真实名称;" description:"添加人真实名称"`
 	ModifyTime      string `gorm:"column:modify_time;type:datetime;default:NULL;" description:"modify_time"`
 	CreateTime      string `gorm:"column:create_time;type:datetime;default:NULL;" description:"create_time"`
 }
@@ -73,8 +81,11 @@ func (m *Question) ToView() QuestionView {
 	}
 	return QuestionView{
 		QuestionId:      m.QuestionId,
+		QuestionTitle:   m.QuestionTitle,
 		QuestionContent: m.QuestionContent,
 		Sort:            m.Sort,
+		SysUserId:       m.SysUserId,
+		SysUserRealName: m.SysUserRealName,
 		ModifyTime:      modifyTime,
 		CreateTime:      createTime,
 	}
@@ -102,8 +113,11 @@ func (m *Question) GetByCondition(condition string, pars []interface{}) (item *Q
 	return
 }
 
-func (m *Question) GetListByCondition(condition string, pars []interface{}, startSize, pageSize int) (items []*Question, err error) {
-	sqlStr := fmt.Sprintf(`SELECT * FROM %s WHERE 1=1 %s order by question_id desc LIMIT ?,?`, m.TableName(), condition)
+func (m *Question) GetListByCondition(field, condition string, pars []interface{}, startSize, pageSize int) (items []*Question, err error) {
+	if field == "" {
+		field = "*"
+	}
+	sqlStr := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s order by question_id desc LIMIT ?,?`, field, m.TableName(), condition)
 	pars = append(pars, startSize, pageSize)
 	err = global.DbMap[utils.DbNameAI].Raw(sqlStr, pars...).Find(&items).Error
 
@@ -128,7 +142,19 @@ func (m *Question) GetPageListByCondition(condition string, pars []interface{},
 		return
 	}
 	if total > 0 {
-		items, err = m.GetListByCondition(condition, pars, startSize, pageSize)
+		items, err = m.GetListByCondition(``, condition, pars, startSize, pageSize)
+	}
+
+	return
+}
+
+func (m *Question) GetTitlePageListByCondition(condition string, pars []interface{}, startSize, pageSize int) (total int, items []*Question, err error) {
+	total, err = m.GetCountByCondition(condition, pars)
+	if err != nil {
+		return
+	}
+	if total > 0 {
+		items, err = m.GetListByCondition(`question_id,question_title,sort`, condition, pars, startSize, pageSize)
 	}
 
 	return

+ 18 - 0
routers/commentsRouter.go

@@ -8755,6 +8755,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_api/controllers/llm:QuestionController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/llm:QuestionController"],
+        beego.ControllerComments{
+            Method: "Detail",
+            Router: `/question/detail`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_api/controllers/llm:QuestionController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/llm:QuestionController"],
         beego.ControllerComments{
             Method: "Edit",
@@ -8773,6 +8782,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_api/controllers/llm:QuestionController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/llm:QuestionController"],
+        beego.ControllerComments{
+            Method: "TitleList",
+            Router: `/question/title/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_api/controllers/llm:UserChatController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/llm:UserChatController"],
         beego.ControllerComments{
             Method: "ChatRecordList",

+ 288 - 0
services/elastic/rag_question.go

@@ -0,0 +1,288 @@
+package elastic
+
+import (
+	"context"
+	"encoding/json"
+	"eta/eta_api/models/rag"
+	"eta/eta_api/utils"
+	"fmt"
+	"github.com/olivere/elastic/v7"
+	"time"
+)
+
+// 问题索引
+var EsRagQuestionName = utils.EsRagQuestionName
+
+type RagQuestionItem struct {
+	QuestionId      int       `gorm:"column:question_id;type:int(9) UNSIGNED;primaryKey;not null;" description:"question_id"`
+	QuestionTitle   string    `gorm:"column:question_title;type:varchar(255);comment:问题标题;" description:"问题标题"`
+	QuestionContent string    `gorm:"column:question_content;type:varchar(255);comment:问题内容;" description:"问题内容"`
+	Sort            int       `gorm:"column:sort;type:int(11);comment:排序;default:0;" description:"排序"`
+	SysUserId       int       `gorm:"column:sys_user_id;type:int(11);comment:添加人id;default:0;" description:"添加人id"`
+	SysUserRealName string    `gorm:"column:sys_user_real_name;type:varchar(255);comment:添加人真实名称;" description:"添加人真实名称"`
+	ModifyTime      time.Time `gorm:"column:modify_time;type:datetime;default:NULL;" description:"modify_time"`
+	CreateTime      time.Time `gorm:"column:create_time;type:datetime;default:NULL;" description:"create_time"`
+}
+
+func (m *RagQuestionItem) ToView() rag.QuestionView {
+	var modifyTime, createTime string
+
+	if !m.CreateTime.IsZero() {
+		createTime = m.CreateTime.Format(utils.FormatDateTime)
+	}
+	if !m.ModifyTime.IsZero() {
+		modifyTime = m.ModifyTime.Format(utils.FormatDateTime)
+	}
+
+	return rag.QuestionView{
+		QuestionId:      m.QuestionId,
+		QuestionTitle:   m.QuestionTitle,
+		QuestionContent: m.QuestionContent,
+		Sort:            m.Sort,
+		SysUserId:       m.SysUserId,
+		SysUserRealName: m.SysUserRealName,
+		ModifyTime:      modifyTime,
+		CreateTime:      createTime,
+	}
+}
+
+func (m *RagQuestionItem) ToViewList(list []*RagQuestionItem) (wechatArticleViewList []rag.QuestionView) {
+	wechatArticleViewList = make([]rag.QuestionView, 0)
+
+	for _, v := range list {
+		wechatArticleViewList = append(wechatArticleViewList, v.ToView())
+	}
+	return
+}
+
+// RagQuestionEsAddOrEdit
+// @Description: 新增/编辑微信文章
+// @author: Roc
+// @datetime 2025-03-13 10:24:05
+// @param docId string
+// @param item WechatArticleAndPlatform
+// @return err error
+func RagQuestionEsAddOrEdit(docId string, item RagQuestionItem) (err error) {
+	if docId == "" {
+		return
+	}
+	if EsRagQuestionName == `` {
+		return
+	}
+	defer func() {
+		if err != nil {
+			fmt.Println("WechatArticleEsAddOrEdit Err:", err.Error())
+		}
+	}()
+	client := utils.EsClient
+
+	resp, err := client.Index().Index(EsRagQuestionName).Id(docId).BodyJson(item).Refresh("true").Do(context.Background())
+	if err != nil {
+		fmt.Println("新增失败:", err.Error())
+		return err
+	}
+	if resp.Status == 0 {
+		fmt.Println("新增成功", resp.Result)
+		err = nil
+	} else {
+		fmt.Println("WechatArticleEsAddOrEdit", resp.Status, resp.Result)
+	}
+
+	return
+}
+
+// WechatArticleEsDel
+// @Description: 删除微信文章
+// @author: Roc
+// @datetime 2025-03-13 10:23:55
+// @param docId string
+// @return err error
+func RagQuestionEsDel(docId string) (err error) {
+	if docId == "" {
+		return
+	}
+	if EsRagQuestionName == `` {
+		return
+	}
+	defer func() {
+		if err != nil {
+			fmt.Println("EsDeleteEdbInfoData Err:", err.Error())
+		}
+	}()
+	client := utils.EsClient
+
+	resp, err := client.Delete().Index(EsRagQuestionName).Id(docId).Refresh(`true`).Do(context.Background())
+	if err != nil {
+		return
+	}
+	if resp.Status == 0 {
+		fmt.Println("删除成功")
+	} else {
+		fmt.Println("WechatArticleEsDel", resp.Status, resp.Result)
+	}
+
+	return
+}
+
+// RagQuestionEsSearch
+// @Description: 搜索
+// @author: Roc
+// @datetime 2025-03-13 19:54:54
+// @param keywordStr string
+// @param tagIdList []int
+// @param platformIdList []int
+// @param from int
+// @param size int
+// @param sortMap map[string]string
+// @return total int64
+// @return list []*RagQuestionItem
+// @return err error
+func RagQuestionEsSearch(keywordStr string, from, size int, sortMap map[string]string) (total int64, list []*RagQuestionItem, err error) {
+	indexName := EsRagQuestionName
+	list = make([]*RagQuestionItem, 0)
+	defer func() {
+		if err != nil {
+			fmt.Println("SearchEdbInfoData Err:", err.Error())
+		}
+	}()
+
+	query := elastic.NewBoolQuery()
+
+	// 名字匹配
+	if keywordStr != `` {
+		query = query.Must(elastic.NewMultiMatchQuery(keywordStr, "QuestionContent"))
+	}
+
+	// 排序
+	sortList := make([]*elastic.FieldSort, 0)
+	// 如果没有关键字,那么就走指标id倒序
+
+	for orderKey, orderType := range sortMap {
+		switch orderType {
+		case "asc":
+			sortList = append(sortList, elastic.NewFieldSort(orderKey).Asc())
+		case "desc":
+			sortList = append(sortList, elastic.NewFieldSort(orderKey).Desc())
+
+		}
+
+	}
+
+	return searchRagQuestion(indexName, query, sortList, from, size)
+}
+
+// searchRagQuestion 查询es中的数据
+func searchRagQuestion(indexName string, query elastic.Query, sortList []*elastic.FieldSort, from, size int) (total int64, list []*RagQuestionItem, err error) {
+	total, err = searchRagQuestionTotal(indexName, query)
+	if err != nil {
+		return
+	}
+
+	// 获取列表数据
+	list, err = searchRagQuestionList(indexName, query, sortList, from, size)
+	if err != nil {
+		return
+	}
+
+	return
+}
+
+// searchEdbInfoDataTotal
+// @Description: 查询es中的数量
+// @author: Roc
+// @datetime 2024-12-23 11:19:04
+// @param indexName string
+// @param query elastic.Query
+// @return total int64
+// @return err error
+func searchRagQuestionTotal(indexName string, query elastic.Query) (total int64, err error) {
+	defer func() {
+		if err != nil {
+			fmt.Println("searchEdbInfoDataTotal Err:", err.Error())
+		}
+	}()
+	client := utils.EsClient
+
+	//根据条件数量统计
+	requestTotalHits := client.Count(indexName).Query(query)
+	total, err = requestTotalHits.Do(context.Background())
+	if err != nil {
+		return
+	}
+
+	return
+}
+
+// searchEdbInfoDataList
+// @Description: 查询es中的明细数据
+// @author: Roc
+// @datetime 2024-12-23 11:18:48
+// @param indexName string
+// @param query elastic.Query
+// @param sortList []*elastic.FieldSort
+// @param from int
+// @param size int
+// @return list []*data_manage.EdbInfoList
+// @return err error
+func searchRagQuestionList(indexName string, query elastic.Query, sortList []*elastic.FieldSort, from, size int) (list []*RagQuestionItem, err error) {
+	list = make([]*RagQuestionItem, 0)
+	defer func() {
+		if err != nil {
+			fmt.Println("searchEdbInfoDataList Err:", err.Error())
+		}
+	}()
+	client := utils.EsClient
+	// 高亮
+	highlight := elastic.NewHighlight()
+	highlight = highlight.Fields(elastic.NewHighlighterField("Content"))
+	highlight = highlight.PreTags("<font color='red'>").PostTags("</font>")
+
+	//request := client.Search(indexName).Highlight(highlight).From(from).Size(size) // sets the JSON request
+	request := client.Search(indexName).From(from).Size(size) // sets the JSON request
+
+	// 如果有指定排序,那么就按照排序来
+	if len(sortList) > 0 {
+		for _, v := range sortList {
+			request = request.SortBy(v)
+		}
+	}
+
+	searchMap := make(map[string]string)
+
+	searchResp, err := request.Query(query).Do(context.Background())
+	if err != nil {
+		return
+	}
+	//fmt.Println(searchResp)
+	//fmt.Println(searchResp.Status)
+	if searchResp.Status != 0 {
+		return
+	}
+	//total = searchResp.TotalHits()
+	if searchResp.Hits != nil {
+		for _, v := range searchResp.Hits.Hits {
+			if _, ok := searchMap[v.Id]; !ok {
+				itemJson, tmpErr := v.Source.MarshalJSON()
+				if tmpErr != nil {
+					err = tmpErr
+					fmt.Println("movieJson err:", err)
+					return
+				}
+				item := new(RagQuestionItem)
+				tmpErr = json.Unmarshal(itemJson, &item)
+				if tmpErr != nil {
+					fmt.Println("json.Unmarshal movieJson err:", tmpErr)
+					err = tmpErr
+					return
+				}
+				if len(v.Highlight["QuestionContent"]) > 0 {
+					item.QuestionContent = v.Highlight["QuestionContent"][0]
+				}
+				list = append(list, item)
+				searchMap[v.Id] = v.Id
+			}
+		}
+	}
+
+	return
+}

+ 62 - 3
services/wechat_platform.go

@@ -534,7 +534,7 @@ func getAnswerByContent(wechatArticleId int, docId string) (answer string, addAr
 	addArticleChatRecordList = make([]*rag.WechatArticleChatRecord, 0)
 
 	questionObj := rag.Question{}
-	questionList, err := questionObj.GetListByCondition(``, []interface{}{}, 0, 100)
+	questionList, err := questionObj.GetListByCondition(``, ``, []interface{}{}, 0, 100)
 	if err != nil {
 		err = fmt.Errorf("获取问题列表失败,Err:" + err.Error())
 		return
@@ -1014,8 +1014,8 @@ func AddOrEditEsWechatArticleAbstract(articleAbstractId int) {
 	err = elastic.WechatArticleAbstractEsAddOrEdit(strconv.Itoa(articleAbstractId), esItem)
 }
 
-// AddOrEditEsWechatArticleAbstract
-// @Description: 新增/编辑微信文章摘要入ES
+// DelEsWechatArticleAbstract
+// @Description: 删除ES中的微信文章摘要
 // @author: Roc
 // @datetime 2025-03-13 14:13:47
 // @param articleAbstractId int
@@ -1034,3 +1034,62 @@ func DelEsWechatArticleAbstract(articleAbstractId int) {
 
 	err = elastic.WechatArticleAbstractEsDel(strconv.Itoa(articleAbstractId))
 }
+
+// AddOrEditEsRagQuestion
+// @Description: 新增/编辑知识库问题入ES
+// @author: Roc
+// @datetime 2025-03-28 11:25:50
+// @param questionId int
+func AddOrEditEsRagQuestion(questionId int) {
+	if utils.EsWechatArticleName == `` {
+		return
+	}
+
+	var err error
+	defer func() {
+		if err != nil {
+			utils.FileLog.Error("添加公众号微信信息到ES失败,err:%v", err)
+			fmt.Println("添加公众号微信信息到ES失败,err:", err)
+		}
+	}()
+	obj := rag.Question{}
+	questionInfo, err := obj.GetByID(questionId)
+	if err != nil {
+		err = fmt.Errorf("获取公众号文章信息失败,Err:" + err.Error())
+		return
+	}
+
+	esItem := elastic.RagQuestionItem{
+		QuestionId:      questionInfo.QuestionId,
+		QuestionTitle:   questionInfo.QuestionTitle,
+		QuestionContent: questionInfo.QuestionContent,
+		Sort:            questionInfo.Sort,
+		SysUserId:       questionInfo.SysUserId,
+		SysUserRealName: questionInfo.SysUserRealName,
+		ModifyTime:      questionInfo.ModifyTime,
+		CreateTime:      questionInfo.CreateTime,
+	}
+
+	err = elastic.RagQuestionEsAddOrEdit(strconv.Itoa(questionInfo.QuestionId), esItem)
+}
+
+// DelEsRagQuestion
+// @Description: 删除ES中的知识库问题
+// @author: Roc
+// @datetime 2025-03-28 11:26:40
+// @param questionId int
+func DelEsRagQuestion(questionId int) {
+	if utils.EsWechatArticleAbstractName == `` {
+		return
+	}
+
+	var err error
+	defer func() {
+		if err != nil {
+			utils.FileLog.Error("添加公众号微信信息到ES失败,err:%v", err)
+			fmt.Println("添加公众号微信信息到ES失败,err:", err)
+		}
+	}()
+
+	err = elastic.RagQuestionEsDel(strconv.Itoa(questionId))
+}

+ 17 - 1
utils/common.go

@@ -1869,7 +1869,7 @@ func GetDateByDateTypeV2(dateType int, tmpStartDate, tmpEndDate string, startYea
 			startDate = startDate + "-01"
 		}
 		if strings.Count(endDate, "-") == 1 {
-			endTime, err := time.ParseInLocation(FormatYearMonthDate, endDate,time.Local)
+			endTime, err := time.ParseInLocation(FormatYearMonthDate, endDate, time.Local)
 			if err != nil {
 				return
 			}
@@ -3095,3 +3095,19 @@ func RemoveSpecialChars(text string) string {
 	reg := regexp.MustCompile(`[^\p{Han}\p{L}\p{N}\x{3000}-\x{303F}]`)
 	return reg.ReplaceAllString(text, "")
 }
+
+// GetFirstNChars
+// @Description: 截取字符串的前N个字符
+// @author: Roc
+// @datetime 2025-03-28 10:17:23
+// @param s string
+// @param max int
+// @return string
+func GetFirstNChars(s string, max int) string {
+	s = strings.NewReplacer("\r", "", "\n", "").Replace(strings.TrimSpace(s))
+	runes := []rune(s)
+	if len(runes) < max {
+		max = len(runes)
+	}
+	return string(runes[:max])
+}

+ 1 - 0
utils/config.go

@@ -148,6 +148,7 @@ var (
 	EsDataSourceIndexName          string // 数据源ES索引名称
 	EsWechatArticleName            string // ES索引名称-微信文章
 	EsWechatArticleAbstractName    string // ES索引名称-微信文章摘要
+	EsRagQuestionName              string // ES索引名称-知识库问题
 )
 
 var (