store

package
v0.0.0-...-3f9b805 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 13, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Overview

Package store 提供跨会话持久记忆存储

本包实现对标 LangGraph Memory Store 的跨会话持久记忆系统,提供:

  • 命名空间隔离:按 user/org/agent/topic 层级组织记忆
  • JSON 文档存储:每条记忆是一个 JSON 文档
  • 语义检索:可选的向量搜索能力
  • TTL 过期:记忆自动过期清理

使用示例:

// 创建内存存储(用于开发和测试)
store := store.NewInMemoryStore()

// 存储一条记忆
store.Put(ctx, []string{"users", "u123"}, "preferences", map[string]any{
    "theme": "dark",
    "language": "zh-CN",
})

// 检索记忆
item, _ := store.Get(ctx, []string{"users", "u123"}, "preferences")

// 语义搜索
results, _ := store.Search(ctx, []string{"users", "u123"}, &store.SearchQuery{
    Query: "用户偏好",
    Limit: 10,
})

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Context

type Context = context.Context

Context 是 context.Context 的别名

type FileStore

type FileStore struct {
	// contains filtered or unexported fields
}

FileStore 基于文件系统的持久化 MemoryStore 实现

将每条记忆存储为一个独立的 JSON 文件,目录结构按命名空间组织。 适合单机部署和快速开始,无需外部依赖。

目录结构示例:

baseDir/
├── users/
│   └── u123/
│       ├── preferences.json
│       └── history.json
└── agents/
    └── a1/
        └── config.json

特性:

  • 命名空间映射为子目录
  • 每条记忆一个 JSON 文件
  • 原子写入(tmp + rename),防止写入中断导致损坏
  • 支持 TTL 过期(启动时和定期扫描清理过期文件)
  • 后台 goroutine 定期清理过期条目

线程安全:所有方法都是并发安全的。

使用示例:

store, err := NewFileStore("/data/memory")
if err != nil {
    log.Fatal(err)
}
defer store.Close()

store.Put(ctx, []string{"users", "u1"}, "prefs", map[string]any{
    "theme": "dark",
})

func NewFileStore

func NewFileStore(baseDir string, opts ...FileStoreOption) (*FileStore, error)

NewFileStore 创建文件存储实例

baseDir: 数据存储根目录,不存在时自动创建。 会启动一个后台协程定期清理过期条目,使用完毕后应调用 Close() 释放资源。

func (*FileStore) Close

func (s *FileStore) Close() error

Close 关闭存储,停止后台清理协程

func (*FileStore) Delete

func (s *FileStore) Delete(ctx context.Context, namespace []string, key string) error

Delete 删除一条记忆

func (*FileStore) DeleteNamespace

func (s *FileStore) DeleteNamespace(ctx context.Context, namespace []string) error

DeleteNamespace 删除整个命名空间及其下所有记忆

func (*FileStore) Get

func (s *FileStore) Get(ctx context.Context, namespace []string, key string) (*Item, error)

Get 获取一条记忆

func (*FileStore) List

func (s *FileStore) List(ctx context.Context, namespace []string, opts ...ListOption) ([]*Item, error)

List 列出命名空间下的所有记忆

func (*FileStore) Put

func (s *FileStore) Put(ctx context.Context, namespace []string, key string, value map[string]any, opts ...PutOption) error

Put 存储一条记忆

func (*FileStore) Search

func (s *FileStore) Search(ctx context.Context, namespace []string, query *SearchQuery) ([]*SearchResult, error)

Search 搜索记忆

type FileStoreOption

type FileStoreOption func(*FileStore)

FileStoreOption 是 FileStore 的配置选项

func WithFileCleanupInterval

func WithFileCleanupInterval(d time.Duration) FileStoreOption

WithFileCleanupInterval 设置 TTL 过期清理间隔

默认每 5 分钟清理一次过期条目

type InMemoryOption

type InMemoryOption func(*InMemoryStore)

InMemoryOption 是 InMemoryStore 的配置选项

func WithCleanupInterval

func WithCleanupInterval(d time.Duration) InMemoryOption

WithCleanupInterval 设置 TTL 过期清理间隔

默认每分钟清理一次过期条目

type InMemoryStore

type InMemoryStore struct {
	// contains filtered or unexported fields
}

