[integrations][anthropic] Stop sending rejected sampling parameters - #1037
Open
weiqingy wants to merge 1 commit into
Open
[integrations][anthropic] Stop sending rejected sampling parameters#1037weiqingy wants to merge 1 commit into
weiqingy wants to merge 1 commit into
Conversation
5 tasks
Claude Opus 4.7 and later, and the Sonnet, Fable and Mythos 5 lines, answer a non-default temperature, top_p or top_k with a 400. Sending the provider default or omitting the parameter stays acceptable everywhere, so the parameter is dropped rather than clamped: substituting the default would quietly change sampling behavior instead of leaving it to the provider. All three parameters are gated, on every path that reaches the request. In Java that is the top-level temperature read and the additional_kwargs switch, where a key without a case label is forwarded as a raw body property and so reaches the API ungated. Python gates the merged kwargs above its single create call. Adding a temperature case to that switch means an additional_kwargs value now takes precedence over the top-level one. Previously the two were emitted as a typed field and a raw property under the same key, producing duplicate JSON keys, which is undefined. The typed and raw routes serialize identically for a number, so accepting models see no change. The warn-once bookkeeping is keyed on the model and the parameter rather than the model alone. Keyed on the model, a second parameter dropped for a model that had already warned was discarded silently. Generated-by: Claude Code 2.1.234 (Claude Opus 5)
weiqingy
force-pushed
the
1036-anthropic-temperature
branch
from
August 23, 2026 05:10
3ad8bf2 to
178c0f5
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Linked issue: #1036
Purpose of change
Claude Opus 4.7+ and the Sonnet, Fable and Mythos 5 lines return HTTP 400 for a non-default
temperature,top_portop_k. The Anthropic integration defaultstemperatureto0.1and sent it on every request without checking the model, so picking one of those models turned every chat call into a provider error. Both languages had the defect.All three parameters are now dropped on models that reject them, in both languages. Dropped rather than clamped: omitting the parameter is accepted everywhere, while substituting the provider default would quietly change sampling behaviour. Each drop is logged once per model and parameter.
Three paths could reach the wire, and all three are gated:
temperatureadditional_kwargs→top_p/top_kadditional_kwargs→temperaturecaselabel, so forwarded as a raw body propertyPython gates the merged kwargs immediately above its single
createcall.The model list is deliberately separate from the prefill and structured-output lists in this connection: the three boundaries do not coincide. Structured output starts at 4.5, prefill rejection at 4.6, sampling rejection at 4.7, so Claude 4.6 rejects a prefill while still accepting a temperature. A test pins that.
One behaviour change. A caller setting
temperatureboth at the top level and inadditional_kwargsnow has theadditional_kwargsvalue win. Previously both were emitted under the same key, producing{"temperature":0.1,"temperature":0.5}, which is undefined. Typed and raw routes serialize identically for a number, so accepting models see no change on the wire.One bug fix beyond the 400. The warn-once bookkeeping was keyed on the model alone, so a second parameter dropped for an already-warned model was discarded silently. It is now keyed on model and parameter.
Tests
Java 81 in
AnthropicChatModelConnectionTest, 83 in the module. Python 84 passed, 2 skipped. Spotless, Ruff and RAT clean.Coverage was driven by mutation testing. Every mutant in scope dies in both languages: the guard removed per parameter, each parameter's routing removed, and the warn key reverted to model-only.
Worth knowing for future edits: an unrecognised key is forwarded as a raw body property, so asserting the typed accessor is empty does not prove a parameter was left off. The drop tests assert the raw body too.
Not covered: a rewrite that keeps the dedup helper but rebuilds the message at the call site and logs unconditionally. Observing the
LOG.warncall itself needs a logging binding in a module that has none.API
No public API change.
temperature,top_pandtop_kkeep their names, types and defaults; only whether they reach the provider depends on the model. No change on models that accept sampling parameters, including the defaultclaude-sonnet-4-20250514.Documentation
doc-neededdoc-not-neededdoc-includedchat_models.md: bothtemperaturerows note the parameter is not sent on Claude 4.7+; the Javaadditional_kwargsrow addstemperatureand states the precedence. The Pythonadditional_kwargsrow was removed because that parameter does not exist in the Python setup.Was this patch authored or co-authored using generative AI tooling?
Generated-by: Claude Code 2.1.234 (Claude Opus 5)