Skip to content

v0.40.0

Latest

Choose a tag to compare

@github-actions github-actions released this 17 Oct 21:35

Added

  • A recalled memory says where it came from: MemoryUnit.SourceRef and MemoryUnit.DerivedFrom. RememberAsync(…, sourceRef) / EncodeRequest.SourceRef take the caller's message or turn id and a recalled memory hands it back; a summary,
    a merge or a reflection lists the memories it was made from (DerivedFrom, read from the summary_of / merged_from /
    source_ids metadata those already wrote). Both live in Metadata, so every store keeps them with no schema change.
    Breaking for implementers of IMemoryService (one more optional parameter before cancellationToken).

Changed

  • Recall no longer favours a long memory for containing the query's words because it is long. The keyword part of the
    combined score counted each query word a memory contains, whatever its length, so a long answer that mentions most
    words outranked a short statement that is the answer. A contained word now counts by BM25's term-frequency and length
    factor (k1 1.2, b 0.75, relative to the candidates' average length), capped at its old value — an average-length
    memory scores as before. Measured with bge-m3: BEAM 100K NDCG@10 +0.013 [+0.007, +0.019]; LongMemEval_S (120 questions)
    NDCG@10 +0.007 [−0.005, +0.020], no type significantly lower.

Fixed

  • A promoted fact no longer erases what the profile already held under its key. Fast-track promotion wrote every fact with
    IArchiveStore.SetAsync, so a fact that replaced an earlier one left no history (GetHistoryAsync returned only the new
    value) and the same fact promoted again reset its confirmation count to 1. A different value now supersedes the current one
    through ArchiveAndUpdateAsync (the earlier value stays, inactive, with its ValidTo), and the same value is a confirmation
    (ConfirmAsync).
  • Forgetting a user (ForgetUserAsync) removes the user's profile too. The facts promoted into IArchiveStore survived
    the GDPR deletion and stayed readable through the profile and conflict APIs. Breaking for implementers of
    IArchiveStore: RemoveAllAsync(userId) is new.
  • The profile (IArchiveStore) is kept in the configured memory store, so it survives a restart. It lived in a
    process-local dictionary, so with the SQLite or VectorStore store every promoted fact, confirmation and version history
    was lost when the process stopped. Each entry is now a memory under the user key ArchiveUserKey.For(userId) — every store
    partitions by user, so profile entries never appear in the user's recall — and fact validation during promotion sees the
    profile's active entries, so a fact that contradicts the profile is detected. A read's time is kept (at most one write per
    entry per hour), as retention and decay read it. Breaking: ArchiveStoreService's constructor takes the IMemoryStore
    first; for implementers of IArchiveStore, GetStatsAsync and HasProfileAsync replace the
    synchronous GetStats and HasProfile. Breaking for code that enumerates IMemoryStore.GetUserIdsAsync: profile keys
    are listed there — skip them with ArchiveUserKey.IsArchiveKey (a store migration keeps copying them, which carries the
    profiles).

Removed

  • Breaking: the memory lineage tracker (IMemoryLineageTracker, InMemoryLineageTracker and their event, option and
    enum types).
    It was registered by AddMemoryIndexer() but nothing recorded into it, so every lineage query answered
    empty. Where a memory came from is now on the memory itself — MemoryUnit.SourceRef and MemoryUnit.DerivedFrom above.
  • Breaking: the virtual context manager (IVirtualContextManager, VirtualContextManager, VCMOptions and their
    result, state and enum types — VirtualContextState, EvictionResult, ConsolidationResult in MemoryIndexer.Interfaces,
    TierMigrationResult, SessionEndResult, ContextUsageStatistics, ContextActionRecommendation, ContextSaturationLevel).

    It was registered by AddMemoryIndexer() but used by nothing in the library, and it held one conversation's paging state in
    a singleton, so a process could page for only one conversation. The MemoryIndexer:VCM:WorkingMemory and
    MemoryIndexer:VCM:SemanticStore sections keep working; the other MemoryIndexer:VCM settings are no longer read.
  • Breaking: IScopeManager keeps only ResolveScopeAsync. The topic-tracking members (CurrentState, InitializeAsync,
    RecordTurnAsync, DetectTopicChangeAsync, GetCurrentTopicId, FilterByScope, EndSessionAsync, GetStatistics),
    ScopeState, ScopeResolution, ScopeBoundaryType, ScopeStatistics and ScopeManagerOptions (MemoryIndexer:ScopeManager)
    are gone — nothing in the remember/recall path read them since topic tracking stopped running there in 0.38.0. ScopeManager
    is stateless and its constructor takes only the logger. Migration: an implementer of IScopeManager keeps only
    ResolveScopeAsync.