"""Session summarization: compact a session's raw exchanges into a stored gist. This is the compaction half of the tiered memory. Raw exchanges stay for detail recall; the summary is what surfaces when an *older* session is recalled later — "a month ago is a general idea," per the design. """ from __future__ import annotations from lyra import config, llm, logbus, memory from lyra.llm import Backend # Re-summarize a session once it has accumulated this many new raw exchanges # beyond what its current summary covers. SUMMARIZE_AFTER = 20 _PROMPT = """You are compacting a conversation into a long-term memory record \ (not replying to anyone). Write a concise gist of the session below: what was \ discussed, key decisions or outcomes, concrete specifics worth keeping (names, \ places, numbers, hands), and the user's apparent mood/state. Third person, \ referring to the user as "Brian". 4-8 sentences. No preamble.""" def _transcript(exchanges: list[memory.Exchange]) -> str: return "\n".join(f"{ex.role}: {ex.content}" for ex in exchanges) def summarize_session(session_id: str, backend: Backend | None = None) -> str | None: """(Re)generate and store the gist for a session. Returns the summary text. Returns None if the session has no exchanges. The summarizer defaults to the local backend so routine compaction stays free. """ exchanges = memory.history(session_id) if not exchanges: return None backend = backend or config.load().summary_backend messages = [ {"role": "system", "content": _PROMPT}, {"role": "user", "content": _transcript(exchanges)}, ] gist = llm.complete(messages, backend=backend) last_id = exchanges[-1].id memory.store_summary(session_id, gist, last_id) logbus.log( "info", "summarized session", session=session_id, exchanges=len(exchanges), backend=backend, ) return gist def maybe_summarize(session_id: str, backend: Backend | None = None) -> None: """Summarize the session if enough new turns have accumulated since last time.""" if memory.unsummarized_count(session_id) >= SUMMARIZE_AFTER: summarize_session(session_id, backend=backend)