package biz import ( "ai_scheduler/internal/biz/do" "ai_scheduler/internal/data/constants" errors "ai_scheduler/internal/data/error" "ai_scheduler/internal/gateway" "ai_scheduler/internal/pkg/rec_extra" "context" "encoding/json" "strings" "time" "ai_scheduler/internal/entitys" "github.com/gofiber/fiber/v2/log" ) // AiRouterBiz 智能路由服务 type AiRouterBiz struct { do *do.Do handle *do.Handle } // NewAiRouterBiz 创建路由服务 func NewAiRouterBiz( do *do.Do, handle *do.Handle, ) *AiRouterBiz { return &AiRouterBiz{ do: do, handle: handle, } } // 路由处理WebSocket请求 // // 参数: // - client: 网关客户端 // - req: 聊天请求结构体 // // 返回: // - err: 错误信息 func (r *AiRouterBiz) RouteWithSocket(client *gateway.Client, req *entitys.ChatSockRequest) (err error) { // 创建请求上下文数据 requireData := &entitys.RequireData{ Req: req, } //初始化通道/上下文 ctx, clearFunc := r.do.MakeCh(client, requireData) defer func() { if err != nil { entitys.ResError(requireData.Ch, "", err.Error()) } clearFunc() }() //数据验证和收集 if err = r.do.DataAuth(ctx, client, requireData); err != nil { log.Errorf("数据验证和收集失败: %s", err.Error()) return } //组装意图识别 rec, sys, err := r.SetRec(ctx, requireData) if err != nil { log.Errorf("组装意图识别失败: %s", err.Error()) return } //意图识别 err = r.handle.Recognize(ctx, &rec, sys) if err != nil { log.Errorf("意图识别失败: %s", err.Error()) return } //任务处理 rec_extra.SetTaskRecExt(requireData, &rec) //向下传递 if err = r.handle.HandleMatch(ctx, client, &rec, requireData); err != nil { log.Errorf("任务处理失败: %s", err.Error()) return } return } func (r *AiRouterBiz) SetRec(ctx context.Context, requireData *entitys.RequireData) (match entitys.Recognize, sys do.PromptOption, err error) { // 参数空值检查 if requireData == nil || requireData.Req == nil { return match, sys, errors.NewBusinessErr(500, "请求参数为空") } // 对应不同的appKey, 配置不同的系统提示词 switch requireData.Sys.AppKey { default: sys = &do.WithSys{} } // 1. 系统提示词 match.SystemPrompt = requireData.Sys.SysPrompt // 2. 用户输入和文件处理 match.UserContent, err = r.buildUserContent(requireData) if err != nil { log.Errorf("构建用户内容失败: %s", err.Error()) return } // 3. 聊天记录 - 只有在有历史记录时才构建 if len(requireData.Histories) > 0 { match.ChatHis = r.buildChatHistory(requireData) } // 4. 任务列表 - 预分配切片容量 if len(requireData.Tasks) > 0 { match.Tasks = make([]entitys.RegistrationTask, 0, len(requireData.Tasks)) for _, task := range requireData.Tasks { taskConfig := entitys.TaskConfigDetail{} if err = json.Unmarshal([]byte(task.Config), &taskConfig); err != nil { log.Errorf("解析任务配置失败: %s, 任务ID: %s", err.Error(), task.Index) continue // 解析失败时跳过该任务,而不是直接返回错误 } match.Tasks = append(match.Tasks, entitys.RegistrationTask{ Name: task.Index, Desc: task.Desc, TaskConfigDetail: taskConfig, // 直接使用解析后的配置,避免重复构建 }) } } match.Ch = requireData.Ch return } // buildUserContent 构建用户内容 func (r *AiRouterBiz) buildUserContent(requireData *entitys.RequireData) (*entitys.RecognizeUserContent, error) { // 预分配文件切片容量(最多2个文件:File和Img) files := make([]*entitys.RecognizeFile, 0, 2) // 处理文件和图片 fileUrls := []string{requireData.Req.File, requireData.Req.Img} for _, item := range fileUrls { // 处理逗号分隔的多个URL urlList := strings.Split(item, ",") for _, url := range urlList { if url != "" { files = append(files, &entitys.RecognizeFile{FileUrl: url}) } } } // 构建并返回用户内容 return &entitys.RecognizeUserContent{ Text: requireData.Req.Text, File: files, ActionCardUrl: "", // TODO: 后续实现操作卡片功能 Tag: requireData.Req.Tags, }, nil } // buildChatHistory 构建聊天历史 func (r *AiRouterBiz) buildChatHistory(requireData *entitys.RequireData) entitys.ChatHis { // 预分配消息切片容量(每个历史记录生成2条消息) messages := make([]entitys.HisMessage, 0, len(requireData.Histories)*2) // 构建聊天记录 for _, h := range requireData.Histories { // 用户消息 messages = append(messages, entitys.HisMessage{ Role: constants.RoleUser, // 用户角色 Content: h.Ans, // 用户输入内容 Timestamp: h.CreateAt.Format(time.DateTime), }) // 助手消息 messages = append(messages, entitys.HisMessage{ Role: constants.RoleAssistant, // 助手角色 Content: h.Ques, // 助手回复内容 Timestamp: h.CreateAt.Format(time.DateTime), }) } // 构建聊天历史上下文 return entitys.ChatHis{ SessionId: requireData.Session, Messages: messages, Context: entitys.HisContext{ UserLanguage: constants.LangZhCN, // 默认中文 SystemMode: constants.SystemModeTechnicalSupport, // 默认技术支持模式 }, } }