package llm import ( "encoding/json" "eta/eta_api/controllers" "eta/eta_api/models" "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" "strings" "time" ) // QuestionController // @Description: 提示词库管理 type QuestionController struct { controllers.BaseAuthController } // List // @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/list [get] func (c *QuestionController) List() { 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) 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.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) } } 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) 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{ List: viewList, Paging: page, } br.Ret = 200 br.Success = true br.Msg = "获取成功" 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 新增提示词 // @Param request body request.AddQuestionReq true "type json string" // @Success 200 Ret=200 新增成功 // @router /question/add [post] func (c *QuestionController) Add() { br := new(models.BaseResponse).Init() defer func() { c.Data["json"] = br c.ServeJSON() }() var req request.AddQuestionReq err := json.Unmarshal(c.Ctx.Input.RequestBody, &req) if err != nil { br.Msg = "参数解析异常!" br.ErrMsg = "参数解析失败,Err:" + err.Error() return } req.Content = strings.TrimSpace(req.Content) if req.Content == "" { 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(), CreateTime: time.Now(), } err = item.Create() if err != nil { br.Msg = "添加失败" br.ErrMsg = "添加失败,Err:" + err.Error() return } // 新增/编辑ES数据 go services.AddOrEditEsRagQuestion(item.QuestionId) br.Ret = 200 br.Success = true br.Msg = `添加成功` } // Edit // @Title 编辑提示词 // @Description 编辑提示词 // @Param request body request.EditQuestionReq true "type json string" // @Success 200 Ret=200 新增成功 // @router /question/edit [post] func (c *QuestionController) Edit() { br := new(models.BaseResponse).Init() defer func() { c.Data["json"] = br c.ServeJSON() }() var req request.EditQuestionReq err := json.Unmarshal(c.Ctx.Input.RequestBody, &req) if err != nil { br.Msg = "参数解析异常!" br.ErrMsg = "参数解析失败,Err:" + err.Error() return } if req.QuestionId <= 0 { br.Msg = "提示词id不能为空" br.IsSendEmail = false return } req.Content = strings.TrimSpace(req.Content) if req.Content == "" { br.Msg = "请输入提示词" br.IsSendEmail = false return } obj := rag.Question{} item, err := obj.GetByID(req.QuestionId) if err != nil { br.Msg = "修改失败" br.ErrMsg = "修改失败,查找提示词失败,Err:" + err.Error() if utils.IsErrNoRow(err) { br.Msg = "提示词不存在" br.IsSendEmail = false } return } // 编辑提示词: if item.IsDefault == 1 { total, err := services.GetNotFinishGenerateAbstractTaskNumByQuestionId(item.QuestionId) if err != nil { br.Msg = "修改失败" br.ErrMsg = "权限校验失败,Err:" + err.Error() return } if total > 0 { br.Msg = "当前提示词正在生成摘要,请稍后再修改" return } } // 添加问题的历史记录 rag.AddQuestionHistoryByQuestion(item) item.QuestionTitle = utils.GetFirstNChars(req.Content, 20) item.QuestionContent = req.Content item.Version++ item.GenerateStatus = `undo` item.ModifyTime = time.Now() err = item.Update([]string{"question_title", "question_content", `version`, `generate_status`, "modify_time"}) if err != nil { br.Msg = "修改失败" br.ErrMsg = "修改失败,Err:" + err.Error() return } // 新增/编辑ES数据 go services.AddOrEditEsRagQuestion(item.QuestionId) br.Ret = 200 br.Success = true br.Msg = `修改成功` } // Del // @Title 删除提示词 // @Description 删除提示词 // @Param request body request.EditQuestionReq true "type json string" // @Success 200 Ret=200 新增成功 // @router /question/del [post] func (c *QuestionController) Del() { br := new(models.BaseResponse).Init() defer func() { c.Data["json"] = br c.ServeJSON() }() var req request.EditQuestionReq err := json.Unmarshal(c.Ctx.Input.RequestBody, &req) if err != nil { br.Msg = "参数解析异常!" br.ErrMsg = "参数解析失败,Err:" + err.Error() return } if req.QuestionId <= 0 { br.Msg = "提示词id不能为空" br.IsSendEmail = false return } obj := rag.Question{} item, err := obj.GetByID(req.QuestionId) if err != nil { br.Msg = "修改失败" br.ErrMsg = "修改失败,查找提示词失败,Err:" + err.Error() if utils.IsErrNoRow(err) { br.Msg = "提示词不存在" br.IsSendEmail = false } return } // 删除提示词:若删除默认提示词,提示:当前提示词不允许删除;若删除非默认提示词:提示删除成功(项目eta4.0,时间:2025-4-16 17:39:38) if item.IsDefault == 1 { br.Msg = "当前提示词不允许删除!" return } // 添加问题的历史记录 rag.AddQuestionHistoryByQuestion(item) err = item.Del() if err != nil { br.Msg = "删除失败" br.ErrMsg = "删除失败,Err:" + err.Error() return } // 删除ES数据 go services.DelEsRagQuestion(item.QuestionId) br.Ret = 200 br.Success = true br.Msg = `删除成功` } // SetDefault // @Title 设置默认提示词 // @Description 设置默认提示词 // @Param request body request.EditQuestionReq true "type json string" // @Success 200 Ret=200 设置成功 // @router /question/default/set [post] func (c *QuestionController) SetDefault() { br := new(models.BaseResponse).Init() defer func() { c.Data["json"] = br c.ServeJSON() }() var req request.EditQuestionReq err := json.Unmarshal(c.Ctx.Input.RequestBody, &req) if err != nil { br.Msg = "参数解析异常!" br.ErrMsg = "参数解析失败,Err:" + err.Error() return } if req.QuestionId <= 0 { br.Msg = "提示词id不能为空" br.IsSendEmail = false return } obj := rag.Question{} item, err := obj.GetByID(req.QuestionId) if err != nil { br.Msg = "修改失败" br.ErrMsg = "修改失败,查找提示词失败,Err:" + err.Error() if utils.IsErrNoRow(err) { br.Msg = "提示词不存在" br.IsSendEmail = false } return } if item.IsDefault == 1 { br.Msg = "该提示词已经是默认提示词,无需设置" br.IsSendEmail = false return } item.IsDefault = 1 item.GenerateStatus = `undo` item.ModifyTime = time.Now() err = item.Update([]string{"is_default", "generate_status", "modify_time"}) if err != nil { br.Msg = "设置失败" br.ErrMsg = "设置失败,Err:" + err.Error() return } br.Ret = 200 br.Success = true br.Msg = `设置成功` } // UnSetDefault // @Title 取消设置默认提示词 // @Description 取消设置默认提示词 // @Param request body request.EditQuestionReq true "type json string" // @Success 200 Ret=200 设置成功 // @router /question/default/unset [post] func (c *QuestionController) UnSetDefault() { br := new(models.BaseResponse).Init() defer func() { c.Data["json"] = br c.ServeJSON() }() var req request.EditQuestionReq err := json.Unmarshal(c.Ctx.Input.RequestBody, &req) if err != nil { br.Msg = "参数解析异常!" br.ErrMsg = "参数解析失败,Err:" + err.Error() return } if req.QuestionId <= 0 { br.Msg = "提示词id不能为空" br.IsSendEmail = false return } obj := rag.Question{} item, err := obj.GetByID(req.QuestionId) if err != nil { br.Msg = "修改失败" br.ErrMsg = "修改失败,查找提示词失败,Err:" + err.Error() if utils.IsErrNoRow(err) { br.Msg = "提示词不存在" br.IsSendEmail = false } return } if item.IsDefault == 0 { br.Msg = "该提示词不是默认提示词,无需取消" br.IsSendEmail = false return } // 如果是取消已经设置成默认的提示词,那么需要判断是否有正在生成摘要的提示词任务,如果存在的话,那么就不允许取消 auth, err := services.CheckOpQuestionAuth() if err != nil { br.Msg = "修改失败" br.ErrMsg = "权限校验失败,Err:" + err.Error() return } if !auth { br.Msg = "当前有提示词正在生成摘要,请稍后再修改" return } item.IsDefault = 1 item.GenerateStatus = `undo` item.ModifyTime = time.Now() err = item.Update([]string{"is_default", "generate_status", "modify_time"}) if err != nil { br.Msg = "取消设置失败" br.ErrMsg = "取消设置失败,Err:" + err.Error() return } // todo 对应的提示词生成的摘要库和向量库内容也取消,同时需要加锁,不允许重复操作 br.Ret = 200 br.Success = true br.Msg = `取消设置成功` } // GenerateAbstract // @Title 生成摘要 // @Description 生成摘要 // @Param request body request.EditQuestionReq true "type json string" // @Success 200 Ret=200 设置成功 // @router /question/abstract/generate [post] func (c *QuestionController) GenerateAbstract() { br := new(models.BaseResponse).Init() defer func() { c.Data["json"] = br c.ServeJSON() }() var req request.EditQuestionReq err := json.Unmarshal(c.Ctx.Input.RequestBody, &req) if err != nil { br.Msg = "参数解析异常!" br.ErrMsg = "参数解析失败,Err:" + err.Error() return } if req.QuestionId <= 0 { br.Msg = "提示词id不能为空" br.IsSendEmail = false return } obj := rag.Question{} item, err := obj.GetByID(req.QuestionId) if err != nil { br.Msg = "修改失败" br.ErrMsg = "修改失败,查找提示词失败,Err:" + err.Error() if utils.IsErrNoRow(err) { br.Msg = "提示词不存在" br.IsSendEmail = false } return } if item.IsDefault != 1 { br.Msg = "该提示词不是默认提示词,不允许生成" br.IsSendEmail = false return } if item.GenerateStatus != `undo` { br.Msg = "该提示词已经生成过摘要,不允许重复生成" br.IsSendEmail = false return } // 如果是需要对提示词做摘要的生成,那么需要判断是否有正在生成摘要的提示词任务,如果存在的话,那么就不允许生成(暂定,后面可以改成加到任务中去,等上一个批次的任务完成后,继续该任务) auth, err := services.CheckOpQuestionAuth() if err != nil { br.Msg = "修改失败" br.ErrMsg = "权限校验失败,Err:" + err.Error() return } if !auth { br.Msg = "当前有提示词正在生成摘要,请稍后再重新生成" return } // 标记摘要生成状态,避免重复生成 item.GenerateStatus = `done` item.ModifyTime = time.Now() err = item.Update([]string{"generate_status", "modify_time"}) if err != nil { br.Msg = "取消设置失败" br.ErrMsg = "取消设置失败,Err:" + err.Error() return } // 添加任务 services.AddGenerateAbstractTask(item, c.SysUser) // todo 开始任务 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("结束了") // } //}