Skip to content

fix(hosted_vllm): map output_config effort and adaptive thinking to reasoning_effort - #44563

Open
iosayin wants to merge 2 commits into
BerriAI:mainfrom
iosayin:fix/44560-output-config-effort-hosted-vllm
Open

iosayin wants to merge 2 commits into
BerriAI:mainfrom
iosayin:fix/44560-output-config-effort-hosted-vllm

Conversation

@iosayin

@iosayin iosayin commented Oct 5, 2026

Copy link
Copy Markdown

Title

fix(hosted_vllm): map output_config effort and adaptive thinking to reasoning_effort

Relevant issues

Fixes #44560

Type

Bug Fix

Description

When calling /v1/messages or passing requests with adaptive thinking and output configuration (e.g. thinking: {"type": "adaptive"} and output_config: {"effort": "low"} or thinking: {"type": "adaptive", "effort": ...}), HostedVLLMChatConfig.map_openai_params previously only handled thinking.get("type") == "enabled" with token budgets.

This PR updates HostedVLLMChatConfig.map_openai_params to:

  1. Extract output_config and map output_config["effort"], or thinking["effort"], to reasoning_effort when reasoning_effort is not already explicitly specified.
  2. Cleanly strip output_config and thinking so OpenAI-compatible hosted vLLM backends receive clean top-level reasoning_effort.
  3. Add comprehensive unit tests in test_hosted_vllm_supports_thinking.

Tests

  • Added unit tests in tests/unit/llms/hosted_vllm/chat/test_hosted_vllm_chat_transformation.py
  • All hosted_vllm transformation tests pass locally

@iosayin
iosayin requested a review from a team October 5, 2026 09:52
@CLAassistant

CLAassistant commented Oct 5, 2026 •

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@greptile-apps

greptile-apps Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 4/5

[Medium risk] Maps new reasoning parameters in the hosted vLLM adapter.

The PR should not merge until direct chat requests can carry output_config.effort through preprocessing and the repository’s test-comment requirement is satisfied

Findings

  1. P1 Output effort never reaches mapper ▶
  2. P2 Empty branch obscures precedence ▶
  3. P2 Test narration violates comment rule ▶

Summary

The PR adds hosted vLLM mappings from adaptive thinking and output_config.effort to reasoning_effort, with direct mapper tests. Direct chat calls still lose output_config during earlier request preprocessing, so that part of the fix does not reach the provider

Reviews (1) · Last reviewed commit: "fix(hosted_vllm): map output_config effo..."

if _tools is not None:
non_default_params["tools"] = _tools

output_config: Final = non_default_params.pop("output_config", None)

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.

P1 Output effort never reaches mapper Direct completion() calls discard output_config during preprocessing, so this mapping cannot send the requested effort to hosted vLLM. The new tests bypass preprocessing

Knowledge Base Used: Model invocation runtime

Comment on lines +110 to +111
elif thinking is not None and isinstance(thinking, dict) and thinking.get("type") == "enabled":
pass

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.

P2 Empty branch obscures precedence This branch only executes pass. Removing it would preserve behavior and make the effort precedence easier to follow

Suggested change
elif thinking is not None and isinstance(thinking, dict) and thinking.get("type") == "enabled":
pass

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

)
assert optional_params["reasoning_effort"] == "low"

# Test output_config.effort is mapped to reasoning_effort

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.

P2 Test narration violates comment rule The new comments here and below restate the assertions. The repository prohibits such comments; remove both before merging

Context Used: AGENTS.md (source)

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@codecov

codecov Bot commented Oct 5, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@codspeed

codspeed Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 31 untouched benchmarks


Comparing iosayin:fix/44560-output-config-effort-hosted-vllm (68f0a52) with main (d7210f9)

Open in CodSpeed

@aayushbaluni

Copy link
Copy Markdown

Nice — thanks for picking this up, and your reading of the mapping matches the
trace I posted on #44560. Three notes, offered as review rather than as a
competing claim; I am happy for this to be the fix.

1. Dead branch. The final elif is a no-op and can go:

