Skip to content

feat(inference): add context and output compression for inference requests - #6305

Open
elinacse wants to merge 10 commits into
ogx-ai:mainfrom
elinacse:feat/context-output-compression
Open

feat(inference): add context and output compression for inference requests#6305
elinacse wants to merge 10 commits into
ogx-ai:mainfrom
elinacse:feat/context-output-compression

Conversation

@elinacse

Copy link
Copy Markdown
Contributor

What does this PR do?

Agentic workloads push far more tokens per request than traditional chat use cases, and conversation history grows unbounded across tool-calling loops. This adds an opt-in compression hook to InferenceRouter, applied uniformly to every chat completion request regardless of caller (direct Chat Completions calls or internal calls from the Responses orchestrator) or backend provider.

CompressionConfig (a new top-level StackConfig.compression field, off by default) enables: deduplication of repeated tool-call outputs, truncation of oversized tool outputs, token-budget-based windowing of the oldest conversation turns (grouped so tool_calls and their responses are never split apart), optional LLM-based summarization of windowed-out turns, and a default/clamp for max_tokens/max_completion_tokens.

Fixes #6147

…uests

Agentic workloads push far more tokens per request than traditional chat
use cases, and conversation history grows unbounded across tool-calling
loops. This adds an opt-in compression hook to InferenceRouter, applied
uniformly to every chat completion request regardless of caller (direct
Chat Completions calls or internal calls from the Responses orchestrator)
or backend provider.

CompressionConfig (a new top-level StackConfig.compression field, off by
default) enables: deduplication of repeated tool-call outputs, truncation
of oversized tool outputs, token-budget-based windowing of the oldest
conversation turns (grouped so tool_calls and their responses are never
split apart), optional LLM-based summarization of windowed-out turns, and
a default/clamp for max_tokens/max_completion_tokens.

Addresses ogx-ai#6147.

Signed-off-by: elina priyadarshinee <elina.priyadarshinee1@ibm.com>
@mergify

mergify Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

This pull request has merge conflicts that must be resolved before it can be merged. @elinacse please rebase it. https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork

@mergify mergify Bot added the needs-rebase label Jul 20, 2026
@mergify mergify Bot removed the needs-rebase label Jul 20, 2026
elinacse and others added 2 commits July 23, 2026 08:20
Fixes ruff isort failure flagged by pre-commit CI.

Signed-off-by: elina priyadarshinee <elina.priyadarshinee1@ibm.com>
@elinacse

Copy link
Copy Markdown
Contributor Author

@franciscojavierarceo please help in reviewing this PR. Thanks !

@mattf mattf left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

what do you think about starting with headroom and focusing on responses?

headroom can be used as a library to compress() messages before they're passed to chat completions.

currently, our chat completions endpoint faithfully handles io without pre or post processing, while the responses endpoint is more agentic and may adjust io as appropriate. this can be a feature of the agentic responses loop.

elinacse and others added 3 commits July 24, 2026 09:05
…to the Responses agentic loop

Per review feedback: the Chat Completions endpoint should remain a faithful
passthrough with no pre/post-processing, matching OpenAI's contract. Only the
Responses API is agentic and free to adjust I/O as it drives its multi-turn
tool-calling loop, so compression belongs there rather than in InferenceRouter,
which is shared by every caller regardless of endpoint.

CompressionConfig moves from a top-level StackConfig.compression field to a
per-provider BuiltinResponsesImplConfig.compression_config, threaded through
OpenAIResponsesImpl into StreamingResponseOrchestrator. It's applied to the
outgoing request built on each inference call in the agentic loop, and never
touches the persisted conversation history (self.final_messages). The
compression module itself (dedup, truncation, token-budget windowing with
turn-grouping, LLM-based summarization of dropped turns) is unchanged and
moves from providers/utils/inference/ to responses/builtin/responses/ to
reflect its new ownership.

We also looked at using the headroom-ai library to replace the hand-rolled
dedup/truncation logic, per the reviewer's suggestion. Testing found
headroom's compress() hangs (30s+, unresponsive to signal-based timeouts) on
ordinary tool-role messages -- the exact content type this feature exists to
compress -- so we're keeping the existing logic for now and following up with
the reviewer separately on that part of the suggestion.

Signed-off-by: elina priyadarshinee
Signed-off-by: elina priyadarshinee <elina.priyadarshinee1@ibm.com>
instead of instance state.
"""
# 1. Per-request override (fail hard if invalid)
if extra_body and (enc_name := extra_body.get("tokenizer_encoding")):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice reuse of the compaction chain here 👍

Small thing: this per-request tokenizer_encoding override never fires — the callers don't pass extra_body through, so it's honored for compaction but ignored here.

self.extra_body is already available at the streaming.py call site — mind threading it through?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: add context and output compression (similar to project headroom)

3 participants