memory

package
v0.5.1 Latest Latest
Warning

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

Go to latest
Published: Apr 19, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Index

Constants

View Source
const SharedAgentID = "__shared__"

SharedAgentID is the reserved agent ID for the shared memory namespace. Facts stored here are readable by all agents via RecallShared and RecallAll.

Concurrency note: bbolt serialises concurrent write access via a file-level lock. Multiple processes writing shared memory will serialise, not race. Concurrent reads are always safe.

Variables

This section is empty.

Functions

func ExtractFacts

func ExtractFacts(ctx context.Context, text string, cfg ExtractConfig) ([]string, error)

ExtractFacts calls the configured LLM and returns a slice of atomic facts extracted from text. Each element is a self-contained declarative sentence suitable for passing directly to Put / Remember.

Without an Anthropic API key, ExtractFacts returns the raw text as a single fact (graceful degradation — useful in offline or test contexts).

Types

type ConsolidateConfig

type ConsolidateConfig interface {
	GetAnthropicAPIKey() string
	GetConsolidateLLM() string
	GetConsolidateModel() string
	GetConsolidateThreshold() int
	GetDecayHalfLife() time.Duration
}

ConsolidateConfig is the subset of configuration used by consolidation. Defined as an interface to avoid a circular import with the root package.

type EntityExtractorAccessor

type EntityExtractorAccessor interface {
	ExtractIDs(text string) ([]string, error) // returns canonical node IDs
}

EntityExtractorAccessor extracts entities from a text string. Implemented by pkg/kg.EntityExtractor.

type ExtractConfig

type ExtractConfig interface {
	GetAnthropicAPIKey() string
	GetConsolidateModel() string // reuses the same model field
}

ExtractConfig is the subset of configuration needed for fact extraction. Satisfied by graymatter.Config via the same method-set pattern as ConsolidateConfig.

type Fact

type Fact struct {
	ID          string    `json:"id"`
	AgentID     string    `json:"agent_id"`
	Text        string    `json:"text"`
	CreatedAt   time.Time `json:"created_at"`
	AccessedAt  time.Time `json:"accessed_at"`
	AccessCount int       `json:"access_count"`
	// Weight is the decay-adjusted relevance score in [0, 1].
	// New facts start at 1.0 and decay over time via the forgetting curve.
	Weight    float64   `json:"weight"`
	Embedding []float32 `json:"embedding,omitempty"`
}

Fact is a single unit of memory: a piece of text an agent observed, enriched with metadata used for retrieval scoring and decay.

type GraphAccessor

type GraphAccessor interface {
	// Upsert inserts or updates a node in the graph.
	UpsertNode(id, label, entityType string) error
	// NeighborTexts returns text labels of nodes reachable from nodeID within depth hops.
	NeighborTexts(nodeID string, depth int) ([]string, error)
}

GraphAccessor is a narrow interface that pkg/memory uses to interact with the knowledge graph without importing pkg/kg (prevents import cycles).

type MemoryStats

type MemoryStats struct {
	AgentID   string    `json:"agent_id"`
	FactCount int       `json:"fact_count"`
	OldestAt  time.Time `json:"oldest_at"`
	NewestAt  time.Time `json:"newest_at"`
	AvgWeight float64   `json:"avg_weight"`
}

MemoryStats holds aggregate statistics for a single agent.

type Store

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

Store is the central storage layer. It combines bbolt for durable structured storage with a pluggable VectorStore for similarity search. All public methods are safe for concurrent use.

func Open

func Open(cfg StoreConfig) (*Store, error)

Open creates or opens the GrayMatter store at cfg.DataDir.

func (*Store) Close

func (s *Store) Close() error

Close signals all background goroutines to stop, waits for them to exit, then flushes and closes the underlying stores.

func (*Store) Consolidate

func (s *Store) Consolidate(ctx context.Context, agentID string, cfg ConsolidateConfig) error

Consolidate runs the full consolidation pipeline for agentID:

  1. Apply exponential decay weights to all facts.
  2. If fact count > threshold, LLM-summarise the weakest batch.
  3. Prune facts with weight < 0.01.

func (*Store) DB

func (s *Store) DB() *bolt.DB

DB exposes the raw bbolt handle (used by session package).

func (*Store) Delete

func (s *Store) Delete(agentID, factID string) error

Delete removes a fact by ID for agentID.

func (*Store) LaunchAsyncConsolidate

func (s *Store) LaunchAsyncConsolidate(agentID string, cfg ConsolidateConfig)

LaunchAsyncConsolidate starts MaybeConsolidate in a tracked, bounded goroutine. Non-blocking: if the semaphore is at capacity the trigger is silently dropped rather than blocking the caller.

func (*Store) List

func (s *Store) List(agentID string) ([]Fact, error)

List returns all facts for agentID, sorted newest first.

func (*Store) ListAgents

func (s *Store) ListAgents() ([]string, error)

ListAgents returns all known agent IDs.

func (*Store) MaybeConsolidate

func (s *Store) MaybeConsolidate(ctx context.Context, agentID string, cfg ConsolidateConfig) error

MaybeConsolidate triggers consolidation only when the fact count for agentID meets or exceeds the threshold. Safe to call concurrently.

func (*Store) PendingVectorCount added in v0.3.0

func (s *Store) PendingVectorCount() int

