AI智能体设计模式系列(八)—— 记忆管理模式

有效的记忆管理对于智能 Agent 保留信息至关重要。与人类类似,Agent 需要不同类型的记忆才能高效运 行。本章深入探讨记忆管理,特别关注 Agent 的即时(短期)和持久(长期)记忆需求。

在 Agent 系统中,记忆指代 Agent 保留并利用过去交互、观察和学习经验的能力。这种能力支持 Agent 做 出明智决策、维护对话上下文并随时间持续改进。Agent 记忆通常分为两大主要类型:

短期记忆(上下文记忆):

类似于工作记忆,保存当前处理或最近访问的信息。对于使用大语言模型 (LLM)的 Agent,短期记忆主要存在于上下文窗口中。该窗口包含最近消息、Agent 回复、工具使用结 果以及当前交互中的 Agent 反思,所有这些都为 LLM 的后续响应和操作提供信息支撑。上下文窗口容 量有限,制约了 Agent 可直接访问的近期信息量。高效的短期记忆管理涉及在有限空间内保留最相关 信息,可能通过总结旧对话片段或突出关键细节等技术实现。具有"长上下文"窗口的模型仅扩展了短 期记忆容量,允许单次交互保存更多信息。然而,这种上下文仍是临时的,会话结束即丢失,且每次处理可能成本高昂。因此,Agent 需要独立记忆类型实现真正持久性、调用过往信息并建立持久知识库。

长期记忆(持久记忆):

作为 Agent 跨交互、任务或延长期间所需信息的存储库,类似于长期知识库。

数据通常存储在 Agent 即时处理环境之外,常见于数据库、知识图谱或向量数据库中。在向量数据库中,信息被转换为数字向量存储,使 Agent 能基于语义相似性(而非精确关键字匹配)检索数据,此 过程称为语义搜索。当 Agent 需要长期记忆信息时,会查询外部存储、检索相关数据并集成到短期上 下文供即时使用,从而结合先前知识与当前交互。

模式概览

是什么:

Agent 系统需记住过去交互信息以执行复杂任务并提供连贯体验。缺乏记忆机制时,Agent 无法维 护对话上下文、从经验学习或个性化响应,被限制在简单一次性交互中,无法处理多步骤过程或变化需求。 核心问题是如何有效管理单个对话的即时临时信息和随时间积累的持久知识。

为什么:

标准化解决方案是实现区分短期和长期存储的双组件记忆系统:短期上下文记忆在 LLM 窗口内保 存最近交互维护对话流;长期记忆使用外部数据库(如向量存储)实现高效语义检索。Google ADK 等框架提供特定组件管理此过程(如 Session 管理对话线程,State 处理临时数据)。专用 MemoryService 与长期 知识库交互,允许 Agent 检索相关过去信息纳入当前上下文。

经验法则:

当 Agent 需做更多事(非仅回答单个问题)时使用此模式。对于需维护对话上下文、跟踪多步骤 任务进度或通过回忆用户偏好历史个性化交互的 Agent,此模式必不可少。当 Agent 需基于过去成功/失败 或新信息学习适应时,应实现记忆管理。

图 1:记忆管理设计模式

关键要点

・ 记忆对于Agent跟踪事物、学习和个性化交互至关重要

・ 对话式AI依赖单个聊天中即时上下文的短期内存和跨多个会话持久知识的长期内存

・ 短期记忆(即时信息)是临时的,通常受LLM上下文窗口或框架传递上下文方式的限制

・ 长期记忆(持久信息)使用向量数据库等外部存储跨不同聊天保存信息,并通过搜索访问

・ LangChain提供如ConversationBufferMemory的实用工具,自动将单个对话历史注入提示,使Agent能回忆即时上下文

・ LangGraph 通过使用存储来保存和检索跨不同用户会话的语义事实、情景经验甚至可更新程序规则,实现高级长期内存

实际应用与用例

记忆管理对于 Agent 跟踪信息并随时间智能执行至关重要。这是 Agent 超越基本问答能力的必要条件。主要 应用包括:

  • ・ 聊天机器人与对话式 AI:维护对话流程依赖短期记忆。聊天机器人需记住先前用户输入以提供连贯响 应。长期记忆使聊天机器人能回忆用户偏好、过往问题或先前讨论,提供个性化和持续交互

  • ・ 面向任务的 Agent:管理多步骤任务的 Agent 需要短期记忆跟踪先前步骤、当前进度和总体目标。此 类信息可能驻留于任务上下文或临时存储中。长期记忆对于访问不在即时上下文中的特定用户相关数 据至关重要

  • ・ 个性化体验:提供定制交互的 Agent 利用长期记忆存储和检索用户偏好、过往行为和个人信息。这使 Agent 能调整其响应和建议

  • ・ 学习与改进: Agent 可通过从过去交互中学习来提升性能。成功策略、错误和新信息存储于长期记忆 中,促进未来适应。强化学习 Agent 以此方式存储学习策略或知识

  • ・ 信息检索(RAG):设计用于回答问题的 Agent 访问知识库(即其长期记忆),通常在检索增强生成 (RAG)中实现。Agent 检索相关文档或数据以指导其响应

    ・ 自主系统:机器人或自动驾驶汽车需要记忆存储地图、路线、对象位置和学习行为。这涉及用于即时 环境的短期记忆和用于通用环境知识的长期记忆

LangChain 和 LangGraph 中的记忆管理

在 LangChain 和 LangGraph 中,Memory 是创建智能自然对话应用的关键组件。它使 AI Agent 能够记住过 去交互信息、从反馈中学习并适应用户偏好。LangChain 的记忆功能通过引用存储历史来丰富当前提示,然 后记录最新交换供将来使用,从而提供此基础。随着 Agent 处理更复杂任务,这种能力对效率和用户满意度 变得至关重要。

短期记忆:

这是线程范围的,意味着它跟踪单个会话或线程内正在进行的对话。它提供即时上下文,但完整 历史可能挑战 LLM 的上下文窗口,导致错误或性能下降。LangGraph 将短期记忆作为 Agent 状态的一部分 管理,该状态通过检查点器持久化,允许随时恢复线程。

长期记忆:

存储跨会话的用户特定或应用级数据,在对话线程间共享。它保存在自定义"命名空间"中,可 在任何线程的任何时间调用。LangGraph 提供存储来保存和调用长期记忆,使 Agent 能无限期保留知识。

LangChain 提供了多种工具管理对话历史,从手动控制到链内自动集成

记忆管理应用案例DEMO

设计一个记忆管理系统,它可以与Agent集成,跟踪对话历史、用户偏好和任务上下文。

记忆管理系统将包括:

  1. 短期记忆:存储当前会话的对话历史和上下文。

  2. 长期记忆:存储用户偏好、历史对话摘要、学习到的知识等,可以跨会话使用。

  3. 记忆检索:根据当前上下文从长期记忆中检索相关信息。

我们将使用向量存储(vector store)来存储长期记忆,以便进行相似性检索。同时,我们也会使用传统数据库来存储结构化记忆。

设计思路:

  • 1、每个Agent都有自己的记忆系统。

  • 2、短期记忆使用一个固定大小的队列,存储最近的交互。

  • 3、长期记忆使用向量数据库(如Qdrant)存储记忆片段,每个记忆片段包括内容、时间戳、重要性分数等元数据。

  • 4、定期将短期记忆中的重要信息存储到长期记忆中。

步骤:

  1. 1、定义记忆结构。

  2. 2、实现短期记忆(RecentMemory)。

  3. 3、实现长期记忆(LongTermMemory),包括存储和检索。

  4. 4、实现记忆管理(MemoryManager)来协调短期和长期记忆。

  5. 5、将记忆系统集成到Agent中。

项目结构

html 复制代码
memory-system/
├── internal/
│   ├── memory/
│   │   ├── manager.go
│   │   ├── short_term.go
│   │   ├── long_term.go
│   │   ├── episodic.go
│   │   ├── semantic.go
│   │   ├── procedural.go
│   │   └── retrieval.go
│   ├── vector/
│   │   ├── store.go
│   │   ├── embedding.go
│   │   └── similarity.go
│   ├── agent/
│   │   └── cognitive.go
│   └── orchestration/
│       └── workflow.go
├── pkg/
│   ├── langchain/
│   └── langgraph/
├── examples/
└── deployments/

1. 记忆管理核心系统

internal/memory/manager.go

Go 复制代码
package memory

import (
	"context"
	"encoding/json"
	"fmt"
	"log"
	"sync"
	"time"

	"memory-system/internal/vector"
)

type MemoryType string

const (
	MemoryTypeShortTerm   MemoryType = "short_term"
	MemoryTypeLongTerm    MemoryType = "long_term"
	MemoryTypeEpisodic    MemoryType = "episodic"
	MemoryTypeSemantic    MemoryType = "semantic"
	MemoryTypeProcedural  MemoryType = "procedural"
	MemoryTypeWorking     MemoryType = "working"
)

type ImportanceLevel int

const (
	ImportanceLow    ImportanceLevel = 1
	ImportanceMedium ImportanceLevel = 3
	ImportanceHigh   ImportanceLevel = 5
	ImportanceCritical ImportanceLevel = 10
)

type Memory struct {
	ID           string                 `json:"id"`
	Content      string                 `json:"content"`
	Embedding    []float32              `json:"embedding,omitempty"`
	Metadata     map[string]interface{} `json:"metadata"`
	MemoryType   MemoryType             `json:"memory_type"`
	Importance   ImportanceLevel        `json:"importance"`
	CreatedAt    time.Time              `json:"created_at"`
	LastAccessed time.Time              `json:"last_accessed"`
	AccessCount  int                    `json:"access_count"`
	DecayFactor  float64                `json:"decay_factor"` // 0-1, 1表示不衰减
	Tags         []string               `json:"tags"`
	Relations    []string               `json:"relations"` // 相关记忆ID
}

