Documentation
¶
Index ¶
- Constants
- Variables
- func AssembleCountEvidence(query string, facts []MemoryEntry) string
- func CalculateRecencyBoost(deltaHours float64) float64
- func CalculateRelevanceScore(entry MemoryEntry) float64
- func CalculateTemporalDecay(entry MemoryEntry) float64
- func ClassifyIngestSourceHint(hint string) string
- func ConvTag(id string) string
- func CosineSimilarity(a, b []float32) float64
- func DefaultEmbeddingModelFromEnv() string
- func DefaultONNXModelCacheDirName() string
- func EntryEntityKeys(e MemoryEntry) []string
- func EntryHasTag(e MemoryEntry, tag string) bool
- func EntryHasTagPrefix(e MemoryEntry, prefix string) bool
- func EntryValidAt(e MemoryEntry, asOf time.Time) bool
- func ExtractAtomicFacts(entry MemoryEntry) []string
- func FormatSourceHintTag(hint string) string
- func GenerateMemoryID() string
- func GenerateSimpleEmbedding(text string, dim int) []float32
- func HugotCacheDirName(hfModel string) string
- func MultiFactorScore(entry MemoryEntry, queryVec []float32) float64
- func ParseValidityWindow(e MemoryEntry) (from, until *time.Time)
- func PopulateTemporalTags(cycle int) []string
- func ResolveEmbeddingDim(modelPath string) int
- func ResolveEmbeddingDimFromEnv() int
- type BatchCollectionError
- type BatchEmbeddingFunc
- type CollectionCreateResult
- type CompactionAction
- type CompactionConfig
- type CompactionStrategy
- type EmbeddingFunc
- type EntityGraph
- type FactsAsOfOptions
- type GONNXEmbedder
- func (e *GONNXEmbedder) Backend() string
- func (e *GONNXEmbedder) BatchFunc() BatchEmbeddingFunc
- func (e *GONNXEmbedder) Close() error
- func (e *GONNXEmbedder) Dimension() int
- func (e *GONNXEmbedder) Embed(text string) ([]float32, error)
- func (e *GONNXEmbedder) EmbedBatch(texts []string) ([][]float32, error)
- func (e *GONNXEmbedder) Func() EmbeddingFunc
- type GONNXOptions
- type HugotBackendConfig
- type ListMemoryOptions
- type MemoryContent
- type MemoryEntry
- type MemoryMetrics
- type MemoryProvenance
- type MemoryRelations
- type MemoryStats
- type MemoryTier
- type MultiHopOptions
- type PalaceConfig
- type PalaceStore
- func (ps *PalaceStore) AddEntityRelationship(entity, related string)
- func (ps *PalaceStore) AutoRecMemCompaction(generateFn func(prompt string) string, vectorCb VectorStoreCallback)
- func (ps *PalaceStore) EvictWorkingTier(maxAgeHours int, maxCount int)
- func (ps *PalaceStore) ExpandRelatedEntities(seed string, maxHops int) []string
- func (ps *PalaceStore) ExpandRelatedEntitiesHops(seed string, maxHops int) map[string]int
- func (ps *PalaceStore) GetRelatedEntities(entity string) []string
- func (ps *PalaceStore) GetStats() MemoryStats
- func (ps *PalaceStore) IngestTurn(turn MemoryEntry) error
- func (ps *PalaceStore) InvalidateMetaIndex()
- func (ps *PalaceStore) ListEntriesInTier(tier MemoryTier) []MemoryEntry
- func (ps *PalaceStore) ListFactsAsOf(opts FactsAsOfOptions) []MemoryEntry
- func (ps *PalaceStore) ListMemoryWithOptions(opts ListMemoryOptions) []MemoryEntry
- func (ps *PalaceStore) Load(id string, tier MemoryTier) (MemoryEntry, bool)
- func (ps *PalaceStore) MetaIndexLen() int
- func (ps *PalaceStore) MetaIndexRebuilds() uint64
- func (ps *PalaceStore) MultiHopRetrieve(opts MultiHopOptions) []MemoryEntry
- func (ps *PalaceStore) PerformCompaction(targetTier MemoryTier, cfg CompactionConfig, ...) error
- func (ps *PalaceStore) PromoteToContextual(threshold float64)
- func (ps *PalaceStore) ReadWithChainOfNote(retrieved []MemoryEntry, query string) (string, error)
- func (ps *PalaceStore) SearchMemory(query string, tier *MemoryTier, limit int, vec []float32) []MemoryEntry
- func (ps *PalaceStore) SearchMemoryWithOptions(query string, opts SearchMemoryOptions) []MemoryEntry
- func (ps *PalaceStore) SemanticRefine(cluster []MemoryEntry) error
- func (ps *PalaceStore) SupersedeEntityFacts(entityKey string, asOf time.Time) (int, error)
- func (ps *PalaceStore) Write(entry MemoryEntry) error
- func (ps *PalaceStore) WriteAndSupersede(entry MemoryEntry, supersedeKeys []string) error
- func (ps *PalaceStore) WriteLatent(entry MemoryEntry) error
- type SearchMemoryOptions
- type SearchResult
- type VectorStore
- func (vs *VectorStore) BatchUpsert(points []*qdrant.PointStruct) error
- func (vs *VectorStore) CreateBatchSparseCollections(names []string) error
- func (vs *VectorStore) CreateBatchSparseCollectionsContext(ctx context.Context, names []string) error
- func (vs *VectorStore) CreateBatchSparseCollectionsWithConcurrency(names []string, concurrency int) error
- func (vs *VectorStore) CreateBatchSparseCollectionsWithConcurrencyContext(ctx context.Context, names []string, concurrency int) error
- func (vs *VectorStore) CreateBatchSparseCollectionsWithResults(ctx context.Context, names []string) ([]CollectionCreateResult, error)
- func (vs *VectorStore) CreateBatchSparseCollectionsWithResultsAndConcurrency(ctx context.Context, names []string, concurrency int) ([]CollectionCreateResult, error)
- func (vs *VectorStore) CreateCollection(dim int) error
- func (vs *VectorStore) CreateSparseCollection() error
- func (vs *VectorStore) SearchByText(text string, limit int, filter map[string]interface{}, withPayload bool) ([]SearchResult, error)
- func (vs *VectorStore) SearchSimilar(queryVec []float32, limit int, filter map[string]interface{}, withPayload bool) ([]SearchResult, error)
- func (vs *VectorStore) SearchSparse(queryIndices []uint32, queryValues []float32, limit int, ...) ([]SearchResult, error)
- func (vs *VectorStore) StoreSparseVector(id string, indices []uint32, values []float32, payload map[string]interface{}) error
- func (vs *VectorStore) StoreVector(id string, vec []float32, payload map[string]interface{}) error
- type VectorStoreCallback
Constants ¶
const ( // MiniLMEmbeddingDim is the output size for all-MiniLM-L6-v2 (and KnightsAnalytics ONNX export). MiniLMEmbeddingDim = 384 // MiniLMMaxSeqTokens is the BERT position limit for all-MiniLM-L6-v2 ONNX exports. MiniLMMaxSeqTokens = 512 // DefaultHashEmbeddingDim is the dimension used by GenerateSimpleEmbedding when dim <= 0. DefaultHashEmbeddingDim = 768 // EnvONNXModelPath points at a hugot model directory (tokenizer + model.onnx) or a single .onnx file. EnvONNXModelPath = "MEMORY_ONNX_MODEL_PATH" // EnvEmbeddingStrict disables hash fallback when ONNX inference fails (recommended in production). EnvEmbeddingStrict = "MEMORY_EMBEDDING_STRICT" )
const ( // EnvHugotBackend selects the hugot inference backend: go (default), ort, or auto. EnvHugotBackend = "MEMORY_HUGOT_BACKEND" // EnvORTLibraryDir is the directory containing libonnxruntime.so/.dylib (ORT builds only). EnvORTLibraryDir = "MEMORY_ORT_LIBRARY_DIR" // EnvORTCuda enables the CUDA execution provider when set to 1/true. EnvORTCuda = "MEMORY_ORT_CUDA" // EnvORTCoreML enables the CoreML execution provider when set to 1/true. EnvORTCoreML = "MEMORY_ORT_COREML" // EnvORTCudaDeviceID selects the CUDA device (default 0). EnvORTCudaDeviceID = "MEMORY_ORT_CUDA_DEVICE_ID" )
const ( // DefaultONNXModelHF is the hugot-style ONNX export id. KnightsAnalytics has // not published this repo (HF 404 with auth). Download falls back to BAAI. DefaultONNXModelHF = "KnightsAnalytics/bge-small-en-v1.5" // BAAIONNXModelHF is the public BGE-small-en-v1.5 source (onnx/model.onnx). // Reshaped into hugot layout (root model.onnx) as testdata/models/BAAI_bge-small-en-v1.5. BAAIONNXModelHF = "BAAI/bge-small-en-v1.5" // LegacyONNXModelHF is the previous default (384-d MiniLM). LegacyONNXModelHF = "KnightsAnalytics/all-MiniLM-L6-v2" // BGESmallEmbeddingDim is the output width for BAAI/bge-small-en-v1.5 ONNX exports. BGESmallEmbeddingDim = 384 // EnvEmbeddingModelHF overrides the Hugging Face model id used for documentation and download scripts. EnvEmbeddingModelHF = "MEMORY_EMBEDDING_MODEL" )
const ConvTagPrefix = "conv:"
ConvTagPrefix groups haystack sessions that belong to one conversation/palace retrieve key (T1). Retrieve with SessionID=conv_id matches entries tagged conv:<conv_id> even when MemoryEntry.SessionID is the inner haystack session.
const DefaultPalaceBaseDir = ".palace"
DefaultPalaceBaseDir is the local palace root used when PalaceConfig.BaseDir (or NewPalaceStore's argument) is empty. Relative to the process working directory. Not a leftover product path and not a hosted palace.
const SourceHintPrivate = "private"
SourceHintPrivate is the default local-palace ingest class. It maps to the TUI ClassifyDigestSourceHint private bucket (private, palace, local, …).
const SourceHintTagPrefix = "source_hint:"
SourceHintTagPrefix is the Content.Tags / TemporalTags prefix for an observable source class (source_hint:private, source_hint:mesh, …).
Variables ¶
var DefaultCompactionConfig = CompactionConfig{ Tier2Strategy: StrategyPatternExtraction, Tier3Strategy: StrategyCorePrinciple, TemporalWindowSize: 12, SimilarityThreshold: 0.75, DataSim: 0.7, DataCount: 5, ProtectHighScoreFacts: true, FactScoreThreshold: 0.90, }
Functions ¶
func AssembleCountEvidence ¶ added in v1.5.12
func AssembleCountEvidence(query string, facts []MemoryEntry) string
AssembleCountEvidence lists unique matching fact snippets for a count query (named-pattern first, then first-person noun overlap). Deduped, not persisted. Clothing count queries diversify by action+object (dry-clean / return / pick-up × boot / blazer / generic) so a compound "return … pick them up" is two bullets and dry-clean survives when the query only says pick/return/store. Empty when the query is not a count question or no facts match.
func CalculateRecencyBoost ¶
CalculateRecencyBoost returns recency boost factor
func CalculateRelevanceScore ¶
func CalculateRelevanceScore(entry MemoryEntry) float64
CalculateRelevanceScore combines score impact, recency, temporal decay, usage
func CalculateTemporalDecay ¶
func CalculateTemporalDecay(entry MemoryEntry) float64
CalculateTemporalDecay implements H-Mem style forgetting curve
func ClassifyIngestSourceHint ¶ added in v1.5.10
ClassifyIngestSourceHint maps a source hint or tag to mesh, private, or "". Aligned with TUI ClassifyDigestSourceHint cite-both buckets. Host process labels (mcp_memory_ingest_turn, source:iomesh-memory-mcp) are not a class. Catalog/grant/external stay host concerns and return "".
func DefaultEmbeddingModelFromEnv ¶
func DefaultEmbeddingModelFromEnv() string
DefaultEmbeddingModelFromEnv returns the configured HF model id or DefaultONNXModelHF.
func DefaultONNXModelCacheDirName ¶
func DefaultONNXModelCacheDirName() string
DefaultONNXModelCacheDirName is the testdata/models subdirectory for the default ONNX export.
func EntryEntityKeys ¶
func EntryEntityKeys(e MemoryEntry) []string
EntryEntityKeys extracts entity-like keys from an entry for multi-hop matching. Sources:
- TemporalTags with "entity:" prefix → value after prefix (e.g. entity:person:alice → person:alice)
- TemporalTags with "subject:" prefix → full tag (subject:auth)
- Content.Tags with entity:/subject: prefixes (same rules)
- Relations.RelatedConcepts (trimmed non-empty strings as-is)
Duplicates are removed; order is stable (first-seen).
func EntryHasTag ¶
func EntryHasTag(e MemoryEntry, tag string) bool
EntryHasTag reports whether e has an exact tag match in TemporalTags or Content.Tags.
func EntryHasTagPrefix ¶
func EntryHasTagPrefix(e MemoryEntry, prefix string) bool
EntryHasTagPrefix reports whether e has a TemporalTags or Content.Tags entry with the given prefix.
func EntryValidAt ¶
func EntryValidAt(e MemoryEntry, asOf time.Time) bool
EntryValidAt reports whether e is considered valid at asOf.
Rules (bi-temporal lite — validity window on entries, not full dual clocks):
- Zero asOf is treated as time.Now().UTC().
- When valid_from / valid_until tags are present: - if valid_from is set and asOf.Before(from) → false - if valid_until is set and !asOf.Before(until) → false (valid_until is an exclusive end: asOf == until is invalid)
- When NO validity tags at all: fall back to "known by asOf" — valid if entryEventTime is zero OR !entryEventTime.After(asOf) (entry exists / was recorded by asOf).
This is not a full temporal knowledge graph (no transaction time, no edge validity). Hosts that write validity tags get windowed facts; untagged entries remain historically "known once recorded."
func ExtractAtomicFacts ¶
func ExtractAtomicFacts(entry MemoryEntry) []string
ExtractAtomicFacts extracts high-value personal facts from a memory entry.
func FormatSourceHintTag ¶ added in v1.5.10
FormatSourceHintTag returns source_hint:<hint> for a non-empty hint.
func GenerateSimpleEmbedding ¶
GenerateSimpleEmbedding (deterministic hash-based fallback)
func HugotCacheDirName ¶
HugotCacheDirName returns the local directory name hugot uses for a Hugging Face model id.
func MultiFactorScore ¶
func MultiFactorScore(entry MemoryEntry, queryVec []float32) float64
MultiFactorScore implements full H-Mem scoring
func ParseValidityWindow ¶
func ParseValidityWindow(e MemoryEntry) (from, until *time.Time)
ParseValidityWindow reads valid_from / valid_until from TemporalTags. Missing or unparseable bounds are open-ended (nil).
Tag format: "valid_from:<RFC3339>" and "valid_until:<RFC3339>" (time.RFC3339 / time.RFC3339Nano accepted via time.Parse).
func PopulateTemporalTags ¶
PopulateTemporalTags (cycle-aware)
func ResolveEmbeddingDim ¶
ResolveEmbeddingDim returns the Qdrant/Palace vector width for the active embedding backend. When an ONNX model path is configured, infers dimension from the model directory name; otherwise hash (768).
func ResolveEmbeddingDimFromEnv ¶
func ResolveEmbeddingDimFromEnv() int
ResolveEmbeddingDimFromEnv reads MEMORY_ONNX_MODEL_PATH and returns the matching dimension.
Types ¶
type BatchCollectionError ¶
type BatchCollectionError struct {
Failures []CollectionCreateResult
}
func (*BatchCollectionError) Error ¶
func (e *BatchCollectionError) Error() string
func (*BatchCollectionError) Is ¶
func (e *BatchCollectionError) Is(target error) bool
func (*BatchCollectionError) Unwrap ¶
func (e *BatchCollectionError) Unwrap() []error
type BatchEmbeddingFunc ¶
BatchEmbeddingFunc embeds multiple texts in one forward pass when supported (e.g. GONNXEmbedder).
type CollectionCreateResult ¶
type CompactionAction ¶
type CompactionConfig ¶
type CompactionConfig struct {
Tier2Strategy CompactionStrategy `json:"tier2_strategy"`
Tier3Strategy CompactionStrategy `json:"tier3_strategy"`
LastEvaluatedCycle int `json:"last_evaluated_cycle"`
AvgScoreBefore float64 `json:"avg_score_before"`
AvgScoreAfter float64 `json:"avg_score_after"`
Improvement float64 `json:"improvement"`
// H-Mem inspired
TemporalWindowSize int `json:"temporal_window_size"` // beta-like (e.g. cycles or months)
SimilarityThreshold float64 `json:"similarity_threshold"` // alpha
// RecMem phase-transition (Phase 1)
DataSim float64 `json:"data_sim"` // geometric similarity radius (default 0.7)
DataCount int `json:"data_count"` // critical recurrence count (default 5)
// LongMemEval production hardening
ProtectHighScoreFacts bool `json:"protect_high_score_facts"` // default true
FactScoreThreshold float64 `json:"fact_score_threshold"` // default 0.90
}
CompactionConfig (extended with RecMem phase-transition parameters)
type CompactionStrategy ¶
type CompactionStrategy string
CompactionStrategy types (from ossa, kept for compatibility)
const ( StrategySimpleSummary CompactionStrategy = "simple_summary" StrategyPatternExtraction CompactionStrategy = "pattern_extraction" StrategyCorePrinciple CompactionStrategy = "core_principle" )
type EmbeddingFunc ¶
EmbeddingFunc is injectable for semantic embeddings (Phase 5.1)
func NewGONNXEmbeddingFunc ¶
func NewGONNXEmbeddingFunc(modelPath string) (EmbeddingFunc, error)
NewGONNXEmbeddingFunc returns a Palace-compatible EmbeddingFunc backed by pure-Go ONNX. modelPath may be empty to use GenerateSimpleEmbedding (dev/tests). modelPath may be a hugot model directory or a direct path to a single .onnx file.
func NewGONNXEmbeddingFuncFromEnv ¶
func NewGONNXEmbeddingFuncFromEnv() (EmbeddingFunc, error)
NewGONNXEmbeddingFuncFromEnv loads MEMORY_ONNX_MODEL_PATH when set; otherwise hash embeddings.
type EntityGraph ¶
EntityGraph for H-Mem KG integration (richer relational graph)
type FactsAsOfOptions ¶
type FactsAsOfOptions struct {
// AsOf is the validity instant (zero = Now UTC).
AsOf time.Time
// Query optional case-insensitive substring on Summary / Full / OriginalText.
Query string
// SessionID, when non-empty, keeps matching SessionID or conv:<SessionID> tags (T1).
SessionID string
// SessionIDs, when non-empty, is an any-of filter (union with SessionID).
SessionIDs []string
// Entity filters TemporalTags:
// - if Entity contains ':', exact match on "entity:<value>" (or Entity itself
// when it already has the "entity:" prefix);
// - otherwise any TemporalTag with prefix "entity:" that contains Entity.
Entity string
// Limit caps results (default 50 when <= 0).
Limit int
// Tier when non-nil: only that tier. When nil: Working+Contextual+Semantic
// (exclude Archival unless IncludeArchival).
Tier *MemoryTier
// IncludeArchival, when true and Tier==nil, also includes Archival.
IncludeArchival bool
}
FactsAsOfOptions configures as-of validity listing (K4 first slice / s616).
Filters apply before Limit so many invalid-at-asOf entries do not underfill.
type GONNXEmbedder ¶
type GONNXEmbedder struct {
// contains filtered or unexported fields
}
GONNXEmbedder runs sentence embeddings via hugot FeatureExtractionPipeline. Call Close when done to release the hugot session.
func NewGONNXEmbedder ¶
func NewGONNXEmbedder(opts GONNXOptions) (*GONNXEmbedder, error)
NewGONNXEmbedder loads a hugot-compatible ONNX model directory and starts a feature-extraction pipeline.
func (*GONNXEmbedder) Backend ¶
func (e *GONNXEmbedder) Backend() string
Backend returns the active hugot backend label (gomlx, ort+cpu, ort+cuda:0, ort+coreml).
func (*GONNXEmbedder) BatchFunc ¶
func (e *GONNXEmbedder) BatchFunc() BatchEmbeddingFunc
BatchFunc returns a Palace-compatible batch embedding closure for SearchMemory batch scoring.
func (*GONNXEmbedder) Close ¶
func (e *GONNXEmbedder) Close() error
Close releases hugot session resources.
func (*GONNXEmbedder) Dimension ¶
func (e *GONNXEmbedder) Dimension() int
Dimension returns the native embedding width produced by the loaded ONNX model.
func (*GONNXEmbedder) Embed ¶
func (e *GONNXEmbedder) Embed(text string) ([]float32, error)
Embed returns an L2-normalized embedding for text.
func (*GONNXEmbedder) EmbedBatch ¶
func (e *GONNXEmbedder) EmbedBatch(texts []string) ([][]float32, error)
EmbedBatch returns L2-normalized embeddings for all texts in one pipeline forward pass.
func (*GONNXEmbedder) Func ¶
func (e *GONNXEmbedder) Func() EmbeddingFunc
Func returns an EmbeddingFunc that preserves the PalaceConfig injectable signature. The returned closure keeps the embedder alive; callers should not discard the embedder until all embedding work is finished (or use Func() only via NewGONNXEmbeddingFunc).
type GONNXOptions ¶
type GONNXOptions struct {
ModelPath string
// Strict disables silent fallback to GenerateSimpleEmbedding on inference errors.
Strict bool
// HugotBackend overrides MEMORY_HUGOT_BACKEND for this embedder (go, ort, auto).
HugotBackend HugotBackendConfig
}
GONNXOptions configures a hugot ONNX embedder (GoMLX by default; ORT when built with -tags ORT).
type HugotBackendConfig ¶
type HugotBackendConfig struct {
Backend string // go, ort, auto
LibraryDir string
Cuda bool
CoreML bool
DeviceID string
}
HugotBackendConfig holds resolved hugot session options from the environment.
func ResolveHugotBackendFromEnv ¶
func ResolveHugotBackendFromEnv() HugotBackendConfig
ResolveHugotBackendFromEnv reads MEMORY_HUGOT_BACKEND and ORT accelerator env vars.
func (HugotBackendConfig) HugotBackendLabel ¶
func (c HugotBackendConfig) HugotBackendLabel() string
HugotBackendLabel returns a log-friendly backend description.
type ListMemoryOptions ¶
type ListMemoryOptions struct {
SessionID string
// SessionIDs, when non-empty, is an any-of filter (union with SessionID).
// conv:<id> tags match the same way as SearchMemoryWithOptions (T1).
SessionIDs []string
// TimeFrom / TimeTo filter by entry event time (see entryEventTime). Both inclusive when set.
TimeFrom *time.Time
TimeTo *time.Time
// Tag exact-matches any of TemporalTags or Content.Tags.
Tag string
// TagPrefix matches tag strings with strings.HasPrefix (e.g. "subject:", "session_seq:").
TagPrefix string
// Query optional case-insensitive substring on Summary / Full / OriginalText.
Query string
// Limit caps results (default 50 when <= 0 — timeline-friendly; not search's 10).
Limit int
// Tier when non-nil: only that tier. When nil: Working+Contextual+Semantic
// (exclude Archival by default to match the public MCP host timeline).
Tier *MemoryTier
// IncludeArchival, when true and Tier==nil, also includes Archival.
IncludeArchival bool
// Ascending: false = newest first (default); true = oldest first.
Ascending bool
}
ListMemoryOptions configures event-time ordered listing with optional filters (K2 / s611).
Filters are applied before Limit so windowed/session timelines do not underfill when many out-of-scope entries exist (same underfill class as SearchMemoryWithOptions K1).
Complexity: FS Palace is source of truth. When the best-effort meta index is enabled (default), ListMemoryWithOptions filters on lightweight entryMeta and loads full JSON only for survivors (s1066). Write/unlink patches a clean index in place (#63). A durable snapshot at indexes/event-time.json (#44) avoids re-parsing every tier JSON on a fresh process when the stamp matches. With DisableMetaIndex, falls back to O(n) full entry scan.
type MemoryContent ¶
type MemoryContent struct {
Summary string `json:"summary"`
Full string `json:"full,omitempty"`
Tags []string `json:"tags,omitempty"`
Embedding []float32 `json:"embedding,omitempty"`
EmbeddingModel string `json:"embedding_model,omitempty"`
EmbeddingDim int `json:"embedding_dim,omitempty"`
}
MemoryContent holds summary/full/tags and optional persisted ONNX vectors. Embedding fields are omitted unless PersistEmbeddings is on and the model is a non-hash id. Hash vectors are never stored (kernel #45).
type MemoryEntry ¶
type MemoryEntry struct {
ID string `json:"id"`
Type string `json:"type"`
Tier MemoryTier `json:"tier"`
Version int `json:"version"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Cycle int `json:"cycle"`
TemporalTags []string `json:"temporal_tags,omitempty"`
AccessCount int `json:"access_count"`
LastAccessed time.Time `json:"last_accessed,omitempty"`
// === LongMemEval / turn-level granularity extensions (production implementation) ===
TurnID string `json:"turn_id,omitempty"` // explicit round/turn identifier
SessionID string `json:"session_id,omitempty"` // multi-session grouping
Timestamp time.Time `json:"timestamp,omitempty"` // precise event time for temporal reasoning
ExtractedFacts []string `json:"extracted_facts,omitempty"` // fact-augmented for better recall
Keyphrases []string `json:"keyphrases,omitempty"` // keyphrase expansion for indexing
OriginalText string `json:"original_text,omitempty"` // raw turn text for provenance
Content MemoryContent `json:"content"`
Provenance MemoryProvenance `json:"provenance"`
Metrics MemoryMetrics `json:"metrics"`
Relations MemoryRelations `json:"relations"`
}
MemoryEntry is the core unit stored in the Palace. Extended for LongMemEval production readiness: explicit turn/session granularity + fact-augmented indexing.
type MemoryMetrics ¶
type MemoryMetrics struct {
ScoreImpact float64 `json:"score_impact,omitempty"`
UsageCount int `json:"usage_count"`
LastAccessed time.Time `json:"last_accessed,omitempty"`
}
MemoryMetrics for scoring and access
type MemoryProvenance ¶
type MemoryProvenance struct {
SourceCycle int `json:"source_cycle"`
SourceStep string `json:"source_step,omitempty"`
// SourceHint is the cite-both source class (private|mesh|…). IngestTurn
// defaults this to "private" on the local-palace path when the caller
// does not already supply a classifiable hint or tag. Distinct from
// SourceStep (process name such as mcp_memory_ingest_turn).
SourceHint string `json:"source_hint,omitempty"`
ParentIDs []string `json:"parent_ids,omitempty"`
ToolCalls []string `json:"tool_calls,omitempty"`
}
MemoryProvenance tracks origin
type MemoryRelations ¶
type MemoryRelations struct {
ImprovesUpon []string `json:"improves_upon,omitempty"`
RelatedConcepts []string `json:"related_concepts,omitempty"`
Backlinks []string `json:"backlinks,omitempty"`
}
MemoryRelations for graph links
type MemoryStats ¶
type MemoryStats struct {
WorkingCount int
ContextualCount int
ArchivalCount int
SemanticCount int // Phase 3
TotalEntries int
LastCompaction time.Time
}
MemoryStats provides observability metrics
type MemoryTier ¶
type MemoryTier int
MemoryTier defines the three-tier hierarchical memory (inspired by ossa Palace + H-Mem ideas)
const ( TierWorking MemoryTier = 1 TierContextual MemoryTier = 2 TierArchival MemoryTier = 3 // TierSemantic is used for high-fidelity atomic facts protected by RecMem Phase 3 TierSemantic MemoryTier = 4 )
type MultiHopOptions ¶
type MultiHopOptions struct {
// SeedEntity is the starting entity key (normalized). Prefer exact graph node keys.
SeedEntity string
// SeedQuery optional: if set, run SearchMemoryWithOptions with Query then derive
// entity seeds from top hits' TemporalTags entity:* and RelatedConcepts
// (combined with SeedEntity when both are set).
SeedQuery string
// MaxHops default 2; clamped to 1..4. Hop 0 is the seed itself.
MaxHops int
// Limit default 20; applied AFTER expansion + entry collect + filters.
Limit int
// SessionID, when non-empty, keeps matching SessionID or conv:<SessionID> tags (T1).
SessionID string
// SessionIDs, when non-empty, is an any-of filter (union with SessionID).
SessionIDs []string
// AsOf optional EntryValidAt filter (before Limit).
AsOf *time.Time
// Tier when non-nil: only that tier. When nil: Working+Contextual+Semantic
// (exclude Archival unless IncludeArchival).
Tier *MemoryTier
// IncludeArchival, when true and Tier==nil, also includes Archival.
IncludeArchival bool
// QueryVec optional pass-through when seeding via SeedQuery search.
QueryVec []float32
// PreferShorterHops ranks by minimum BFS hop distance from seed (lower first),
// then event time descending within the same hop. Default true (nil or true).
// Set to a false pointer to opt out and use legacy seed-match-first sort.
PreferShorterHops *bool
}
MultiHopOptions configures associative / multi-hop lite retrieval over the EntityGraph plus entry entity tags (A2 first slice / s619; hop ranking s1067; residual pin s1278).
BFS over GetRelatedEntities and entry collect via TemporalTags / Content.Tags / RelatedConcepts. Not a full Zep / Graphiti knowledge graph. Hop-distance ranking is path-aware ranking lite (prefer shorter BFS hops), not typed-edge / embedding-guided path scoring. Not a full graph RAG.
type PalaceConfig ¶
type PalaceConfig struct {
// BaseDir is the local palace root. Empty uses DefaultPalaceBaseDir (".palace").
BaseDir string
MaxWorkingEntries int
MaxWorkingAgeHours int
CompactionConfig CompactionConfig
EmbeddingFunc EmbeddingFunc `json:"-"` // pluggable (Phase 5.1)
BatchEmbeddingFunc BatchEmbeddingFunc `json:"-"` // optional ONNX batch path (Phase 5.1)
// PersistEmbeddings stores ONNX vectors on MemoryContent when true.
// Default false: Write does not persist embeddings. Hash models
// (EmbeddingModel empty or "hash") are never persisted even when true.
PersistEmbeddings bool
// EmbeddingModel is "hash" or empty for GenerateSimpleEmbedding; ONNX
// callers set a model id (e.g. "bge-small-en-v1.5"). Persist and search
// match on this string — not EmbeddingFunc pointer identity.
EmbeddingModel string
// EmbeddingDim is the expected vector width. 0 infers from EmbeddingFunc
// output or DefaultHashEmbeddingDim.
EmbeddingDim int
// DisableMetaIndex forces ListMemoryWithOptions to use the full FS scan path
// instead of the best-effort in-memory metadata index (K2 residual / s1066).
// Default false (index enabled). Useful for parity tests.
DisableMetaIndex bool
// DisableDurableIndex skips load/save of indexes/event-time.json.
// The in-memory meta index still runs unless DisableMetaIndex is set.
// Default false (durable snapshot enabled). FS Palace remains source of truth.
DisableDurableIndex bool
}
PalaceConfig for configurable PalaceStore creation (Phase 4.3)
type PalaceStore ¶
type PalaceStore struct {
BaseDir string
Config PalaceConfig
// contains filtered or unexported fields
}
PalaceStore provides file-backed hierarchical memory storage.
func NewPalaceStore ¶
func NewPalaceStore(baseDir string) *PalaceStore
NewPalaceStore is a convenience constructor (uses defaults). Empty baseDir defaults to DefaultPalaceBaseDir.
func NewPalaceStoreWithConfig ¶
func NewPalaceStoreWithConfig(cfg PalaceConfig) *PalaceStore
NewPalaceStoreWithConfig creates PalaceStore with full configuration (Phase 4.3). Empty BaseDir defaults to DefaultPalaceBaseDir (".palace") under the process cwd. EmbeddingModel is left empty (hash default) unless the caller set it. PersistEmbeddings stays false unless the caller set it.
func (*PalaceStore) AddEntityRelationship ¶
func (ps *PalaceStore) AddEntityRelationship(entity, related string)
AddEntityRelationship adds normalized entity links (H-Mem style). Ensures BaseDir/relations exists before write (safe if ensureDirs was skipped or the directory was removed). Shared graph rewrite is serialized on writeMu and written via temp+rename at 0600 (#86).
func (*PalaceStore) AutoRecMemCompaction ¶
func (ps *PalaceStore) AutoRecMemCompaction(generateFn func(prompt string) string, vectorCb VectorStoreCallback)
AutoRecMemCompaction is the production entry point for automatic RecMem formation.
func (*PalaceStore) EvictWorkingTier ¶
func (ps *PalaceStore) EvictWorkingTier(maxAgeHours int, maxCount int)
EvictWorkingTier performs age/size-based eviction from Working tier (Phase 4.2)
func (*PalaceStore) ExpandRelatedEntities ¶
func (ps *PalaceStore) ExpandRelatedEntities(seed string, maxHops int) []string
ExpandRelatedEntities BFS from seed over GetRelatedEntities up to maxHops (includes seed at hop 0). maxHops is clamped to 1..4.
Returns unique entity keys in BFS discovery order (seed first).
func (*PalaceStore) ExpandRelatedEntitiesHops ¶
func (ps *PalaceStore) ExpandRelatedEntitiesHops(seed string, maxHops int) map[string]int
ExpandRelatedEntitiesHops BFS from seed over GetRelatedEntities up to maxHops (includes seed at hop 0). maxHops is clamped to 1..4.
Returns entity key → minimum hop distance from seed. Empty seed → nil.
func (*PalaceStore) GetRelatedEntities ¶
func (ps *PalaceStore) GetRelatedEntities(entity string) []string
GetRelatedEntities returns related entities for graph traversal
func (*PalaceStore) GetStats ¶
func (ps *PalaceStore) GetStats() MemoryStats
GetStats returns observability metrics (Phase 1.2)
func (*PalaceStore) IngestTurn ¶
func (ps *PalaceStore) IngestTurn(turn MemoryEntry) error
IngestTurn is the primary production entry point for LongMemEval benchmark and ego online session processing. It writes the parent turn first, then each non-empty ExtractedFacts child as type turn_fact. When ExtractedFacts is empty, facts are auto-extracted from the turn text.
Child Content.Tags inherit the parent turn's Content.Tags (trimmed, de-duplicated) and always include the structural markers fact_augmented and from_turn. The kernel does not stamp longmemeval; callers that want that label (the LongMemEval harness under cmd/longmemeval-* and internal/longmemeval) pass it on the parent so children inherit it.
Local-palace IngestTurn stamps an observable private source class when the caller does not already provide a classifiable source hint or tag: Provenance.SourceHint is set to "private" and Content.Tags gains source_hint:private. Mesh-class hints (source_hint:mesh, source:mesh, …) stay distinct and are not overwritten. Host process labels such as mcp_memory_ingest_turn / source:iomesh-memory-mcp are not a cite-both class. Fact children inherit SourceHint and the source_hint:* tag.
Fact-augmented children get valid_from stamped when unset; child Write errors are returned.
Partial persist is the contract: a child Write error does not roll back the parent or earlier facts already written. A non-nil error does not mean nothing persisted. Not all-or-nothing.
func (*PalaceStore) InvalidateMetaIndex ¶
func (ps *PalaceStore) InvalidateMetaIndex()
InvalidateMetaIndex is the exported test/debug hook for force-rebuild.
func (*PalaceStore) ListEntriesInTier ¶
func (ps *PalaceStore) ListEntriesInTier(tier MemoryTier) []MemoryEntry
ListEntriesInTier returns all entries in the given tier, sorted by relevance score (descending).
func (*PalaceStore) ListFactsAsOf ¶
func (ps *PalaceStore) ListFactsAsOf(opts FactsAsOfOptions) []MemoryEntry
ListFactsAsOf lists entries valid at AsOf with optional filters. Filters apply before Limit (underfill class, same as K1/K2).
Order of operations: collect candidates → session → entity → query → EntryValidAt(asOf) → sort (Semantic first, then event time desc) → limit.
Default tiers when Tier == nil: Working + Contextual + Semantic (+ Archival if IncludeArchival).
Bi-temporal lite (validity window tags). Not full Graphiti dual clocks + graph. FS Palace remains O(n) over tier files.
func (*PalaceStore) ListMemoryWithOptions ¶
func (ps *PalaceStore) ListMemoryWithOptions(opts ListMemoryOptions) []MemoryEntry
ListMemoryWithOptions returns entries ordered by event time with optional filters applied before Limit (K2 / s611 timeline surface; s1066 meta index when enabled).
Order of operations: collect candidates → session → time → tag filters → query substring → sort by entryEventTime → limit.
func (*PalaceStore) Load ¶
func (ps *PalaceStore) Load(id string, tier MemoryTier) (MemoryEntry, bool)
Load retrieves by ID and tier. Production: no side-effect prints, clean bool return.
func (*PalaceStore) MetaIndexLen ¶
func (ps *PalaceStore) MetaIndexLen() int
MetaIndexLen returns the number of entries currently cached in the meta index (0 if dirty/unbuilt). Intended for tests and observability — not a product API.
func (*PalaceStore) MetaIndexRebuilds ¶
func (ps *PalaceStore) MetaIndexRebuilds() uint64
MetaIndexRebuilds returns how many full tier-JSON walks rebuildMetaIndexLocked has run on this store. Tests use this to prove Write/unlink patched in place. Not a product API.
func (*PalaceStore) MultiHopRetrieve ¶
func (ps *PalaceStore) MultiHopRetrieve(opts MultiHopOptions) []MemoryEntry
MultiHopRetrieve performs multi-hop lite associative retrieval:
- Resolve seeds (SeedEntity and/or entities from SeedQuery search hits)
- ExpandRelatedEntitiesHops for each seed (min hop across seeds)
- Collect entries from default tiers matching any expanded entity
- Optional AsOf + SessionID filters BEFORE Limit
- Sort: lower min hop first (default), then event time desc within hop (legacy: seed-match first when PreferShorterHops is explicitly false)
- Limit
Default MaxHops=2 (clamped 1..4), Limit=20. Default tiers: Working + Contextual + Semantic (+ Archival if IncludeArchival). PreferShorterHops defaults true (path-aware ranking lite / s1067).
func (*PalaceStore) PerformCompaction ¶
func (ps *PalaceStore) PerformCompaction( targetTier MemoryTier, cfg CompactionConfig, generateFn func(prompt string) string, vectorCallback VectorStoreCallback, ) error
PerformCompaction runs agent-managed compaction with H-Mem temporal window + alpha constraints. Now respects LongMemEval fact protection and turn granularity. Product Write errors from SUMMARIZE / MERGE / CREATE_CORE_PRINCIPLE / ARCHIVE are returned.
func (*PalaceStore) PromoteToContextual ¶
func (ps *PalaceStore) PromoteToContextual(threshold float64)
PromoteToContextual promotes high-relevance Working entries (Phase 4.2)
func (*PalaceStore) ReadWithChainOfNote ¶
func (ps *PalaceStore) ReadWithChainOfNote(retrieved []MemoryEntry, query string) (string, error)
ReadWithChainOfNote formats retrieved MemoryEntry items into a Chain-of-Note style prompt.
func (*PalaceStore) SearchMemory ¶
func (ps *PalaceStore) SearchMemory(query string, tier *MemoryTier, limit int, vec []float32) []MemoryEntry
SearchMemory provides hybrid retrieval (keyword + vector + temporal) - Phase 4.1. Thin wrapper over SearchMemoryWithOptions with no session/time filters and ReRankTemporal=false. When tier is nil, default tiers skip Archival (Working+Contextual+Semantic) unless the query has no keyword hits on those tiers (low-confidence fallback; #87).
func (*PalaceStore) SearchMemoryWithOptions ¶
func (ps *PalaceStore) SearchMemoryWithOptions(query string, opts SearchMemoryOptions) []MemoryEntry
SearchMemoryWithOptions provides hybrid retrieval with optional session, time-window, and temporal re-ranking. Uses the configured EmbeddingFunc for vector re-ranking. A persisted Content.Embedding is reused when EmbeddingModel and dim match the query vec / store config; otherwise the entry is re-embedded. Keyword hits still rank ahead of Limit.
Default tiers when Tier==nil match ListMemoryWithOptions: Working+Contextual+Semantic. Archival is included when IncludeArchival is set, or when the default-tier keyword hit set is empty (low-confidence fallback). That fallback is the empty keyword-hit set, not a numeric cosine cutoff (Memory P0: do not invent a threshold). Count queries (`how many` / `how much`) union matching turn_facts from the session/`conv:` candidate set, rank named-pattern facts above fallback chatter, then session-diversify before Limit.
func (*PalaceStore) SemanticRefine ¶
func (ps *PalaceStore) SemanticRefine(cluster []MemoryEntry) error
SemanticRefine (RecMem Phase 3) protects high-stake atomic facts from clusters. Products get SessionID / Timestamp from the parent and valid_from when unset.
func (*PalaceStore) SupersedeEntityFacts ¶
SupersedeEntityFacts finds entries matching entityKey (via EntryEntityKeys / entity: tags) that are still open at asOf (EntryValidAt), and writes valid_until = asOf (exclusive end matching existing FactsAsOf semantics). Does not delete entries.
Matching: normalize entityKey to lower-case trim; an entry matches when any key from EntryEntityKeys equals that normalized form (also lower-cased). Empty entityKey is a no-op (returns 0, nil).
Bi-temporal lite supersession — not automatic NLP contradiction detection, not full Zep dual-clock KG. Callers pass explicit entity keys.
Returns the count of updated entries.
func (*PalaceStore) Write ¶
func (ps *PalaceStore) Write(entry MemoryEntry) error
Write persists a MemoryEntry with an atomic write (temp file + rename).
Versioning is caller-managed and best-effort. Version==0 is stored as 1. archiveToVersions writes versions/memory-entries/<id>/v{Version}.json for the incoming entry; its errors are non-fatal and do not fail Write. A second Write of the same ID and Version overwrites both the live tier file and that snapshot. Callers who want history must increment Version themselves. This is not automatic overwrite versioning and not a hosted version store.
PersistEmbeddings default false strips embedding fields before marshal (including stuffed floats). Hash models (EmbeddingModel empty or "hash") never persist vectors, even when the flag is true (kernel #45). When the flag is on and EmbeddingModel is a non-hash id, the JSON rename is the ingest ack; embedding is then filled best-effort. Embed miss, empty output, or panic is not an ingest failure.
func (*PalaceStore) WriteAndSupersede ¶
func (ps *PalaceStore) WriteAndSupersede(entry MemoryEntry, supersedeKeys []string) error
WriteAndSupersede writes entry first (stamping valid_from=now when unset), then runs SupersedeEntityFacts for each supersedeKeys entry, excluding the newly written entry's ID so it is not closed by its own write.
asOf for supersession is the same UTC now used for valid_from stamping.
func (*PalaceStore) WriteLatent ¶
func (ps *PalaceStore) WriteLatent(entry MemoryEntry) error
WriteLatent stores entry in the subconscious latent buffer (RecMem Phase 1). No immediate promotion or LLM compaction is triggered.
Versioning is caller-managed and best-effort, same as Write: Version==0 is stored as 1; archiveToVersions errors are non-fatal; callers who want history must increment Version themselves. Overwrite does not auto-increment.
type SearchMemoryOptions ¶
type SearchMemoryOptions struct {
// SessionID, when non-empty, keeps entries whose SessionID matches or that
// carry tag conv:<SessionID> (T1: inner haystack sessions under one conv).
SessionID string
// SessionIDs, when non-empty, is an any-of filter (union with SessionID).
SessionIDs []string
// TimeFrom / TimeTo filter by entry event time (see entryEventTime).
// Both bounds are inclusive when set.
TimeFrom *time.Time
TimeTo *time.Time
// AsOf, when non-nil, drops candidates where !EntryValidAt(e, *AsOf) before Limit
// (K4 facts-as-of / validity window; see EntryValidAt).
AsOf *time.Time
// Limit caps the result set (default 10 when <= 0).
Limit int
// Tier, when non-nil, restricts candidates to that tier.
Tier *MemoryTier
// QueryVec, when non-empty, ranks candidates by cosine similarity.
// Keyword hits (if the query has tokens of length >= 3) are kept ahead of
// non-hits so hash embeddings cannot drop a literal match past Limit.
QueryVec []float32
// ReRankTemporal, when true, sorts results by CalculateRelevanceScore descending
// after the keyword/vector path (before Limit). Keyword hits stay ahead of
// non-hits so temporal re-rank cannot drop a literal match past Limit.
ReRankTemporal bool
// IncludeArchival, when true and Tier==nil, also includes Archival.
// Default retrieve is Working+Contextual+Semantic (same as ListMemoryWithOptions).
IncludeArchival bool
}
SearchMemoryOptions configures hybrid retrieval with optional session, time-window, as-of validity, and temporal re-ranking filters.
type SearchResult ¶
SearchResult represents a single vector search hit with score and payload.
type VectorStore ¶
VectorStore provides optional vector capabilities using official Qdrant Go client v1 Production implementation with full dense/sparse query support, proper error handling, and payload extraction.
func NewVectorStore ¶
func NewVectorStore(rawURL, collection string) *VectorStore
NewVectorStore initializes the official Qdrant client.
func (*VectorStore) BatchUpsert ¶
func (vs *VectorStore) BatchUpsert(points []*qdrant.PointStruct) error
BatchUpsert upserts multiple points at once
func (*VectorStore) CreateBatchSparseCollections ¶
func (vs *VectorStore) CreateBatchSparseCollections(names []string) error
func (*VectorStore) CreateBatchSparseCollectionsContext ¶
func (vs *VectorStore) CreateBatchSparseCollectionsContext(ctx context.Context, names []string) error
func (*VectorStore) CreateBatchSparseCollectionsWithConcurrency ¶
func (vs *VectorStore) CreateBatchSparseCollectionsWithConcurrency(names []string, concurrency int) error
func (*VectorStore) CreateBatchSparseCollectionsWithConcurrencyContext ¶
func (vs *VectorStore) CreateBatchSparseCollectionsWithConcurrencyContext(ctx context.Context, names []string, concurrency int) error
CreateBatchSparseCollectionsWithConcurrencyContext is the context-aware version with custom concurrency.
func (*VectorStore) CreateBatchSparseCollectionsWithResults ¶
func (vs *VectorStore) CreateBatchSparseCollectionsWithResults(ctx context.Context, names []string) ([]CollectionCreateResult, error)
func (*VectorStore) CreateBatchSparseCollectionsWithResultsAndConcurrency ¶
func (vs *VectorStore) CreateBatchSparseCollectionsWithResultsAndConcurrency(ctx context.Context, names []string, concurrency int) ([]CollectionCreateResult, error)
func (*VectorStore) CreateCollection ¶
func (vs *VectorStore) CreateCollection(dim int) error
CreateCollection creates a dense vector collection with cosine distance.
func (*VectorStore) CreateSparseCollection ¶
func (vs *VectorStore) CreateSparseCollection() error
CreateSparseCollection creates a sparse vector collection.
func (*VectorStore) SearchByText ¶
func (vs *VectorStore) SearchByText(text string, limit int, filter map[string]interface{}, withPayload bool) ([]SearchResult, error)
SearchByText performs text-based semantic search.
func (*VectorStore) SearchSimilar ¶
func (vs *VectorStore) SearchSimilar(queryVec []float32, limit int, filter map[string]interface{}, withPayload bool) ([]SearchResult, error)
SearchSimilar performs dense vector similarity search using the official Qdrant Query API.
func (*VectorStore) SearchSparse ¶
func (vs *VectorStore) SearchSparse(queryIndices []uint32, queryValues []float32, limit int, filter map[string]interface{}, withPayload bool) ([]SearchResult, error)
SearchSparse performs sparse vector similarity search using the official Qdrant Query API.
func (*VectorStore) StoreSparseVector ¶
func (vs *VectorStore) StoreSparseVector(id string, indices []uint32, values []float32, payload map[string]interface{}) error
StoreSparseVector upserts a sparse vector with payload
func (*VectorStore) StoreVector ¶
func (vs *VectorStore) StoreVector(id string, vec []float32, payload map[string]interface{}) error
StoreVector upserts a dense vector with payload
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
longmemeval-bench
command
|
|
|
longmemeval-server
command
|
|
|
longmemeval-v2-bench
command
|
|
|
two-process-writer-probe
command
Two-process writer probe child: one PalaceStore process against a shared root.
|
Two-process writer probe child: one PalaceStore process against a shared root. |
|
examples
|
|
|
ttfh_rca
command
TTFH-shaped walking skeleton for the palace kernel.
|
TTFH-shaped walking skeleton for the palace kernel. |
|
internal
|
|
|
onnxdownload
Package onnxdownload is the fail-soft helper for scripts/download_onnx_model.go.
|
Package onnxdownload is the fail-soft helper for scripts/download_onnx_model.go. |
|
writerprobe
Package writerprobe is last-write-wins evidence for two OS processes on one palace root.
|
Package writerprobe is last-write-wins evidence for two OS processes on one palace root. |
|
Download the default KnightsAnalytics bge-small-en-v1.5 ONNX model for local Palace recall.
|
Download the default KnightsAnalytics bge-small-en-v1.5 ONNX model for local Palace recall. |