InMemoryStore 基于内存的 MemoryStore 实现

适用于开发和测试场景。支持:

  • 命名空间隔离
  • TTL 自动过期清理
  • 基础关键词搜索

线程安全:所有方法都是并发安全的。

使用示例:

store := NewInMemoryStore()
defer store.Close()

store.Put(ctx, []string{"users", "u1"}, "profile", map[string]any{
    "name": "张三",
    "age":  30,
})

func NewInMemoryStore

func NewInMemoryStore(opts ...InMemoryOption) *InMemoryStore

NewInMemoryStore 创建内存存储实例

会启动一个后台协程定期清理过期条目, 使用完毕后应调用 Close() 释放资源。

func (*InMemoryStore) Close

func (s *InMemoryStore) Close() error

Close 关闭存储,停止后台清理协程

func (*InMemoryStore) Delete

func (s *InMemoryStore) Delete(_ context.Context, namespace []string, key string) error

Delete 删除一条记忆

func (*InMemoryStore) DeleteNamespace

func (s *InMemoryStore) DeleteNamespace(_ context.Context, namespace []string) error

DeleteNamespace 删除整个命名空间

func (*InMemoryStore) Get

func (s *InMemoryStore) Get(_ context.Context, namespace []string, key string) (*Item, error)

Get 获取一条记忆

func (*InMemoryStore) List

func (s *InMemoryStore) List(_ context.Context, namespace []string, opts ...ListOption) ([]*Item, error)

List 列出命名空间下的所有记忆

func (*InMemoryStore) Put

func (s *InMemoryStore) Put(_ context.Context, namespace []string, key string, value map[string]any, opts ...PutOption) error

Put 存储一条记忆

func (*InMemoryStore) Search

func (s *InMemoryStore) Search(_ context.Context, namespace []string, query *SearchQuery) ([]*SearchResult, error)

Search 搜索记忆

支持关键词搜索(在 Value 中查找包含 Query 的文本字段) 和元数据过滤(精确匹配 Filter 中的所有字段)

type Item

type Item struct {
	// Namespace 命名空间路径
	Namespace []string `json:"namespace"`

	// Key 唯一键(在命名空间内唯一)
	Key string `json:"key"`

	// Value JSON 文档内容
	Value map[string]any `json:"value"`

	// CreatedAt 创建时间
	CreatedAt time.Time `json:"created_at"`

	// UpdatedAt 最后更新时间
	UpdatedAt time.Time `json:"updated_at"`

	// ExpiresAt 过期时间(nil 表示永不过期)
	ExpiresAt *time.Time `json:"expires_at,omitempty"`
}

Item 记忆条目

每条记忆是一个带命名空间的 JSON 文档

func (*Item) IsExpired

func (item *Item) IsExpired() bool

IsExpired 检查记忆是否已过期

type ListOption

type ListOption func(*listOptions)

ListOption 是 List 操作的可选配置

func WithKeyPrefix

func WithKeyPrefix(prefix string) ListOption

WithKeyPrefix 按键前缀过滤

func WithListLimit

func WithListLimit(limit int) ListOption

WithListLimit 设置列表返回数量上限

func WithListOffset

func WithListOffset(offset int) ListOption

WithListOffset 设置列表分页偏移量

func WithOrderDesc

func WithOrderDesc() ListOption

WithOrderDesc 设置降序排列(按更新时间)

type MemoryStore

type MemoryStore interface {
	// Put 存储一条记忆
	//
	// namespace: 命名空间路径,如 ["users", "u123"]
	// key: 记忆键名,在命名空间内唯一
	// value: JSON 文档(任意 map 数据)
	// opts: 可选配置(TTL、索引字段等)
	//
	// 如果 key 已存在,则覆盖更新
	Put(ctx Context, namespace []string, key string, value map[string]any, opts ...PutOption) error

	// Get 获取一条记忆
	//
	// 返回 nil, nil 表示记忆不存在
	Get(ctx Context, namespace []string, key string) (*Item, error)

	// Search 搜索记忆
	//
	// 支持语义搜索(需配置 Embedder)和元数据过滤
	// 如果 query.Query 非空且存储支持语义搜索,则执行向量相似度搜索
	// 否则回退到关键词匹配
	Search(ctx Context, namespace []string, query *SearchQuery) ([]*SearchResult, error)

	// Delete 删除一条记忆
	//
	// 如果记忆不存在,不返回错误
	Delete(ctx Context, namespace []string, key string) error

	// List 列出命名空间下的所有记忆
	//
	// 支持分页和排序
	List(ctx Context, namespace []string, opts ...ListOption) ([]*Item, error)

	// DeleteNamespace 删除整个命名空间及其下所有记忆
	//
	// 递归删除所有子命名空间
	DeleteNamespace(ctx Context, namespace []string) error
}