type MemoryManager struct {
	shortTerm     *ShortTermMemory
	longTerm      *LongTermMemory
	episodic      *EpisodicMemory
	semantic      *SemanticMemory
	procedural    *ProceduralMemory
	vectorStore   *vector.Store
	compressor    *MemoryCompressor
	retriever     *MemoryRetriever
	mu            sync.RWMutex
	agentID       string
	config        MemoryConfig
}

type MemoryConfig struct {
	ShortTermCapacity    int           `json:"short_term_capacity"`
	ShortTermTTL         time.Duration `json:"short_term_ttl"`
	CompressionThreshold int           `json:"compression_threshold"`
	RetentionPeriod      time.Duration `json:"retention_period"`
	ImportanceThreshold  ImportanceLevel `json:"importance_threshold"`
}

func NewMemoryManager(agentID string, config MemoryConfig) *MemoryManager {
	vs := vector.NewStore(fmt.Sprintf("memory_%s", agentID))
	
	return &MemoryManager{
		shortTerm:    NewShortTermMemory(config.ShortTermCapacity),
		longTerm:     NewLongTermMemory(vs),
		episodic:     NewEpisodicMemory(vs),
		semantic:     NewSemanticMemory(vs),
		procedural:   NewProceduralMemory(),
		vectorStore:  vs,
		compressor:   NewMemoryCompressor(),
		retriever:    NewMemoryRetriever(vs),
		agentID:      agentID,
		config:       config,
	}
}

// 记忆存储接口
func (mm *MemoryManager) Store(ctx context.Context, content string, memoryType MemoryType, metadata map[string]interface{}) (string, error) {
	mm.mu.Lock()
	defer mm.mu.Unlock()
	
	// 评估记忆重要性
	importance := mm.evaluateImportance(content, metadata, memoryType)
	
	// 创建记忆对象
	memory := &Memory{
		ID:           generateMemoryID(),
		Content:      content,
		MemoryType:   memoryType,
		Importance:   importance,
		Metadata:     metadata,
		CreatedAt:    time.Now(),
		LastAccessed: time.Now(),
		DecayFactor:  mm.calculateDecayFactor(importance),
		Tags:         extractTags(content, metadata),
	}
	
	// 根据记忆类型存储到相应系统
	switch memoryType {
	case MemoryTypeShortTerm:
		return mm.shortTerm.Store(memory)
	case MemoryTypeEpisodic:
		return mm.episodic.Store(ctx, memory)
	case MemoryTypeSemantic:
		return mm.semantic.Store(ctx, memory)
	case MemoryTypeProcedural:
		return mm.procedural.Store(memory)
	default:
		// 默认存储到长期记忆
		return mm.longTerm.Store(ctx, memory)
	}
}

// 记忆检索接口
func (mm *MemoryManager) Retrieve(ctx context.Context, query string, memoryTypes []MemoryType, limit int) ([]*Memory, error) {
	mm.mu.RLock()
	defer mm.mu.RUnlock()
	
	var allResults []*Memory
	
	// 从短期记忆检索
	if contains(memoryTypes, MemoryTypeShortTerm) {
		shortTermResults := mm.shortTerm.Search(query, limit)
		allResults = append(allResults, shortTermResults...)
	}
	
	// 从长期记忆检索(向量相似性搜索)
	if len(memoryTypes) > 0 && !onlyShortTerm(memoryTypes) {
		longTermResults, err := mm.retriever.Retrieve(ctx, query, memoryTypes, limit)
		if err != nil {
			log.Printf("Long term memory retrieval error: %v", err)
		} else {
			allResults = append(allResults, longTermResults...)
		}
	}
	
	// 按相关性排序
	scoredResults := mm.scoreAndRank(allResults, query)
	
	// 更新访问记录
	for _, memory := range scoredResults {
		mm.updateAccess(memory.ID)
	}
	
	return scoredResults, nil
}

// 上下文增强检索(类似RAG)
func (mm *MemoryManager) RetrieveWithContext(ctx context.Context, query string, contextInfo map[string]interface{}, limit int) ([]*Memory, error) {
	// 构建增强查询
	enhancedQuery := mm.buildEnhancedQuery(query, contextInfo)
	
	// 检索相关记忆
	memories, err := mm.Retrieve(ctx, enhancedQuery, []MemoryType{
		MemoryTypeEpisodic,
		MemoryTypeSemantic,
		MemoryTypeLongTerm,
	}, limit)
	if err != nil {
		return nil, err
	}
	
	// 基于上下文过滤和排序
	filtered := mm.contextualFilter(memories, contextInfo)
	
	return filtered, nil
}

// 记忆压缩和巩固
func (mm *MemoryManager) Consolidate(ctx context.Context) error {
	mm.mu.Lock()
	defer mm.mu.Unlock()
	
	// 检查是否需要压缩短期记忆
	if mm.shortTerm.Count() > mm.config.CompressionThreshold {
		log.Printf("Memory consolidation triggered for agent %s", mm.agentID)
		
		// 获取短期记忆
		shortTermMemories := mm.shortTerm.GetAll()
		
		// 压缩和转移到长期记忆
		compressed, err := mm.compressor.Compress(shortTermMemories)
		if err != nil {
			return err
		}
		
		// 存储压缩后的记忆
		for _, memory := range compressed {
			memory.MemoryType = MemoryTypeLongTerm
			if _, err := mm.longTerm.Store(ctx, memory); err != nil {
				log.Printf("Failed to store compressed memory: %v", err)
			}
		}
		
		// 清理短期记忆
		mm.shortTerm.Clear()
		
		log.Printf("Consolidated %d memories into long-term storage", len(compressed))
	}
	
	// 清理过期或低重要性的记忆
	if err := mm.cleanup(ctx); err != nil {
		return err
	}
	
	return nil
}

// 记忆重要性评估
func (mm *MemoryManager) evaluateImportance(content string, metadata map[string]interface{}, memoryType MemoryType) ImportanceLevel {
	importance := ImportanceMedium
	
	// 基于内容长度和复杂性
	contentLength := len(content)
	if contentLength > 500 {
		importance = ImportanceHigh
	}
	
	// 基于情感强度
	if sentiment, ok := metadata["sentiment"].(float64); ok {
		if sentiment > 0.7 || sentiment < -0.7 {
			importance = ImportanceHigh
		}
	}
	
	// 基于用户交互
	if interactionType, ok := metadata["interaction_type"].(string); ok {
		switch interactionType {
		case "correction", "feedback", "preference":
			importance = ImportanceHigh
		case "question", "command":
			importance = ImportanceMedium
		default:
			importance = ImportanceLow
		}
	}
	
	// 基于记忆类型
	switch memoryType {
	case MemoryTypeEpisodic:
		importance = ImportanceHigh // 经历性记忆通常重要
	case MemoryTypeProcedural:
		importance = ImportanceCritical // 程序性记忆对任务执行关键
	}
	
	// 基于重复频率
	if frequency, ok := metadata["frequency"].(int); ok && frequency > 5 {
		importance = ImportanceHigh
	}
	
	return importance
}

// 记忆衰减和遗忘
func (mm *MemoryManager) calculateDecayFactor(importance ImportanceLevel) float64 {
	// 重要性越高,衰减越慢
	baseDecay := 0.95
	importanceFactor := float64(importance) / 10.0
	
	return baseDecay * importanceFactor
}

// 记忆更新和强化
func (mm *MemoryManager) Reinforce(memoryID string, reinforcement float64) error {
	mm.mu.Lock()
	defer mm.mu.Unlock()
	
	// 更新衰减因子,强化记忆
	// 这里简化实现,实际应该更新所有存储中的记忆
	return nil
}

// 记忆关联发现
func (mm *MemoryManager) DiscoverAssociations(ctx context.Context, memoryID string) ([]*Memory, error) {
	memory, err := mm.retriever.GetByID(ctx, memoryID)
	if err != nil {
		return nil, err
	}
	
	// 基于内容和元数据发现关联
	associations, err := mm.findRelatedMemories(ctx, memory)
	if err != nil {
		return nil, err
	}
	
	// 更新关联关系
	memory.Relations = make([]string, len(associations))
	for i, assoc := range associations {
		memory.Relations[i] = assoc.ID
	}
	
	return associations, nil
}

2. 短期记忆实现

internal/memory/short_term.go

Go 复制代码
package memory

import (
	"container/list"
	"strings"
	"sync"
	"time"
)

type ShortTermMemory struct {
	items      *list.List
	capacity   int
	ttl        time.Duration
	mu         sync.RWMutex
	accessLog  map[string]time.Time
	importance map[string]ImportanceLevel
}

func NewShortTermMemory(capacity int) *ShortTermMemory {
	return &ShortTermMemory{
		items:      list.New(),
		capacity:   capacity,
		ttl:        30 * time.Minute, // 默认30分钟TTL
		accessLog:  make(map[string]time.Time),
		importance: make(map[string]ImportanceLevel),
	}
}

func (stm *ShortTermMemory) Store(memory *Memory) (string, error) {
	stm.mu.Lock()
	defer stm.mu.Unlock()
	
	// 检查是否达到容量限制
	if stm.items.Len() >= stm.capacity {
		// 移除最旧或最不重要的记忆
		stm.evict()
	}
	
	// 添加到链表前端(最近使用的在前)
	stm.items.PushFront(memory)
	
	// 记录元数据
	stm.accessLog[memory.ID] = time.Now()
	stm.importance[memory.ID] = memory.Importance
	
	return memory.ID, nil
}

func (stm *ShortTermMemory) Retrieve(memoryID string) (*Memory, bool) {
	stm.mu.RLock()
	defer stm.mu.RUnlock()
	
	// 查找记忆
	for e := stm.items.Front(); e != nil; e = e.Next() {
		memory := e.Value.(*Memory)
		if memory.ID == memoryID {
			// 更新访问时间
			stm.accessLog[memoryID] = time.Now()
			return memory, true
		}
	}
	
	return nil, false
}

func (stm *ShortTermMemory) Search(query string, limit int) []*Memory {
	stm.mu.RLock()
	defer stm.mu.RUnlock()
	
	var results []*Memory
	
	for e := stm.items.Front(); e != nil && len(results) < limit; e = e.Next() {
		memory := e.Value.(*Memory)
		
		// 简单文本匹配(实际应该使用嵌入向量)
		if strings.Contains(strings.ToLower(memory.Content), strings.ToLower(query)) {
			results = append(results, memory)
			
			// 更新访问时间
			stm.accessLog[memory.ID] = time.Now()
		}
	}
	
	return results
}

func (stm *ShortTermMemory) GetAll() []*Memory {
	stm.mu.RLock()
	defer stm.mu.RUnlock()
	
	var memories []*Memory
	for e := stm.items.Front(); e != nil; e = e.Next() {
		memories = append(memories, e.Value.(*Memory))
	}
	
	return memories
}

func (stm *ShortTermMemory) evict() {
	// 基于重要性、访问频率和时间的复杂淘汰策略
	
	// 首先移除过期的记忆
	stm.removeExpired()
	
	// 如果仍然需要空间,移除最不重要的
	if stm.items.Len() >= stm.capacity {
		var toRemove *list.Element
		lowestImportance := ImportanceCritical
		
		for e := stm.items.Back(); e != nil; e = e.Prev() {
			memory := e.Value.(*Memory)
			importance := stm.importance[memory.ID]
			
			if importance < lowestImportance {
				lowestImportance = importance
				toRemove = e
			}
		}
		
		if toRemove != nil {
			memory := toRemove.Value.(*Memory)
			delete(stm.accessLog, memory.ID)
			delete(stm.importance, memory.ID)
			stm.items.Remove(toRemove)
		}
	}
}

func (stm *ShortTermMemory) removeExpired() {
	now := time.Now()
	
	for e := stm.items.Front(); e != nil; {
		next := e.Next()
		memory := e.Value.(*Memory)
		
		if lastAccess, ok := stm.accessLog[memory.ID]; ok {
			if now.Sub(lastAccess) > stm.ttl {
				// 记忆过期,移除
				delete(stm.accessLog, memory.ID)
				delete(stm.importance, memory.ID)
				stm.items.Remove(e)
			}
		}
		
		e = next
	}
}

func (stm *ShortTermMemory) Clear() {
	stm.mu.Lock()
	defer stm.mu.Unlock()
	
	stm.items.Init()
	stm.accessLog = make(map[string]time.Time)
	stm.importance = make(map[string]ImportanceLevel)
}

func (stm *ShortTermMemory) Count() int {
	stm.mu.RLock()
	defer stm.mu.RUnlock()
	return stm.items.Len()
}

// 工作记忆实现(类似人类工作记忆)
type WorkingMemory struct {
	shortTerm      *ShortTermMemory
	focus          *Memory // 当前焦点
	chunkSize      int
	rehearsalTimer *time.Timer
}

func NewWorkingMemory(capacity, chunkSize int) *WorkingMemory {
	return &WorkingMemory{
		shortTerm: NewShortTermMemory(capacity),
		chunkSize: chunkSize,
	}
}

func (wm *WorkingMemory) SetFocus(memory *Memory) {
	wm.focus = memory
	
	// 启动复述计时器(防止遗忘)
	if wm.rehearsalTimer != nil {
		wm.rehearsalTimer.Stop()
	}
	
	wm.rehearsalTimer = time.AfterFunc(30*time.Second, func() {
		wm.rehearse()
	})
}

func (wm *WorkingMemory) rehearse() {
	if wm.focus != nil {
		// 复述增强记忆
		wm.shortTerm.Store(wm.focus)
		
		// 重新启动计时器
		wm.rehearsalTimer = time.AfterFunc(30*time.Second, func() {
			wm.rehearse()
		})
	}
}

func (wm *WorkingMemory) Chunk(memories []*Memory) [][]*Memory {
	var chunks [][]*Memory
	for i := 0; i < len(memories); i += wm.chunkSize {
		end := i + wm.chunkSize
		if end > len(memories) {
			end = len(memories)
		}
		chunks = append(chunks, memories[i:end])
	}
	return chunks
}

3. 长期记忆系统

internal/memory/long_term.go

Go 复制代码
package memory

import (
	"context"
	"encoding/json"
	"fmt"
	"log"
	"time"

	"memory-system/internal/vector"
)

type LongTermMemory struct {
	vectorStore *vector.Store
	namespace   string
	index       map[string]*Memory
	mu          sync.RWMutex
}

func NewLongTermMemory(vs *vector.Store) *LongTermMemory {
	return &LongTermMemory{
		vectorStore: vs,
		namespace:   "long_term",
		index:       make(map[string]*Memory),
	}
}

func (ltm *LongTermMemory) Store(ctx context.Context, memory *Memory) (string, error) {
	ltm.mu.Lock()
	defer ltm.mu.Unlock()
	
	// 生成嵌入向量
	if len(memory.Embedding) == 0 {
		embedding, err := ltm.vectorStore.Embedder.Embed(memory.Content)
		if err != nil {
			return "", fmt.Errorf("failed to generate embedding: %v", err)
		}
		memory.Embedding = embedding
	}
	
	// 存储到向量数据库
	if err := ltm.vectorStore.Upsert(ctx, ltm.namespace, memory.ID, memory.Embedding, memory.Metadata); err != nil {
		return "", err
	}
	
	// 序列化并存储完整记忆对象
	data, err := json.Marshal(memory)
	if err != nil {
		return "", err
	}
	
	// 存储到持久化存储(这里简化,实际应该用数据库)
	if err := ltm.vectorStore.Set(ctx, fmt.Sprintf("memory:%s", memory.ID), data); err != nil {
		return "", err
	}
	
	// 更新索引
	ltm.index[memory.ID] = memory
	
	// 记录存储日志
	log.Printf("Stored long-term memory: %s (importance: %d)", memory.ID, memory.Importance)
	
	return memory.ID, nil
}

func (ltm *LongTermMemory) Retrieve(ctx context.Context, memoryID string) (*Memory, error) {
	ltm.mu.RLock()
	
	// 先从内存索引查找
	if memory, exists := ltm.index[memoryID]; exists {
		ltm.mu.RUnlock()
		ltm.updateAccess(memory)
		return memory, nil
	}
	ltm.mu.RUnlock()
	
	// 从持久化存储加载
	data, err := ltm.vectorStore.Get(ctx, fmt.Sprintf("memory:%s", memoryID))
	if err != nil {
		return nil, err
	}
	
	var memory Memory
	if err := json.Unmarshal(data, &memory); err != nil {
		return nil, err
	}
	
	// 更新索引
	ltm.mu.Lock()
	ltm.index[memoryID] = &memory
	ltm.mu.Unlock()
	
	ltm.updateAccess(&memory)
	
	return &memory, nil
}

func (ltm *LongTermMemory) Search(ctx context.Context, query string, limit int) ([]*Memory, error) {
	// 生成查询的嵌入向量
	queryEmbedding, err := ltm.vectorStore.Embedder.Embed(query)
	if err != nil {
		return nil, err
	}
	
	// 在向量空间搜索
	results, err := ltm.vectorStore.Search(ctx, ltm.namespace, queryEmbedding, limit)
	if err != nil {
		return nil, err
	}
	
	// 加载完整记忆对象
	var memories []*Memory
	for _, result := range results {
		memory, err := ltm.Retrieve(ctx, result.ID)
		if err != nil {
			log.Printf("Failed to retrieve memory %s: %v", result.ID, err)
			continue
		}
		
		// 计算相关性分数
		memory.Metadata["relevance_score"] = result.Score
		memories = append(memories, memory)
		
		// 更新访问记录
		ltm.updateAccess(memory)
	}
	
	return memories, nil
}

func (ltm *LongTermMemory) updateAccess(memory *Memory) {
	memory.LastAccessed = time.Now()
	memory.AccessCount++
	
	// 异步更新存储
	go func() {
		data, err := json.Marshal(memory)
		if err != nil {
			log.Printf("Failed to marshal memory for update: %v", err)
			return
		}
		
		ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
		defer cancel()
		
		if err := ltm.vectorStore.Set(ctx, fmt.Sprintf("memory:%s", memory.ID), data); err != nil {
			log.Printf("Failed to update memory access record: %v", err)
		}
	}()
}

// 记忆清理:移除过期或低重要性的记忆
func (ltm *LongTermMemory) Cleanup(ctx context.Context, threshold ImportanceLevel, maxAge time.Duration) error {
	ltm.mu.Lock()
	defer ltm.mu.Unlock()
	
	var toDelete []string
	now := time.Now()
	
	for id, memory := range ltm.index {
		// 检查重要性
		if memory.Importance < threshold {
			// 检查是否很久没访问
			if now.Sub(memory.LastAccessed) > maxAge {
				toDelete = append(toDelete, id)
			}
		}
	}
	
	// 执行删除
	for _, id := range toDelete {
		// 从向量存储删除
		if err := ltm.vectorStore.Delete(ctx, ltm.namespace, id); err != nil {
			log.Printf("Failed to delete vector for memory %s: %v", id, err)
		}
		
		// 从键值存储删除
		if err := ltm.vectorStore.Del(ctx, fmt.Sprintf("memory:%s", id)); err != nil {
			log.Printf("Failed to delete memory %s: %v", id, err)
		}
		
		// 从索引删除
		delete(ltm.index, id)
		
		log.Printf("Cleaned up memory: %s", id)
	}
	
	return nil
}

// 记忆关联图
type MemoryGraph struct {
	nodes map[string]*MemoryNode
	edges map[string][]*MemoryEdge
}

type MemoryNode struct {
	Memory  *Memory
	Centrality float64
}

type MemoryEdge struct {
	SourceID string
	TargetID string
	Weight   float64 // 关联强度
	Type     string  // 关联类型:similar, temporal, causal, etc.
}

func NewMemoryGraph() *MemoryGraph {
	return &MemoryGraph{
		nodes: make(map[string]*MemoryNode),
		edges: make(map[string][]*MemoryEdge),
	}
}

func (mg *MemoryGraph) AddMemory(memory *Memory) {
	mg.nodes[memory.ID] = &MemoryNode{
		Memory: memory,
	}
}

func (mg *MemoryGraph) AddEdge(sourceID, targetID string, weight float64, edgeType string) {
	edge := &MemoryEdge{
		SourceID: sourceID,
		TargetID: targetID,
		Weight:   weight,
		Type:     edgeType,
	}
	
	mg.edges[sourceID] = append(mg.edges[sourceID], edge)
	
	// 无向图,添加反向边
	reverseEdge := &MemoryEdge{
		SourceID: targetID,
		TargetID: sourceID,
		Weight:   weight,
		Type:     edgeType,
	}
	mg.edges[targetID] = append(mg.edges[targetID], reverseEdge)
}

func (mg *MemoryGraph) FindRelated(memoryID string, limit int) []*Memory {
	var related []*Memory
	
	if edges, exists := mg.edges[memoryID]; exists {
		// 按权重排序
		sortEdgesByWeight(edges)
		
		for i := 0; i < len(edges) && i < limit; i++ {
			if node, ok := mg.nodes[edges[i].TargetID]; ok {
				related = append(related, node.Memory)
			}
		}
	}
	
	return related
}

// 计算中心性(识别重要记忆节点)
func (mg *MemoryGraph) CalculateCentrality() {
	for id := range mg.nodes {
		// 简单度中心性
		degree := len(mg.edges[id])
		mg.nodes[id].Centrality = float64(degree)
	}
}

4. 经历性记忆和语义记忆

internal/memory/episodic.go

Go 复制代码
package memory

import (
	"context"
	"encoding/json"
	"fmt"
	"time"

	"memory-system/internal/vector"
)

// 经历性记忆:存储具体事件和经历
type EpisodicMemory struct {
	vectorStore *vector.Store
	namespace   string
	timeIndex   *TimeIndex
}

type Event struct {
	Memory
	Timestamp   time.Time              `json:"timestamp"`
	Location    string                 `json:"location,omitempty"`
	Participants []string              `json:"participants,omitempty"`
	Emotion     string                 `json:"emotion,omitempty"`
	Significance float64               `json:"significance"` // 0-1
}

func NewEpisodicMemory(vs *vector.Store) *EpisodicMemory {
	return &EpisodicMemory{
		vectorStore: vs,
		namespace:   "episodic",
		timeIndex:   NewTimeIndex(),
	}
}

func (em *EpisodicMemory) Store(ctx context.Context, memory *Memory) (string, error) {
	// 转换为事件
	event := &Event{
		Memory:      *memory,
		Timestamp:   time.Now(),
		Significance: em.calculateSignificance(memory),
	}
	
	// 提取事件元数据
	em.extractEventMetadata(event)
	
	// 生成时间序列索引
	em.timeIndex.Add(event.ID, event.Timestamp, event.Significance)
	
	// 存储到向量数据库
	embedding, err := em.vectorStore.Embedder.Embed(event.Content)
	if err != nil {
		return "", err
	}
	event.Embedding = embedding
	
	// 序列化事件
	data, err := json.Marshal(event)
	if err != nil {
		return "", err
	}
	
	// 存储
	if err := em.vectorStore.Upsert(ctx, em.namespace, event.ID, embedding, map[string]interface{}{
		"type":        "episodic",
		"timestamp":   event.Timestamp,
		"significance": event.Significance,
		"data":        string(data),
	}); err != nil {
		return "", err
	}
	
	return event.ID, nil
}

func (em *EpisodicMemory) RetrieveByTime(ctx context.Context, start, end time.Time, limit int) ([]*Event, error) {
	// 从时间索引获取事件ID
	eventIDs := em.timeIndex.GetRange(start, end, limit)
	
	// 加载事件
	var events []*Event
	for _, id := range eventIDs {
		event, err := em.loadEvent(ctx, id)
		if err != nil {
			continue
		}
		events = append(events, event)
	}
	
	return events, nil
}

func (em *EpisodicMemory) RetrieveSimilarEvents(ctx context.Context, query string, limit int) ([]*Event, error) {
	// 向量相似性搜索
	queryEmbedding, err := em.vectorStore.Embedder.Embed(query)
	if err != nil {
		return nil, err
	}
	
	results, err := em.vectorStore.Search(ctx, em.namespace, queryEmbedding, limit)
	if err != nil {
		return nil, err
	}
	
	var events []*Event
	for _, result := range results {
		// 解析事件数据
		var event Event
		dataStr, ok := result.Metadata["data"].(string)
		if !ok {
			continue
		}
		
		if err := json.Unmarshal([]byte(dataStr), &event); err != nil {
			continue
		}
		
		event.Metadata["relevance_score"] = result.Score
		events = append(events, &event)
	}
	
	return events, nil
}

// 时间线重建
func (em *EpisodicMemory) ReconstructTimeline(ctx context.Context, start, end time.Time) ([]*Event, error) {
	// 获取时间范围内的事件
	events, err := em.RetrieveByTime(ctx, start, end, 1000)
	if err != nil {
		return nil, err
	}
	
	// 按时间排序
	sort.Slice(events, func(i, j int) bool {
		return events[i].Timestamp.Before(events[j].Timestamp)
	})
	
	return events, nil
}

// 经历性记忆整合(形成故事)
func (em *EpisodicMemory) IntegrateIntoStory(ctx context.Context, eventIDs []string) (string, error) {
	var events []*Event
	for _, id := range eventIDs {
		event, err := em.loadEvent(ctx, id)
		if err != nil {
			continue
		}
		events = append(events, event)
	}
	
	// 按时间排序
	sort.Slice(events, func(i, j int) bool {
		return events[i].Timestamp.Before(events[j].Timestamp)
	})
	
	// 生成故事叙述
	story := em.generateNarrative(events)
	
	return story, nil
}

func (em *EpisodicMemory) calculateSignificance(memory *Memory) float64 {
	significance := 0.5 // 基础值
	
	// 基于重要性
	significance += float64(memory.Importance) * 0.1
	
	// 基于情感强度
	if sentiment, ok := memory.Metadata["sentiment"].(float64); ok {
		significance += math.Abs(sentiment) * 0.2
	}
	
	// 基于新颖性(与其他记忆的相似度)
	// 这里简化实现
	
	return math.Min(significance, 1.0)
}

internal/memory/semantic.go

Go 复制代码
package memory

import (
	"context"
	"encoding/json"
	"fmt"

	"memory-system/internal/vector"
)

// 语义记忆:存储事实、概念和知识
type SemanticMemory struct {
	vectorStore *vector.Store
	namespace   string
	concepts    map[string]*Concept
	ontology    *Ontology
}

type Fact struct {
	Memory
	Subject    string                 `json:"subject"`
	Predicate  string                 `json:"predicate"`
	Object     interface{}            `json:"object"`
	Confidence float64                `json:"confidence"`
	Sources    []string               `json:"sources"` // 信息来源
}

type Concept struct {
	Name       string                 `json:"name"`
	Definition string                 `json:"definition"`
	Attributes map[string]interface{} `json:"attributes"`
	Instances  []string               `json:"instances"` // 实例ID
	Relations  map[string][]string    `json:"relations"` // 相关概念
}

type Ontology struct {
	concepts   map[string]*Concept
	hierarchy  map[string][]string // 父子关系
	properties map[string][]string // 概念属性
}

func NewSemanticMemory(vs *vector.Store) *SemanticMemory {
	return &SemanticMemory{
		vectorStore: vs,
		namespace:   "semantic",
		concepts:    make(map[string]*Concept),
		ontology:    NewOntology(),
	}
}

func (sm *SemanticMemory) Store(ctx context.Context, memory *Memory) (string, error) {
	// 解析语义内容
	fact, err := sm.parseFact(memory.Content)
	if err != nil {
		// 如果不是事实,可能是一个概念定义
		concept, err := sm.parseConcept(memory.Content)
		if err != nil {
			// 作为一般语义记忆存储
			return sm.storeGenericSemantic(ctx, memory)
		}
		return sm.storeConcept(ctx, concept)
	}
	
	return sm.storeFact(ctx, fact)
}

func (sm *SemanticMemory) storeFact(ctx context.Context, fact *Fact) (string, error) {
	// 生成事实的嵌入向量
	embedding, err := sm.vectorStore.Embedder.Embed(fmt.Sprintf("%s %s %v", 
		fact.Subject, fact.Predicate, fact.Object))
	if err != nil {
		return "", err
	}
	
	fact.Embedding = embedding
	
	// 序列化事实
	data, err := json.Marshal(fact)
	if err != nil {
		return "", err
	}
	
	// 存储到向量数据库
	metadata := map[string]interface{}{
		"type":       "fact",
		"subject":    fact.Subject,
		"predicate":  fact.Predicate,
		"object":     fact.Object,
		"confidence": fact.Confidence,
		"data":       string(data),
	}
	
	if err := sm.vectorStore.Upsert(ctx, sm.namespace, fact.ID, embedding, metadata); err != nil {
		return "", err
	}
	
	// 更新概念系统
	sm.updateConceptWithFact(fact)
	
	return fact.ID, nil
}

func (sm *SemanticMemory) storeConcept(ctx context.Context, concept *Concept) (string, error) {
	// 生成概念的嵌入向量
	embedding, err := sm.vectorStore.Embedder.Embed(concept.Definition)
	if err != nil {
		return "", err
	}
	
	// 存储概念
	sm.concepts[concept.Name] = concept
	sm.ontology.AddConcept(concept)
	
	// 存储到向量数据库
	metadata := map[string]interface{}{
		"type":       "concept",
		"name":       concept.Name,
		"definition": concept.Definition,
		"attributes": concept.Attributes,
	}
	
	if err := sm.vectorStore.Upsert(ctx, sm.namespace, concept.Name, embedding, metadata); err != nil {
		return "", err
	}
	
	return concept.Name, nil
}

// 事实查询
func (sm *SemanticMemory) QueryFacts(ctx context.Context, subject, predicate string, limit int) ([]*Fact, error) {
	// 构建查询
	query := subject
	if predicate != "" {
		query = fmt.Sprintf("%s %s", subject, predicate)
	}
	
	// 向量搜索
	queryEmbedding, err := sm.vectorStore.Embedder.Embed(query)
	if err != nil {
		return nil, err
	}
	
	results, err := sm.vectorStore.Search(ctx, sm.namespace, queryEmbedding, limit)
	if err != nil {
		return nil, err
	}
	
	var facts []*Fact
	for _, result := range results {
		if resultType, ok := result.Metadata["type"].(string); ok && resultType == "fact" {
			dataStr, ok := result.Metadata["data"].(string)
			if !ok {
				continue
			}
			
			var fact Fact
			if err := json.Unmarshal([]byte(dataStr), &fact); err != nil {
				continue
			}
			
			facts = append(facts, &fact)
		}
	}
	
	return facts, nil
}

// 推理:基于现有事实推断新事实
func (sm *SemanticMemory) Infer(ctx context.Context, subject, predicate string) (interface{}, float64, error) {
	// 查找直接事实
	facts, err := sm.QueryFacts(ctx, subject, predicate, 5)
	if err != nil {
		return nil, 0, err
	}
	
	// 如果有直接事实,返回置信度最高的
	if len(facts) > 0 {
		bestFact := facts[0]
		for _, fact := range facts[1:] {
			if fact.Confidence > bestFact.Confidence {
				bestFact = fact
			}
		}
		return bestFact.Object, bestFact.Confidence, nil
	}
	
	// 如果没有直接事实,尝试推理
	// 1. 查找相似主体
	// 2. 查找属性继承
	// 3. 查找规则应用
	
	return nil, 0, fmt.Errorf("cannot infer fact")
}

// 知识图谱查询
func (sm *SemanticMemory) QueryKnowledgeGraph(ctx context.Context, startConcept string, depth int) (map[string][]string, error) {
	graph := make(map[string][]string)
	
	// BFS遍历概念关系
	queue := []string{startConcept}
	visited := make(map[string]bool)
	currentDepth := 0
	
	for len(queue) > 0 && currentDepth <= depth {
		levelSize := len(queue)
		
		for i := 0; i < levelSize; i++ {
			concept := queue[0]
			queue = queue[1:]
			
			if visited[concept] {
				continue
			}
			visited[concept] = true
			
			// 获取相关概念
			if c, exists := sm.concepts[concept]; exists {
				graph[concept] = []string{}
				for relType, relatedConcepts := range c.Relations {
					for _, related := range relatedConcepts {
						graph[concept] = append(graph[concept], fmt.Sprintf("%s:%s", relType, related))
						if !visited[related] {
							queue = append(queue, related)
						}
					}
				}
			}
		}
		
		currentDepth++
	}
	
	return graph, nil
}

5. 程序性记忆

internal/memory/procedural.go

Go 复制代码
package memory

import (
	"encoding/json"
	"fmt"
	"time"
)

// 程序性记忆:存储技能、程序和习惯
type ProceduralMemory struct {
	skills      map[string]*Skill
	procedures  map[string]*Procedure
	habits      map[string]*Habit
	performance map[string]*PerformanceRecord
}

type Skill struct {
	Name        string                 `json:"name"`
	Description string                 `json:"description"`
	Steps       []*SkillStep           `json:"steps"`
	Complexity  int                    `json:"complexity"` // 1-10
	Mastery     float64                `json:"mastery"`    // 0-1
	LastUsed    time.Time              `json:"last_used"`
	UsageCount  int                    `json:"usage_count"`
	Variations  map[string]interface{} `json:"variations"` // 不同情境下的变体
}

type SkillStep struct {
	Action      string                 `json:"action"`
	Conditions  []string               `json:"conditions,omitempty"`
	Expected    interface{}            `json:"expected,omitempty"`
	TimeEstimate time.Duration         `json:"time_estimate,omitempty"`
	Critical    bool                   `json:"critical"` // 是否关键步骤
}

type Procedure struct {
	Name        string                 `json:"name"`
	Goal        string                 `json:"goal"`
	Steps       []*ProcedureStep       `json:"steps"`
	Preconditions []string             `json:"preconditions"`
	Postconditions []string            `json:"postconditions"`
	SuccessRate float64                `json:"success_rate"`
	AverageTime time.Duration          `json:"average_time"`
}

type Habit struct {
	Name        string                 `json:"name"`
	Trigger     string                 `json:"trigger"`
	Routine     []string               `json:"routine"` // 关联的技能或程序
	Reward      string                 `json:"reward"`
	Strength    float64                `json:"strength"` // 习惯强度
	Frequency   time.Duration          `json:"frequency"`
	LastPerformed time.Time            `json:"last_performed"`
}

type PerformanceRecord struct {
	SkillID     string                 `json:"skill_id"`
	Timestamp   time.Time              `json:"timestamp"`
	Duration    time.Duration          `json:"duration"`
	Success     bool                   `json:"success"`
	Quality     float64                `json:"quality"` // 0-1
	Difficulty  float64                `json:"difficulty"`
	Feedback    string                 `json:"feedback,omitempty"`
	Improvements []string              `json:"improvements,omitempty"`
}

func NewProceduralMemory() *ProceduralMemory {
	return &ProceduralMemory{
		skills:      make(map[string]*Skill),
		procedures:  make(map[string]*Procedure),
		habits:      make(map[string]*Habit),
		performance: make(map[string]*PerformanceRecord),
	}
}

func (pm *ProceduralMemory) Store(memory *Memory) (string, error) {
	// 尝试解析为技能、程序或习惯
	var skill Skill
	if err := json.Unmarshal([]byte(memory.Content), &skill); err == nil {
		return pm.storeSkill(&skill)
	}
	
	var procedure Procedure
	if err := json.Unmarshal([]byte(memory.Content), &procedure); err == nil {
		return pm.storeProcedure(&procedure)
	}
	
	var habit Habit
	if err := json.Unmarshal([]byte(memory.Content), &habit); err == nil {
		return pm.storeHabit(&habit)
	}
	
	// 作为通用程序性记忆存储
	return pm.storeGeneric(memory)
}

func (pm *ProceduralMemory) storeSkill(skill *Skill) (string, error) {
	// 检查是否已存在
	if existing, exists := pm.skills[skill.Name]; exists {
		// 合并或更新
		pm.mergeSkills(existing, skill)
	} else {
		pm.skills[skill.Name] = skill
	}
	
	// 初始化掌握度
	if skill.Mastery == 0 {
		skill.Mastery = 0.1 // 基础掌握度
	}
	
	return skill.Name, nil
}

func (pm *ProceduralMemory) ExecuteSkill(ctx context.Context, skillName string, parameters map[string]interface{}) (interface{}, error) {
	skill, exists := pm.skills[skillName]
	if !exists {
		return nil, fmt.Errorf("skill not found: %s", skillName)
	}
	
	// 记录开始时间
	startTime := time.Now()
	
	// 执行技能步骤
	var result interface{}
	var success bool = true
	var quality float64 = 1.0
	
	for _, step := range skill.Steps {
		stepResult, err := pm.executeSkillStep(ctx, step, parameters)
		if err != nil {
			// 关键步骤失败导致整个技能失败
			if step.Critical {
				success = false
				break
			}
			// 非关键步骤失败降低质量
			quality *= 0.8
		}
		
		// 合并结果
		result = pm.mergeResults(result, stepResult)
	}
	
	// 记录性能
	duration := time.Since(startTime)
	record := &PerformanceRecord{
		SkillID:    skillName,
		Timestamp:  startTime,
		Duration:   duration,
		Success:    success,
		Quality:    quality,
		Difficulty: pm.calculateDifficulty(skill, parameters),
	}
	
	pm.recordPerformance(record)
	
	// 更新技能掌握度
	pm.updateMastery(skill, record)
	
	// 更新最后使用时间
	skill.LastUsed = time.Now()
	skill.UsageCount++
	
	if !success {
		return nil, fmt.Errorf("skill execution failed")
	}
	
	return result, nil
}

func (pm *ProceduralMemory) updateMastery(skill *Skill, record *PerformanceRecord) {
	// 基于性能更新掌握度
	baseImprovement := 0.1
	
	if record.Success {
		// 成功执行增加掌握度
		improvement := baseImprovement * record.Quality
		
		// 考虑难度因素
		if record.Difficulty > 0.7 {
			improvement *= 1.5 // 困难任务掌握更快
		}
		
		skill.Mastery = math.Min(1.0, skill.Mastery+improvement)
	} else {
		// 失败降低掌握度,但不会低于基础值
		penalty := baseImprovement * 0.5
		skill.Mastery = math.Max(0.1, skill.Mastery-penalty)
	}
	
	// 衰减:长期不使用会降低掌握度
	timeSinceLastUse := time.Since(skill.LastUsed)
	if timeSinceLastUse > 30*24*time.Hour { // 30天
		decay := 0.01 * float64(timeSinceLastUse/(30*24*time.Hour))
		skill.Mastery = math.Max(0.1, skill.Mastery-decay)
	}
}

// 技能转移:将掌握的技能应用到新情境
func (pm *ProceduralMemory) TransferSkill(sourceSkill, targetContext string, similarity float64) (*Skill, error) {
	source, exists := pm.skills[sourceSkill]
	if !exists {
		return nil, fmt.Errorf("source skill not found: %s", sourceSkill)
	}
	
	// 创建转移后的技能
	transferred := &Skill{
		Name:        fmt.Sprintf("%s_in_%s", sourceSkill, targetContext),
		Description: fmt.Sprintf("Adaptation of %s for %s context", sourceSkill, targetContext),
		Steps:       make([]*SkillStep, len(source.Steps)),
		Complexity:  source.Complexity,
		Mastery:     source.Mastery * similarity, // 转移效率取决于相似度
	}
	
	// 调整步骤以适应新情境
	for i, step := range source.Steps {
		transferredStep := &SkillStep{
			Action:      step.Action,
			Conditions:  make([]string, len(step.Conditions)),
			Expected:    step.Expected,
			TimeEstimate: step.TimeEstimate,
			Critical:    step.Critical,
		}
		
		// 调整条件
		for j, condition := range step.Conditions {
			transferredStep.Conditions[j] = pm.adaptCondition(condition, targetContext)
		}
		
		transferred.Steps[i] = transferredStep
	}
	
	// 存储转移后的技能
	pm.skills[transferred.Name] = transferred
	
	return transferred, nil
}

// 习惯形成
func (pm *ProceduralMemory) FormHabit(trigger, routine, reward string) (*Habit, error) {
	habit := &Habit{
		Name:        fmt.Sprintf("habit_%d", time.Now().Unix()),
		Trigger:     trigger,
		Routine:     []string{routine},
		Reward:      reward,
		Strength:    0.1, // 初始强度
		Frequency:   24 * time.Hour,
		LastPerformed: time.Now(),
	}
	
	pm.habits[habit.Name] = habit
	
	return habit, nil
}

func (pm *ProceduralMemory) StrengthenHabit(habitName string, repetitionQuality float64) {
	if habit, exists := pm.habits[habitName]; exists {
		// 基于重复质量增强习惯强度
		strengthIncrease := 0.1 * repetitionQuality
		habit.Strength = math.Min(1.0, habit.Strength+strengthIncrease)
		
		habit.LastPerformed = time.Now()
		habit.Frequency = time.Duration(float64(habit.Frequency) * 0.95) // 频率增加
	}
}

// 自动化检测:识别可以自动化的程序
func (pm *ProceduralMemory) DetectAutomationOpportunities() []string {
	var opportunities []string
	
	for _, skill := range pm.skills {
		// 高掌握度、高频使用、低复杂度的技能适合自动化
		if skill.Mastery > 0.8 && skill.UsageCount > 10 && skill.Complexity < 5 {
			opportunities = append(opportunities, skill.Name)
		}
	}
	
	return opportunities
}

6. LangChain和LangGraph集成

pkg/langchain/memory.go

Go 复制代码
package langchain

import (
	"context"
	"fmt"
	"strings"

	"github.com/tmc/langchaingo/llms"
	"github.com/tmc/langchaingo/memory"
	"github.com/tmc/langchaingo/schema"
)

// LangChain记忆包装器
type LangChainMemory struct {
	conversationBuffer memory.ConversationBuffer
	entityMemory      memory.ConversationEntityMemory
	summaryMemory     memory.ConversationSummaryBuffer
	vectorMemory      memory.ConversationVectorStoreRetriever
	customMemory      *CustomMemory
}

type CustomMemory struct {
	shortTermBuffer []schema.ChatMessage
	longTermStore   map[string][]schema.ChatMessage
	metadata        map[string]interface{}
}

func NewLangChainMemory(llm llms.Model) *LangChainMemory {
	// 创建不同类型的记忆
	convBuffer := memory.NewConversationBuffer()
	entityMem := memory.NewConversationEntityMemory(llm)
	summaryMem := memory.NewConversationSummaryBuffer(llm, 2000)
	
	return &LangChainMemory{
		conversationBuffer: convBuffer,
		entityMemory:      entityMem,
		summaryMemory:     summaryMem,
		customMemory:      NewCustomMemory(),
	}
}

func (lcm *LangChainMemory) SaveContext(ctx context.Context, inputValues, outputValues map[string]any) error {
	// 保存到对话缓冲
	if err := lcm.conversationBuffer.SaveContext(ctx, inputValues, outputValues); err != nil {
		return err
	}
	
	// 保存到实体记忆
	if err := lcm.entityMemory.SaveContext(ctx, inputValues, outputValues); err != nil {
		return err
	}
	
	// 保存到摘要记忆
	if err := lcm.summaryMemory.SaveContext(ctx, inputValues, outputValues); err != nil {
		return err
	}
	
	// 保存到自定义记忆
	return lcm.customMemory.SaveContext(ctx, inputValues, outputValues)
}

func (lcm *LangChainMemory) LoadMemoryVariables(ctx context.Context, inputs map[string]any) (map[string]any, error) {
	result := make(map[string]any)
	
	// 加载对话历史
	if vars, err := lcm.conversationBuffer.LoadMemoryVariables(ctx, inputs); err == nil {
		result["history"] = vars["history"]
	}
	
	// 加载实体信息
	if vars, err := lcm.entityMemory.LoadMemoryVariables(ctx, inputs); err == nil {
		result["entities"] = vars["entities"]
	}
	
	// 加载摘要
	if vars, err := lcm.summaryMemory.LoadMemoryVariables(ctx, inputs); err == nil {
		result["summary"] = vars["summary"]
	}
	
	// 加载自定义记忆
	if vars, err := lcm.customMemory.LoadMemoryVariables(ctx, inputs); err == nil {
		result["custom"] = vars["custom"]
	}
	
	return result, nil
}

// 增强的对话记忆
type EnhancedConversationMemory struct {
	buffer        *ConversationBufferWindow
	summary       *ConversationSummary
	entityTracker *EntityTracker
	topicTracker  *TopicTracker
	sentiment     *SentimentTracker
}

func NewEnhancedConversationMemory(llm llms.Model, windowSize int) *EnhancedConversationMemory {
	return &EnhancedConversationMemory{
		buffer:        NewConversationBufferWindow(windowSize),
		summary:       NewConversationSummary(llm),
		entityTracker: NewEntityTracker(llm),
		topicTracker:  NewTopicTracker(),
		sentiment:     NewSentimentTracker(llm),
	}
}

func (ecm *EnhancedConversationMemory) AddMessage(role, content string) {
	message := schema.ChatMessage{
		Role:    role,
		Content: content,
	}
	
	// 添加到缓冲区
	ecm.buffer.Add(message)
	
	// 更新摘要
	ecm.summary.Update(content)
	
	// 提取实体
	entities := ecm.entityTracker.Extract(content)
	ecm.entityTracker.Update(entities)
	
	// 检测话题
	topic := ecm.topicTracker.Detect(content)
	ecm.topicTracker.Update(topic)
	
	// 分析情感
	sentiment := ecm.sentiment.Analyze(content)
	ecm.sentiment.Update(sentiment)
}

func (ecm *EnhancedConversationMemory) GetContext() string {
	var contextBuilder strings.Builder
	
	// 添加最近对话
	contextBuilder.WriteString("Recent conversation:\n")
	for _, msg := range ecm.buffer.GetMessages() {
		contextBuilder.WriteString(fmt.Sprintf("%s: %s\n", msg.Role, msg.Content))
	}
	
	// 添加摘要
	if summary := ecm.summary.Get(); summary != "" {
		contextBuilder.WriteString("\nConversation summary:\n")
		contextBuilder.WriteString(summary)
	}
	
	// 添加实体信息
	if entities := ecm.entityTracker.Get(); len(entities) > 0 {
		contextBuilder.WriteString("\nRelevant entities:\n")
		for _, entity := range entities {
			contextBuilder.WriteString(fmt.Sprintf("- %s: %s\n", entity.Type, entity.Name))
		}
	}
	
	// 添加当前话题
	if topic := ecm.topicTracker.GetCurrent(); topic != "" {
		contextBuilder.WriteString(fmt.Sprintf("\nCurrent topic: %s\n", topic))
	}
	
	// 添加情感状态
	if sentiment := ecm.sentiment.Get(); sentiment != "" {
		contextBuilder.WriteString(fmt.Sprintf("\nSentiment: %s\n", sentiment))
	}
	
	return contextBuilder.String()
}

7. 实际应用示例

examples/chatbot_memory.go

Go 复制代码
package main

import (
	"context"
	"fmt"
	"log"
	"time"

	"memory-system/internal/memory"
	"memory-system/pkg/langchain"
	"github.com/tmc/langchaingo/llms/openai"
)

func main() {
	ctx := context.Background()
	
	// 初始化LLM
	llm, err := openai.New()
	if err != nil {
		log.Fatal(err)
	}
	
	// 创建记忆管理器
	memoryConfig := memory.MemoryConfig{
		ShortTermCapacity:    50,
		ShortTermTTL:         30 * time.Minute,
		CompressionThreshold: 40,
		RetentionPeriod:      7 * 24 * time.Hour,
		ImportanceThreshold:  memory.ImportanceMedium,
	}
	
	memManager := memory.NewMemoryManager("chatbot_v1", memoryConfig)
	
	// 创建LangChain记忆
	lcMemory := langchain.NewLangChainMemory(llm)
	
	// 示例1:对话式AI记忆
	runConversationalAI(ctx, memManager, lcMemory, llm)
	
	// 示例2:任务型Agent记忆
	runTaskAgent(ctx, memManager)
	
	// 示例3:个性化推荐系统
	runPersonalizationSystem(ctx, memManager)
}

func runConversationalAI(ctx context.Context, memManager *memory.MemoryManager, lcMemory *langchain.LangChainMemory, llm llms.Model) {
	fmt.Println("=== 对话式AI记忆示例 ===")
	
	// 模拟对话
	conversations := []struct {
		user     string
		response string
	}{
		{"你好,我叫张三", "你好张三!很高兴认识你。你今天怎么样?"},
		{"我很好,谢谢。我喜欢打篮球和看电影", "太棒了!篮球和电影都是很好的爱好。你最喜欢的电影是什么?"},
		{"我最喜欢《肖申克的救赎》,它给了我很多启发", "《肖申克的救赎》确实是一部经典!它教会我们永不放弃希望。"},
		{"对了,你能推荐一些类似的电影吗?", "当然!基于你喜欢《肖申克的救赎》,我推荐《阿甘正传》、《美丽人生》和《当幸福来敲门》。"},
		{"谢谢推荐!我的生日是6月15日", "不客气!我已经记住你的生日是6月15日了。到时候我会祝福你的!"},
	}
	
	// 处理对话
	for i, conv := range conversations {
		fmt.Printf("\n用户: %s\n", conv.user)
		fmt.Printf("AI: %s\n", conv.response)
		
		// 存储用户输入
		userMemoryID, _ := memManager.Store(ctx, conv.user, memory.MemoryTypeEpisodic, map[string]interface{}{
			"speaker":     "user",
			"turn":        i,
			"timestamp":   time.Now(),
			"sentiment":   0.8,
		})
		
		// 存储AI响应
		aiMemoryID, _ := memManager.Store(ctx, conv.response, memory.MemoryTypeEpisodic, map[string]interface{}{
			"speaker":     "ai",
			"turn":        i,
			"timestamp":   time.Now(),
			"in_response_to": userMemoryID,
		})
		
		// 提取和存储用户偏好
		if i == 1 { // "我喜欢打篮球和看电影"
			memManager.Store(ctx, "用户喜欢打篮球", memory.MemoryTypeSemantic, map[string]interface{}{
				"subject":    "用户",
				"predicate":  "喜欢",
				"object":     "打篮球",
				"confidence": 0.9,
				"source":     userMemoryID,
			})
			
			memManager.Store(ctx, "用户喜欢看电影", memory.MemoryTypeSemantic, map[string]interface{}{
				"subject":    "用户",
				"predicate":  "喜欢",
				"object":     "看电影",
				"confidence": 0.9,
				"source":     userMemoryID,
			})
		}
		
		if i == 2 { // 最喜欢的电影
			memManager.Store(ctx, "用户最喜欢的电影是《肖申克的救赎》", memory.MemoryTypeSemantic, map[string]interface{}{
				"subject":    "用户",
				"predicate":  "最喜欢",
				"object":     "电影《肖申克的救赎》",
				"confidence": 0.95,
				"source":     userMemoryID,
			})
		}
		
		if i == 4 { // 生日信息
			memManager.Store(ctx, "用户的生日是6月15日", memory.MemoryTypeEpisodic, map[string]interface{}{
				"type":       "personal_info",
				"category":   "生日",
				"value":      "6月15日",
				"importance": memory.ImportanceHigh,
				"source":     userMemoryID,
			})
		}
		
		// 使用LangChain记忆
		lcMemory.SaveContext(ctx, map[string]any{
			"input": conv.user,
		}, map[string]any{
			"output": conv.response,
		})
	}
	
	// 测试记忆检索
	fmt.Println("\n=== 记忆检索测试 ===")
	
	// 检索关于用户喜好的记忆
	preferences, err := memManager.Retrieve(ctx, "用户喜欢什么", []memory.MemoryType{
		memory.MemoryTypeSemantic,
		memory.MemoryTypeEpisodic,
	}, 5)
	
	if err != nil {
		log.Printf("检索失败: %v", err)
	} else {
		fmt.Println("检索到的用户喜好:")
		for _, pref := range preferences {
			fmt.Printf("- %s (类型: %s, 重要性: %d)\n", 
				pref.Content, pref.MemoryType, pref.Importance)
		}
	}
	
	// 测试个性化响应
	fmt.Println("\n=== 个性化响应生成 ===")
	
	// 基于记忆生成个性化响应
	contextMemories, _ := memManager.RetrieveWithContext(ctx, "推荐电影", map[string]interface{}{
		"user_preferences": "喜欢《肖申克的救赎》",
		"context":          "电影推荐",
	}, 3)
	
	if len(contextMemories) > 0 {
		fmt.Println("基于以下记忆生成响应:")
		for _, mem := range contextMemories {
			fmt.Printf("  - %s\n", mem.Content)
		}
		
		// 这里可以调用LLM生成响应
		response := generatePersonalizedResponse(contextMemories, "推荐电影")
		fmt.Printf("个性化响应: %s\n", response)
	}
	
	// 记忆巩固
	fmt.Println("\n=== 记忆巩固 ===")
	if err := memManager.Consolidate(ctx); err != nil {
		log.Printf("记忆巩固失败: %v", err)
	} else {
		fmt.Println("记忆巩固完成")
	}
}

func runTaskAgent(ctx context.Context, memManager *memory.MemoryManager) {
	fmt.Println("\n\n=== 任务型Agent记忆示例 ===")
	
	// 复杂任务分解和跟踪
	task := "计划一个去日本东京的5天旅行,预算5000美元"
	
	fmt.Printf("任务: %s\n", task)
	
	// 存储任务目标
	taskID, _ := memManager.Store(ctx, task, memory.MemoryTypeShortTerm, map[string]interface{}{
		"type":        "task",
		"status":      "planning",
		"complexity":  8,
		"deadline":    time.Now().Add(24 * time.Hour),
	})
	
	// 模拟任务执行步骤
	steps := []struct {
		action     string
		result     string
		difficulty int
	}{
		{"研究东京景点", "找到了东京塔、浅草寺、秋叶原等主要景点", 3},
		{"查找航班信息", "找到了往返机票约1200美元", 4},
		{"预订酒店", "预订了银座附近的酒店,4晚800美元", 5},
		{"规划每日行程", "制定了详细的5天行程计划", 7},
		{"计算预算", "总预算约4500美元,在预算范围内", 6},
	}
	
	// 执行任务步骤
	for i, step := range steps {
		fmt.Printf("\n步骤%d: %s\n", i+1, step.action)
		fmt.Printf("结果: %s\n", step.result)
		
		// 存储步骤记忆
		stepID, _ := memManager.Store(ctx, step.action, memory.MemoryTypeEpisodic, map[string]interface{}{
			"task_id":    taskID,
			"step":       i + 1,
			"result":     step.result,
			"difficulty": step.difficulty,
			"timestamp":  time.Now(),
		})
		
		// 存储结果
		memManager.Store(ctx, step.result, memory.MemoryTypeSemantic, map[string]interface{}{
			"task_id": taskID,
			"step_id": stepID,
			"type":    "task_result",
		})
		
		// 如果是困难步骤,存储为程序性记忆
		if step.difficulty >= 5 {
			memManager.Store(ctx, fmt.Sprintf("如何%s: %s", step.action, step.result), 
				memory.MemoryTypeProcedural, map[string]interface{}{
					"skill":      step.action,
					"complexity": step.difficulty,
					"success":    true,
				})
		}
		
		// 更新任务状态
		if i == len(steps)-1 {
			memManager.Store(ctx, "任务完成", memory.MemoryTypeEpisodic, map[string]interface{}{
				"task_id":   taskID,
				"status":    "completed",
				"timestamp": time.Now(),
			})
		}
	}
	
	// 检索任务历史
	fmt.Println("\n=== 任务历史检索 ===")
	taskHistory, err := memManager.Retrieve(ctx, "东京旅行任务", []memory.MemoryType{
		memory.MemoryTypeEpisodic,
		memory.MemoryTypeShortTerm,
	}, 10)
	
	if err == nil {
		fmt.Println("任务执行历史:")
		for _, mem := range taskHistory {
			if step, ok := mem.Metadata["step"].(int); ok {
				fmt.Printf("  步骤%d: %s\n", step, mem.Content)
			}
		}
	}
	
	// 提取学到的技能
	fmt.Println("\n=== 学到的技能 ===")
	learnedSkills, _ := memManager.Retrieve(ctx, "如何", []memory.MemoryType{
		memory.MemoryTypeProcedural,
	}, 5)
	
	fmt.Println("从任务中学到的技能:")
	for _, skill := range learnedSkills {
		fmt.Printf("  - %s\n", skill.Content)
	}
}

func runPersonalizationSystem(ctx context.Context, memManager *memory.MemoryManager) {
	fmt.Println("\n\n=== 个性化推荐系统示例 ===")
	
	// 模拟用户交互历史
	interactions := []struct {
		item      string
		action    string
		rating    int
		timestamp time.Time
	}{
		{"电影《盗梦空间》", "观看", 5, time.Now().Add(-30 * 24 * time.Hour)},
		{"电影《星际穿越》", "观看", 4, time.Now().Add(-25 * 24 * time.Hour)},
		{"电影《信条》", "观看", 3, time.Now().Add(-20 * 24 * time.Hour)},
		{"书籍《三体》", "阅读", 5, time.Now().Add(-15 * 24 * time.Hour)},
		{"书籍《流浪地球》", "阅读", 4, time.Now().Add(-10 * 24 * time.Hour)},
		{"游戏《赛博朋克2077》", "游玩", 2, time.Now().Add(-5 * 24 * time.Hour)},
	}
	
	// 记录用户偏好
	for _, interaction := range interactions {
		// 存储交互经历
		memManager.Store(ctx, fmt.Sprintf("用户%s了%s,评分%d星", 
			interaction.action, interaction.item, interaction.rating),
			memory.MemoryTypeEpisodic, map[string]interface{}{
				"item":       interaction.item,
				"action":     interaction.action,
				"rating":     interaction.rating,
				"category":   getCategory(interaction.item),
				"timestamp":  interaction.timestamp,
				"importance": calculateImportance(interaction.rating, interaction.timestamp),
			})
		
		// 提取偏好模式
		if interaction.rating >= 4 {
			memManager.Store(ctx, fmt.Sprintf("用户喜欢%s类型的%s", 
				getCategory(interaction.item), interaction.item),
				memory.MemoryTypeSemantic, map[string]interface{}{
					"preference": getCategory(interaction.item),
					"item":       interaction.item,
					"strength":   float64(interaction.rating) / 5.0,
					"evidence":   interaction.timestamp,
				})
		}
	}
	
	// 生成用户画像
	fmt.Println("=== 用户画像 ===")
	
	// 检索用户偏好
	preferences, _ := memManager.Retrieve(ctx, "用户喜欢", []memory.MemoryType{
		memory.MemoryTypeSemantic,
	}, 10)
	
	preferenceMap := make(map[string]float64)
	for _, pref := range preferences {
		if prefCat, ok := pref.Metadata["preference"].(string); ok {
			if strength, ok := pref.Metadata["strength"].(float64); ok {
				preferenceMap[prefCat] += strength
			}
		}
	}
	
	fmt.Println("用户偏好强度:")
	for category, strength := range preferenceMap {
		fmt.Printf("  %s: %.2f\n", category, strength)
	}
	
	// 基于记忆的推荐
	fmt.Println("\n=== 个性化推荐 ===")
	
	// 新项目候选
	candidates := []string{
		"电影《沙丘》",
		"电影《矩阵重启》",
		"书籍《球状闪电》",
		"游戏《艾尔登法环》",
		"电影《瞬息全宇宙》",
	}
	
	// 为每个候选项目计算推荐分数
	for _, candidate := range candidates {
		category := getCategory(candidate)
		
		// 检索相关记忆
		relatedMemories, _ := memManager.Retrieve(ctx, category, []memory.MemoryType{
			memory.MemoryTypeSemantic,
			memory.MemoryTypeEpisodic,
		}, 5)
		
		// 计算推荐分数
		score := calculateRecommendationScore(candidate, category, relatedMemories, preferenceMap)
		
		fmt.Printf("  %s: 推荐分数 %.2f\n", candidate, score)
	}
	
	// 长期记忆分析
	fmt.Println("\n=== 长期记忆分析 ===")
	
	// 查找行为模式
	patterns := analyzeBehaviorPatterns(ctx, memManager)
	
	fmt.Println("发现的行为模式:")
	for _, pattern := range patterns {
		fmt.Printf("  - %s\n", pattern)
	}
}