PendingVectorCount returns the number of facts currently waiting to be indexed in the vector store. A non-zero value after a quiescent period indicates a persistent embedder/vector-store failure worth investigating.

func (*Store) Put

func (s *Store) Put(ctx context.Context, agentID, text string) error

Put stores a new observation for agentID.

Durability model:

  1. Compute embedding (best-effort; on failure the fact is keyword-only).
  2. Single bbolt transaction commits the fact AND, if an embedding exists, a marker in bucketPendingVector. The marker is the durable "this still needs to land in the vector store" intent.
  3. Inline vector upsert. On success the marker is cleared. On failure the marker remains and the background reconciler will retry it; the caller still sees nil because bbolt is the source of truth.

This closes the crash window between the bbolt write and the vector write: after a crash, reconcileVectors() at Open() drains the pending bucket.

func (*Store) PutShared

func (s *Store) PutShared(ctx context.Context, text string) error

PutShared stores a new observation in the shared memory namespace. Shared facts are accessible to all agents via RecallShared and RecallAll.

func (*Store) Recall

func (s *Store) Recall(ctx context.Context, agentID, query string, topK int) ([]string, error)

Recall performs hybrid retrieval for agentID given a query string. It fuses three signals via Reciprocal Rank Fusion (RRF):

  1. Vector similarity (cosine, pluggable VectorStore) — when embeddings available
  2. Keyword relevance (TF-IDF approximation over bbolt facts)
  3. Recency score (exponential decay from CreatedAt)

Returns the top-k fact texts, ready to inject into a system prompt.

func (*Store) RecallAll

func (s *Store) RecallAll(ctx context.Context, agentID, query string, topK int) ([]string, error)

RecallAll merges agent-scoped and shared-scoped results, deduplicates, and re-ranks by Reciprocal Rank Fusion. It returns at most topK combined facts.

func (*Store) RecallShared

func (s *Store) RecallShared(ctx context.Context, query string, topK int) ([]string, error)

RecallShared returns the top-k most relevant shared facts for query.

func (*Store) SetKG

func (s *Store) SetKG(graph GraphAccessor, extractor EntityExtractorAccessor)

SetKG wires an optional knowledge graph and entity extractor into the store. Call this after Open() to enable graph enrichment in Recall and Consolidate. Both arguments are optional; pass nil to disable the corresponding feature.

func (*Store) Stats

func (s *Store) Stats(agentID string) (MemoryStats, error)

Stats returns aggregate statistics for agentID.

func (*Store) UpdateFact

func (s *Store) UpdateFact(agentID string, f Fact) error

UpdateFact persists a modified fact (used by consolidation + decay).

type StoreConfig

type StoreConfig struct {
	DataDir       string
	Embedder      embedding.Provider
	DecayHalfLife time.Duration

	// VectorBackend overrides the default chromem-go vector store.
	// If nil, a persistent chromem-go instance is created under DataDir/vectors.
	// Use this to plug in Qdrant, Weaviate, pgvector, or any VectorStore impl.
	VectorBackend VectorStore

	// MaxAsyncConsolidations bounds concurrent background consolidations.
	// 0 is normalised to 2 by Open().
	MaxAsyncConsolidations int

	// OnConsolidateError is called when an async consolidation goroutine errors.
	// If nil, errors are discarded. Must be safe for concurrent use.
	OnConsolidateError func(agentID string, err error)

	// OnVectorIndexError is called when an inline vector upsert fails after the
	// bbolt write has already committed. The fact remains in the pending-vector
	// queue and will be retried by the background reconciler. Must be safe for
	// concurrent use.
	OnVectorIndexError func(agentID, factID string, err error)

	// VectorReconcileInterval controls how often the background reconciler
	// drains the pending-vector queue. 0 disables the background loop entirely
	// (Open() still runs one drain at startup).
	VectorReconcileInterval time.Duration

	// OnRecall, if non-nil, is called after each Recall with timing and count.
	OnRecall func(agentID, query string, resultCount int, duration time.Duration)

	// OnPut, if non-nil, is called after each successful Put.
	OnPut func(agentID, factID string, duration time.Duration)

	// Logger receives structured log events. Uses log.Default() if nil.
	Logger interface {
		Printf(format string, v ...any)
	}
}

StoreConfig is passed to Open to configure the Store.

type VectorResult added in v0.2.0

type VectorResult struct {
	ID         string
	Content    string
	Similarity float32
}

VectorResult is a single result from a vector similarity query.

type VectorStore added in v0.2.0

type VectorStore interface {
	// AddDocument upserts a document with its pre-computed embedding.
	AddDocument(ctx context.Context, collection, id, content string, embedding []float32, metadata map[string]string) error

	// Query returns at most n documents ranked by cosine similarity to embedding.
	Query(ctx context.Context, collection string, embedding []float32, n int) ([]VectorResult, error)

	// EnsureCollection creates the collection if it does not exist.
	EnsureCollection(collection string) error

	// Close flushes and releases any resources held by the store.
	Close() error
}

VectorStore is the pluggable vector search backend. The default implementation wraps chromem-go (zero-infra, pure-Go, persistent). Future implementations can wrap Qdrant, Weaviate, pgvector, etc.

Implementations must be safe for concurrent use.

Jump to

Keyboard shortcuts

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