Skip to content

feat: add summarization compactor - #12296

Merged
sjrl merged 30 commits into
mainfrom
feat/summarization-compactor
Aug 19, 2026
Merged

feat: add summarization compactor#12296
sjrl merged 30 commits into
mainfrom
feat/summarization-compactor

Conversation

@sjrl

@sjrl sjrl commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Related Issues

Proposed Changes:

Added the experimental SummarizationCompactor, which progressively summarizes a conversation until it fits a target token budget. This preserves useful context from long-running Agents instead of dropping older messages outright.

The compactor reads the conversation as two regions. History runs from the end of the leading system messages up to the latest real user message; the current task runs from that user message to the end. It always summarizes history before the current task. Within each region, it summarizes original messages before combining existing summaries. When a historical turn contains both original messages and an existing summary, it summarizes the whole turn together to preserve chronological context. Each round uses the first applicable tier in this order:

  1. historical_turns: Starting with the oldest, summarize as few turns that still contain original messages as needed to reach the target.
  2. historical_summaries: When no original messages remain in history, combine as few of its oldest summaries as needed to reach the target.
  3. current_task_steps: Summarize the fewest oldest steps needed to reach the target while preserving the min_keep_steps newest steps.
  4. current_task_summaries: When no more steps can be summarized, combine as few of the current task's oldest summaries as needed to reach the target.

Each summary records the summarization strategy and the number of messages it replaced under the context_compaction key in its meta.

Compaction has a floor it cannot go below: the leading system messages, one combined historical summary, the latest user message, one combined current-task summary, and the min_keep_steps newest steps. Once the conversation is reduced to that state, compact returns None because there is nothing left that may be given up, even if the result is still above the target.

approximate_summary_tokens is the expected length of each summary. It is an estimate used to plan how much of the conversation to summarize, not a limit imposed on the model. A higher value summarizes more of the conversation per round and is more likely to bring the result under the target, at the cost of giving up more context. Configure any generation limit directly on the Chat Generator.

A generated summary is only applied when it reduces the measured conversation size; a response with no usable text is treated as a failure. By default, a failed summarization logs a warning and preserves any progress already made. Set raise_on_failure=True to propagate the error instead.

from haystack.components.agents import Agent
from haystack.components.generators.chat import OpenAIResponsesChatGenerator
from haystack.hooks.compaction import CompactionHook, SummarizationCompactor

agent_generator = OpenAIResponsesChatGenerator(model="gpt-5.4")
summary_generator = OpenAIResponsesChatGenerator(model="gpt-5.4-nano")

compaction_hook = CompactionHook(
    compactor=SummarizationCompactor(
        chat_generator=summary_generator,
        min_keep_steps=2,
        approximate_summary_tokens=1_024,
    ),
    context_window=400_000,
    compact_at=0.7,
    compact_to=0.4,
)

agent = Agent(
    chat_generator=agent_generator,
    hooks={"before_llm": [compaction_hook]},
)

How did you test it?

Added new tests.

Notes for the reviewer

Checklist

  • I have read the contributors guidelines and the code of conduct.
  • I have updated the related issue with new insights and changes.
  • I have added unit tests and updated the docstrings.
  • I've used one of the conventional commit types for my PR title: fix:, feat:, build:, chore:, ci:, docs:, style:, refactor:, perf:, test: and added ! in case the PR includes breaking changes.
  • I have documented my code.
  • I have added a release note file, following the contributors guidelines.
  • I have run pre-commit hooks and fixed any issue.

@vercel

vercel Bot commented Aug 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
haystack-docs Ignored Ignored Preview Aug 19, 2026 12:54pm

Request Review

@sjrl
sjrl changed the base branch from main to fix-sliding-window August 11, 2026 07:28
@github-actions github-actions Bot added the type:documentation Improvements on the docs label Aug 11, 2026
@sjrl
sjrl force-pushed the fix-sliding-window branch from 85bd98e to 1a971d5 Compare August 11, 2026 07:29
@sjrl
sjrl force-pushed the feat/summarization-compactor branch from fbf90d6 to 695a56b Compare August 11, 2026 07:29
@github-actions

github-actions Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Coverage report

Click to see where and how coverage changed

FileStatementsMissingCoverageCoverage
(new stmts)
Lines missing
  haystack/hooks/compaction
  __init__.py
  summarization.py 89, 314-317, 475-479, 483-484, 488-492
  haystack/token_counters
  utils.py
Project Total  

This report was generated by python-coverage-comment-action

@sjrl
sjrl force-pushed the feat/summarization-compactor branch from cc63567 to 64dddb8 Compare August 13, 2026 11:06
@sjrl
sjrl changed the base branch from main to codex/chat-generator-parameter-mapping August 13, 2026 11:06
Comment thread haystack/hooks/compaction/summarization.py Outdated
Base automatically changed from codex/chat-generator-parameter-mapping to main August 13, 2026 14:31
@sjrl
sjrl marked this pull request as ready for review August 19, 2026 07:40
@sjrl
sjrl requested a review from a team as a code owner August 19, 2026 07:40
@sjrl
sjrl requested review from anakin87 and removed request for a team August 19, 2026 07:40

@anakin87 anakin87 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The implementation looks reasonable and quite clear to me

I left some (initial) minor comments

Comment thread haystack/hooks/compaction/summarization.py
Comment thread haystack/hooks/compaction/summarization.py Outdated
Comment thread haystack/hooks/compaction/summarization.py
Comment thread haystack/token_counters/utils.py
Comment thread haystack/hooks/compaction/summarization.py Outdated
Comment thread haystack/hooks/compaction/summarization.py Outdated
Comment thread haystack/hooks/compaction/summarization.py Outdated
Comment thread haystack/hooks/compaction/summarization.py Outdated
@sjrl
sjrl requested a review from anakin87 August 19, 2026 12:01

@anakin87 anakin87 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

Let's remember to document it in a future PR

@sjrl

sjrl commented Aug 19, 2026

Copy link
Copy Markdown
Contributor Author

Looks good!

Let's remember to document it in a future PR

yup that's coming next!

@sjrl
sjrl merged commit beafed3 into main Aug 19, 2026
25 checks passed
@sjrl
sjrl deleted the feat/summarization-compactor branch August 19, 2026 13:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

topic:tests type:documentation Improvements on the docs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants