记忆

自动记忆捕获

事件驱动的记忆自动捕获系统,支持 Tags 标签

自动记忆捕获 (Auto Capture)

自动记忆捕获系统从对话和事件中自动生成记忆,支持标签(Tags)系统便于检索和分类。

核心概念

pkg/memory/auto/
├── types.go          # Memory, CaptureEvent, Tags 类型
├── capture.go        # 自动捕获器
└── store_inmemory.go # 内存存储实现

记忆作用域

type MemoryScope string

const (
    ScopeGlobal  MemoryScope = "global"  // 全局记忆(用户级)
    ScopeProject MemoryScope = "project" // 项目记忆
    ScopeSession MemoryScope = "session" // 会话记忆
)

数据结构

// Memory 自动捕获的记忆
type Memory struct {
    ID           string         // 记忆 ID
    Scope        MemoryScope    // 作用域
    ProjectID    string         // 项目 ID
    SessionID    string         // 会话 ID
    Title        string         // 标题(简短描述)
    Content      string         // 详细内容
    Tags         []string       // 标签列表
    Source       MemorySource   // 来源
    Confidence   float64        // 置信度 (0.0-1.0)
    AccessCount  int            // 访问次数
    LastAccessed time.Time      // 最后访问时间
    Metadata     map[string]any
    CreatedAt    time.Time
    UpdatedAt    time.Time
}

// MemorySource 记忆来源
const (
    SourceDialog MemorySource = "dialog" // 来自对话
    SourceTool   MemorySource = "tool"   // 来自工具调用
    SourceSystem MemorySource = "system" // 来自系统
    SourceUser   MemorySource = "user"   // 来自用户显式操作
)

基本用法

创建捕获器

import "github.com/astercloud/aster/pkg/memory/auto"

// 创建内存存储
store := auto.NewInMemoryStore(nil)

// 创建捕获器
capturer := auto.NewCapturer(store, &auto.CapturerConfig{
    MinConfidence:         0.5,   // 最低置信度阈值
    MaxMemoriesPerProject: 1000,  // 每项目最大记忆数
    AutoTagging:           true,  // 自动添加标签
    DeduplicateWindow:     time.Hour, // 去重时间窗口
})

从对话中捕获

ctx := context.Background()

// 从用户消息中自动捕获记忆
memory, err := capturer.CaptureFromDialog(ctx, projectID, sessionID, "user", userMessage)
if memory != nil {
    fmt.Printf("捕获记忆: %s (tags: %v)\n", memory.Title, memory.Tags)
}

从事件中捕获

// 任务完成事件
memory, err := capturer.CaptureFromEvent(ctx, &auto.CaptureEvent{
    Type:      auto.EventTaskCompleted,
    ProjectID: projectID,
    Data: map[string]any{
        "task":        "实现用户认证模块",
        "description": "完成了 JWT 认证和刷新 token 逻辑",
        "tags":        []string{"backend", "auth"},
    },
    Timestamp: time.Now(),
})

// 功能实现事件
capturer.CaptureFromEvent(ctx, &auto.CaptureEvent{
    Type:      auto.EventFeatureImplemented,
    ProjectID: projectID,
    Data: map[string]any{
        "feature": "Visual Workflow Enhancement",
        "tags":    []string{"frontend", "vue"},
    },
})

// 决策事件
capturer.CaptureFromEvent(ctx, &auto.CaptureEvent{
    Type:      auto.EventDecisionMade,
    ProjectID: projectID,
    Data: map[string]any{
        "decision":    "使用 PostgreSQL 而非 MySQL",
        "description": "考虑到 JSON 支持和扩展性",
    },
})

事件类型

const (
    EventTaskCompleted      EventType = "task_completed"      // 任务完成
    EventFeatureImplemented EventType = "feature_implemented" // 功能实现
    EventDecisionMade       EventType = "decision_made"       // 做出决策
    EventPreferenceExpressed EventType = "preference_expressed" // 表达偏好
    EventErrorResolved      EventType = "error_resolved"      // 错误解决
    EventMilestoneReached   EventType = "milestone_reached"   // 达到里程碑
)

标签系统

自动标签提取

捕获器内置默认标签提取器,根据关键词自动添加标签:

// 默认关键词 -> 标签映射
"实现" / "implement" -> #implementation
"修复" / "fix" / "bug" -> #bugfix
"功能" / "feature" -> #feature
"优化" / "optimize" -> #optimization
"重构" / "refactor" -> #refactor
"测试" / "test" -> #testing
"文档" / "doc" -> #documentation
"完成" / "complete" / "done" -> #completed
"前端" / "frontend" -> #frontend
"后端" / "backend" -> #backend
"api" -> #api
"数据库" / "database" -> #database

自定义标签提取器

type TagExtractor interface {
    Extract(text string) []TagSuggestion
}

// 实现自定义提取器
type DomainTagExtractor struct {
    domainKeywords map[string]string
}

func (e *DomainTagExtractor) Extract(text string) []auto.TagSuggestion {
    var suggestions []auto.TagSuggestion
    for keyword, tag := range e.domainKeywords {
        if strings.Contains(strings.ToLower(text), keyword) {
            suggestions = append(suggestions, auto.TagSuggestion{
                Tag:        tag,
                Confidence: 0.8,
                Reason:     "domain keyword: " + keyword,
            })
        }
    }
    return suggestions
}

// 注册自定义提取器
capturer.RegisterTagExtractor(&DomainTagExtractor{
    domainKeywords: map[string]string{
        "machine learning": "ml",
        "deep learning":    "dl",
        "neural network":   "nn",
    },
})

记忆存储

内存存储

store := auto.NewInMemoryStore(&auto.InMemoryStoreConfig{
    MaxMemories: 10000, // 最大记忆数
})

// 存储接口
type Store interface {
    Save(ctx context.Context, memory *Memory) error
    Load(ctx context.Context, id string) (*Memory, error)
    List(ctx context.Context, scope MemoryScope, projectID string, limit int) ([]*Memory, error)
    Search(ctx context.Context, query string, tags []string, limit int) ([]*Memory, error)
    Delete(ctx context.Context, id string) error
}

搜索记忆

// 按关键词搜索
memories, err := store.Search(ctx, "workflow", nil, 10)

// 按标签过滤
memories, err = store.Search(ctx, "", []string{"frontend", "vue"}, 10)

// 组合搜索
memories, err = store.Search(ctx, "实现", []string{"backend"}, 10)

获取统计

stats := store.GetStats()
// {
//   "total_memories": 150,
//   "tag_counts": {"#implementation": 45, "#bugfix": 30, ...},
//   "project_counts": {"project-1": 80, "project-2": 70}
// }

与其他模块集成

结合项目记忆

import (
    "github.com/astercloud/aster/pkg/memory/auto"
    "github.com/astercloud/aster/pkg/memory/project"
)

// 捕获记忆后同步到项目文件
memory, _ := capturer.CaptureFromDialog(ctx, projectID, sessionID, "user", message)
if memory != nil {
    projectStore.AppendEntry(ctx, projectID, project.SectionPreferences, &project.Entry{
        Content: memory.Content,
        Source:  "auto_capture",
    })
}

最佳实践

  1. 设置合适的置信度阈值 - 避免捕获噪音
  2. 使用标签分类 - 便于后续检索和分析
  3. 定期清理 - 删除低价值记忆,保持存储高效
  4. 异步捕获 - 不阻塞主流程
  5. 结合项目记忆 - 重要记忆同步到持久化存储