Skip to main content

SummarizeStrategy

Struct SummarizeStrategy 

Source
pub struct SummarizeStrategy { /* private fields */ }
Expand description

Summarization trim strategy: over-budget old messages → summarizer → one System summary message.

§Behavior

  • Keep the most recent rounds verbatim: keep complete rounds from the tail forward until the budget is approached (the budget first deducts a reservation for the summary output, see with_summary_max_tokens); at least the most recent round is kept (kept even when a single round exceeds the budget; nothing more can be compacted);
  • Incremental compaction: when over budget again, the previous summary message goes to the summarizer as input (prior summary), producing an integrated new summary — the summary is never compacted repeatedly (semantic drift), and information already compacted is not lost;
  • Materialization: replace: true, the compaction result is written back to storage with zero recomputation afterwards;
  • Failure degradation: when the summarizer call fails, degrade to window dropping (projection — storage keeps the original text, retried on the next over-budget retrieval); the conversation is not interrupted.

The summary message uses the System role and sits at the front of the sequence (a summary is not conversation content but history compaction; the System role also avoids consecutive User messages after compaction). The summary message’s tokens count toward the budget and obey the window trim rules like any other message.

§Comparison

Compared to the default WindowDrop: window dropping is a lossless projection with cheap per-turn recomputation, suited to ad-hoc inspection; this strategy trades one summarizer call for a longer compactable span, suited to long conversations that must not exceed limits, at the cost of the summarizer call (cost + latency) and information loss.

§Example

Inject the summarization strategy (using FakeProvider in place of a real summarizer to demonstrate the full flow):

use std::sync::Arc;
use molo::memory::{Memory, SummarizeStrategy, WindowMemory};
use molo::{FakeProvider, FakeReply, Message};

#[tokio::main]
async fn main() -> Result<(), molo::memory::MemoryError> {
    let fake = Arc::new(FakeProvider::new([FakeReply::Text("Key points from earlier rounds".into())]));
    let mut memory = WindowMemory::new(30)
        .with_strategy(Arc::new(SummarizeStrategy::new(fake)));
    for i in 1..=4 {
        memory.record(Message::user(format!("Question from round {i}"))).await?;
        memory.record(Message::assistant(format!("Answer from round {i}"))).await?;
    }

    // 44 tokens total > budget 30: compacted to [summary, most recent round].
    let context = memory.context().await?;
    assert_eq!(context.len(), 3);
    assert!(matches!(context[0], Message::System(_)));
    assert_eq!(context[1], Message::user("Question from round 4"));
    Ok(())
}

Implementations§

Source§

impl SummarizeStrategy

Source

pub fn new(provider: impl Provider + 'static) -> Self

Creates a summarization strategy with the default prompt and a default summary output cap (1024 tokens).

Source

pub fn with_prompt(self, prompt: impl Into<String>) -> Self

Replaces the default summarization prompt (instruction + requirements; the history text is appended by the strategy).

Source

pub fn with_summary_max_tokens(self, max_tokens: u32) -> Self

Sets the token cap for the summary output (default 1024).

The value doubles as the budget reservation for kept rounds: the kept rounds’ token total stays within “budget − summary cap”, leaving room for the summary output.

Trait Implementations§

Source§

impl Debug for SummarizeStrategy

Source§

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

Formats the value using the given formatter. Read more
Source§

impl TrimStrategy for SummarizeStrategy

Source§

fn trim<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, messages: &'life1 [Message], budget: &'life2 Budget, counter: &'life3 dyn TokenCounter, ) -> Pin<Box<dyn Future<Output = Result<TrimResult, MemoryError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

Trims a message sequence against a budget and counter, returning the trim result (semantics in TrimResult). Read more
Source§

fn trim_with_counts<'life0, 'life1, 'life2, 'life3, 'life4, 'async_trait>( &'life0 self, messages: &'life1 [Message], counts: &'life2 [usize], budget: &'life3 Budget, counter: &'life4 dyn TokenCounter, ) -> Pin<Box<dyn Future<Output = Result<TrimResult, MemoryError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait, 'life4: 'async_trait,

Trims with per-message token counts; the default implementation delegates to trim, so custom strategies need not know about it. WindowDrop overrides it to amortized O(1) — counts are cached by Memory, avoiding per-message recounts inside the strategy (and saving IO with remote counters).

Auto Trait Implementations§

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<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> 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, 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: Sized + 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: Sized + 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> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

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<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