Skip to content

fix(adapters,vertex): pass output_config through to backends that accept it (closes #23380, supersedes #23475/#23396/#23706/#22727) - #26439

Merged
mateo-berri merged 3 commits into
BerriAI:litellm_oss_staging_04_25_2026from
dkindlund:fix/output-config-passthrough-consolidated
Apr 25, 2026
Merged

fix(adapters,vertex): pass output_config through to backends that accept it (closes #23380, supersedes #23475/#23396/#23706/#22727)#26439
mateo-berri merged 3 commits into
BerriAI:litellm_oss_staging_04_25_2026from
dkindlund:fix/output-config-passthrough-consolidated

Conversation

@dkindlund

Copy link
Copy Markdown
Contributor

Summary

Pass output_config through to backends that accept it (Vertex AI Claude, Anthropic-direct) and stop forwarding the raw Anthropic-shaped key into OpenAI-format completion calls where it triggers 400 "Extra inputs are not permitted." Consolidates four stalled community PRs that addressed overlapping aspects of the same root bug, incorporates every Greptile review concern that was outstanding on those PRs, and closes one functional gap they all missed (format + effort mixed payload on Vertex).

Closes / supersedes

ID Title Status
Closes #23380 [Bug]: Dropped output_config parameter in Messages API prevents schema and effort constraints OPEN
Supersedes #23475 fix(vertex): stop stripping output_config and output_format from VertexAI Claude requests OPEN, stalled since Mar 19
Supersedes #23396 fix: pass output_config for VertexAI Claude structured output OPEN, stalled since Mar 25
Supersedes #23706 fix(anthropic-adapter): exclude output_config from extra_kwargs in Anthropic adapter OPEN, stalled since Mar 16
Supersedes #22727 fix(anthropic-adapter): strip output_config for non-Anthropic backends OPEN, stalled since Mar 4

Original authors credited via Co-Authored-By trailers: @netbrah, @s-zx, @invoicepulse, @cfdude.

Related issues (not closed by this PR but reference the same cluster)

#26423, #25079, #24549, #25971, #25957, #26163, #24856

What was broken

                ┌──────────────────────────────────────────────────────┐
                │ output_config is the Anthropic Messages API field    │
                │ that controls structured outputs (`.format`) and     │
                │ reasoning effort (`.effort`). LiteLLM was silently   │
                │ stripping it on multiple paths, hiding Structured    │
                │ Outputs from callers who explicitly requested them.  │
                └────────────────────────┬─────────────────────────────┘
                                         │
        ┌────────────────────────────────┼────────────────────────────────────┐
        ▼                                ▼                                    ▼
 Vertex AI Claude                Vertex AI Claude               Anthropic /v1/messages
 (Chat Completions path)         (Messages path)                → /chat/completions adapter
        │                                │                                    │
        │  unconditional pop()           │  unconditional pop()               │  raw output_config
        │  of output_config              │  of output_config                  │  re-merged into
        │  AND output_format             │  AND output_format                 │  completion_kwargs
        ▼                                ▼                                    │  AFTER translator
 200 with prose,                 200 with prose,                              │  already mapped its
 schema silently                 schema silently                              │  meaningful parts
 dropped                         dropped                                      ▼
                                                                       400 "Extra inputs
                                                                       are not permitted"
                                                                       on Azure / Fireworks /
                                                                       Bedrock Nova

Anthropic accepts output_config and validates the schema. The bug reporter's empirical confirmation:

# Same payload to Anthropic-direct → 400 invalid_request_error (validates the field is being received and parsed)
# Same payload through LiteLLM proxy → 200 with prose (silent strip)

Approach

Vertex AI Claude (both transformation paths)

Replace data.pop("output_config", None) with a sanitizer that strips only the Vertex-unsupported keys (today: effort) from output_config, forwarding format and the legacy top-level output_format. Helper lives in the chat-completion module and is imported by the Messages module so there's one source of truth.

# Old (silent strip):
data.pop("output_config", None)
data.pop("output_format", None)

# New (per-key sanitization):
_sanitize_vertex_anthropic_output_params(data)
# - output_config containing only ``effort`` → dropped (Vertex 400s on it)
# - output_config containing ``format`` → forwarded
# - output_config containing both → ``effort`` filtered, ``format`` kept
# - output_format → forwarded as-is
# - non-dict output_config → dropped defensively

The _VERTEX_UNSUPPORTED_OUTPUT_CONFIG_KEYS constant gives maintainers one place to extend as Vertex parity drifts.

Anthropic adapter (/v1/messages/chat/completions)

Add output_config to a named module-level constant ANTHROPIC_ONLY_REQUEST_KEYS and wire it into excluded_keys. The translator above the re-merge has already mapped output_config.formatresponse_format and output_config.effortreasoning_effort for non-Claude targets. Re-adding the raw key was either redundant (Anthropic-family target sees both response_format AND a duplicate output_config) or harmful (non-Anthropic target rejects unknown field).

ANTHROPIC_ONLY_REQUEST_KEYS: frozenset[str] = frozenset({"output_config"})
# ...
excluded_keys = ANTHROPIC_ONLY_REQUEST_KEYS | {"anthropic_messages"}

Also replaces extra_kwargs or {} with extra_kwargs if extra_kwargs is not None else {} so callers passing an explicit empty dict don't get a default substituted (Greptile P2 on PR #22727 — the masked-empty-dict bug that hid the fallback inference path from being tested).

Greptile feedback addressed (every concern from the four superseded PRs)

Source PR Greptile concern How this PR addresses it
#23475 "Misleading comment on output_format pass-through" — said the field flowed through OpenAI-compat when actually only via mock injection The Sonnet 4.5 test now asserts output_format flows through the mock path explicitly and notes that map_openai_params still uses tools for the OpenAI-compat path
#23396 (P1) "effort key leaks through when format is also present" — combined payload would still 400 on Vertex _sanitize_vertex_anthropic_output_params filters per-key, so format + effort becomes format only. Dedicated test: test_vertex_ai_anthropic_output_config_format_plus_effort_strips_only_effort
#23396 "Existing tests now fail after this change" (the two *_dropped tests asserted the old strip behavior) Both old assertions removed/rewritten; new tests assert the corrected per-key behavior
#23706 "Hardcoded exclusion may not scale" Replaced inline literal with named module-level constant ANTHROPIC_ONLY_REQUEST_KEYS + comment instructing future maintainers where to extend
#23706 "Fragile sys.path.insert working-directory-relative path" New test file uses os.path.join(os.path.dirname(__file__), ...) anchored to file location
#22727 (P0) "Pre-setting async_complete_streaming_response triggers unconditional early return" Not applicable here — this PR doesn't touch streaming logging. The author addressed it in their final commit on #22727
#22727 (P1) "Mock hides regression — test mocks async_success_handler" This PR's tests don't mock the function under test. Adapter tests drive _prepare_completion_kwargs directly and inspect its return value
#22727 (P2) "Missing Vertex AI Claude detection" — _is_anthropic_claude only checked anthropic/bedrock Approach changed: instead of conditional strip based on target provider detection, the strip is unconditional because the translator has already extracted the meaningful parts. No detection logic needed; correctness no longer depends on getting Vertex AI Claude detection right
#22727 (P2) "Missing tests for output_config stripping" New file test_handler_output_config_passthrough.py covers strip with effort-only, strip with format-only, regression guard for unrelated extras, empty-extra-kwargs, None-extra-kwargs
#22727 (P2) "Helper masks empty dict argument" — extra_kwargs or {default} substitutes default for {} Replaced with if extra_kwargs is not None else {} and dedicated test test_explicit_empty_dict_does_not_substitute_default
(PR #24114, related class of bug from another cluster) "inspect.getsource source-text tests are fragile" All new tests are runtime behavior — no source-text inspection
(PR #24114, related) "Custom assertion messages are dead code (tuple comma)" All new assertions use positional message argument

Tests

tests/test_litellm/llms/vertex_ai/vertex_ai_partner_models/anthropic/test_vertex_ai_partner_models_anthropic_transformation.py
  test_vertex_ai_anthropic_output_config_effort_only_dropped                                    PASSED
  test_vertex_ai_anthropic_output_config_format_passes_through                                  PASSED
  test_vertex_ai_anthropic_output_config_format_plus_effort_strips_only_effort                  PASSED
  test_vertex_ai_anthropic_output_config_non_dict_dropped                                       PASSED
  test_vertex_ai_anthropic_output_format_preserved_output_config_effort_dropped                 PASSED
  test_sanitize_vertex_anthropic_output_params_unit                                             PASSED
  test_vertex_ai_claude_sonnet_4_5_structured_output_fix                                        PASSED  (updated to assert flow-through, not strip)
  + 12 unrelated existing tests PASSED (regression guard)

tests/test_litellm/llms/anthropic/experimental_pass_through/adapters/test_handler_output_config_passthrough.py (new file)
  TestAnthropicOnlyRequestKeysExport::test_constant_exposed                                     PASSED
  TestAnthropicOnlyRequestKeysExport::test_contains_output_config                               PASSED
  TestEmptyExtraKwargsPath::test_explicit_empty_dict_does_not_substitute_default                PASSED
  TestEmptyExtraKwargsPath::test_none_extra_kwargs_handled_safely                               PASSED
  TestOutputConfigStrippedFromCompletionKwargs::test_other_extra_kwargs_still_passed_through    PASSED
  TestOutputConfigStrippedFromCompletionKwargs::test_output_config_with_effort_is_stripped      PASSED
  TestOutputConfigStrippedFromCompletionKwargs::test_output_config_with_format_is_stripped_format_already_translated  PASSED

26/26 pass with this commit. The new tests fail (or fail to import) on main without it.

Manual reproduction

# Before the fix
curl -X POST "https://<litellm-proxy>/v1/messages" \
  -H "Authorization: Bearer <litellm-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "vertex_ai/claude-sonnet-4@20250514",
    "max_tokens": 1024,
    "messages": [{"role": "user", "content": "Return a person object."}],
    "output_config": {"format": {"type": "json_schema", "schema": {"type": "object", "additionalProperties": false, "properties": {"name": {"type": "string"}, "age": {"type": "integer"}}}}}
  }'
# → 200 with prose, schema silently dropped
# → /spend/logs shows no indication of the strip
# → client believes Structured Outputs is in effect

# After the fix
# → Vertex receives the schema
# → Validates per-Anthropic semantics
# → Returns structured JSON OR a clear 400 explaining the schema problem

Out of scope (deliberately deferred)

  • max_tokens capping from PR fix(anthropic-adapter): strip output_config for non-Anthropic backends #22727 — independent concern. Should land as its own PR with focused tests for Bedrock Nova / strict-limit providers.
  • Architectural rework of excluded_keys — Greptile flagged the point-fix-growth pattern. Named constant addresses the maintainability concern; a registry-based approach can come as a follow-up.
  • Anthropic-direct /v1/messages strip investigation — the bug report mentions a strip on Anthropic-direct that I could not reproduce via code reading. The transformation path explicitly forwards output_config. If users still see the strip on Anthropic-direct after this PR lands, it's a separate downstream issue worth a fresh bug report.

Test plan

  • make test-unit for the touched test files
  • Verify tests fail on main without this commit
  • black --check clean
  • CI green (will check after push)

🤖 Generated with Claude Code

yuneng-berri and others added 2 commits April 23, 2026 17:55
…ept it

Resolves the silent strip of Anthropic Structured Outputs across the
Vertex AI Claude transformation paths and the Anthropic-adapter
re-merge. Consolidates and supersedes four stalled community PRs
addressing overlapping aspects of the same root bug:

- BerriAI#23475 (Vertex AI Claude blanket-strip removal)
- BerriAI#23396 (Vertex AI Claude conditional passthrough)
- BerriAI#23706 (Anthropic adapter exclude output_config from non-Anthropic
  backends)
- BerriAI#22727 (Anthropic adapter strip output_config for non-Anthropic
  backends)

Closes / addresses: BerriAI#23380 (Vertex AI Claude output_config drop),
related: BerriAI#26423, BerriAI#25079, BerriAI#24549, BerriAI#25971, BerriAI#25957, BerriAI#26163, BerriAI#24856.

What was broken
---------------
* Vertex AI Claude paths called ``data.pop("output_config")`` and
  ``data.pop("output_format")`` unconditionally even when Vertex
  accepted those fields. Callers asking for Structured Outputs got a
  200 with prose and never knew the schema constraints had been
  silently dropped (often masked for months by permissive fallback
  parsers).
* The ``/v1/messages`` -> ``/chat/completions`` adapter
  (``LiteLLMMessagesToCompletionTransformationHandler``) re-merged the
  raw Anthropic-shaped ``output_config`` into ``completion_kwargs``
  AFTER the translator already mapped its meaningful parts to
  ``response_format`` / ``reasoning_effort``. Non-Anthropic backends
  (Azure OpenAI, Fireworks, Bedrock Nova, etc.) then 400'd with
  "Extra inputs are not permitted".

Approach
--------
Vertex AI Claude (chat-completion + experimental_pass_through paths):
  Replace the unconditional pop with a sanitizer
  ``_sanitize_vertex_anthropic_output_params`` that strips only the
  Vertex-unsupported keys (today: ``effort``) from ``output_config``
  while forwarding ``format`` and the legacy top-level
  ``output_format``. Defensive: non-dict ``output_config`` values are
  dropped to avoid sending malformed payloads downstream.
  Greptile P1 from PR BerriAI#23396 addressed: when ``output_config`` carries
  both ``format`` and ``effort``, the prior conditional pass-through
  forwarded ``effort`` and reproduced the 400. The new helper filters
  per-key.

Anthropic ``/v1/messages`` adapter:
  Add ``output_config`` to a named module-level constant
  ``ANTHROPIC_ONLY_REQUEST_KEYS`` and wire it into ``excluded_keys`` so
  the post-translation re-merge skips re-adding the raw key. This
  fixes the 400 on non-Anthropic backends and avoids the conflicting
  duplicate (``response_format`` + raw ``output_config``) on
  Anthropic-family backends.
  Greptile P2 from PR BerriAI#23706 addressed: the constant gives reviewers
  one grep target instead of an inline literal that silently grows.
  Greptile P2 from PR BerriAI#22727 addressed: ``extra_kwargs or {}`` is
  replaced with explicit ``is None`` checks so empty-dict callers no
  longer skip the fallback path.

Tests
-----
* tests/test_litellm/llms/vertex_ai/vertex_ai_partner_models/anthropic/
  test_vertex_ai_partner_models_anthropic_transformation.py:
  - 5 new/updated cases plus a direct unit test for
    ``_sanitize_vertex_anthropic_output_params``.
  - Updated ``test_vertex_ai_claude_sonnet_4_5_structured_output_fix``
    so its mock-injected ``output_format`` is asserted to FLOW THROUGH
    (the original test asserted the now-buggy strip behavior).
* tests/test_litellm/llms/anthropic/experimental_pass_through/
  adapters/test_handler_output_config_passthrough.py (new):
  - Constant export sanity, output_config strip with ``effort`` only,
    output_config strip with ``format`` only, regression guard that
    unrelated extras still flow, explicit-empty-dict path, and the
    ``extra_kwargs=None`` no-crash path.

Test-quality fixes incorporated from Greptile review on the
superseded PRs:
* No ``inspect.getsource`` source-text assertions (PR BerriAI#24114 / BerriAI#23475).
* ``sys.path`` insertion is anchored to ``__file__`` (PR BerriAI#23706).
* Assertion messages are positional, not tuple (PR BerriAI#24114-class bug).
* No ``or {}`` masking explicit empty dicts in helper signatures
  (PR BerriAI#22727).

Verified locally: 26/26 pass with this commit. The new tests
fail (or fail to import) on ``main`` without it.

Out of scope
------------
* The ``max_tokens`` capping logic from PR BerriAI#22727 — independent
  concern, deserves its own PR with a focused test plan.
* Architectural rework of the ``excluded_keys`` mechanism (Greptile
  P2 on PR BerriAI#23706 noted point-fix growth). The named constant gives
  maintainers a clear place to extend; a registry-based approach
  would be a follow-up.

Co-Authored-By: netbrah <netbrah>
Co-Authored-By: s-zx <s-zx>
Co-Authored-By: invoicepulse <invoicepulse>
Co-Authored-By: cfdude <cfdude>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@veria-ai

veria-ai Bot commented Apr 24, 2026

Copy link
Copy Markdown
Contributor

This PR adds parameter filtering and translation logic for Anthropic's output_config field when routing requests through the adapter to non-Anthropic backends (Vertex AI, Azure OpenAI, etc.). The changes are confined to request parameter sanitization — filtering known-unsupported keys, translating between API formats, and adding type checks. No injection surfaces, auth changes, secrets handling, or other security-relevant patterns.


Status: 0 open
Risk: 1/10

Posted by Veria AI · 2026-04-24T16:05:06.898Z

@codspeed-hq

codspeed-hq Bot commented Apr 24, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 16 untouched benchmarks


Comparing dkindlund:fix/output-config-passthrough-consolidated (79517bc) with main (7b47dff)

Open in CodSpeed

@greptile-apps

greptile-apps Bot commented Apr 24, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes silent stripping of output_config on two Vertex AI Claude transformation paths (chat-completion and Messages pass-through) and on the Anthropic-to-OpenAI adapter, consolidating four stalled community PRs. The core fix replaces unconditional data.pop(\"output_config\") calls with a shared sanitize_vertex_anthropic_output_params helper that strips only Vertex-unsupported sub-keys (currently effort) while forwarding supported ones (format); on the adapter path a new ANTHROPIC_ONLY_REQUEST_KEYS constant prevents the raw Anthropic-shaped field from leaking into completion_kwargs after translation.

Confidence Score: 5/5

Safe to merge; fixes a confirmed silent-drop bug with correct per-key sanitization, good test coverage, and only P2 findings

No P0 or P1 issues found. The two P2 findings (None/absent key ambiguity in the sanitizer, and falsy-vs-None check in the translator) have no realistic impact on production inputs. The PR includes 26 passing tests, reversed test assertions are intentional and correctly reflect the fixed behavior, and the shared helper avoids the duplicate-logic problem of the superseded PRs.

output_params_utils.py (None vs absent key edge case) and transformation.py adapter (falsy output_format check semantics)

Important Files Changed

Filename Overview
litellm/llms/vertex_ai/vertex_ai_partner_models/anthropic/output_params_utils.py New shared sanitization helper for Vertex AI Claude; correctly filters unsupported sub-keys (effort) while preserving supported ones (format); minor edge case: .get() cannot distinguish absent key from key set to None, leaving null values in the dict
litellm/llms/anthropic/experimental_pass_through/adapters/handler.py Adds ANTHROPIC_ONLY_REQUEST_KEYS constant and wires output_config into excluded_keys to prevent the raw Anthropic field from leaking into completion_kwargs; None-check fix for extra_kwargs is correct
litellm/llms/anthropic/experimental_pass_through/adapters/transformation.py Extends _translate_output_format_to_openai to accept output_config.format as a fallback when output_format is absent; uses falsy check (if not output_format:) which silently treats empty-dict output_format the same as absent
litellm/llms/vertex_ai/vertex_ai_partner_models/anthropic/transformation.py Replaces unconditional pop() of output_config/output_format with call to sanitize_vertex_anthropic_output_params; clean delegation to shared helper
litellm/llms/vertex_ai/vertex_ai_partner_models/anthropic/experimental_pass_through/transformation.py Mirrors the chat-completion path change — replaces unconditional pop() with sanitize_vertex_anthropic_output_params; one source of truth for both transformation paths
tests/test_litellm/llms/anthropic/experimental_pass_through/adapters/test_handler_output_config_passthrough.py New test file covering all key scenarios: strip, translate, precedence, empty/None extra_kwargs, and constant export; behavioral tests rather than source inspection; no real network calls
tests/test_litellm/llms/vertex_ai/vertex_ai_partner_models/anthropic/test_vertex_ai_partner_models_anthropic_transformation.py Existing tests updated to reflect corrected behavior (output_format now forwarded, effort dropped); assertions reversed from prior strip-everything behavior — valid since the stripping was the bug; new tests added for per-key sanitization scenarios

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Client sends output_config] --> B{Which path?}
    B --> C[Vertex AI Claude\nchat-completion path]
    B --> D[Vertex AI Claude\nMessages pass-through path]
    B --> E[Anthropic adapter\n/v1/messages → /chat/completions]
    C --> F[sanitize_vertex_anthropic_output_params]
    D --> F
    F --> G{output_config sub-keys}
    G -->|effort only| H[Drop output_config entirely\navoid Vertex 400]
    G -->|format only| I[Forward output_config as-is\nVertex accepts format]
    G -->|format + effort| J[Strip effort, keep format\nForward sanitized output_config]
    G -->|non-dict| K[Drop defensively]
    E --> L[Extract output_config\ninto request_data]
    L --> M[translate_anthropic_to_openai\nmaps format→response_format\neffort→reasoning_effort]
    M --> N[excluded_keys filter\nANTHROPIC_ONLY_REQUEST_KEYS\nprevents raw output_config\nre-merge into completion_kwargs]
    N --> O[completion_kwargs has\nresponse_format / reasoning_effort\nbut NOT raw output_config]
Loading

Reviews (2): Last reviewed commit: "fix: address Greptile review feedback on..." | Re-trigger Greptile

Comment thread litellm/llms/anthropic/experimental_pass_through/adapters/handler.py Outdated
Three concerns raised by bot reviewers, all addressed:

1. CodeQL cyclic-import warning
   ``experimental_pass_through/transformation.py`` imported from the
   parent ``..transformation`` module, which CodeQL flagged as a
   potential cycle. Extracted the helper into a new leaf module
   ``vertex_ai_partner_models/anthropic/output_params_utils.py`` that
   has no heavy imports of its own. Both transformation files now
   import from it cleanly. Renamed the helper from the underscore-
   prefixed ``_sanitize_vertex_anthropic_output_params`` to the
   public ``sanitize_vertex_anthropic_output_params`` since it is now
   shared across modules.

2. Greptile P2: redundant ``None`` guard on ``extra_kwargs``
   ``handler.py`` had two ``extra_kwargs = extra_kwargs if ... else {}``
   coercions; the second was a no-op because line 220 already
   coerced. Removed the second one and added a NOTE comment so future
   readers understand ``extra_kwargs`` is guaranteed non-None at the
   point of use.

3. Greptile P2: misleading "already translated" docstring
   The docstring claimed the translator above mapped
   ``output_config.format`` to ``response_format``, but Greptile
   correctly traced the code and found that only the legacy top-level
   ``output_format`` was being translated — ``output_config.format``
   was being silently dropped on the adapter path. Two-part fix:

   a. Code: extended ``_translate_output_format_to_openai`` to accept
      both shapes (top-level ``output_format`` AND
      ``output_config.format`` sub-key). Top-level still takes
      precedence when both are supplied. This means callers using the
      newer Anthropic Structured Outputs API now have their schema
      properly forwarded to non-Anthropic backends as
      ``response_format``.

   b. Tests: rewrote the misleading docstring to describe what
      actually happens, plus added two new tests:
      * ``test_output_format_top_level_still_translates`` —
        regression guard for the legacy path
      * ``test_output_format_takes_precedence_over_output_config_format``
        — documents the precedence rule explicitly

Tests: 28/28 pass (was 26/26 before; +2 for the new translation
behavior + precedence). All run in ~0.5s, no real network calls.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@dkindlund

Copy link
Copy Markdown
Contributor Author

@greptile-apps, can you please re-review?

@krrish-berri-2

Copy link
Copy Markdown
Contributor

@dkindlund — could you add a screenshot or short video showing that this change works as expected? It really helps reviewers verify the fix quickly. Thanks!

@krrish-berri-2

Copy link
Copy Markdown
Contributor

@mateo-berri didn't we recently work on this?

is this still a relevant PR?

@mateo-berri

Copy link
Copy Markdown
Contributor

We merged a PR for Bedrock but not Vertex. This is a legit value add. I can take over reviewing

@krrish-berri-2

Copy link
Copy Markdown
Contributor

@mateo-berri assigned to you

@mateo-berri
mateo-berri changed the base branch from main to litellm_internal_staging April 25, 2026 22:35
@mateo-berri
mateo-berri changed the base branch from litellm_internal_staging to litellm_oss_staging_04_25_2026 April 25, 2026 22:35
@mateo-berri
mateo-berri requested review from ishaan-berri and removed request for ishaan-berri April 25, 2026 22:36

@mateo-berri mateo-berri left a comment

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.

LGTM. Thank you for the contribution!

@mateo-berri
mateo-berri merged commit b55a0f0 into BerriAI:litellm_oss_staging_04_25_2026 Apr 25, 2026
52 of 53 checks passed
yugborana pushed a commit to yugborana/litellm that referenced this pull request Jun 2, 2026
Three concerns raised by bot reviewers, all addressed:

1. CodeQL cyclic-import warning
   ``experimental_pass_through/transformation.py`` imported from the
   parent ``..transformation`` module, which CodeQL flagged as a
   potential cycle. Extracted the helper into a new leaf module
   ``vertex_ai_partner_models/anthropic/output_params_utils.py`` that
   has no heavy imports of its own. Both transformation files now
   import from it cleanly. Renamed the helper from the underscore-
   prefixed ``_sanitize_vertex_anthropic_output_params`` to the
   public ``sanitize_vertex_anthropic_output_params`` since it is now
   shared across modules.

2. Greptile P2: redundant ``None`` guard on ``extra_kwargs``
   ``handler.py`` had two ``extra_kwargs = extra_kwargs if ... else {}``
   coercions; the second was a no-op because line 220 already
   coerced. Removed the second one and added a NOTE comment so future
   readers understand ``extra_kwargs`` is guaranteed non-None at the
   point of use.

3. Greptile P2: misleading "already translated" docstring
   The docstring claimed the translator above mapped
   ``output_config.format`` to ``response_format``, but Greptile
   correctly traced the code and found that only the legacy top-level
   ``output_format`` was being translated — ``output_config.format``
   was being silently dropped on the adapter path. Two-part fix:

   a. Code: extended ``_translate_output_format_to_openai`` to accept
      both shapes (top-level ``output_format`` AND
      ``output_config.format`` sub-key). Top-level still takes
      precedence when both are supplied. This means callers using the
      newer Anthropic Structured Outputs API now have their schema
      properly forwarded to non-Anthropic backends as
      ``response_format``.

   b. Tests: rewrote the misleading docstring to describe what
      actually happens, plus added two new tests:
      * ``test_output_format_top_level_still_translates`` —
        regression guard for the legacy path
      * ``test_output_format_takes_precedence_over_output_config_format``
        — documents the precedence rule explicitly

Tests: 28/28 pass (was 26/26 before; +2 for the new translation
behavior + precedence). All run in ~0.5s, no real network calls.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
fzowl pushed a commit to fzowl/litellm that referenced this pull request Jun 24, 2026
Three concerns raised by bot reviewers, all addressed:

1. CodeQL cyclic-import warning
   ``experimental_pass_through/transformation.py`` imported from the
   parent ``..transformation`` module, which CodeQL flagged as a
   potential cycle. Extracted the helper into a new leaf module
   ``vertex_ai_partner_models/anthropic/output_params_utils.py`` that
   has no heavy imports of its own. Both transformation files now
   import from it cleanly. Renamed the helper from the underscore-
   prefixed ``_sanitize_vertex_anthropic_output_params`` to the
   public ``sanitize_vertex_anthropic_output_params`` since it is now
   shared across modules.

2. Greptile P2: redundant ``None`` guard on ``extra_kwargs``
   ``handler.py`` had two ``extra_kwargs = extra_kwargs if ... else {}``
   coercions; the second was a no-op because line 220 already
   coerced. Removed the second one and added a NOTE comment so future
   readers understand ``extra_kwargs`` is guaranteed non-None at the
   point of use.

3. Greptile P2: misleading "already translated" docstring
   The docstring claimed the translator above mapped
   ``output_config.format`` to ``response_format``, but Greptile
   correctly traced the code and found that only the legacy top-level
   ``output_format`` was being translated — ``output_config.format``
   was being silently dropped on the adapter path. Two-part fix:

   a. Code: extended ``_translate_output_format_to_openai`` to accept
      both shapes (top-level ``output_format`` AND
      ``output_config.format`` sub-key). Top-level still takes
      precedence when both are supplied. This means callers using the
      newer Anthropic Structured Outputs API now have their schema
      properly forwarded to non-Anthropic backends as
      ``response_format``.

   b. Tests: rewrote the misleading docstring to describe what
      actually happens, plus added two new tests:
      * ``test_output_format_top_level_still_translates`` —
        regression guard for the legacy path
      * ``test_output_format_takes_precedence_over_output_config_format``
        — documents the precedence rule explicitly

Tests: 28/28 pass (was 26/26 before; +2 for the new translation
behavior + precedence). All run in ~0.5s, no real network calls.
fzowl pushed a commit to fzowl/litellm that referenced this pull request Jun 24, 2026
…sthrough-consolidated

fix(adapters,vertex): pass output_config through to backends that accept it (closes BerriAI#23380, supersedes BerriAI#23475/BerriAI#23396/BerriAI#23706/BerriAI#22727)
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.

5 participants