|
@@ -0,0 +1,147 @@
|
|
|
+package llm
|
|
|
+
|
|
|
+import (
|
|
|
+ "encoding/json"
|
|
|
+ "eta/eta_api/global"
|
|
|
+ "eta/eta_api/models/llm"
|
|
|
+ "eta/eta_api/utils"
|
|
|
+ "eta/eta_api/utils/redis"
|
|
|
+ "fmt"
|
|
|
+ "time"
|
|
|
+)
|
|
|
+
|
|
|
+const (
|
|
|
+ redisChatPrefix = "chat:zet:"
|
|
|
+ redisTTL = 24 * time.Hour // Redis 缓存过期时间
|
|
|
+)
|
|
|
+
|
|
|
+// AddChatRecord 添加聊天记录到 Redis
|
|
|
+func AddChatRecord(record *llm.UserChatRecordRedis) error {
|
|
|
+ key := fmt.Sprintf("%s%d", redisChatPrefix, record.ChatId)
|
|
|
+ data, err := json.Marshal(record)
|
|
|
+ if err != nil {
|
|
|
+ return fmt.Errorf("序列化聊天记录失败: %w", err)
|
|
|
+ }
|
|
|
+ zSet, _ := utils.Rc.ZRangeWithScores(key)
|
|
|
+ if len(zSet) == 0 {
|
|
|
+ // 设置过期时间
|
|
|
+ _ = utils.Rc.Expire(key, 24*time.Hour)
|
|
|
+ }
|
|
|
+ zSet = append(zSet, &redis.Zset{
|
|
|
+ Member: data,
|
|
|
+ Score: float64(time.Now().Unix()),
|
|
|
+ })
|
|
|
+ err = utils.Rc.ZAdd(key, zSet...)
|
|
|
+ if err != nil {
|
|
|
+ return fmt.Errorf("保存聊天记录到 Redis 失败: %w", err)
|
|
|
+ }
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+// GetChatRecordsFromRedis 从 Redis 获取聊天记录
|
|
|
+func GetChatRecordsFromRedis(chatId int) (redisList []*llm.UserChatRecordRedis, err error) {
|
|
|
+ key := fmt.Sprintf("%s%d", redisChatPrefix, chatId)
|
|
|
+ zSet, _ := utils.Rc.ZRangeWithScores(key)
|
|
|
+ if len(zSet) == 0 {
|
|
|
+ // 缓存不存在,从数据库拉取数据
|
|
|
+ records, dbErr := GetChatRecordsFromDB(chatId)
|
|
|
+ if dbErr != nil {
|
|
|
+ err = fmt.Errorf("从数据库获取聊天记录失败: %w", dbErr)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ // 将数据保存到 Redis
|
|
|
+ for _, record := range records {
|
|
|
+ redisRecord := &llm.UserChatRecordRedis{
|
|
|
+ ChatId: chatId,
|
|
|
+ ChatUserType: record.ChatUserType,
|
|
|
+ Content: record.Content,
|
|
|
+ SendTime: record.SendTime.Format(utils.FormatDateTime),
|
|
|
+ }
|
|
|
+ redisList = append(redisList, redisRecord)
|
|
|
+ if err = AddChatRecord(redisRecord); err != nil {
|
|
|
+ err = fmt.Errorf("保存聊天记录到 Redis 失败: %w", err)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return
|
|
|
+ }
|
|
|
+ for _, z := range zSet {
|
|
|
+ var redisRecord llm.UserChatRecordRedis
|
|
|
+ if err = json.Unmarshal([]byte(z.Member.(string)), &redisRecord); err != nil {
|
|
|
+ return nil, fmt.Errorf("解析聊天记录失败: %w", err)
|
|
|
+ }
|
|
|
+ redisList = append(redisList, &redisRecord)
|
|
|
+ }
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+//// SaveChatRecordsToDB 将 Redis 中的聊天记录保存到数据库
|
|
|
+//func SaveChatRecordsToDB(chatID int) error {
|
|
|
+// key := fmt.Sprintf("%s%d", redisChatPrefix, chatID)
|
|
|
+// val, err := global.Redis.Get(global.Context, key).Result()
|
|
|
+// if err == redis.Nil {
|
|
|
+// return nil // 缓存不存在,无需保存
|
|
|
+// } else if err != nil {
|
|
|
+// return fmt.Errorf("从 Redis 获取聊天记录失败: %w", err)
|
|
|
+// }
|
|
|
+//
|
|
|
+// var records []*llm.UserChatRecord
|
|
|
+// if err := json.Unmarshal([]byte(val), &records); err != nil {
|
|
|
+// return fmt.Errorf("解析聊天记录失败: %w", err)
|
|
|
+// }
|
|
|
+//
|
|
|
+// o := global.DbMap[utils.DbNameAI]
|
|
|
+// for _, record := range records {
|
|
|
+// if err := o.Create(record).Error; err != nil {
|
|
|
+// return fmt.Errorf("保存聊天记录到数据库失败: %w", err)
|
|
|
+// }
|
|
|
+// }
|
|
|
+//
|
|
|
+// // 删除 Redis 缓存
|
|
|
+// if err := global.Redis.Del(global.Context, key).Err(); err != nil {
|
|
|
+// return fmt.Errorf("删除 Redis 缓存失败: %w", err)
|
|
|
+// }
|
|
|
+//
|
|
|
+// return nil
|
|
|
+//}
|
|
|
+//
|
|
|
+//// SaveAllChatRecordsToDB 定时任务保存所有 Redis 中的聊天记录到数据库
|
|
|
+//func SaveAllChatRecordsToDB() {
|
|
|
+// keys, err := global.Redis.Keys(global.Context, redisChatPrefix+"*").Result()
|
|
|
+// if err != nil {
|
|
|
+// log.Printf("获取 Redis 键失败: %v", err)
|
|
|
+// return
|
|
|
+// }
|
|
|
+//
|
|
|
+// for _, key := range keys {
|
|
|
+// chatIDStr := strings.TrimPrefix(key, redisChatPrefix)
|
|
|
+// chatID, err := strconv.Atoi(chatIDStr)
|
|
|
+// if err != nil {
|
|
|
+// log.Printf("解析聊天ID失败: %v", err)
|
|
|
+// continue
|
|
|
+// }
|
|
|
+//
|
|
|
+// if err := SaveChatRecordsToDB(chatID); err != nil {
|
|
|
+// log.Printf("保存聊天记录到数据库失败: %v", err)
|
|
|
+// }
|
|
|
+// }
|
|
|
+//}
|
|
|
+//
|
|
|
+//// RemoveChatRecord 从 Redis 删除聊天记录
|
|
|
+//func RemoveChatRecord(chatID int) error {
|
|
|
+// key := fmt.Sprintf("%s%d", redisChatPrefix, chatID)
|
|
|
+// if err := global.Redis.Del(global.Context, key).Err(); err != nil {
|
|
|
+// return fmt.Errorf("删除 Redis 缓存失败: %w", err)
|
|
|
+// }
|
|
|
+// return nil
|
|
|
+//}
|
|
|
+
|
|
|
+func GetChatRecordsFromDB(chatID int) ([]*llm.UserChatRecord, error) {
|
|
|
+ o := global.DbMap[utils.DbNameAI]
|
|
|
+ var records []*llm.UserChatRecord
|
|
|
+ if err := o.Where("chat_id = ?", chatID).Find(&records).Error; err != nil {
|
|
|
+ return nil, fmt.Errorf("从数据库获取聊天记录失败: %w", err)
|
|
|
+ }
|
|
|
+ return records, nil
|
|
|
+}
|