elif thinking is not None and isinstance(thinking, dict) and thinking.get("type") == "enabled":
    pass

The if "reasoning_effort" not in non_default_params guard above already covers
"leave an explicit reasoning_effort alone", so this adds nothing but a reader's
double-take.

2. One question worth settling before merge, and I genuinely do not know the
answer: the tests call map_openai_params directly with output_config and
thinking in non_default_params, which proves the mapping works if those
keys arrive. What I could not establish is whether they still arrive on the
/v1/messages path that #44560 actually reports.

The reason I ask: in
litellm/llms/anthropic/pass_through/messages/transformation.py, the adaptive
path derives Anthropic's native thinking from the effort, and when
AnthropicModelInfo._supports_model_capability(model, "supports_reasoning", ...)
is false it logs DROP_UNSUPPORTED_ADAPTIVE_EFFORT_WARNING, pops thinking,
and then strips effort out of output_config:

if isinstance(output_config, dict) and "effort" in output_config:
    residual = {k: v for k, v in output_config.items() if k != "effort"}

If that runs before the provider's map_openai_params for a hosted_vllm
target, then output_config["effort"] would already be gone by the time this
new code looks for it, and the fix would cover /chat/completions while leaving
the reported /v1/messages case unchanged. If it does not run for
non-Anthropic targets, this is a non-issue and I would just drop the point.

An end-to-end assertion through the /v1/messages entry point — rather than
calling map_openai_params directly — would settle it either way and would be
the thing I would most want in this PR.

3. Scope. @alvarogarciapiz asked for "OpenAI-compatible providers such as
hosted_vllm". This fixes hosted_vllm specifically, so the next
OpenAI-compatible provider with the same shape will need the same patch. That is
a legitimate trade (smaller blast radius, easier to review) — just flagging that
the issue's ask is slightly wider than the change, in case a maintainer would
rather see it one layer up.

Happy to help with any of this, including taking the broader layer as a separate
PR if the maintainers prefer that split — I would rather not duplicate yours.

@aayushbaluni

Copy link
Copy Markdown

Following up on my point 2 above — I traced it, and I owe you a correction plus
a sharper version of the concern.

The file I originally pointed at is not on this path: a native
/v1/messages config exists only for ANTHROPIC, BEDROCK, BEDROCK_MANTLE,
VERTEX_AI, AZURE_AI, MINIMAX, DEEPSEEK, TENCENT, GITHUB_COPILOT,
EDENAI and JSON-configured providers, so hosted_vllm falls through to the
Anthropic→chat-completions adapter. Full trace in
my comment on #44560.

The concern survives in a different form, though. On that adapter path
adapters/transformation.py already maps output_config.effort →
reasoning_effort, and keeps raw output_config out of completion_kwargs. So
by the time HostedVLLMChatConfig.map_openai_params runs, reasoning_effort is
already present — which means if "reasoning_effort" not in non_default_params
is false and the new branch is skipped.

If that reading is right, this PR fixes a direct /chat/completions call that
carries output_config (a real case, worth having) but leaves the
/v1/messages flow in #44560 unchanged. The cheapest way to settle it is one
assertion driven through the /v1/messages entry point instead of calling
map_openai_params directly — if reasoning_effort comes out right, I am
wrong and you can ignore all of this.

I am not trying to talk you out of the PR; I would just hate for #44560 to be
closed by it and the reporter still see zero reasoning tokens. Dead elif from
point 1 still stands either way.

@iosayin

iosayin commented Oct 5, 2026

Copy link
Copy Markdown
Author

"Cannot merge due to insufficient permissions. Skipping merge as requested."

@iosayin

iosayin commented Oct 5, 2026

Copy link
Copy Markdown
Author

Thanks @aayushbaluni for the careful review! Cleaned up the dead elif in HostedVLLMChatConfig.map_openai_params as suggested.

@alvarogarciapiz

Copy link
Copy Markdown

any updates?

This branch has not been deployed

No deployments
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.

[Bug]: output_config.effort is not translated to reasoning_effort for hosted_vllm via /v1/messages

4 participants