feat(inference): add context and output compression for inference requests - #6305
feat(inference): add context and output compression for inference requests#6305elinacse wants to merge 10 commits into
Conversation
…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>
|
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 |
Fixes ruff isort failure flagged by pre-commit CI. Signed-off-by: elina priyadarshinee <elina.priyadarshinee1@ibm.com>
|
@franciscojavierarceo please help in reviewing this PR. Thanks ! |
mattf
left a comment
There was a problem hiding this comment.
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.
…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")): |
There was a problem hiding this comment.
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?
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