ai_scheduler/internal/biz/router.go

179 lines
4.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package biz
import (
"ai_scheduler/internal/biz/do"
"ai_scheduler/internal/data/constants"
"ai_scheduler/internal/gateway"
"context"
"encoding/json"
"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, err := r.SetRec(ctx, requireData)
if err != nil {
log.Errorf("组装意图识别失败: %s", err.Error())
return
}
//意图识别
requireData.Match, err = r.handle.Recognize(ctx, &rec, &do.WithSys{})
if err != nil {
log.Errorf("意图识别失败: %s", err.Error())
return
}
//向下传递
if err = r.handle.HandleMatch(ctx, client, requireData); err != nil {
log.Errorf("任务处理失败: %s", err.Error())
return
}
return
}
func (r *AiRouterBiz) SetRec(ctx context.Context, requireData *entitys.RequireData) (match entitys.Recognize, err error) {
// 参数空值检查
if requireData == nil || requireData.Req == nil {
return match, err
}
// 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 _, url := range fileUrls {
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, // 默认技术支持模式
},
}
}