MemoryStore 跨会话持久记忆存储接口

对标 LangGraph Memory Store,提供命名空间隔离的 KV 存储。 命名空间使用 []string 表示层级路径,如 ["users", "u123", "preferences"]。

所有方法都是并发安全的。

type PersistentMemory

type PersistentMemory struct {
	// contains filtered or unexported fields
}

PersistentMemory 将 MemoryStore 适配为 ai-core memory.Memory 接口

通过桥接模式,让现有的 Agent、WindowMemory、SummaryMemory 等上层组件 无缝使用持久化存储后端(FileStore、RedisStore 等)。

分层架构:

Agent / Application
       ↓ (memory.Memory 接口)
PersistentMemory 适配器
       ↓ (MemoryStore 接口)
InMemoryStore / FileStore / RedisStore

使用示例:

// 使用文件存储作为后端
fileStore, _ := NewFileStore("/data/memory")
mem := NewPersistentMemory(fileStore, []string{"users", "u123"})

// 现在可以像普通 Memory 一样使用
mem.Save(ctx, memory.NewUserEntry("你好"))
entries, _ := mem.Search(ctx, memory.SearchQuery{Limit: 10})

线程安全:所有方法都是并发安全的(由底层 MemoryStore 保证)。

func NewPersistentMemory

func NewPersistentMemory(store MemoryStore, namespace []string, opts ...PersistentMemoryOption) *PersistentMemory

NewPersistentMemory 创建持久化记忆适配器

store: 底层存储(InMemoryStore / FileStore / RedisStore) namespace: 命名空间路径,用于隔离记忆,如 ["users", "u123"]

示例:

mem := NewPersistentMemory(store, []string{"users", "u123"})

func (*PersistentMemory) Clear

func (pm *PersistentMemory) Clear(ctx context.Context) error

Clear 清空当前命名空间下的所有记忆

func (*PersistentMemory) Delete

func (pm *PersistentMemory) Delete(ctx context.Context, id string) error

Delete 删除指定 ID 的记忆条目

func (*PersistentMemory) Get

func (pm *PersistentMemory) Get(ctx context.Context, id string) (*coremem.Entry, error)

Get 根据 ID 获取记忆条目

返回 nil, nil 表示记忆不存在。

func (*PersistentMemory) Namespace

func (pm *PersistentMemory) Namespace() []string

Namespace 返回当前命名空间

func (*PersistentMemory) Save

func (pm *PersistentMemory) Save(ctx context.Context, entry coremem.Entry) error

Save 保存单条记忆条目

将 ai-core Entry 转换为 MemoryStore Item 并持久化。 如果 Entry.ID 为空,会自动生成唯一 ID。

func (*PersistentMemory) SaveBatch

func (pm *PersistentMemory) SaveBatch(ctx context.Context, entries []coremem.Entry) error

SaveBatch 批量保存记忆条目

func (*PersistentMemory) Search

func (pm *PersistentMemory) Search(ctx context.Context, query coremem.SearchQuery) ([]coremem.Entry, error)

Search 搜索记忆条目

将 ai-core SearchQuery 转换为 MemoryStore SearchQuery 执行搜索, 再对结果应用 ai-core 特有的过滤条件(Roles、Since、Until)。

func (*PersistentMemory) Stats

func (pm *PersistentMemory) Stats() coremem.MemoryStats

Stats 返回记忆统计信息

通过 List 获取当前命名空间下的所有条目来计算统计信息。

func (*PersistentMemory) Store

func (pm *PersistentMemory) Store() MemoryStore

Store 返回底层 MemoryStore

type PersistentMemoryOption

type PersistentMemoryOption func(*PersistentMemory)

PersistentMemoryOption 是 PersistentMemory 的配置选项

type PutOption

type PutOption func(*putOptions)

