This commit is contained in:
2026-03-14 10:02:49 +08:00
parent 03b50ef904
commit 830f75a334
75 changed files with 10677 additions and 2 deletions

View File

@@ -0,0 +1,211 @@
// Package service - RAGFlow配置服务
// 功能管理ragflow_config表对话配置chatId、提示词、知识库映射datasetId
package service
import (
"context"
"customer-server/dao"
"customer-server/model/dto"
"gitea.com/red-future/common/ragflow"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/text/gstr"
)
var RAGFlowConfig = new(ragflowConfig)
type ragflowConfig struct{}
// Get 获取RAGFlow配置配置不存在时自动重建
// 参数: ctx - 上下文req - 查询请求(包含客服账号名)
// 返回: res - RAGFlow配置信息提示词、参数等err - 错误信息
// 功能: 查询客服账号的RAGFlow对话配置不存在时自动重建
func (s *ragflowConfig) Get(ctx context.Context, req *dto.GetRAGFlowConfigReq) (res *dto.GetRAGFlowConfigRes, err error) {
config, err := dao.RAGFlowConfig.FindByAccountName(ctx, req.AccountName)
if err != nil {
return nil, gerror.Wrap(err, "查询RAGFlow配置失败")
}
// 配置不存在,尝试自动重建
if config == nil {
g.Log().Warningf(ctx, "客服账号 %s 的RAGFlow配置不存在尝试自动重建...", req.AccountName)
// 查询客服账号获取platform
account, findErr := dao.CustomerServiceAccount.FindByAccountName(ctx, req.AccountName)
if findErr != nil {
return nil, gerror.Wrapf(findErr, "查询客服账号失败")
}
if account == nil {
return nil, gerror.Newf("客服账号 %s 不存在无法自动创建RAGFlow配置", req.AccountName)
}
// 调用重建逻辑
recreateReq := &dto.RecreateRAGFlowConfigReq{
AccountName: req.AccountName,
Platform: account.Platform,
}
if recreateErr := CustomerServiceAccount.RecreateRAGFlowConfig(ctx, recreateReq); recreateErr != nil {
return nil, gerror.Wrapf(recreateErr, "自动重建RAGFlow配置失败")
}
// 重新查询配置
config, err = dao.RAGFlowConfig.FindByAccountName(ctx, req.AccountName)
if err != nil {
return nil, gerror.Wrap(err, "重建后查询配置失败")
}
if config == nil {
return nil, gerror.New("重建后仍无法获取配置")
}
g.Log().Infof(ctx, "成功自动重建客服账号 %s 的RAGFlow配置", req.AccountName)
}
// 返回给前端时去掉自动追加的知识库部分,只显示用户的业务话术
userPrompt := config.Prompt
knowledgePart := "\n\n以下是知识库\n{knowledge}\n以上是知识库。"
if gstr.Contains(userPrompt, knowledgePart) {
userPrompt = gstr.Replace(userPrompt, knowledgePart, "")
}
res = &dto.GetRAGFlowConfigRes{
AccountName: config.AccountName,
Platform: config.Platform,
DatasetId: config.DatasetId,
DatasetName: config.DatasetName,
ChatId: config.ChatId,
Prompt: userPrompt, // 只返回用户部分
DocumentIds: config.DocumentIds,
SimilarityThreshold: config.SimilarityThreshold,
KeywordsSimilarityWeight: config.KeywordsSimilarityWeight,
TopN: config.TopN,
EmptyResponse: config.EmptyResponse,
}
return
}
// UpdatePrompt 更新提示词(配置不存在时自动重建)
// 参数: ctx - 上下文req - 更新提示词请求(包含客服账号名和新提示词)
// 返回: res - 更新结果信息err - 错误信息
// 功能: 更新RAGFlow对话的系统提示词并同步到RAGFlow影响AI回复风格
func (s *ragflowConfig) UpdatePrompt(ctx context.Context, req *dto.UpdatePromptReq) (res *dto.UpdatePromptRes, err error) {
// 1. 查询当前配置
config, err := dao.RAGFlowConfig.FindByAccountName(ctx, req.AccountName)
if err != nil {
return nil, gerror.Wrap(err, "查询RAGFlow配置失败")
}
// 配置不存在,尝试自动重建
if config == nil {
g.Log().Warningf(ctx, "客服账号 %s 的RAGFlow配置不存在尝试自动重建...", req.AccountName)
// 查询客服账号获取platform
account, findErr := dao.CustomerServiceAccount.FindByAccountName(ctx, req.AccountName)
if findErr != nil {
return nil, gerror.Wrapf(findErr, "查询客服账号失败")
}
if account == nil {
return nil, gerror.Newf("客服账号 %s 不存在无法自动创建RAGFlow配置", req.AccountName)
}
// 调用重建逻辑
recreateReq := &dto.RecreateRAGFlowConfigReq{
AccountName: req.AccountName,
Platform: account.Platform,
}
if recreateErr := CustomerServiceAccount.RecreateRAGFlowConfig(ctx, recreateReq); recreateErr != nil {
return nil, gerror.Wrapf(recreateErr, "自动重建RAGFlow配置失败")
}
// 重新查询配置
config, err = dao.RAGFlowConfig.FindByAccountName(ctx, req.AccountName)
if err != nil {
return nil, gerror.Wrap(err, "重建后查询配置失败")
}
if config == nil {
return nil, gerror.New("重建后仍无法获取配置")
}
g.Log().Infof(ctx, "成功自动重建客服账号 %s 的RAGFlow配置", req.AccountName)
}
// 2. 更新字段并自动追加知识库引用
// 用户只需输入业务话术,后端自动在末尾追加标准的知识库引用格式
userPrompt := req.Prompt
// 先移除所有可能的知识库引用部分使用查找并截断方式与List方法保持一致
knowledgePatterns := []string{
"\n\n以下是知识库",
"\n\n以下是知识库",
"\n以下是知识库",
"\n以下是知识库",
}
// 找到最早出现的知识库引用位置并截断
for _, pattern := range knowledgePatterns {
if idx := gstr.Pos(userPrompt, pattern); idx >= 0 {
userPrompt = gstr.SubStr(userPrompt, 0, idx)
break
}
}
// 去除末尾多余的空行
userPrompt = gstr.TrimRight(userPrompt)
// 统一追加标准的知识库引用格式
userPrompt = userPrompt + "\n\n以下是知识库\n{knowledge}\n以上是知识库。"
config.Prompt = userPrompt
if req.SimilarityThreshold != nil {
config.SimilarityThreshold = *req.SimilarityThreshold
}
if req.KeywordsSimilarityWeight != nil {
config.KeywordsSimilarityWeight = *req.KeywordsSimilarityWeight
}
if req.TopN != nil {
config.TopN = *req.TopN
}
if req.EmptyResponse != nil {
config.EmptyResponse = *req.EmptyResponse
}
now := gtime.Now().Time
config.UpdatedAt = &now // 取地址赋值给指针类型
// 3. 调用RAGFlow API更新Chat配置
ragflowClient := ragflow.GetGlobalClient()
updateReq := &ragflow.UpdateChatReq{
Prompt: &ragflow.PromptConfig{
Prompt: config.Prompt,
SimilarityThreshold: config.SimilarityThreshold,
KeywordsSimilarityWeight: config.KeywordsSimilarityWeight,
TopN: config.TopN,
EmptyResponse: config.EmptyResponse,
Variables: []map[string]interface{}{
{
"key": "knowledge",
"optional": true,
},
},
},
DatasetIds: []string{config.DatasetId},
}
if err := ragflowClient.UpdateChat(ctx, config.ChatId, updateReq); err != nil {
return nil, gerror.Wrapf(err, "调用RAGFlow API更新Chat失败")
}
// 4. 更新MongoDB
if err := dao.RAGFlowConfig.UpdateEntity(ctx, config); err != nil {
return nil, gerror.Wrap(err, "更新MongoDB配置失败")
}
g.Log().Infof(ctx, "RAGFlow配置更新成功: account_name=%s, chat_id=%s",
config.AccountName, config.ChatId)
res = &dto.UpdatePromptRes{
Success: true,
Message: "提示词更新成功",
}
return
}