mneme

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jun 1, 2026 License: MIT Imports: 15 Imported by: 0

README

mneme

A small, self-contained agent memory library for Go — drop it into any agent to give it persistent, searchable long-term memory.

You feed it conversation messages; it uses an LLM to extract durable, self-contained facts, embeds and deduplicates them, and stores them in a per-scope vector index. Later you search for the facts relevant to a query.

  • Library-first. Import github.com/AccursedGalaxy/mneme directly. A thin HTTP + MCP server binary wrapping the same core lands later (see PLAN.md).
  • Self-contained. No shared code with any consumer. Its own OpenAI-compatible LLM/embedding client, its own storage.
  • Single binary. Default storage is pure-Go SQLite (no cgo). Pluggable for sqlite-vec / pgvector as you scale, behind the Store interface.
  • Our own prompts. The extraction prompt is ours, scored by a built-in eval harness — not a vendored copy.

Install

go get github.com/AccursedGalaxy/mneme

Quick start

package main

import (
	"context"
	"fmt"

	"github.com/AccursedGalaxy/mneme"
)

func main() {
	m, err := mneme.New() // builds LLM, embedder and store from MNEME_* env
	if err != nil {
		panic(err)
	}
	defer m.Close()

	ctx := context.Background()
	scope := mneme.Scope{UserID: "alice"}

	// Ingest a conversation — durable facts are extracted and stored.
	m.Add(ctx, []mneme.Message{
		{Role: "user", Content: "I moved to Berlin and adopted a tabby cat named Pixel."},
	}, scope)

	// Retrieve by meaning.
	hits, _ := m.Search(ctx, "what pets does the user have?", scope, 3)
	for _, h := range hits {
		fmt.Printf("(%.3f) %s\n", h.Score, h.Text)
	}
}

A runnable version is in examples/basic.

Configuration (env)

mneme.New() builds providers from the environment (override any of them with WithLLM / WithEmbedder / WithStore). The client speaks the OpenAI-compatible wire format, so it works with OpenAI, OpenRouter, Ollama, vLLM, LM Studio, etc.

Env var Meaning Example
MNEME_LLM_BASE_URL OpenAI-compatible base URL https://api.openai.com/v1
MNEME_LLM_API_KEY API key (may be empty for local) sk-…
MNEME_LLM_MODEL extraction model gpt-4o-mini
MNEME_EMBED_BASE_URL embeddings base URL (defaults to LLM base)
MNEME_EMBED_API_KEY embeddings key (defaults to LLM key)
MNEME_EMBED_MODEL embedding model text-embedding-3-small
MNEME_DB_PATH SQLite file path ./mneme.db

Public API

type Memory interface {
	Add(ctx context.Context, msgs []Message, scope Scope) ([]Fact, error)
	Search(ctx context.Context, query string, scope Scope, k int) ([]Fact, error)
	Get(ctx context.Context, id string) (Fact, error)
	Delete(ctx context.Context, id string) error
	Close() error
}

Facts are isolated per Scope (UserID / AgentID / RunID) on both write and search. The pipeline is additive: facts accumulate and are deduped by hash and by the extractor's awareness of existing memories — one LLM call per Add, no update/delete pass in v1.

Eval harness

The extraction prompt is versioned (extractionPromptV1, …) and scored by the harness in eval/, so prompt changes are decisions backed by numbers.

go run ./cmd/eval                    # offline-safe fake embedder, real LLM
go run ./cmd/eval -embedder openai   # real embeddings, true semantic search@k

Current baseline for extractionPromptV1 (gpt-4o-mini, text-embedding-3-small, k=3) — see eval/RESULTS.md:

recall precision specificity search@k dedup aggregate
0.94 0.97 1.00 0.94 1.00 0.97

Unit tests run fully offline with deterministic fakes — no network:

go test ./...

License

MIT — see LICENSE.

Documentation

Overview

Package mneme gives an AI agent persistent, searchable long-term memory.

You feed it conversation messages with Add; it uses an LLM to extract durable, self-contained facts, embeds and deduplicates them, and stores them in a per-scope vector index. Later you call Search to retrieve the facts most relevant to a query within the same scope.

mneme is library-first and self-contained: it carries its own OpenAI-compatible LLM/embedding client (provider/openai) and its own storage (store/sqlite, pure-Go, no cgo). Construct a Memory with New:

m, err := mneme.New() // builds providers + store from MNEME_* env vars
if err != nil { ... }
defer m.Close()

scope := mneme.Scope{UserID: "alice"}
m.Add(ctx, []mneme.Message{{Role: "user", Content: "I drive a Ferrari 488 GTB"}}, scope)
hits, _ := m.Search(ctx, "what car does the user own?", scope, 5)

The pipeline is additive: facts accumulate and are deduped by hash and by the extractor's own awareness of existing memories; there is no update/delete LLM pass in v1. See PLAN.md for the full design.

Example

Example shows the full library surface: construct a Memory, Add a conversation, then Search it back. It uses offline fakes so it runs as part of the test suite; a real consumer would call mneme.New() to build providers from MNEME_* env vars instead.

package main

import (
	"context"
	"fmt"

	"github.com/AccursedGalaxy/mneme"
	"github.com/AccursedGalaxy/mneme/provider/fake"
	"github.com/AccursedGalaxy/mneme/store/sqlite"
)

