115 lines
3.1 KiB
Go
115 lines
3.1 KiB
Go
package service
|
||
|
||
import (
|
||
"context"
|
||
"encoding/json"
|
||
"fmt"
|
||
"time"
|
||
|
||
"github.com/gogf/gf/v2/frame/g"
|
||
)
|
||
|
||
// ==================== Redis 操作 ====================
|
||
|
||
// saveToRedis 保存会话数据到Redis
|
||
func (s *sessionService) saveToRedis(ctx context.Context, sessionId string, requestMessages []map[string]any, responseMessages []map[string]any) error {
|
||
key := fmt.Sprintf("chat:session:%s", sessionId)
|
||
|
||
maxRounds := g.Cfg().MustGet(ctx, "session.maxRounds", 10).Int()
|
||
expireSeconds := g.Cfg().MustGet(ctx, "session.expireTime", 1800).Int64()
|
||
expireTime := time.Duration(expireSeconds) * time.Second
|
||
|
||
data := map[string]any{
|
||
"sessionId": sessionId,
|
||
"requestContent": requestMessages,
|
||
"responseContent": responseMessages,
|
||
"timestamp": time.Now().Unix(),
|
||
}
|
||
|
||
b, err := json.Marshal(data)
|
||
if err != nil {
|
||
return fmt.Errorf("序列化会话数据失败: %w", err)
|
||
}
|
||
|
||
_, err = g.Redis().Do(ctx, "LPUSH", key, string(b))
|
||
if err != nil {
|
||
return fmt.Errorf("写入Redis失败: %w", err)
|
||
}
|
||
|
||
_, err = g.Redis().Do(ctx, "LTRIM", key, 0, maxRounds-1)
|
||
if err != nil {
|
||
return fmt.Errorf("裁剪Redis列表失败: %w", err)
|
||
}
|
||
|
||
_, err = g.Redis().Do(ctx, "EXPIRE", key, int64(expireTime.Seconds()))
|
||
if err != nil {
|
||
return fmt.Errorf("设置过期时间失败: %w", err)
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// getFromRedis 从Redis获取会话历史
|
||
func (s *sessionService) getFromRedis(ctx context.Context, sessionId string) ([]map[string]any, error) {
|
||
key := fmt.Sprintf("chat:session:%s", sessionId)
|
||
|
||
result, err := g.Redis().Do(ctx, "LRANGE", key, 0, -1)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("从Redis获取数据失败: %w", err)
|
||
}
|
||
|
||
if result == nil || result.IsNil() {
|
||
return []map[string]any{}, nil
|
||
}
|
||
|
||
var sessions []map[string]any
|
||
values := result.Strings()
|
||
for _, str := range values {
|
||
var data map[string]any
|
||
if err := json.Unmarshal([]byte(str), &data); err != nil {
|
||
g.Log().Warningf(ctx, "[会话] 解析Redis数据失败 err=%v", err)
|
||
continue
|
||
}
|
||
sessions = append(sessions, data)
|
||
}
|
||
|
||
// 反转(Redis 最新在前 → 时间正序)
|
||
for i, j := 0, len(sessions)-1; i < j; i, j = i+1, j-1 {
|
||
sessions[i], sessions[j] = sessions[j], sessions[i]
|
||
}
|
||
|
||
return sessions, nil
|
||
}
|
||
|
||
// GetSessionHistoryForInference 获取历史会话,返回扁平消息数组(给推理用)
|
||
func (s *sessionService) GetSessionHistoryForInference(ctx context.Context, sessionId string) ([]map[string]any, error) {
|
||
historyData, err := s.getFromRedis(ctx, sessionId)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("获取历史会话失败: %w", err)
|
||
}
|
||
|
||
if len(historyData) == 0 {
|
||
return []map[string]any{}, nil
|
||
}
|
||
|
||
var messages []map[string]any
|
||
for _, round := range historyData {
|
||
if reqMsgs, ok := round["requestContent"].([]interface{}); ok {
|
||
for _, m := range reqMsgs {
|
||
if msg, ok := m.(map[string]interface{}); ok {
|
||
messages = append(messages, msg)
|
||
}
|
||
}
|
||
}
|
||
if respMsgs, ok := round["responseContent"].([]interface{}); ok {
|
||
for _, m := range respMsgs {
|
||
if msg, ok := m.(map[string]interface{}); ok {
|
||
messages = append(messages, msg)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return messages, nil
|
||
}
|