mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-03 02:22:24 +00:00
Fix: skip client compaction pre-processing when compact_20260112 polyfill will run
The _prepare_context_managed_request helper unconditionally applied apply_client_compaction_block_history before invoking the polyfill. When the request also configured a compact_20260112 spec, that pre-processing consumed the client-sent compaction block and collapsed the message history to just the latest user question, starving the polyfill of conversation context. The polyfill's own Phase A (_slice_around_compaction_block) already handles client compaction blocks correctly and inspects the full post-compaction tail for the token-threshold check, so the pre-processing is both redundant and destructive in this case. Now the pre-processing only runs when no compact_20260112 polyfill spec will execute (no spec, drop_params on, or only non-compact edits like clear_tool_uses_20250919). Co-authored-by: Yassin Kortam <yassin@berri.ai>
This commit is contained in:
parent
3356887aa4
commit
571356c5b9
1 changed files with 68 additions and 10 deletions
|
|
@ -36,9 +36,7 @@ if TYPE_CHECKING:
|
|||
|
||||
|
||||
# Anthropic-only keys already mapped by the translator; strip on extra_kwargs re-merge.
|
||||
ANTHROPIC_ONLY_REQUEST_KEYS: frozenset[str] = frozenset(
|
||||
{"output_config"}
|
||||
)
|
||||
ANTHROPIC_ONLY_REQUEST_KEYS: frozenset[str] = frozenset({"output_config"})
|
||||
|
||||
|
||||
async def _prepare_context_managed_request(
|
||||
|
|
@ -57,14 +55,30 @@ async def _prepare_context_managed_request(
|
|||
apply_client_compaction_block_history,
|
||||
)
|
||||
|
||||
history_result = apply_client_compaction_block_history(
|
||||
messages=cast(List[Dict[str, Any]], messages),
|
||||
system=system,
|
||||
# Skip the client-history pre-processing when a ``compact_20260112``
|
||||
# polyfill spec will run: that editor already slices around any client-sent
|
||||
# compaction block in its Phase A (and uses the full post-compaction tail
|
||||
# for its token-threshold check). Pre-collapsing to just the latest user
|
||||
# question here would starve the polyfill of conversation context and
|
||||
# silently drop intermediate turns.
|
||||
polyfill_will_run = _polyfill_will_run(
|
||||
context_management_spec=context_management_spec,
|
||||
drop_params=drop_params,
|
||||
)
|
||||
working_messages = (
|
||||
history_result.messages if history_result is not None else messages
|
||||
)
|
||||
working_system = history_result.system if history_result is not None else system
|
||||
|
||||
if polyfill_will_run:
|
||||
history_result: Optional[PolyfillResult] = None
|
||||
working_messages: List[Dict] = messages
|
||||
working_system: Optional[Any] = system
|
||||
else:
|
||||
history_result = apply_client_compaction_block_history(
|
||||
messages=cast(List[Dict[str, Any]], messages),
|
||||
system=system,
|
||||
)
|
||||
working_messages = (
|
||||
history_result.messages if history_result is not None else messages
|
||||
)
|
||||
working_system = history_result.system if history_result is not None else system
|
||||
|
||||
polyfill_result = await _run_polyfill_if_enabled(
|
||||
model=model,
|
||||
|
|
@ -82,6 +96,50 @@ async def _prepare_context_managed_request(
|
|||
return history_result
|
||||
|
||||
|
||||
def _polyfill_will_run(
|
||||
*,
|
||||
context_management_spec: Any,
|
||||
drop_params: Optional[bool],
|
||||
) -> bool:
|
||||
"""Return True when ``compact_20260112`` will run via the polyfill dispatcher.
|
||||
|
||||
Mirrors the gating in ``_run_polyfill_if_enabled``: an empty spec or
|
||||
effective ``drop_params`` short-circuits the polyfill. The pre-processing
|
||||
skip only applies when the dispatcher will actually invoke
|
||||
``apply_compact_20260112`` (which has its own compaction-block slicing).
|
||||
"""
|
||||
if not context_management_spec:
|
||||
return False
|
||||
|
||||
effective_drop_params = (
|
||||
drop_params if drop_params is not None else litellm.drop_params
|
||||
)
|
||||
if effective_drop_params:
|
||||
return False
|
||||
|
||||
from litellm.llms.anthropic.experimental_pass_through.context_management.constants import (
|
||||
COMPACT_EDIT_TYPE,
|
||||
)
|
||||
|
||||
spec = context_management_spec
|
||||
if isinstance(spec, list):
|
||||
try:
|
||||
from litellm.llms.anthropic.chat.transformation import AnthropicConfig
|
||||
|
||||
spec = AnthropicConfig.map_openai_context_management_to_anthropic(spec)
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
edits = spec.get("edits") if isinstance(spec, dict) else None
|
||||
if not isinstance(edits, list):
|
||||
return False
|
||||
|
||||
return any(
|
||||
isinstance(edit, dict) and edit.get("type") == COMPACT_EDIT_TYPE
|
||||
for edit in edits
|
||||
)
|
||||
|
||||
|
||||
async def _run_polyfill_if_enabled(
|
||||
*,
|
||||
model: str,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue