refactor: 重构advice模块并优化对话功能

This commit is contained in:
renzhiyuan 2026-02-08 16:34:41 +08:00
parent 46049475c1
commit 9590721d30
26 changed files with 794 additions and 110 deletions

File diff suppressed because one or more lines are too long

View File

@ -35,10 +35,10 @@ func NewAdviceAdvicerBiz(
} }
} }
func (a *AdviceAdvicerBiz) Update(ctx context.Context, data *entitys.AdvicerInitReq) error { func (a *AdviceAdvicerBiz) Update(ctx context.Context, data *entitys.AdvicerInitReq) (int32, error) {
birth, err := time.Parse("2006-01-02", data.Birth) birth, err := time.Parse("2006-01-02", data.Birth)
if err != nil { if err != nil {
return err return 0, err
} }
param := &model.AiAdviceAdvicer{ param := &model.AiAdviceAdvicer{
AdvicerID: data.AdvicerID, AdvicerID: data.AdvicerID,
@ -49,13 +49,13 @@ func (a *AdviceAdvicerBiz) Update(ctx context.Context, data *entitys.AdvicerInit
WorkingYears: data.WorkingYears, WorkingYears: data.WorkingYears,
} }
if param.AdvicerID == 0 { if param.AdvicerID == 0 {
_, err = a.advicerImpl.Add(param) err = a.advicerImpl.AddWithData(param)
} else { } else {
cond := builder.NewCond() cond := builder.NewCond()
cond = cond.And(builder.Eq{"advicer_id": param.AdvicerID}) cond = cond.And(builder.Eq{"advicer_id": param.AdvicerID})
err = a.advicerImpl.UpdateByCond(&cond, param) err = a.advicerImpl.UpdateByCond(&cond, param)
} }
return err return param.AdvicerID, err
} }
func (a *AdviceAdvicerBiz) List(ctx context.Context, data *entitys.AdvicerListReq) ([]map[string]interface{}, error) { func (a *AdviceAdvicerBiz) List(ctx context.Context, data *entitys.AdvicerListReq) ([]map[string]interface{}, error) {
@ -66,14 +66,14 @@ func (a *AdviceAdvicerBiz) List(ctx context.Context, data *entitys.AdvicerListRe
return list, err return list, err
} }
func (a *AdviceAdvicerBiz) VersionAdd(ctx context.Context, param *entitys.AdvicerVersionAddReq) (err error) { func (a *AdviceAdvicerBiz) VersionAdd(ctx context.Context, param *entitys.AdvicerVersionAddReq) (id interface{}, err error) {
cond := builder.NewCond() cond := builder.NewCond()
cond = cond.And(builder.Eq{"advicer_id": param.AdvicerID}) cond = cond.And(builder.Eq{"advicer_id": param.AdvicerID})
_, err = a.advicerImpl.GetOneBySearch(&cond) _, err = a.advicerImpl.GetOneBySearch(&cond)
if err != nil { if err != nil {
return errors.New("顾问不存在") return 0, errors.New("顾问不存在")
} }
_, err = a.mongo.Co(a.advicerVersionMongo).InsertOne(ctx, &mongo_model.AdvicerVersionMongo{ res, err := a.mongo.Co(a.advicerVersionMongo).InsertOne(ctx, &mongo_model.AdvicerVersionMongo{
AdvicerId: param.AdvicerID, AdvicerId: param.AdvicerID,
VersionDesc: param.VersionDesc, VersionDesc: param.VersionDesc,
DialectFeatures: param.DialectFeatures, DialectFeatures: param.DialectFeatures,
@ -83,8 +83,10 @@ func (a *AdviceAdvicerBiz) VersionAdd(ctx context.Context, param *entitys.Advice
SignatureDialogues: param.SignatureDialogues, SignatureDialogues: param.SignatureDialogues,
LastUpdateTime: time.Now(), LastUpdateTime: time.Now(),
}) })
if err != nil {
return err return nil, err
}
return res.InsertedID, err
} }
func (a *AdviceAdvicerBiz) VersionUpdate(ctx context.Context, param *entitys.AdvicerVersionUpdateReq) (err error) { func (a *AdviceAdvicerBiz) VersionUpdate(ctx context.Context, param *entitys.AdvicerVersionUpdateReq) (err error) {
@ -118,7 +120,7 @@ func (a *AdviceAdvicerBiz) VersionList(ctx context.Context, param *entitys.Advic
filter := bson.M{} filter := bson.M{}
// 1. advicer_id 条件 // 1. advicer_id 条件
if param.AdvicerId != 0 { if param.AdvicerId != 0 {
filter["AdvicerId"] = param.AdvicerId filter["advicerId"] = param.AdvicerId
} }
// 2. _id 条件 // 2. _id 条件
@ -133,7 +135,7 @@ func (a *AdviceAdvicerBiz) VersionList(ctx context.Context, param *entitys.Advic
// 3. version_desc 模糊查询 // 3. version_desc 模糊查询
if len(param.VersionDesc) != 0 { if len(param.VersionDesc) != 0 {
// 正确的方式:指定字段名 // 正确的方式:指定字段名
filter["VersionDesc"] = bson.M{ filter["versionDesc"] = bson.M{
"$regex": primitive.Regex{ "$regex": primitive.Regex{
Pattern: param.VersionDesc, Pattern: param.VersionDesc,
Options: "i", Options: "i",

View File

@ -2,83 +2,278 @@ package biz
import ( import (
"ai_scheduler/internal/biz/llm_service/third_party" "ai_scheduler/internal/biz/llm_service/third_party"
"ai_scheduler/internal/data/constants"
"ai_scheduler/internal/data/mongo_model"
"ai_scheduler/internal/data/impl"
dbmodel "ai_scheduler/internal/data/model"
"ai_scheduler/internal/entitys" "ai_scheduler/internal/entitys"
"ai_scheduler/internal/pkg" "ai_scheduler/internal/pkg"
"ai_scheduler/utils" "ai_scheduler/utils"
"context" "context"
"encoding/json" "encoding/json"
"strings" "errors"
"time" "fmt"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/volcengine/volcengine-go-sdk/service/arkruntime/model" "github.com/volcengine/volcengine-go-sdk/service/arkruntime/model"
"github.com/volcengine/volcengine-go-sdk/service/arkruntime/model/responses"
"github.com/volcengine/volcengine-go-sdk/volcengine" "github.com/volcengine/volcengine-go-sdk/volcengine"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo/options"
"xorm.io/builder"
"strings"
"time"
) )
type AdviceChatBiz struct { type AdviceChatBiz struct {
hsyq *third_party.Hsyq hsyq *third_party.Hsyq
rdb *utils.Rdb rdb *utils.Rdb
aiAdviceSessionImpl *impl.AiAdviceSessionImpl
aiAdviceModelSupImpl *impl.AiAdviceModelSupImpl
advicerChatHisMongo *mongo_model.AdvicerChatHisMongo
mongo *pkg.Mongo
} }
func NewAdviceChatBiz( func NewAdviceChatBiz(
hsyq *third_party.Hsyq, hsyq *third_party.Hsyq,
rdb *utils.Rdb, rdb *utils.Rdb,
aiAdviceSessionImpl *impl.AiAdviceSessionImpl,
aiAdviceModelSupImpl *impl.AiAdviceModelSupImpl,
advicerChatHisMongo *mongo_model.AdvicerChatHisMongo,
mongo *pkg.Mongo,
) *AdviceChatBiz { ) *AdviceChatBiz {
return &AdviceChatBiz{ return &AdviceChatBiz{
hsyq: hsyq, hsyq: hsyq,
rdb: rdb, rdb: rdb,
aiAdviceSessionImpl: aiAdviceSessionImpl,
aiAdviceModelSupImpl: aiAdviceModelSupImpl,
advicerChatHisMongo: advicerChatHisMongo,
mongo: mongo,
} }
} }
func (a *AdviceChatBiz) Regis(ctx context.Context, chatData *entitys.ChatData) (string, error) { func (a *AdviceChatBiz) contextCache(ctx context.Context, chatData *entitys.ChatData, req *entitys.AdvicerChatRegistReq, projectInfo *entitys.AdvicerProjectInfoRes) (promptJson string, contextCache string, err error) {
sessionId := uuid.New().String() switch constants.Mode(projectInfo.ModelInfo.Mode) {
prompt, err := a.buildBasePrompt(ctx, chatData) case constants.ModeResponse:
prompt, err := a.buildBasePromptResponse(ctx, chatData, req)
if err != nil {
return "", "", err
}
cache, err := a.hsyq.CreateResponse(ctx, projectInfo.ModelInfo.Key, projectInfo.ModelInfo.ChatModel, prompt, "", true)
if err != nil {
return "", "", err
}
contextCache = cache.Id
promptJson = pkg.JsonStringIgonErr(prompt)
case constants.ModeContext:
prompt, err := a.buildBasePromptContext(ctx, chatData, req)
if err != nil {
return "", "", err
}
contextCache, err = a.hsyq.CreateContextCache(ctx, projectInfo.ModelInfo.Key, projectInfo.ModelInfo.ChatModel, prompt)
if err != nil {
return "", "", err
}
promptJson = pkg.JsonStringIgonErr(prompt)
default:
return "", "", fmt.Errorf("未知的mode类型%d", projectInfo.ModelInfo.Mode)
}
return
}
func (a *AdviceChatBiz) Regis(ctx context.Context, chatData *entitys.ChatData, req *entitys.AdvicerChatRegistReq, projectInfo *entitys.AdvicerProjectInfoRes) (string, error) {
promptJson, contextCache, err := a.contextCache(ctx, chatData, req, projectInfo)
if err != nil { if err != nil {
return "", err return "", err
} }
err = a.rdb.Rdb.SetEx(ctx, sessionId, pkg.JsonStringIgonErr(prompt), 3600*time.Second).Err() sessionId := uuid.New().String()
//创建会话
_, err = a.aiAdviceSessionImpl.Add(&dbmodel.AiAdviceSession{
SessionID: sessionId,
ProjectID: projectInfo.Base.ProjectID,
SupID: projectInfo.Base.ModelSupID,
AdvicerVersionID: req.AdvicerVersionId,
ClientID: req.ClientId,
TalkSkillID: req.TalkSkillId,
Mission: req.Mission,
ContextCache: contextCache,
CreateAt: time.Now(),
})
if err != nil {
return "", err
}
err = a.rdb.Rdb.SetEx(ctx, sessionId, promptJson, 3600*time.Second).Err()
return sessionId, err return sessionId, err
} }
func (a *AdviceChatBiz) Chat(ctx context.Context, chat *entitys.AdvicerChatReq) ([]string, error) { func (a *AdviceChatBiz) Chat(ctx context.Context, chat *entitys.AdvicerChatReq) (assistant mongo_model.Assistant, err error) {
var session dbmodel.AiAdviceSession
cond := builder.NewCond()
cond = cond.And(builder.Eq{"session_id": chat.SessionId})
err = a.aiAdviceSessionImpl.GetOneBySearchToStrut(&cond, &session)
if err != nil {
return assistant, err
}
if session.SessionID == "" {
return assistant, errors.New("未找到会话信息")
}
if len(chat.Content) == 0 { if len(chat.Content) == 0 {
return nil, nil return assistant, nil
} }
basePromptJson, err := a.getChatDataFromStringSessionId(ctx, chat.SessionId) var modelInfo dbmodel.AiAdviceModelSup
cond = builder.NewCond()
cond = cond.And(builder.Eq{"sup_id": session.SupID})
err = a.aiAdviceModelSupImpl.GetOneBySearchToStrut(&cond, &modelInfo)
if err != nil { if err != nil {
return nil, err return assistant, err
} }
prompt, err := a.setContent(ctx, basePromptJson, chat.Content) if modelInfo.SupID == 0 {
return assistant, errors.New("未找到模型信息")
}
//basePromptJson, err := a.getChatDataFromStringSessionId(ctx, chat.SessionId)
//if err != nil {
// return nil, err
//}
chatHis, err := a.getChatHis(ctx, session.SessionID, 6)
prompt, err := a.buildChatPromptResponse(ctx, chat, &session, chatHis)
if err != nil { if err != nil {
return nil, err return assistant, err
} }
resContent, err := a.callLlm(ctx, prompt, fileModel) resContent, err := a.callLlmResponse(ctx, prompt, modelInfo.Key, modelInfo.ChatModel, session.ContextCache)
if err != nil { if err != nil {
return nil, err return assistant, err
} }
resSlice := strings.Split(resContent, "\n")
return resSlice, nil result := resContent.Output[0].GetOutputMessage().Content[0].GetText().GetText()
if err = json.Unmarshal([]byte(result), &assistant); err != nil {
return assistant, err
}
chatCtx, cancel := context.WithCancel(context.Background())
go func(session dbmodel.AiAdviceSession) {
defer cancel()
_, _ = a.mongo.Co(a.advicerChatHisMongo).InsertOne(chatCtx, &mongo_model.AdvicerChatHisMongo{
SessionId: chat.SessionId,
User: chat.Content,
Assistant: assistant,
InToken: resContent.Usage.InputTokens,
OutToken: resContent.Usage.OutputTokens,
CreatAt: time.Now(),
})
if assistant.MissionStatus == "fail" || assistant.MissionStatus == "complete" {
cond = builder.NewCond()
cond = cond.And(builder.Eq{"session_id": chat.SessionId})
session.MissionStatus = assistant.MissionStatus
session.MissionCompleteDesc = assistant.MissionCompleteDesc
_ = a.aiAdviceSessionImpl.UpdateByCond(&cond, session)
}
}(session)
return
} }
func (a *AdviceChatBiz) buildBasePrompt(ctx context.Context, chatData *entitys.ChatData) ([]*model.ChatCompletionMessage, error) { func (a *AdviceChatBiz) buildChatPromptResponse(ctx context.Context, chat *entitys.AdvicerChatReq, session *dbmodel.AiAdviceSession, chatList []mongo_model.AdvicerChatHisMongoEntity) ([]*responses.InputItem, error) {
var message = make([]*model.ChatCompletionMessage, 3)
var message = make([]*responses.InputItem, 3)
message[0] = &responses.InputItem{
Union: &responses.InputItem_EasyMessage{
EasyMessage: &responses.ItemEasyMessage{
Role: responses.MessageRole_system,
Content: &responses.MessageContent{Union: &responses.MessageContent_StringValue{StringValue: a.taskPrompt(session)}},
},
},
}
message[1] = &responses.InputItem{
Union: &responses.InputItem_EasyMessage{
EasyMessage: &responses.ItemEasyMessage{
Role: responses.MessageRole_system,
Content: &responses.MessageContent{Union: &responses.MessageContent_StringValue{StringValue: "历史聊天记录:\n" + pkg.JsonStringIgonErr(chatList)}},
},
},
}
message[2] = &responses.InputItem{
Union: &responses.InputItem_EasyMessage{
EasyMessage: &responses.ItemEasyMessage{
Role: responses.MessageRole_user,
Content: &responses.MessageContent{Union: &responses.MessageContent_StringValue{StringValue: chat.Content}},
},
},
}
return message, nil
}
func (a *AdviceChatBiz) getChatHis(ctx context.Context, sessionId string, limit int64) (chatList []mongo_model.AdvicerChatHisMongoEntity, err error) {
chatList = make([]mongo_model.AdvicerChatHisMongoEntity, 0)
filter := bson.M{}
filter["sessionId"] = sessionId
cursor, err := a.mongo.Co(a.advicerChatHisMongo).Find(ctx, filter, options.Find().SetLimit(limit))
if err != nil {
return chatList, err
}
for cursor.Next(ctx) {
var chatHIS mongo_model.AdvicerChatHisMongo
if err := cursor.Decode(&chatHIS); err != nil {
return nil, err
}
chatList = append(chatList, chatHIS.Entity())
}
if err := cursor.Err(); err != nil {
return nil, err
}
return
}
func (a *AdviceChatBiz) buildChatPrompt(ctx context.Context, chat *entitys.AdvicerChatReq, session *dbmodel.AiAdviceSession, modelInfo *dbmodel.AiAdviceModelSup) (model.ContextChatCompletionRequest, error) {
var message = make([]*model.ChatCompletionMessage, 2)
message[0] = &model.ChatCompletionMessage{
Role: model.ChatMessageRoleUser,
Content: &model.ChatCompletionMessageContent{
StringValue: volcengine.String(chat.Content),
},
}
message[1] = &model.ChatCompletionMessage{
Role: model.ChatMessageRoleAssistant,
Content: &model.ChatCompletionMessageContent{
StringValue: volcengine.String(a.taskPrompt(session)),
},
}
req := model.ContextChatCompletionRequest{
ContextID: session.ContextCache,
Model: modelInfo.ChatModel,
Messages: message,
Stream: false,
}
return req, nil
}
func (a *AdviceChatBiz) taskPrompt(session *dbmodel.AiAdviceSession) string {
//type mission struct {
// missionName string
// status string
// missionCompleteDesc string
//}
//var m = &mission{
// missionName: session.Mission,
// status: pkg.Ter(session.MissionStatus == 1, "进行中", "已完成"),
// missionCompleteDesc: session.MissionCompleteDesc,
//}
//missionJon, _ := json.Marshal(m)
return "[当前时间]" + time.Now().Format("2006-01-02 15:04:05")
}
func (a *AdviceChatBiz) buildBasePromptContext(ctx context.Context, chatData *entitys.ChatData, req *entitys.AdvicerChatRegistReq) ([]*model.ChatCompletionMessage, error) {
var message = make([]*model.ChatCompletionMessage, 2)
message[0] = &model.ChatCompletionMessage{ message[0] = &model.ChatCompletionMessage{
Role: model.ChatMessageRoleSystem, Role: model.ChatMessageRoleSystem,
Content: &model.ChatCompletionMessageContent{ Content: &model.ChatCompletionMessageContent{
StringValue: volcengine.String(a.sysPrompt(chatData)), StringValue: volcengine.String(a.sysPrompt(chatData, req)),
}, },
} }
message[1] = &model.ChatCompletionMessage{ message[1] = &model.ChatCompletionMessage{
Role: model.ChatMessageRoleUser, Role: model.ChatMessageRoleSystem,
Content: &model.ChatCompletionMessageContent{
StringValue: volcengine.String("{{chat_content}}"),
},
}
message[2] = &model.ChatCompletionMessage{
Role: model.ChatMessageRoleAssistant,
Content: &model.ChatCompletionMessageContent{ Content: &model.ChatCompletionMessageContent{
StringValue: volcengine.String(a.assistantPrompt(chatData)), StringValue: volcengine.String(a.assistantPrompt(chatData)),
}, },
@ -86,7 +281,28 @@ func (a *AdviceChatBiz) buildBasePrompt(ctx context.Context, chatData *entitys.C
return message, nil return message, nil
} }
func (a *AdviceChatBiz) setContent(ctx context.Context, basePromptJson string, content string) ([]*model.ChatCompletionMessage, error) { func (a *AdviceChatBiz) buildBasePromptResponse(ctx context.Context, chatData *entitys.ChatData, req *entitys.AdvicerChatRegistReq) ([]*responses.InputItem, error) {
var message = make([]*responses.InputItem, 2)
message[0] = &responses.InputItem{
Union: &responses.InputItem_EasyMessage{
EasyMessage: &responses.ItemEasyMessage{
Role: responses.MessageRole_system,
Content: &responses.MessageContent{Union: &responses.MessageContent_StringValue{StringValue: a.sysPrompt(chatData, req)}},
},
},
}
message[1] = &responses.InputItem{
Union: &responses.InputItem_EasyMessage{
EasyMessage: &responses.ItemEasyMessage{
Role: responses.MessageRole_system,
Content: &responses.MessageContent{Union: &responses.MessageContent_StringValue{StringValue: a.assistantPrompt(chatData)}},
},
},
}
return message, nil
}
func (a *AdviceChatBiz) setContent(ctx context.Context, basePromptJson string, content string, session *dbmodel.AiAdviceSession) ([]*model.ChatCompletionMessage, error) {
promptJson := strings.ReplaceAll(basePromptJson, "{{chat_content}}", content) promptJson := strings.ReplaceAll(basePromptJson, "{{chat_content}}", content)
var basePrompt []*model.ChatCompletionMessage var basePrompt []*model.ChatCompletionMessage
err := json.Unmarshal([]byte(promptJson), &basePrompt) err := json.Unmarshal([]byte(promptJson), &basePrompt)
@ -97,8 +313,14 @@ func (a *AdviceChatBiz) setContent(ctx context.Context, basePromptJson string, c
return basePrompt, nil return basePrompt, nil
} }
func (a *AdviceChatBiz) sysPrompt(chatData *entitys.ChatData) string { func (a *AdviceChatBiz) sysPrompt(chatData *entitys.ChatData, req *entitys.AdvicerChatRegistReq) string {
return "【场景】现在你是专业的顾问我们在聊天软件里面聊天当前时间是2026/01/30 16:13:30\n【要求】提供的json内容包含顾问项目对话技巧客户信息请根据json内容进行模仿真人进行对话** 绝对不能让对方看出来你是ai!**\n【规则】\n1.必须模仿顾问的聊天方式不能有markdown格式聊天内容必须贴近聊天软件的正常聊天非客户要求不要自顾自的介绍项目开场白不要太长\n2.不要有任何特殊格式,有比较长的对话内容注意提行\n3.尽量邀约对方来项目上来\n4.不能有任何画外音的文字格式出现!比如(等待对方回复)" var prompt strings.Builder
prompt.WriteString(constants.BasePrompt)
prompt.WriteString(req.Mission)
prompt.WriteString(constants.BasePrompt2)
return prompt.String()
} }
func (a *AdviceChatBiz) assistantPrompt(chatData *entitys.ChatData) string { func (a *AdviceChatBiz) assistantPrompt(chatData *entitys.ChatData) string {
@ -115,10 +337,18 @@ func (a *AdviceChatBiz) getChatDataFromStringSessionId(ctx context.Context, sess
return cache.Val(), cache.Err() return cache.Val(), cache.Err()
} }
func (a *AdviceChatBiz) callLlm(ctx context.Context, prompt []*model.ChatCompletionMessage, modelName string) (string, error) { func (a *AdviceChatBiz) callLlm(ctx context.Context, request model.ContextChatCompletionRequest, key string) (string, error) {
res, err := a.hsyq.RequestHsyq(ctx, key, modelName, prompt) res, err := a.hsyq.ChatWithRequest(ctx, key, request)
if err != nil { if err != nil {
return "", err return "", err
} }
return *res.Choices[0].Message.Content.StringValue, nil return *res.Choices[0].Message.Content.StringValue, nil
} }
func (a *AdviceChatBiz) callLlmResponse(ctx context.Context, request []*responses.InputItem, key string, modelName string, id string) (*responses.ResponseObject, error) {
res, err := a.hsyq.CreateResponse(ctx, key, modelName, request, id, false)
if err != nil {
return nil, err
}
return res, nil
}

View File

@ -29,9 +29,9 @@ func NewAdviceClientBiz(
} }
} }
func (a *AdviceClientBiz) Add(ctx context.Context, param *entitys.AdvicerClientAddReq) (err error) { func (a *AdviceClientBiz) Add(ctx context.Context, param *entitys.AdvicerClientAddReq) (id interface{}, err error) {
_, err = a.mongo.Co(a.AdvicerClientMongo).InsertOne(ctx, &mongo_model.AdvicerClientMongo{ res, err := a.mongo.Co(a.AdvicerClientMongo).InsertOne(ctx, &mongo_model.AdvicerClientMongo{
ProjectId: param.ProjectId, ProjectId: param.ProjectId,
AdvicerId: param.AdvicerId, AdvicerId: param.AdvicerId,
PersonalInfo: param.PersonalInfo, PersonalInfo: param.PersonalInfo,
@ -41,8 +41,10 @@ func (a *AdviceClientBiz) Add(ctx context.Context, param *entitys.AdvicerClientA
DecisionProfile: param.DecisionProfile, DecisionProfile: param.DecisionProfile,
LastUpdateTime: time.Now(), LastUpdateTime: time.Now(),
}) })
if err != nil {
return err return nil, err
}
return res.InsertedID, err
} }
func (a *AdviceClientBiz) Update(ctx context.Context, param *entitys.AdvicerrClientUpdateReq) (err error) { func (a *AdviceClientBiz) Update(ctx context.Context, param *entitys.AdvicerrClientUpdateReq) (err error) {

View File

@ -149,7 +149,7 @@ func (a *AdviceFileBiz) callLlm(ctx context.Context, prompt string, modelName st
StringValue: volcengine.String(prompt), StringValue: volcengine.String(prompt),
}, },
} }
res, err := a.hsyq.RequestHsyq(ctx, key, modelName, message) res, err := a.hsyq.Chat(ctx, key, modelName, message)
if err != nil { if err != nil {
return "", err return "", err
} }

View File

@ -1,10 +1,11 @@
package biz package biz
import ( import (
"ai_scheduler/internal/data/impl"
"ai_scheduler/internal/data/model"
"ai_scheduler/internal/data/mongo_model" "ai_scheduler/internal/data/mongo_model"
"ai_scheduler/internal/entitys" "ai_scheduler/internal/entitys"
"ai_scheduler/internal/pkg" "ai_scheduler/internal/pkg"
"errors"
"fmt" "fmt"
"time" "time"
@ -12,26 +13,60 @@ import (
"go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/bson/primitive"
"xorm.io/builder"
) )
type AdviceProjectBiz struct { type AdviceProjectBiz struct {
AdvicerProjectMongo *mongo_model.AdvicerProjectMongo AdvicerProjectMongo *mongo_model.AdvicerProjectMongo
mongo *pkg.Mongo adviceProjectImpl *impl.AdviceProjectImpl
aiAdviceModelSupImpl *impl.AiAdviceModelSupImpl
mongo *pkg.Mongo
} }
func NewAdviceProjectBiz( func NewAdviceProjectBiz(
advicerProjectMongo *mongo_model.AdvicerProjectMongo, advicerProjectMongo *mongo_model.AdvicerProjectMongo,
adviceProjectImpl *impl.AdviceProjectImpl,
aiAdviceModelSupImpl *impl.AiAdviceModelSupImpl,
mongo *pkg.Mongo, mongo *pkg.Mongo,
) *AdviceProjectBiz { ) *AdviceProjectBiz {
return &AdviceProjectBiz{ return &AdviceProjectBiz{
AdvicerProjectMongo: advicerProjectMongo, AdvicerProjectMongo: advicerProjectMongo,
mongo: mongo, mongo: mongo,
adviceProjectImpl: adviceProjectImpl,
aiAdviceModelSupImpl: aiAdviceModelSupImpl,
} }
} }
func (a *AdviceProjectBiz) Add(ctx context.Context, param *entitys.AdvicerProjectAddReq) (err error) { func (a *AdviceProjectBiz) BaseAdd(ctx context.Context, param *entitys.AdvicerProjectBaseAddReq) (res *entitys.AdvicerProjectBaseAddRes, err error) {
add := &model.AiAdviceProject{
Name: param.Name,
ModelSupID: param.ModelSupId,
}
err = a.adviceProjectImpl.AddWithData(add)
if err != nil {
return nil, err
}
return &entitys.AdvicerProjectBaseAddRes{
ProjectId: add.ProjectID,
}, err
}
_, err = a.mongo.Co(a.AdvicerProjectMongo).InsertOne(ctx, &mongo_model.AdvicerProjectMongo{ func (a *AdviceProjectBiz) BaseUpdate(ctx context.Context, param *entitys.AdvicerProjectBaseUpdateReq) (err error) {
if param.ProjectId == 0 {
return
}
cond := builder.NewCond()
cond = cond.And(builder.Eq{"project_id": param.ProjectId})
err = a.adviceProjectImpl.UpdateByCond(&cond, &model.AiAdviceProject{
Name: param.Name,
ModelSupID: param.ModelSupId,
})
return err
}
func (a *AdviceProjectBiz) Add(ctx context.Context, param *entitys.AdvicerProjectAddReq) (id interface{}, err error) {
res, err := a.mongo.Co(a.AdvicerProjectMongo).InsertOne(ctx, &mongo_model.AdvicerProjectMongo{
ProjectId: param.ProjectId, ProjectId: param.ProjectId,
ProjectInfo: param.ProjectInfo, ProjectInfo: param.ProjectInfo,
RegionValue: param.RegionValue, RegionValue: param.RegionValue,
@ -42,22 +77,27 @@ func (a *AdviceProjectBiz) Add(ctx context.Context, param *entitys.AdvicerProjec
LastUpdateTime: time.Now(), LastUpdateTime: time.Now(),
}) })
return err return res.InsertedID, err
} }
func (a *AdviceProjectBiz) Update(ctx context.Context, param *entitys.AdvicerrProjectUpdateReq) (err error) { func (a *AdviceProjectBiz) Update(ctx context.Context, param *entitys.AdvicerrProjectUpdateReq) (err error) {
filter := bson.M{} filter := bson.M{}
if len(param.Id) == 0 { if len(param.Id) != 0 {
return errors.New("ID不能为空") objectID, err := primitive.ObjectIDFromHex(param.Id)
if err != nil {
return fmt.Errorf("ID转换失败: %w", err)
}
filter["_id"] = objectID
} }
objectID, err := primitive.ObjectIDFromHex(param.Id) if param.ProjectId != 0 {
if err != nil {
return fmt.Errorf("ID转换失败: %w", err) filter["projectId"] = param.ProjectId
} }
filter["_id"] = objectID
update := bson.M{ update := bson.M{
"$set": &mongo_model.AdvicerProjectMongo{ "$set": &mongo_model.AdvicerProjectMongo{
ProjectId: param.ProjectId, ProjectId: param.ProjectId,
ProjectInfo: param.ProjectInfo,
RegionValue: param.RegionValue, RegionValue: param.RegionValue,
CompetitionComparison: param.CompetitionComparison, CompetitionComparison: param.CompetitionComparison,
CoreSellingPoints: param.CoreSellingPoints, CoreSellingPoints: param.CoreSellingPoints,
@ -70,7 +110,53 @@ func (a *AdviceProjectBiz) Update(ctx context.Context, param *entitys.AdvicerrPr
return res.Err() return res.Err()
} }
func (a *AdviceProjectBiz) Info(ctx context.Context, param *entitys.AdvicerProjectInfoReq) (info mongo_model.AdvicerProjectMongo, err error) { func (a *AdviceProjectBiz) Info(ctx context.Context, param *entitys.AdvicerProjectInfoReq) (info *entitys.AdvicerProjectInfoRes, err error) {
configInfo, err := a.ConfigInfo(ctx, param)
if err != nil {
return nil, err
}
baseInfo, err := a.BaseInfo(configInfo.ProjectId)
if err != nil {
return nil, err
}
supInfo, err := a.ModelInfo(baseInfo.ModelSupID)
if err != nil {
return nil, err
}
return &entitys.AdvicerProjectInfoRes{
ConfigInfo: configInfo,
Base: baseInfo,
ModelInfo: supInfo,
}, nil
}
func (a *AdviceProjectBiz) BaseInfo(projectId int32) (baseInfo model.AiAdviceProject, err error) {
if projectId == 0 {
return
}
cond := builder.NewCond()
cond = cond.And(builder.Eq{"project_id": projectId})
err = a.adviceProjectImpl.GetOneBySearchToStrut(&cond, &baseInfo)
if err != nil {
return baseInfo, err
}
return baseInfo, nil
}
func (a *AdviceProjectBiz) ModelInfo(supId int32) (supInfo model.AiAdviceModelSup, err error) {
if supId == 0 {
return
}
cond := builder.NewCond()
cond = cond.And(builder.Eq{"sup_id": supId})
err = a.aiAdviceModelSupImpl.GetOneBySearchToStrut(&cond, &supInfo)
if err != nil {
return supInfo, err
}
return supInfo, nil
}
func (a *AdviceProjectBiz) ConfigInfo(ctx context.Context, param *entitys.AdvicerProjectInfoReq) (info mongo_model.AdvicerProjectMongo, err error) {
filter := bson.M{} filter := bson.M{}
if param.ProjectId != 0 { if param.ProjectId != 0 {

View File

@ -29,9 +29,9 @@ func NewAdviceSkillBiz(
} }
} }
func (a *AdviceSkillBiz) VersionAdd(ctx context.Context, param *entitys.AdvicerTalkSkillAddReq) (err error) { func (a *AdviceSkillBiz) VersionAdd(ctx context.Context, param *entitys.AdvicerTalkSkillAddReq) (id interface{}, err error) {
_, err = a.mongo.Co(a.AdvicerTalkSkillMongo).InsertOne(ctx, &mongo_model.AdvicerTalkSkillMongo{ res, err := a.mongo.Co(a.AdvicerTalkSkillMongo).InsertOne(ctx, &mongo_model.AdvicerTalkSkillMongo{
ProjectId: param.ProjectId, ProjectId: param.ProjectId,
AdvicerId: param.AdvicerId, AdvicerId: param.AdvicerId,
Desc: param.Desc, Desc: param.Desc,
@ -42,8 +42,10 @@ func (a *AdviceSkillBiz) VersionAdd(ctx context.Context, param *entitys.AdvicerT
CommunicationRhythm: param.CommunicationRhythm, CommunicationRhythm: param.CommunicationRhythm,
LastUpdateTime: time.Now(), LastUpdateTime: time.Now(),
}) })
if err != nil {
return err return nil, err
}
return res.InsertedID, err
} }
func (a *AdviceSkillBiz) VersionUpdate(ctx context.Context, param *entitys.AdvicerTalkSkillUpdateReq) (err error) { func (a *AdviceSkillBiz) VersionUpdate(ctx context.Context, param *entitys.AdvicerTalkSkillUpdateReq) (err error) {

View File

@ -9,6 +9,7 @@ import (
"github.com/volcengine/volcengine-go-sdk/service/arkruntime" "github.com/volcengine/volcengine-go-sdk/service/arkruntime"
"github.com/volcengine/volcengine-go-sdk/service/arkruntime/model" "github.com/volcengine/volcengine-go-sdk/service/arkruntime/model"
"github.com/volcengine/volcengine-go-sdk/service/arkruntime/model/responses" "github.com/volcengine/volcengine-go-sdk/service/arkruntime/model/responses"
"github.com/volcengine/volcengine-go-sdk/volcengine"
) )
type Hsyq struct { type Hsyq struct {
@ -38,7 +39,7 @@ func (h *Hsyq) getClient(key string) *arkruntime.Client {
} }
// 火山引擎 // 火山引擎
func (h *Hsyq) RequestHsyq(ctx context.Context, key string, modelName string, prompt []*model.ChatCompletionMessage) (model.ChatCompletionResponse, error) { func (h *Hsyq) Chat(ctx context.Context, key string, modelName string, prompt []*model.ChatCompletionMessage) (model.ChatCompletionResponse, error) {
req := model.CreateChatCompletionRequest{ req := model.CreateChatCompletionRequest{
Model: modelName, Model: modelName,
Messages: prompt, Messages: prompt,
@ -54,6 +55,68 @@ func (h *Hsyq) RequestHsyq(ctx context.Context, key string, modelName string, pr
return resp, err return resp, err
} }
// 火山引擎
func (h *Hsyq) ChatWithRequest(ctx context.Context, key string, request model.ContextChatCompletionRequest) (model.ChatCompletionResponse, error) {
resp, err := h.getClient(key).CreateContextChatCompletion(ctx, request)
if err != nil {
return model.ChatCompletionResponse{ID: ""}, err
}
log.Info("token用量", resp.Usage.TotalTokens, "输入:", resp.Usage.PromptTokens, "输出:", resp.Usage.CompletionTokens)
return resp, err
}
func (h *Hsyq) CreateContextCache(ctx context.Context, key string, modelName string, prompt []*model.ChatCompletionMessage) (string, error) {
req := model.CreateContextRequest{
Model: modelName,
Messages: prompt,
TTL: volcengine.Int(3600),
Mode: model.ContextModeSession,
TruncationStrategy: &model.TruncationStrategy{Type: model.TruncationStrategyTypeRollingTokens},
}
resp, err := h.getClient(key).CreateContext(ctx, req)
if err != nil {
return "", err
}
log.Info("token用量", resp.Usage.TotalTokens, "输入:", resp.Usage.PromptTokens, "输出:", resp.Usage.CompletionTokens)
return resp.ID, err
}
func (h *Hsyq) CreateResponse(ctx context.Context, key string, modelName string, prompt []*responses.InputItem, id string, isRegis bool) (*responses.ResponseObject, error) {
req := &responses.ResponsesRequest{
Model: modelName,
Input: &responses.ResponsesInput{
Union: &responses.ResponsesInput_ListValue{
ListValue: &responses.InputItemList{ListValue: prompt},
},
},
Stream: new(bool),
Thinking: &responses.ResponsesThinking{Type: responses.ThinkingType_disabled.Enum()},
}
if isRegis {
prefix := true
req.Caching = &responses.ResponsesCaching{Type: responses.CacheType_enabled.Enum(), Prefix: &prefix}
req.ExpireAt = volcengine.Int64(time.Now().Unix() + 3600)
}
if len(id) != 0 {
req.PreviousResponseId = &id
//req.Text = &responses.ResponsesText{
// Format: &responses.TextFormat{
// Type: responses.TextType_json_object,
// Schema:
// }
//}
}
resp, err := h.getClient(key).CreateResponses(ctx, req)
if err != nil {
return nil, err
}
log.Info("token用量", resp.Usage.TotalTokens, "输入:", resp.Usage.InputTokens, "输出:", resp.Usage.OutputTokens)
return resp, err
}
func (h *Hsyq) RequestHsyqJson(ctx context.Context, key string, modelName string, prompt []*responses.InputItem) (*responses.ResponseObject, error) { func (h *Hsyq) RequestHsyqJson(ctx context.Context, key string, modelName string, prompt []*responses.InputItem) (*responses.ResponseObject, error) {
req := responses.ResponsesRequest{ req := responses.ResponsesRequest{
Model: modelName, Model: modelName,

View File

@ -0,0 +1,25 @@
package constants
type SupWay int32
const (
SupWayHsyq SupWay = iota + 1
)
type Mode int32
const (
ModeResponse Mode = 1
ModeContext Mode = 2
)
const BasePrompt = `**[场景]**现在你是专业的顾问我们在聊天软件里面聊天
**[要求]**提供的json内容包含顾问项目对话技巧客户信息请根据json内容进行模仿真人进行对话** 绝对不能让对方看出来你是ai!**
**[规则]**
1.必须模仿顾问的聊天方式不能有markdown格式聊天内容必须贴近聊天软件的正常聊天非客户要求不要自顾自的介绍项目开场白不要太长
2.不要有任何特殊格式有比较长的对话内容注意提行
3.结合[任务内容]信息若任务状态为"in_progress",则在对话中尽量完成任务;如果任务状态为"completed""fail",则主动结束对话,且该轮对话中不再更新任务状态mission_complete_desc记录最终结果且不再更改不要每一句对话都包含任务内容不要目的性太强
4.不能有任何画外音的文字格式出现比如等待对方回复
**[任务内容]**`
const BasePrompt2 = "**[输出格式]**\n- **格式类型**严格输出json格式字符串不需要其他任何格式和内容\n- **数据结构**\n {\n \"result\": \"{{chat_content}}\",\n \"mission\": \"{{mission}}\"\n \"mission_status\": \"{{mission_status}}\",\n \"mission_complete_desc\": \"{{mission_complete_desc}}\"\n }\n\n**[字段说明]**\n1. **result** (字符串)\n - 对应变量:`{{chat_content}}`\n - 内容:顾问的实际对话内容\n - 要求:自然语言回复,面向用户\n\n2. **mission** (字符串)\n - 对应变量:`{{mission}}`\n - 取值:任务内容\n - 说明:需要完成的任务内容\n\n3. **mission_status** (字符串)\n - 对应变量:`{{mission_status}}`\n - 取值:`\"completed\"` 或 `\"in_progress\"` 或 `\"fail\"`\n - 说明:标识当前任务完成状态\n - `\"completed\"`:任务已全部完成\n - `\"in_progress\"`:任务仍在进行中\n - `\"fail\"`:任务失败,客户已经明确拒绝或者对任务内容表达反对\n\n4. **mission_complete_desc** (字符串)\n - 对应变量:`{{mission_complete_desc}}`\n - 内容根据mission_status提供相应描述\n - 当`mission_status: \"completed\"`时:简要总结任务完成情况\n - 当`mission_status: \"in_progress\"`时:说明下一步需要做什么\n\n**[示例]**\n{\n\"result\": \"需要我给您安排时间吗\",\n\"mission\": \"邀请客户到售楼部\",\n\"mission_status\": \"in_progress\",\n\"mission_complete_desc\": \"需要用户确认什么时候到售楼部\"\n}\n\n{\n\"result\": \"好的,那就周日下午两点,我到时候在售楼部等您,来了记得给我打电话\",\n\"mission_status\": \"completed\",\n\"mission_complete_desc\": \"客户确认周日下午两点到售楼部\"\n}\n\n**[强制要求]**\n1. 必须输出完整、有效的JSON对象\n2. 所有字段均为必需字段,不可省略\n3. JSON格式必须严格正确无语法错误\n4. `mission_status`只能使用指定的两个值\n5. `result`字段内容需符合对话语境"

View File

@ -0,0 +1,17 @@
package impl
import (
"ai_scheduler/internal/data/model"
"ai_scheduler/tmpl/dataTemp"
"ai_scheduler/utils"
)
type AiAdviceModelSupImpl struct {
dataTemp.DataTemp
}
func NewAiAdviceModelSupImpl(db *utils.Db) *AiAdviceModelSupImpl {
return &AiAdviceModelSupImpl{
DataTemp: *dataTemp.NewDataTemp(db, new(model.AiAdviceModelSup)),
}
}

View File

@ -0,0 +1,17 @@
package impl
import (
"ai_scheduler/internal/data/model"
"ai_scheduler/tmpl/dataTemp"
"ai_scheduler/utils"
)
type AiAdviceSessionImpl struct {
dataTemp.DataTemp
}
func NewAiAdviceSessionImpl(db *utils.Db) *AiAdviceSessionImpl {
return &AiAdviceSessionImpl{
DataTemp: *dataTemp.NewDataTemp(db, new(model.AiAdviceSession)),
}
}

View File

@ -24,4 +24,6 @@ var ProviderImpl = wire.NewSet(
NewAdviceTalkImpl, NewAdviceTalkImpl,
NewAdviceAdvicerVersionImpl, NewAdviceAdvicerVersionImpl,
NewAdviceClientImpl, NewAdviceClientImpl,
NewAiAdviceSessionImpl,
NewAiAdviceModelSupImpl,
) )

View File

@ -0,0 +1,29 @@
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
package model
import (
"time"
)
const TableNameAiAdviceModelSup = "ai_advice_model_sup"
// AiAdviceModelSup mapped from table <ai_advice_model_sup>
type AiAdviceModelSup struct {
SupID int32 `gorm:"column:sup_id;primaryKey;autoIncrement:true" json:"sup_id"`
SupName string `gorm:"column:sup_name;not null;comment:备注" json:"sup_name"` // 备注
SupWay int32 `gorm:"column:sup_way;not null;comment:供应方1火山引擎" json:"sup_way"` // 供应方1火山引擎
Key string `gorm:"column:key;not null" json:"key"`
FileModel string `gorm:"column:file_model;not null;comment:文件读取model" json:"file_model"` // 文件读取model
JSONModel string `gorm:"column:json_model;not null;comment:json格式处理model" json:"json_model"` // json格式处理model
ChatModel string `gorm:"column:chat_model;not null;comment:对话模型" json:"chat_model"` // 对话模型
Mode int32 `gorm:"column:mode;not null;comment:模式" json:"mode"` // 模式
CreateAt time.Time `gorm:"column:create_at;default:CURRENT_TIMESTAMP" json:"create_at"`
}
// TableName AiAdviceModelSup's table name
func (*AiAdviceModelSup) TableName() string {
return TableNameAiAdviceModelSup
}

View File

@ -12,14 +12,10 @@ const TableNameAiAdviceProject = "ai_advice_project"
// AiAdviceProject mapped from table <ai_advice_project> // AiAdviceProject mapped from table <ai_advice_project>
type AiAdviceProject struct { type AiAdviceProject struct {
ProjectID int32 `gorm:"column:project_id;primaryKey;autoIncrement:true" json:"project_id"` ProjectID int32 `gorm:"column:project_id;primaryKey;autoIncrement:true" json:"project_id"`
Name string `gorm:"column:name;not null;comment:姓名" json:"name"` // 姓名 Name string `gorm:"column:name;not null;comment:姓名" json:"name"` // 姓名
RegionValue string `gorm:"column:region_value;comment:区域价值话术库" json:"region_value"` // 区域价值话术库 ModelSupID int32 `gorm:"column:model_sup_id;not null;comment:模型提供方配置关联advicer_model_sup" json:"model_sup_id"` // 模型提供方配置关联advicer_model_sup
CompetitionComparison string `gorm:"column:competition_comparison;comment:竞品对比话术" json:"competition_comparison"` // 竞品对比话术 CreateAt time.Time `gorm:"column:create_at;default:CURRENT_TIMESTAMP" json:"create_at"`
CoreSellingPoints string `gorm:"column:core_selling_points;comment:项目核心卖点" json:"core_selling_points"` // 项目核心卖点
SupportingFacilities string `gorm:"column:supporting_facilities;comment:配套体系" json:"supporting_facilities"` // 配套体系
DeveloperBacking string `gorm:"column:developer_backing;comment:开发商背书" json:"developer_backing"` // 开发商背书
CreateAt time.Time `gorm:"column:create_at;default:CURRENT_TIMESTAMP" json:"create_at"`
} }
// TableName AiAdviceProject's table name // TableName AiAdviceProject's table name

View File

@ -0,0 +1,32 @@
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
package model
import (
"time"
)
const TableNameAiAdviceSession = "ai_advice_session"
// AiAdviceSession mapped from table <ai_advice_session>
type AiAdviceSession struct {
ID int32 `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
SessionID string `gorm:"column:session_id;not null" json:"session_id"`
ProjectID int32 `gorm:"column:project_id;not null" json:"project_id"`
SupID int32 `gorm:"column:sup_id;not null" json:"sup_id"`
AdvicerVersionID string `gorm:"column:advicer_version_id;not null;comment:顾问版本" json:"advicer_version_id"` // 顾问版本
ClientID string `gorm:"column:client_id;not null;comment:客户信息id" json:"client_id"` // 客户信息id
TalkSkillID string `gorm:"column:talk_skill_id;not null;comment:聊天话术id" json:"talk_skill_id"` // 聊天话术id
ContextCache string `gorm:"column:context_cache;not null;comment:上下文缓存信息(火山引擎)" json:"context_cache"` // 上下文缓存信息(火山引擎)
Mission string `gorm:"column:mission;not null;comment:任务" json:"mission"` // 任务
MissionStatus string `gorm:"column:mission_status;not null;default:1;comment:任务状态" json:"mission_status"` // 任务状态
MissionCompleteDesc string `gorm:"column:mission_complete_desc;not null;comment:任务完成描述" json:"mission_complete_desc"` // 任务完成描述
CreateAt time.Time `gorm:"column:create_at;default:CURRENT_TIMESTAMP" json:"create_at"`
}
// TableName AiAdviceSession's table name
func (*AiAdviceSession) TableName() string {
return TableNameAiAdviceSession
}

View File

@ -0,0 +1,46 @@
package mongo_model
import (
"time"
)
type AdvicerChatHisMongo struct {
SessionId string `json:"sessionId" bson:"sessionId"`
User string `json:"User" bson:"User"`
Assistant Assistant `json:"assistant" bson:"assistant"`
InToken int64 `json:"inToken" bson:"inToken"`
OutToken int64 `json:"outToken" bson:"outToken"`
CreatAt time.Time `json:"creatAt" bson:"creatAt"`
}
func NewAdvicerChatHisMongo() *AdvicerChatHisMongo {
return &AdvicerChatHisMongo{}
}
func (a *AdvicerChatHisMongo) MongoTableName() string {
return "advicer_chat_his"
}
type AdvicerChatHisMongoEntity struct {
User string `json:"user"`
Assistant string `json:"assistant"`
MissionStatus string `json:"missionStatus"`
MissionNext string `json:"missionNext"`
CreateAt string `json:"createAt"`
}
func (a *AdvicerChatHisMongo) Entity() AdvicerChatHisMongoEntity {
return AdvicerChatHisMongoEntity{
User: a.User,
Assistant: a.Assistant.Result,
MissionStatus: a.Assistant.MissionStatus,
MissionNext: a.Assistant.MissionCompleteDesc,
CreateAt: a.CreatAt.Format(time.DateTime),
}
}
type Assistant struct {
Result string `json:"result"`
MissionStatus string `json:"mission_status"`
MissionCompleteDesc string `json:"mission_complete_desc"`
}

View File

@ -7,4 +7,5 @@ var ProviderSetMongo = wire.NewSet(
NewAdvicerTalkSkillMongo, NewAdvicerTalkSkillMongo,
NewAdvicerProjectMongo, NewAdvicerProjectMongo,
NewAdvicerClientMongo, NewAdvicerClientMongo,
NewAdvicerChatHisMongo,
) )

View File

@ -1,14 +1,17 @@
package entitys package entitys
import "ai_scheduler/internal/data/mongo_model" import (
"ai_scheduler/internal/data/model"
"ai_scheduler/internal/data/mongo_model"
)
type AdvicerInitReq struct { type AdvicerInitReq struct {
AdvicerID int32 `json:"AdvicerId"` AdvicerID int32 `json:"advicerId"`
ProjectID int32 `json:"ProjectId"` ProjectID int32 `json:"projectId"`
Name string `json:"name"` // 姓名 Name string `json:"name"` // 姓名
Birth string `json:"birth"` // 用户名称 Birth string `json:"birth"` // 用户名称
Gender int32 `json:"gender"` // 1:男2 Gender int32 `json:"gender"` // 1:男2
WorkingYears int32 `json:"WorkingYears"` // 工作年限 WorkingYears int32 `json:"workingYears"` // 工作年限
} }
type AdvicerInfoReq struct { type AdvicerInfoReq struct {
@ -16,7 +19,7 @@ type AdvicerInfoReq struct {
} }
type AdvicerListReq struct { type AdvicerListReq struct {
ProjectId int32 `json:"ProjectId"` ProjectId int32 `json:"projectId"`
} }
type AdvicerVersionAddReq struct { type AdvicerVersionAddReq struct {
@ -92,6 +95,21 @@ type AdvicerTalkSkillInfoReq struct {
Id string `json:"id"` Id string `json:"id"`
} }
type AdvicerProjectBaseAddReq struct {
Name string `json:"name"`
ModelSupId int32 `json:"modelSupId"`
}
type AdvicerProjectBaseAddRes struct {
ProjectId int32 `json:"projectId"`
}
type AdvicerProjectBaseUpdateReq struct {
ProjectId int32 `json:"projectId"`
Name string `json:"name"`
ModelSupId int32 `json:"modelSupId"`
}
type AdvicerProjectAddReq struct { type AdvicerProjectAddReq struct {
ProjectId int32 `json:"projectId" bson:"projectId"` ProjectId int32 `json:"projectId" bson:"projectId"`
ProjectInfo mongo_model.ProjectInfo `json:"projectInfo" bson:"projectInfo"` ProjectInfo mongo_model.ProjectInfo `json:"projectInfo" bson:"projectInfo"`
@ -118,6 +136,12 @@ type AdvicerProjectInfoReq struct {
ProjectId int32 `json:"projectId" bson:"projectId"` ProjectId int32 `json:"projectId" bson:"projectId"`
} }
type AdvicerProjectInfoRes struct {
Base model.AiAdviceProject
ConfigInfo mongo_model.AdvicerProjectMongo
ModelInfo model.AiAdviceModelSup
}
type AdvicerClientAddReq struct { type AdvicerClientAddReq struct {
ProjectId int32 `json:"projectId" bson:"projectId"` ProjectId int32 `json:"projectId" bson:"projectId"`
AdvicerId int32 `json:"advicerId" bson:"advicerId"` AdvicerId int32 `json:"advicerId" bson:"advicerId"`
@ -157,6 +181,7 @@ type AdvicerChatRegistReq struct {
AdvicerVersionId string `json:"advicerVersionId"` AdvicerVersionId string `json:"advicerVersionId"`
ClientId string `json:"clientId"` ClientId string `json:"clientId"`
TalkSkillId string `json:"talkSkillId"` TalkSkillId string `json:"talkSkillId"`
Mission string `json:"mission"`
} }
type AdvicerChatRegistRes struct { type AdvicerChatRegistRes struct {

View File

@ -15,7 +15,7 @@ func HandleResponse(c *fiber.Ctx, data interface{}, e error) (err error) {
case error: case error:
err = data.(error) err = data.(error)
case int, int32, int64, float32, float64, string, bool: case int, int32, int64, float32, float64, string, bool:
c.Response().SetBody([]byte(fmt.Sprintf("%s", data))) c.Response().SetBody([]byte(fmt.Sprintf("%v", data)))
case []byte: case []byte:
c.Response().SetBody(data.([]byte)) c.Response().SetBody(data.([]byte))
default: default:

View File

@ -111,11 +111,13 @@ func SetupRoutes(app *fiber.App, ChatService *services.ChatService, sessionServi
advicer.Post("skill/list", adviceTalkSkill.TalkSkillList) advicer.Post("skill/list", adviceTalkSkill.TalkSkillList)
advicer.Post("skill/add", adviceTalkSkill.TalkSkillAdd) advicer.Post("skill/add", adviceTalkSkill.TalkSkillAdd)
advicer.Post("skill/update", adviceTalkSkill.TalkSkillUpdate) advicer.Post("skill/update", adviceTalkSkill.TalkSkillUpdate)
advicer.Post("skill/del", adviceTalkSkill.TalkSkillUpdate) advicer.Post("skill/del", adviceTalkSkill.TalkSkillDel)
//项目 //项目
advicer.Post("project/add", adviceProject.Add) advicer.Post("project/base/init", adviceProject.BaseInit)
advicer.Post("project/update", adviceProject.Update) advicer.Post("project/base/update", adviceProject.BaseUpdate)
advicer.Post("project/info/add", adviceProject.Add)
advicer.Post("project/info/update", adviceProject.Update)
advicer.Post("project/info", adviceProject.Info) advicer.Post("project/info", adviceProject.Info)
//客户 //客户
@ -124,7 +126,7 @@ func SetupRoutes(app *fiber.App, ChatService *services.ChatService, sessionServi
advicer.Post("client/list", adviceClient.List) advicer.Post("client/list", adviceClient.List)
advicer.Post("client/del", adviceClient.Del) advicer.Post("client/del", adviceClient.Del)
//客户 //会话
advicer.Post("chat/regis", adviceChat.Regis) advicer.Post("chat/regis", adviceChat.Regis)
advicer.Post("chat/chat", adviceChat.Chat) advicer.Post("chat/chat", adviceChat.Chat)
@ -185,6 +187,9 @@ func registerCommon(c *fiber.Ctx, err error) error {
} }
body := c.Response().Body() body := c.Response().Body()
if c.Locals("skip_response_wrap") == true {
return c.JSON(string(body))
}
var rawData json.RawMessage var rawData json.RawMessage
if len(body) > 0 { if len(body) > 0 {
if err := json.Unmarshal(body, &rawData); err != nil { if err := json.Unmarshal(body, &rawData); err != nil {

View File

@ -31,7 +31,8 @@ func (d *AdvicerService) AdvicerUpdate(c *fiber.Ctx) error {
if err := c.BodyParser(req); err != nil { if err := c.BodyParser(req); err != nil {
return err return err
} }
return d.adviceBiz.Update(c.UserContext(), req) id, err := d.adviceBiz.Update(c.UserContext(), req)
return pkg.HandleResponse(c, int(id), err)
} }
func (d *AdvicerService) AdvicerList(c *fiber.Ctx) error { func (d *AdvicerService) AdvicerList(c *fiber.Ctx) error {
@ -48,7 +49,8 @@ func (d *AdvicerService) AdvicerVersionAdd(c *fiber.Ctx) error {
if err := c.BodyParser(req); err != nil { if err := c.BodyParser(req); err != nil {
return err return err
} }
return d.adviceBiz.VersionAdd(c.UserContext(), req) id, err := d.adviceBiz.VersionAdd(c.UserContext(), req)
return pkg.HandleResponse(c, id, err)
} }
func (d *AdvicerService) AdvicerVersionUpdate(c *fiber.Ctx) error { func (d *AdvicerService) AdvicerVersionUpdate(c *fiber.Ctx) error {

View File

@ -53,6 +53,10 @@ func (a *ChatService) Regis(c *fiber.Ctx) error {
if len(req.TalkSkillId) == 0 { if len(req.TalkSkillId) == 0 {
return errorcode.ParamErr("talkSkillId is empty") return errorcode.ParamErr("talkSkillId is empty")
} }
if len(req.Mission) == 0 {
return errorcode.ParamErr("misiion is empty")
}
//顾问版本信息 //顾问版本信息
versionInfo, err := a.adviceAdvicerBiz.VersionInfo(c.UserContext(), &entitys.AdvicerVersionInfoReq{ versionInfo, err := a.adviceAdvicerBiz.VersionInfo(c.UserContext(), &entitys.AdvicerVersionInfoReq{
Id: req.AdvicerVersionId, Id: req.AdvicerVersionId,
@ -68,6 +72,7 @@ func (a *ChatService) Regis(c *fiber.Ctx) error {
if err != nil { if err != nil {
return err return err
} }
//项目信息 //项目信息
projectInfo, err := a.adviceProjectBiz.Info(c.UserContext(), &entitys.AdvicerProjectInfoReq{ projectInfo, err := a.adviceProjectBiz.Info(c.UserContext(), &entitys.AdvicerProjectInfoReq{
ProjectId: advicerInfo.ProjectID, ProjectId: advicerInfo.ProjectID,
@ -75,6 +80,15 @@ func (a *ChatService) Regis(c *fiber.Ctx) error {
if err != nil { if err != nil {
return err return err
} }
if len(projectInfo.ModelInfo.Key) == 0 {
return errorcode.ParamErr("项目未设置模型key")
}
if len(projectInfo.ModelInfo.ChatModel) == 0 {
return errorcode.ParamErr("项目未设置模型对话模型")
}
//销售技巧 //销售技巧
talkSkill, err := a.adviceSkillBiz.Info(c.UserContext(), &entitys.AdvicerTalkSkillInfoReq{ talkSkill, err := a.adviceSkillBiz.Info(c.UserContext(), &entitys.AdvicerTalkSkillInfoReq{
Id: req.TalkSkillId, Id: req.TalkSkillId,
@ -96,11 +110,12 @@ func (a *ChatService) Regis(c *fiber.Ctx) error {
chat := entitys.ChatData{ chat := entitys.ChatData{
ClientInfo: clientInfo.Entity(), ClientInfo: clientInfo.Entity(),
TalkSkill: talkSkill.Entity(), TalkSkill: talkSkill.Entity(),
ProjectInfo: projectInfo.Entity(), ProjectInfo: projectInfo.ConfigInfo.Entity(),
AdvicerInfo: advicerInfo.Entity(), AdvicerInfo: advicerInfo.Entity(),
AdvicerVersion: versionInfo.Entity(), AdvicerVersion: versionInfo.Entity(),
} }
sessionId, err := a.adviceChatBiz.Regis(c.UserContext(), &chat) sessionId, err := a.adviceChatBiz.Regis(c.UserContext(), &chat, req, projectInfo)
log.Info(sessionId) log.Info(sessionId)
return pkg.HandleResponse(c, sessionId, err) return pkg.HandleResponse(c, sessionId, err)
} }
@ -110,7 +125,28 @@ func (a *ChatService) Chat(c *fiber.Ctx) error {
if err := c.BodyParser(req); err != nil { if err := c.BodyParser(req); err != nil {
return err return err
} }
if len(req.SessionId) == 0 {
return errorcode.ParamErr("SessionId is empty")
}
if len(req.Content) == 0 {
return errorcode.ParamErr("Content is empty")
}
res, err := a.adviceChatBiz.Chat(c.UserContext(), req)
log.Info(res)
return pkg.HandleResponse(c, res, err)
}
func (a *ChatService) ChatContext(c *fiber.Ctx) error {
req := &entitys.AdvicerChatReq{}
if err := c.BodyParser(req); err != nil {
return err
}
if len(req.SessionId) == 0 {
return errorcode.ParamErr("SessionId is empty")
}
if len(req.Content) == 0 {
return errorcode.ParamErr("Content is empty")
}
res, err := a.adviceChatBiz.Chat(c.UserContext(), req) res, err := a.adviceChatBiz.Chat(c.UserContext(), req)
log.Info(res) log.Info(res)
return pkg.HandleResponse(c, res, err) return pkg.HandleResponse(c, res, err)

View File

@ -31,7 +31,8 @@ func (d *ClientService) Add(c *fiber.Ctx) error {
if err := c.BodyParser(req); err != nil { if err := c.BodyParser(req); err != nil {
return err return err
} }
return d.AdviceClientBiz.Add(c.UserContext(), req) id, err := d.AdviceClientBiz.Add(c.UserContext(), req)
return pkg.HandleResponse(c, id, err)
} }
func (d *ClientService) Update(c *fiber.Ctx) error { func (d *ClientService) Update(c *fiber.Ctx) error {

View File

@ -3,6 +3,7 @@ package advice
import ( import (
"ai_scheduler/internal/biz" "ai_scheduler/internal/biz"
"ai_scheduler/internal/config" "ai_scheduler/internal/config"
errorcode "ai_scheduler/internal/data/error"
"ai_scheduler/internal/entitys" "ai_scheduler/internal/entitys"
"ai_scheduler/internal/pkg" "ai_scheduler/internal/pkg"
@ -26,12 +27,33 @@ func NewProjectService(
} }
} }
func (d *ProjectService) BaseInit(c *fiber.Ctx) error {
req := &entitys.AdvicerProjectBaseAddReq{}
if err := c.BodyParser(req); err != nil {
return err
}
add, err := d.adviceProjectBiz.BaseAdd(c.UserContext(), req)
return pkg.HandleResponse(c, add, err)
}
func (d *ProjectService) BaseUpdate(c *fiber.Ctx) error {
req := &entitys.AdvicerProjectBaseUpdateReq{}
if err := c.BodyParser(req); err != nil {
return err
}
if req.ProjectId == 0 {
return errorcode.ParamErr("projectId is empty")
}
return d.adviceProjectBiz.BaseUpdate(c.UserContext(), req)
}
func (d *ProjectService) Add(c *fiber.Ctx) error { func (d *ProjectService) Add(c *fiber.Ctx) error {
req := &entitys.AdvicerProjectAddReq{} req := &entitys.AdvicerProjectAddReq{}
if err := c.BodyParser(req); err != nil { if err := c.BodyParser(req); err != nil {
return err return err
} }
return d.adviceProjectBiz.Add(c.UserContext(), req) id, err := d.adviceProjectBiz.Add(c.UserContext(), req)
return pkg.HandleResponse(c, id, err)
} }
func (d *ProjectService) Update(c *fiber.Ctx) error { func (d *ProjectService) Update(c *fiber.Ctx) error {

View File

@ -31,7 +31,8 @@ func (d *TalkSkillService) TalkSkillAdd(c *fiber.Ctx) error {
if err := c.BodyParser(req); err != nil { if err := c.BodyParser(req); err != nil {
return err return err
} }
return d.adviceSkillBiz.VersionAdd(c.UserContext(), req) id, err := d.adviceSkillBiz.VersionAdd(c.UserContext(), req)
return pkg.HandleResponse(c, id, err)
} }
func (d *TalkSkillService) TalkSkillUpdate(c *fiber.Ctx) error { func (d *TalkSkillService) TalkSkillUpdate(c *fiber.Ctx) error {

View File

@ -1,7 +1,6 @@
package dataTemp package dataTemp
import ( import (
"ai_scheduler/internal/pkg/mapstructure"
"ai_scheduler/utils" "ai_scheduler/utils"
"context" "context"
"database/sql" "database/sql"
@ -10,7 +9,6 @@ import (
"github.com/go-kratos/kratos/v2/log" "github.com/go-kratos/kratos/v2/log"
"gorm.io/gorm" "gorm.io/gorm"
"xorm.io/builder" "xorm.io/builder"
) )
@ -62,18 +60,17 @@ func (k DataTemp) GetById(id int32) (data map[string]interface{}, err error) {
} }
func (k DataTemp) Add(data interface{}) (id int, err error) { func (k DataTemp) Add(data interface{}) (id int, err error) {
var primary *PrimaryKey
add := k.Db.Model(k.Model).Create(data) add := k.Db.Model(k.Model).Create(data)
_ = mapstructure.Decode(data, &primary) return 0, add.Error
return primary.Id, add.Error
} }
func (k DataTemp) AddWithData(data interface{}) (interface{}, error) { func (k DataTemp) AddWithData(data interface{}) error {
result := k.Db.Model(k.Model).Create(data) result := k.Db.Model(k.Model).Create(data)
if result.Error != nil { if result.Error != nil {
return data, result.Error return result.Error
} }
return data, nil return nil
} }
func (k DataTemp) GetList(cond *builder.Cond, pageBoIn *ReqPageBo) (list []map[string]interface{}, pageBoOut *RespPageBo, err error) { func (k DataTemp) GetList(cond *builder.Cond, pageBoIn *ReqPageBo) (list []map[string]interface{}, pageBoOut *RespPageBo, err error) {