mnesis.compaction.levels¶
levels
¶
Three-level compaction escalation functions.
This module provides:
-
Summarisation — converts raw messages into a leaf summary node. Three escalation levels: level 1 (structured LLM), level 2 (aggressive LLM), level 3 (deterministic truncation — always succeeds).
-
Condensation — merges one or more existing summary nodes into a single condensed node. Three escalation levels mirror summarisation.
Both operations extract file_xxx identifiers from their inputs and append a
[LCM File IDs: ...] footer to the output, preserving the "lossless"
guarantee across compaction rounds.
Summarisation input cap: messages passed to the LLM summarizer are capped at
MAX_SUMMARISATION_INPUT_FRACTION (75 %) of the compaction model's context
window to prevent the compaction call itself from overflowing.
SummaryCandidate
dataclass
¶
SummaryCandidate(
text: str,
token_count: int,
span_start_message_id: str,
span_end_message_id: str,
compaction_level: int,
messages_covered: int,
)
A candidate compaction summary before it is committed to the store.
CondensationCandidate
dataclass
¶
CondensationCandidate(
text: str,
token_count: int,
parent_node_ids: list[str] = list(),
compaction_level: int = 1,
)
A candidate condensation of one or more existing summary nodes.
compaction_level
class-attribute
instance-attribute
¶
Condensation escalation level: 1 = normal, 2 = aggressive, 3 = deterministic.
level1_summarise
async
¶
level1_summarise(
messages: list[MessageWithParts],
model: str,
budget: ContextBudget,
estimator: TokenEstimator,
llm_call: Any,
compaction_prompt: str | None = None,
model_context_limit: int = 200000,
model_max_output_tokens: int = 0,
compaction_estimator: TokenEstimator | None = None,
) -> SummaryCandidate | None
Attempt Level 1 (selective) summarisation via LLM.
File IDs found in the input messages are automatically appended to the
summary via a [LCM File IDs: ...] footer.
Input messages are capped at 75 % of the compaction model's context window to prevent the summarisation call itself from overflowing.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
messages
|
list[MessageWithParts]
|
All non-summary messages in the session. |
required |
model
|
str
|
Model string to use for compaction. |
required |
budget
|
ContextBudget
|
Token budget for validation. |
required |
estimator
|
TokenEstimator
|
Token estimator for result validation. |
required |
llm_call
|
Any
|
Async callable |
required |
compaction_prompt
|
str | None
|
Custom system prompt override. |
None
|
model_context_limit
|
int
|
Context window of the compaction model. |
200000
|
model_max_output_tokens
|
int
|
Output limit of the compaction model (0 = unknown). |
0
|
compaction_estimator
|
TokenEstimator | None
|
Estimator in the compaction model's units, used to size the input against its window (defaults to estimator). |
None
|
Returns:
| Type | Description |
|---|---|
SummaryCandidate | None
|
SummaryCandidate if successful and fits budget, or None to escalate. |
level2_summarise
async
¶
level2_summarise(
messages: list[MessageWithParts],
model: str,
budget: ContextBudget,
estimator: TokenEstimator,
llm_call: Any,
compaction_prompt: str | None = None,
model_context_limit: int = 200000,
model_max_output_tokens: int = 0,
compaction_estimator: TokenEstimator | None = None,
) -> SummaryCandidate | None
Attempt Level 2 (aggressive) summarisation via LLM.
Uses a more compressed prompt format and drops reasoning details. File IDs found in the input messages are propagated to the summary. Input is capped at 75 % of the compaction model's context window.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
messages
|
list[MessageWithParts]
|
All non-summary messages in the session. |
required |
model
|
str
|
Model string to use for compaction. |
required |
budget
|
ContextBudget
|
Token budget for validation. |
required |
estimator
|
TokenEstimator
|
Token estimator for result validation. |
required |
llm_call
|
Any
|
Async callable. |
required |
compaction_prompt
|
str | None
|
Custom system prompt override. |
None
|
model_context_limit
|
int
|
Context window of the compaction model. |
200000
|
model_max_output_tokens
|
int
|
Output limit of the compaction model (0 = unknown). |
0
|
compaction_estimator
|
TokenEstimator | None
|
Estimator in the compaction model's units, used to size the input against its window (defaults to estimator). |
None
|
Returns:
| Type | Description |
|---|---|
SummaryCandidate | None
|
SummaryCandidate if successful and fits budget, or None to escalate. |
level3_deterministic
¶
level3_deterministic(
messages: list[MessageWithParts],
budget: ContextBudget,
estimator: TokenEstimator,
) -> SummaryCandidate
Level 3 deterministic fallback (no LLM required).
Keeps the most recent messages that fit within 85% of the usable budget, prefixed with a truncation notice. This always produces a valid result.
File IDs found in all input messages (not just kept ones) are preserved
in a [LCM File IDs: ...] footer even when their surrounding context is
truncated — this is the lossless guarantee.
Precedence when the budget is tight: file IDs are reserved first, then
prose fills what remains, so messages are dropped before any file ID is.
Only if the header plus the ID footer cannot fit in 85% of
budget.usable is the footer truncated, keeping the most recently
referenced IDs (by last occurrence; the footer itself stays in
first-occurrence order). A warning with the dropped count is logged; the
raw files stay addressable in the immutable store. Truncating there is the
only way to keep the "always fits the budget" guarantee that lets
compaction make progress. If budget.usable is smaller than the minimal
header, no output can fit, so all IDs are kept (lossless wins).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
messages
|
list[MessageWithParts]
|
All non-summary messages in the session. |
required |
budget
|
ContextBudget
|
Token budget — result is guaranteed to fit within usable. |
required |
estimator
|
TokenEstimator
|
Token estimator. |
required |
Returns:
| Type | Description |
|---|---|
SummaryCandidate
|
SummaryCandidate that fits within budget.usable (barring a budget too |
SummaryCandidate
|
small for even the minimal header), as measured by estimator. |
condense_level1
async
¶
condense_level1(
nodes: list[SummaryNode],
model: str,
budget: ContextBudget,
estimator: TokenEstimator,
llm_call: Any,
model_max_output_tokens: int = 0,
model_context_limit: int = 200000,
compaction_estimator: TokenEstimator | None = None,
) -> CondensationCandidate | None
Attempt Level 1 condensation: merge summary nodes via structured LLM prompt.
The input is capped against the compaction model's window (see
:func:_fit_condensation_nodes): when the nodes do not all fit, the oldest
ones that do are condensed and the candidate's parent_node_ids name
exactly those; the rest stay live for a later round. File IDs from the
condensed nodes are collected and appended to the output via a
[LCM File IDs: ...] footer.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
nodes
|
list[SummaryNode]
|
Summary nodes to condense (must be non-empty). |
required |
model
|
str
|
LLM model string. |
required |
budget
|
ContextBudget
|
Token budget for the condensed result. |
required |
estimator
|
TokenEstimator
|
Token estimator. |
required |
llm_call
|
Any
|
Async callable |
required |
model_max_output_tokens
|
int
|
Output limit of the compaction model (0 = unknown). |
0
|
model_context_limit
|
int
|
Context window of the compaction model. |
200000
|
compaction_estimator
|
TokenEstimator | None
|
Estimator in the compaction model's units, used to size the input against its window (defaults to estimator). |
None
|
Returns:
| Type | Description |
|---|---|
CondensationCandidate | None
|
CondensationCandidate if successful and fits budget, or None to escalate. |
condense_level2
async
¶
condense_level2(
nodes: list[SummaryNode],
model: str,
budget: ContextBudget,
estimator: TokenEstimator,
llm_call: Any,
model_max_output_tokens: int = 0,
model_context_limit: int = 200000,
compaction_estimator: TokenEstimator | None = None,
) -> CondensationCandidate | None
Attempt Level 2 condensation: aggressive merge via compressed prompt.
Each node contributes a bounded excerpt. The input is still capped against
the compaction model's window (as in :func:condense_level1): when the
excerpts do not all fit, the oldest nodes that do are condensed and the
candidate's parent_node_ids name exactly those.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
nodes
|
list[SummaryNode]
|
Summary nodes to condense. |
required |
model
|
str
|
LLM model string. |
required |
budget
|
ContextBudget
|
Token budget. |
required |
estimator
|
TokenEstimator
|
Token estimator. |
required |
llm_call
|
Any
|
Async callable. |
required |
model_max_output_tokens
|
int
|
Output limit of the compaction model (0 = unknown). |
0
|
model_context_limit
|
int
|
Context window of the compaction model. |
200000
|
compaction_estimator
|
TokenEstimator | None
|
Estimator in the compaction model's units, used to size the input against its window (defaults to estimator). |
None
|
Returns:
| Type | Description |
|---|---|
CondensationCandidate | None
|
CondensationCandidate if successful and fits budget, or None to escalate. |
condense_level3_deterministic
¶
condense_level3_deterministic(
nodes: list[SummaryNode],
estimator: TokenEstimator,
budget: ContextBudget,
) -> CondensationCandidate
Level 3 deterministic condensation fallback (no LLM required).
Concatenates the parent summaries' prose (without their own file-ID
footers) up to :data:_CONDENSE_LEVEL3_MAX_TOKENS tokens, then appends a
single [LCM File IDs: ...] footer with the IDs from every parent node.
Bounded like :func:level3_deterministic: the footer and header are sized
against 85% of budget.usable with estimator and the assembled text
is validated against budget.usable. File IDs take precedence over
prose (prose gets what remains), and over the [Condensed from: ...]
parent list, which is replaced by a minimal header when it would crowd the
prose. Only when the footer cannot fit the budget are the least recently
referenced IDs dropped (with a warning); the raw files stay addressable in
the immutable store.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
nodes
|
list[SummaryNode]
|
Summary nodes to condense. |
required |
estimator
|
TokenEstimator
|
Token estimator. |
required |
budget
|
ContextBudget
|
Token budget the result must fit within. |
required |
Returns:
| Type | Description |
|---|---|
CondensationCandidate
|
CondensationCandidate that always succeeds and fits |
CondensationCandidate
|
(barring a budget too small for even the minimal header). |