Files
X-Agents/server/internal/handler/memory_handler.go
DESKTOP-72TV0V4\caoxiaozhu 7b5d4b20a5 feat: 增强Chat记忆模块功能
- 新增记忆搜索API
- 集成向量检索能力
- 引入智能摘要和预压缩机制

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 14:34:38 +08:00

256 lines
6.7 KiB
Go

package handler
import (
"net/http"
"strconv"
"x-agents/server/internal/model"
"x-agents/server/internal/service"
"github.com/gin-gonic/gin"
)
// MemoryHandler 记忆处理器
type MemoryHandler struct {
memoryService *service.MemoryService
}
// NewMemoryHandler 创建记忆处理器
func NewMemoryHandler(memoryService *service.MemoryService) *MemoryHandler {
return &MemoryHandler{
memoryService: memoryService,
}
}
// CreateMemoryRequest 创建记忆请求
type CreateMemoryRequest struct {
AgentID string `json:"agent_id" binding:"required"`
UserID string `json:"user_id"`
Content string `json:"content" binding:"required"`
MemoryType string `json:"memory_type"`
Category string `json:"category"`
Tags string `json:"tags"`
Keywords string `json:"keywords"`
Importance int `json:"importance"`
IsPinned bool `json:"is_pinned"`
}
// SearchMemoryRequest 搜索记忆请求
type SearchMemoryRequest struct {
AgentID string `json:"agent_id" binding:"required"`
UserID string `json:"user_id"`
Keyword string `json:"keyword"`
Tags string `json:"tags"`
Category string `json:"category"`
MemoryType string `json:"memory_type"`
MinScore int `json:"min_score"`
Limit int `json:"limit"`
Offset int `json:"offset"`
}
// UpdateMemoryRequest 更新记忆请求
type UpdateMemoryRequest struct {
Content string `json:"content"`
MemoryType string `json:"memory_type"`
Category string `json:"category"`
Tags string `json:"tags"`
Keywords string `json:"keywords"`
Importance int `json:"importance"`
IsPinned *bool `json:"is_pinned"`
}
// CreateMemory 创建记忆
func (h *MemoryHandler) CreateMemory(c *gin.Context) {
var req CreateMemoryRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// 设置默认值
memoryType := req.MemoryType
if memoryType == "" {
memoryType = "conversation"
}
importance := req.Importance
if importance == 0 {
importance = 5
}
memory, err := h.memoryService.CreateMemory(req.AgentID, req.UserID, req.Content, memoryType, req.Category, req.Tags, req.Keywords, importance, req.IsPinned)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, memory)
}
// GetMemories 获取记忆列表
func (h *MemoryHandler) GetMemories(c *gin.Context) {
agentID := c.Param("id")
userID := c.Query("user_id")
category := c.Query("category")
memoryType := c.Query("memory_type")
limitStr := c.DefaultQuery("limit", "10")
offsetStr := c.DefaultQuery("offset", "0")
limit, err := strconv.Atoi(limitStr)
if err != nil {
limit = 10
}
offset, err := strconv.Atoi(offsetStr)
if err != nil {
offset = 0
}
memories, total, err := h.memoryService.GetMemories(agentID, userID, category, memoryType, limit, offset)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"list": memories, "total": total})
}
// SearchMemories 搜索记忆
func (h *MemoryHandler) SearchMemories(c *gin.Context) {
var req SearchMemoryRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// 设置默认值
limit := req.Limit
if limit == 0 {
limit = 10
}
offset := req.Offset
if offset < 0 {
offset = 0
}
memories, total, err := h.memoryService.SearchMemories(req.AgentID, req.UserID, req.Keyword, req.Tags, req.Category, req.MemoryType, req.MinScore, limit, offset)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"list": memories, "total": total})
}
// GetMemory 获取单个记忆详情
func (h *MemoryHandler) GetMemory(c *gin.Context) {
memoryID := c.Param("memory_id")
memory, err := h.memoryService.GetMemoryByID(memoryID)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Memory not found"})
return
}
c.JSON(http.StatusOK, memory)
}
// UpdateMemory 更新记忆
func (h *MemoryHandler) UpdateMemory(c *gin.Context) {
memoryID := c.Param("memory_id")
var req UpdateMemoryRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
memory, err := h.memoryService.UpdateMemory(memoryID, req.Content, req.MemoryType, req.Category, req.Tags, req.Keywords, req.Importance, req.IsPinned)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, memory)
}
// DeleteMemory 删除记忆
func (h *MemoryHandler) DeleteMemory(c *gin.Context) {
memoryID := c.Param("memory_id")
err := h.memoryService.DeleteMemory(memoryID)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Memory deleted successfully"})
}
// ExportMemories 导出记忆
func (h *MemoryHandler) ExportMemories(c *gin.Context) {
agentID := c.Param("id")
userID := c.Query("user_id")
format := c.DefaultQuery("format", "json")
exportData, err := h.memoryService.ExportMemories(agentID, userID, format)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{
"format": format,
"data": exportData,
})
}
// ImportMemories 导入记忆
type ImportMemoryRequest struct {
AgentID string `json:"agent_id" binding:"required"`
UserID string `json:"user_id"`
Memories []model.ImportItem `json:"memories" binding:"required"`
}
func (h *MemoryHandler) ImportMemories(c *gin.Context) {
var req ImportMemoryRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
count, err := h.memoryService.ImportMemories(req.AgentID, req.UserID, req.Memories)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"imported": count})
}
// GetMemoryCategories 获取记忆分类列表
func (h *MemoryHandler) GetMemoryCategories(c *gin.Context) {
agentID := c.Param("id")
userID := c.Query("user_id")
categories, err := h.memoryService.GetMemoryCategories(agentID, userID)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"categories": categories})
}
// GetMemoryTags 获取记忆标签列表
func (h *MemoryHandler) GetMemoryTags(c *gin.Context) {
agentID := c.Param("id")
userID := c.Query("user_id")
tags, err := h.memoryService.GetMemoryTags(agentID, userID)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"tags": tags})
}