Skip to content

symfonic.capabilities.memory.summary

summary

Scope-bound STM summaries for JIT prompt composition.

The legacy working layer summarized evicted turns, then placed that text in a JIT-only prompt slot. Native composition keeps the same division: an adopter supplies the evicted-turn source, this service produces a summary for exactly one scope, and the capability materializes it before prompt compilation.

EvictedWorkingSource

Bases: Protocol

Provides only the turns evicted from a scope's working window.

STMSummaryPort

Bases: Protocol

Produces an invocation-local summary without retaining session state.

STMSummaryRequest dataclass

STMSummaryRequest(scope: MemoryScope, turn: int = 0)

The invocation-local scope for one summary materialization.

STMSummaryResult dataclass

STMSummaryResult(text: str = '', revision: str = '', degraded: bool = False, reason: str = '')

A summary bound to the scope that supplied its evicted turns.

WorkingMemorySummaryService

WorkingMemorySummaryService(source: EvictedWorkingSource, *, mode: STMSummaryMode = 'extractive', max_chars: int = 1000, model_provider: Any | None = None, model_config: Any | None = None)

Summarize an explicit evicted-turn source for one requested scope.

Source code in src/symfonic/capabilities/memory/summary.py
def __init__(
    self,
    source: EvictedWorkingSource,
    *,
    mode: STMSummaryMode = "extractive",
    max_chars: int = 1000,
    model_provider: Any | None = None,
    model_config: Any | None = None,
) -> None:
    evicted = getattr(source, "evicted", None)
    if not callable(evicted) or not inspect.iscoroutinefunction(evicted):
        raise ConfigurationError(
            "STM summary needs an async evicted(scope) source; a recent-turn source "
            "cannot identify what the working window already discarded."
        )
    if mode not in {"off", "extractive", "llm"}:
        raise ConfigurationError(f"unknown STM summary mode {mode!r}")
    if max_chars < 1:
        raise ConfigurationError("STM summary max_chars must be positive")
    if mode == "llm" and model_provider is None:
        raise ConfigurationError(
            "STM summary mode 'llm' needs an explicit model_provider; native composition "
            "does not borrow the response model."
        )
    self._source = source
    self._mode = mode
    self._max_chars = max_chars
    self._model_provider = model_provider
    self._model_config = model_config

validate_summary

validate_summary(summary: Any) -> None

Refuse a summary collaborator that would fail inside a live turn.

Source code in src/symfonic/capabilities/memory/summary.py
def validate_summary(summary: Any) -> None:
    """Refuse a summary collaborator that would fail inside a live turn."""
    if summary is None:
        return
    method = getattr(summary, "summarize", None)
    if not callable(method) or not inspect.iscoroutinefunction(method):
        raise ConfigurationError(
            "summary must provide async summarize(STMSummaryRequest) -> STMSummaryResult; "
            "normally pass WorkingMemorySummaryService(evicted_source, ...)."
        )