PutOption 是 Put 操作的可选配置

func WithIndex

func WithIndex(fields ...string) PutOption

WithIndex 标记需要建立索引的字段(用于加速检索)

示例:

store.Put(ctx, ns, key, value, store.WithIndex("type", "category"))

func WithTTL

func WithTTL(ttl time.Duration) PutOption

WithTTL 设置记忆的过期时间

示例:

store.Put(ctx, ns, key, value, store.WithTTL(24 * time.Hour))

type RedisStore

type RedisStore struct {
	// contains filtered or unexported fields
}

RedisStore 基于 Redis 的持久化 MemoryStore 实现

将记忆存储在 Redis 中,适合生产环境和分布式部署。

Redis 键结构:

  • 记忆数据:{prefix}{ns1}:{ns2}:{key} → JSON 序列化的 redisItem
  • 命名空间索引:{prefix}ns:{ns1}:{ns2} → Set 类型,存储该命名空间下的所有 key

特性:

  • 利用 Redis TTL 实现记忆过期
  • 利用 Redis Set 实现命名空间索引
  • 基础关键词搜索(遍历匹配)
  • Pipeline 批量操作优化

线程安全:Redis 客户端本身是并发安全的。

使用示例:

client := redis.NewClient(&redis.Options{Addr: "localhost:6379"})
store := NewRedisStore(client)

store.Put(ctx, []string{"users", "u1"}, "prefs", map[string]any{
    "theme": "dark",
})

func NewRedisStore

func NewRedisStore(client *redis.Client, opts ...RedisStoreOption) *RedisStore

NewRedisStore 创建 Redis 存储实例

client: Redis 客户端(调用方负责创建和关闭)

func (*RedisStore) Close

func (s *RedisStore) Close() error

Close 关闭存储

注意:不会关闭 Redis 客户端,客户端的生命周期由调用方管理

func (*RedisStore) Delete

func (s *RedisStore) Delete(ctx context.Context, namespace []string, key string) error

Delete 删除一条记忆

func (*RedisStore) DeleteNamespace

func (s *RedisStore) DeleteNamespace(ctx context.Context, namespace []string) error

DeleteNamespace 删除整个命名空间及其下所有记忆

func (*RedisStore) Get

func (s *RedisStore) Get(ctx context.Context, namespace []string, key string) (*Item, error)

Get 获取一条记忆

func (*RedisStore) List

func (s *RedisStore) List(ctx context.Context, namespace []string, opts ...ListOption) ([]*Item, error)

List 列出命名空间下的所有记忆

func (*RedisStore) Put

func (s *RedisStore) Put(ctx context.Context, namespace []string, key string, value map[string]any, opts ...PutOption) error

Put 存储一条记忆

func (*RedisStore) Search

func (s *RedisStore) Search(ctx context.Context, namespace []string, query *SearchQuery) ([]*SearchResult, error)

Search 搜索记忆

type RedisStoreOption

type RedisStoreOption func(*RedisStore)

RedisStoreOption 是 RedisStore 的配置选项

func WithDefaultTTL

func WithDefaultTTL(ttl time.Duration) RedisStoreOption

WithDefaultTTL 设置默认 TTL

当 Put 未显式指定 TTL 时使用此默认值,0 表示永不过期

func WithRedisPrefix

func WithRedisPrefix(prefix string) RedisStoreOption

WithRedisPrefix 设置 Redis 键前缀

默认前缀为 "hexagon:mem:"

type SearchQuery

type SearchQuery struct {
	// Query 语义搜索文本(如果存储支持向量搜索)
	Query string `json:"query,omitempty"`

	// Filter 元数据过滤条件
	// 支持精确匹配,如 {"type": "preference", "active": true}
	Filter map[string]any `json:"filter,omitempty"`

	// Limit 返回结果数量上限(默认 10)
	Limit int `json:"limit,omitempty"`

	// Offset 分页偏移量
	Offset int `json:"offset,omitempty"`
}

SearchQuery 搜索查询参数

type SearchResult

type SearchResult struct {
	// Item 匹配的记忆条目
	Item *Item `json:"item"`

	// Score 相似度分数(语义搜索时有值,范围 0-1)
	Score float64 `json:"score,omitempty"`
}

SearchResult 搜索结果

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL