Skip to main content

CompactingMemory

Struct CompactingMemory 

Source
pub struct CompactingMemory<M, P, C: Compactor> { /* private fields */ }
Expand description

A ConversationMemory adapter that wraps a backend with a MemoryPolicy and a Compactor, replacing truncated turns with a summary artifact spliced at the front of the loaded history.

CompactingMemory is the next layer above DemotingPolicyMemory: a demotion hook only observes what the policy evicted, while a compactor substitutes the evicted prefix with a derived Message. The loaded history shape is therefore [summary_message, ...kept_window] whenever any compaction has occurred for the conversation, and just kept_window otherwise. The summary itself is recomputed (rolled forward) on every load that produces newly-evicted messages, so older summaries are folded into newer ones via the compactor’s carry_over parameter.

§Concurrency

Concurrent ConversationMemory::load calls on the same conversation_id are serialised at the compaction seam: only one call at a time invokes the compactor for a given conversation. Other concurrent loads observe the in-flight compaction and immediately return the previously-stored summary spliced in front of kept, without re-running the compactor. Newly-evicted messages skipped this way are folded into the next compaction.

Failure visibility. A compactor error is returned only to the caller whose load actually drove the compaction. Concurrent callers that short-circuited on in_flight see Ok([old_summary?, ...kept]) even if the in-flight compaction ultimately failed; the watermark stays unchanged so the next load retries.

§Persistence

The carry-over summary and delivery watermarks are kept in process memory only. Across process restarts, the first load on each conversation re-evicts and re-compacts the same prefix; compactors that have side effects (LLM calls, persistent writes) should deduplicate.

§Prompt shape and budgets

CompactingMemory is policy-agnostic: the wrapped MemoryPolicy decides which messages are kept versus demoted, and only the kept window is bounded by that policy. The summary artifact produced by the Compactor is spliced outside that budget — so the loaded prompt has shape [summary, ...kept_window] where kept_window respects the policy’s bounds and summary adds an extra message on top of it.

Callers that combine CompactingMemory with a token-budgeted policy (e.g. TokenWindowMemory) must use a Compactor that bounds its own artifact, or accept that the loaded prompt may exceed the policy’s budget by the size of the summary. The reference TemplateCompactor grows monotonically by default; configure it with TemplateCompactor::with_max_bytes to cap the rolled-up text.

§Example

use rig_memory::{
    CompactingMemory, InMemoryConversationMemory, SlidingWindowMemory,
    TemplateCompactor,
};

let memory = CompactingMemory::new(
    InMemoryConversationMemory::new(),
    SlidingWindowMemory::last_messages(20),
    TemplateCompactor::new(),
);

Implementations§

Source§

impl<M, P, C: Compactor> CompactingMemory<M, P, C>

Source

pub fn new(inner: M, policy: P, compactor: C) -> Self

Wrap inner so every load runs through policy and demoted messages are summarised by compactor.

Source

pub fn inner(&self) -> &M

Return a reference to the wrapped backend.

Source

pub fn policy(&self) -> &P

Return a reference to the wrapped policy.

Source

pub fn compactor(&self) -> &C

Return a reference to the compactor.

Source

pub fn into_inner(self) -> (M, P, C)

Consume the wrapper and return its three components.

Source

pub fn forget(&self, conversation_id: &str)

Drop the in-process compaction state for conversation_id.

Call this when a conversation has ended to bound memory usage; the state map is otherwise unbounded. If the internal lock has been poisoned by a panic in another thread, this is a no-op.

Source

pub fn tracked_conversations(&self) -> usize

Number of conversations currently tracked in the compaction state map. Useful for telemetry and leak detection. Returns 0 if the internal lock is poisoned.

Trait Implementations§

Source§

impl<M, P, C> ConversationMemory for CompactingMemory<M, P, C>

Source§

fn load<'a>( &'a self, conversation_id: &'a str, ) -> WasmBoxedFuture<'a, Result<Vec<Message>, MemoryError>>

Load the full conversation history for conversation_id. Read more
Source§

fn append<'a>( &'a self, conversation_id: &'a str, messages: Vec<Message>, ) -> WasmBoxedFuture<'a, Result<(), MemoryError>>

Append messages to the conversation identified by conversation_id. Read more
Source§

fn clear<'a>( &'a self, conversation_id: &'a str, ) -> WasmBoxedFuture<'a, Result<(), MemoryError>>

Remove all stored messages for conversation_id.
Source§

impl<M, P, C> Debug for CompactingMemory<M, P, C>
where M: Debug, P: Debug, C: Compactor,

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<M, P, C> !Freeze for CompactingMemory<M, P, C>

§

impl<M, P, C> RefUnwindSafe for CompactingMemory<M, P, C>

§

impl<M, P, C> Send for CompactingMemory<M, P, C>
where M: Send, P: Send,

§

impl<M, P, C> Sync for CompactingMemory<M, P, C>
where M: Sync, P: Sync,

§

impl<M, P, C> Unpin for CompactingMemory<M, P, C>
where M: Unpin, P: Unpin, C: Unpin, <C as Compactor>::Artifact: Unpin,

§

impl<M, P, C> UnsafeUnpin for CompactingMemory<M, P, C>

§

impl<M, P, C> UnwindSafe for CompactingMemory<M, P, C>
where M: UnwindSafe, P: UnwindSafe, C: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> WasmCompatSend for T
where T: Send,

Source§

impl<T> WasmCompatSync for T
where T: Sync,