// 辅助函数
func getCategory(item string) string {
	if contains(item, "电影") {
		return "科幻电影"
	} else if contains(item, "书籍") {
		return "科幻文学"
	} else if contains(item, "游戏") {
		return "电子游戏"
	}
	return "其他"
}

func calculateImportance(rating int, timestamp time.Time) memory.ImportanceLevel {
	// 评分越高越重要,时间越近越重要
	timeFactor := 1.0
	if time.Since(timestamp) < 7*24*time.Hour {
		timeFactor = 1.5
	}
	
	importance := float64(rating) * timeFactor
	
	if importance >= 7.5 {
		return memory.ImportanceHigh
	} else if importance >= 5 {
		return memory.ImportanceMedium
	}
	return memory.ImportanceLow
}

func calculateRecommendationScore(candidate, category string, memories []*memory.Memory, preferences map[string]float64) float64 {
	score := 0.0
	
	// 基础偏好分数
	if pref, exists := preferences[category]; exists {
		score += pref * 0.6
	}
	
	// 相似项目评分
	similarityScore := 0.0
	similarCount := 0
	
	for _, mem := range memories {
		if rating, ok := mem.Metadata["rating"].(int); ok && rating >= 4 {
			similarityScore += float64(rating)
			similarCount++
		}
	}
	
	if similarCount > 0 {
		score += (similarityScore / float64(similarCount*5)) * 0.4
	}
	
	return score
}

func analyzeBehaviorPatterns(ctx context.Context, memManager *memory.MemoryManager) []string {
	// 检索所有交互记忆
	interactions, err := memManager.Retrieve(ctx, "", []memory.MemoryType{
		memory.MemoryTypeEpisodic,
	}, 50)
	
	if err != nil {
		return nil
	}
	
	patterns := []string{}
	
	// 分析时间模式
	weekdayCount := make(map[string]int)
	hourCount := make(map[int]int)
	
	for _, interaction := range interactions {
		if timestamp, ok := interaction.Metadata["timestamp"].(time.Time); ok {
			weekdayCount[timestamp.Weekday().String()]++
			hourCount[timestamp.Hour()]++
		}
	}
	
	// 找出高频时间段
	var maxHour int
	maxCount := 0
	for hour, count := range hourCount {
		if count > maxCount {
			maxCount = count
			maxHour = hour
		}
	}
	
	if maxCount > 5 {
		patterns = append(patterns, fmt.Sprintf("用户通常在%d点活跃", maxHour))
	}
	
	// 分析评分模式
	highRatingItems := []string{}
	for _, interaction := range interactions {
		if rating, ok := interaction.Metadata["rating"].(int); ok && rating >= 4 {
			if item, ok := interaction.Metadata["item"].(string); ok {
				highRatingItems = append(highRatingItems, item)
			}
		}
	}
	
	if len(highRatingItems) > 3 {
		patterns = append(patterns, "用户对科幻类内容评价较高")
	}
	
	return patterns
}

func generatePersonalizedResponse(memories []*memory.Memory, query string) string {
	// 简化的响应生成
	// 实际应该使用LLM
	
	var preferences []string
	for _, mem := range memories {
		if strings.Contains(mem.Content, "喜欢") {
			preferences = append(preferences, mem.Content)
		}
	}
	
	if len(preferences) > 0 {
		return fmt.Sprintf("基于您之前的喜好:%s,我为您推荐以下内容...", 
			strings.Join(preferences, ","))
	}
	
	return "基于我们的对话历史,我建议..."
}

func contains(s, substr string) bool {
	return strings.Contains(s, substr)
}

8. 部署配置

deployments/docker-compose.yml

html 复制代码
version: '3.8'

services:
  memory-service:
    build: .
    ports:
      - "8080:8080"
    environment:
      - REDIS_URL=redis://redis:6379
      - QDRANT_URL=http://qdrant:6333
      - OPENAI_API_KEY=${OPENAI_API_KEY}
      - MEMORY_CONFIG_PATH=/app/configs/memory_config.yaml
    volumes:
      - ./configs:/app/configs
      - ./data:/app/data
    depends_on:
      - redis
      - qdrant
      - postgres

  redis:
    image: redis:alpine
    ports:
      - "6379:6379"
    volumes:
      - redis-data:/data
    command: redis-server --appendonly yes

  qdrant:
    image: qdrant/qdrant
    ports:
      - "6333:6333"
      - "6334:6334"
    volumes:
      - qdrant-data:/qdrant/storage

  postgres:
    image: postgres:15
    environment:
      - POSTGRES_DB=memory_db
      - POSTGRES_USER=memory_user
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
    ports:
      - "5432:5432"
    volumes:
      - postgres-data:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql

  elasticsearch:
    image: elasticsearch:8.10.0
    environment:
      - discovery.type=single-node
      - xpack.security.enabled=false
    ports:
      - "9200:9200"
    volumes:
      - elasticsearch-data:/usr/share/elasticsearch/data

  kibana:
    image: kibana:8.10.0
    ports:
      - "5601:5601"
    environment:
      - ELASTICSEARCH_HOSTS=http://elasticsearch:9200
    depends_on:
      - elasticsearch

  prometheus:
    image: prom/prometheus
    ports:
      - "9090:9090"
    volumes:
      - ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml

  grafana:
    image: grafana/grafana
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}
    volumes:
      - grafana-data:/var/lib/grafana

volumes:
  redis-data:
  qdrant-data:
  postgres-data:
  elasticsearch-data:
  grafana-data:

总结

这个记忆管理系统提供了:

1. 多层次记忆架构

  • 短期记忆:容量有限,快速访问,自动衰减

  • 长期记忆:持久化存储,向量检索,关联发现

  • 经历性记忆:事件和时间线管理

  • 语义记忆:事实、概念和知识图谱

  • 程序性记忆:技能、习惯和自动化

2. 智能记忆管理

  • 重要性评估:基于内容、情感、频率等因素

  • 自动巩固:短期记忆到长期记忆的转移

  • 衰减机制:基于时间和重要性的记忆弱化

  • 关联发现:自动发现记忆之间的关联

3. 实际应用场景

  • 对话式AI:维护上下文,个性化响应

  • 任务型Agent:跟踪进度,学习技能

  • 推荐系统:用户画像,行为模式分析

  • 学习系统:知识积累,技能提升

4. 高级特性

  • 记忆压缩:总结和抽象相似记忆

  • 记忆强化:基于重复和正反馈

  • 记忆转移:跨情境的技能应用

  • 模式发现:从历史中学习行为模式

5. 集成能力

  • LangChain集成:兼容现有AI开发生态

  • LangGraph集成:支持基于图的记忆流

  • 多存储后端:Redis、PostgreSQL、Qdrant等

  • 监控和可观测性:完整的监控体系

这个系统为AI Agent提供了接近人类记忆的认知能力,使其能够真正理解上下文、学习经验、形成习惯,并提供真正个性化的交互体验。

相关推荐
好奇龙猫1 小时前
【人工智能学习-AI入试相关题目练习-第五次】
人工智能·学习
敏叔V5871 小时前
AI应用开发框架对比:LangChain vs. Semantic Kernel vs. DSPy 深度解析
人工智能·驱动开发·langchain
Das11 小时前
【机器学习】04_支持向量机_拉格朗日对偶法
人工智能·机器学习·支持向量机
川西胖墩墩1 小时前
自动化提示工程的演进路径
人工智能
小咖自动剪辑1 小时前
视频去水印与去字幕教程:免费去水印软件与去字幕工具推荐
人工智能·音视频·实时音视频·视频编解码
GISer_Jing1 小时前
1.17-1.23日博客之星投票,每日可投
前端·人工智能·arcgis
檐下翻书1732 小时前
HR人力资源管理流程图在线绘制方法
大数据·人工智能·架构·流程图·论文笔记
liliangcsdn2 小时前
基于策略梯度的高效强化学习算法-GRPO
人工智能
JAI科研2 小时前
MICCAI 2025 IUGC 图像超声关键点检测及超声参数测量挑战赛
人工智能·深度学习·算法·计算机视觉·自然语言处理·视觉检测·transformer