func main() {
	st, _ := sqlite.Open(":memory:")

	m, err := mneme.New(
		mneme.WithStore(st),
		mneme.WithLLM(&fake.LLM{Responses: []string{
			fake.JSON("Alice drives a Ferrari 488 GTB"),
		}}),
		mneme.WithEmbedder(&fake.Embedder{}),
	)
	if err != nil {
		panic(err)
	}
	defer m.Close()

	ctx := context.Background()
	scope := mneme.Scope{UserID: "alice"}

	written, _ := m.Add(ctx, []mneme.Message{
		{Role: "user", Content: "I drive a Ferrari 488 GTB"},
	}, scope)
	fmt.Printf("wrote %d fact(s)\n", len(written))

	hits, _ := m.Search(ctx, "what Ferrari does Alice drive?", scope, 1)
	for _, h := range hits {
		fmt.Println(h.Text)
	}
}
Output:
wrote 1 fact(s)
Alice drives a Ferrari 488 GTB

Index

Examples

Constants

View Source
const DefaultExtractionTopK = 10

DefaultExtractionTopK is how many existing memories are shown to the extractor for dedup/linking when WithExtractionTopK is not set.

View Source
const DefaultPromptVersion = "v1"

DefaultPromptVersion is the prompt version New uses unless WithPromptVersion overrides it.

Variables

This section is empty.

Functions

func PromptVersions

func PromptVersions() []string

PromptVersions returns the registered prompt version names (unordered).

Types

type Fact

type Fact = types.Fact

Public value types are defined once in the leaf package types and re-exported here as aliases, so consumers use mneme.Message / mneme.Scope / mneme.Fact while the store package can share the same types without an import cycle.

type Memory

type Memory interface {
	// Add ingests messages, extracts durable facts, dedups, and stores them.
	// It returns the facts that were newly written (after dedup).
	Add(ctx context.Context, msgs []Message, scope Scope) ([]Fact, error)

	// Search returns the top-k facts most relevant to query within scope,
	// with Score populated, highest first.
	Search(ctx context.Context, query string, scope Scope, k int) ([]Fact, error)

	// Get returns one fact by id.
	Get(ctx context.Context, id string) (Fact, error)

	// Delete removes one fact by id.
	Delete(ctx context.Context, id string) error

	// Close releases resources (the DB handle).
	Close() error
}

Memory is the top-level handle an agent holds. It is safe for concurrent use to the extent its underlying store, LLM and embedder are.

func New

func New(opts ...Option) (Memory, error)

New constructs a Memory. Any of the store, LLM and embedder not supplied via options are built from the MNEME_* environment (see PLAN.md §8). It returns an error if a required provider can be neither supplied nor built.

type Message

type Message = types.Message

Public value types are defined once in the leaf package types and re-exported here as aliases, so consumers use mneme.Message / mneme.Scope / mneme.Fact while the store package can share the same types without an import cycle.

type Option

type Option func(*memory)

Option configures New. Options are applied in order; later ones win.

func WithEmbedder

func WithEmbedder(e provider.Embedder) Option

WithEmbedder sets the embedder. Without it, New builds an OpenAI-compatible client from MNEME_EMBED_* env vars.

func WithExtractionTopK

func WithExtractionTopK(n int) Option

WithExtractionTopK sets how many existing memories are shown to the extractor.

func WithLLM

func WithLLM(l provider.LLM) Option

WithLLM sets the extraction LLM. Without it, New builds an OpenAI-compatible client from MNEME_LLM_* env vars.

func WithPromptVersion

func WithPromptVersion(v string) Option

WithPromptVersion selects the extraction prompt version (see PromptVersions).

func WithStore

func WithStore(s store.Store) Option

WithStore sets the persistence backend. Without it, New builds a SQLite store at MNEME_DB_PATH (default ./mneme.db).

type Scope

type Scope = types.Scope

Public value types are defined once in the leaf package types and re-exported here as aliases, so consumers use mneme.Message / mneme.Scope / mneme.Fact while the store package can share the same types without an import cycle.

Directories

Path Synopsis
cmd
eval command
Command eval runs mneme's prompt-evaluation harness against a live LLM and prints a per-metric table plus an aggregate score per prompt version.
Command eval runs mneme's prompt-evaluation harness against a live LLM and prints a per-metric table plus an aggregate score per prompt version.
Package eval is mneme's prompt evaluation harness.
Package eval is mneme's prompt evaluation harness.
examples
basic command
Command basic is a runnable end-to-end dogfood of the mneme library against a real OpenAI-compatible endpoint.
Command basic is a runnable end-to-end dogfood of the mneme library against a real OpenAI-compatible endpoint.
Package provider defines the LLM and embedding interfaces mneme depends on, plus implementations (an OpenAI-compatible HTTP client in provider/openai and deterministic fakes in provider/fake).
Package provider defines the LLM and embedding interfaces mneme depends on, plus implementations (an OpenAI-compatible HTTP client in provider/openai and deterministic fakes in provider/fake).
fake
Package fake provides deterministic, offline implementations of provider.LLM and provider.Embedder for unit tests.
Package fake provides deterministic, offline implementations of provider.LLM and provider.Embedder for unit tests.
openai
Package openai is a minimal OpenAI-compatible HTTP client implementing provider.LLM and provider.Embedder over net/http with no SDK dependency.
Package openai is a minimal OpenAI-compatible HTTP client implementing provider.LLM and provider.Embedder over net/http with no SDK dependency.
Package store defines the persistence interface for mneme facts and ships a pure-Go SQLite implementation (store/sqlite).
Package store defines the persistence interface for mneme facts and ships a pure-Go SQLite implementation (store/sqlite).
sqlite
Package sqlite is the pure-Go (modernc.org/sqlite, no cgo) default Store for mneme.
Package sqlite is the pure-Go (modernc.org/sqlite, no cgo) default Store for mneme.
Package types holds the small value types shared across mneme's packages.
Package types holds the small value types shared across mneme's packages.

Jump to

Keyboard shortcuts

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