Skip to content
This repository was archived by the owner on Jul 22, 2025. It is now read-only.

Commit 8f4cd2f

Browse files
authored
FEATURE: allow disabling of top_p and temp for thinking models (#1184)
thinking models such as Claude 3.7 Thinking and o1 / o3 do not support top_p or temp. Previously you would have to carefully remove it from everywhere by having it be a provider param we now support blanker removing without forcing people to update automation rules or personas
1 parent f4708d4 commit 8f4cd2f

File tree

10 files changed

+182
-0
lines changed

10 files changed

+182
-0
lines changed

app/models/llm_model.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,23 @@ def self.provider_params
2626
access_key_id: :text,
2727
region: :text,
2828
disable_native_tools: :checkbox,
29+
disable_temperature: :checkbox,
30+
disable_top_p: :checkbox,
2931
enable_reasoning: :checkbox,
3032
reasoning_tokens: :number,
3133
},
3234
anthropic: {
3335
disable_native_tools: :checkbox,
36+
disable_temperature: :checkbox,
37+
disable_top_p: :checkbox,
3438
enable_reasoning: :checkbox,
3539
reasoning_tokens: :number,
3640
},
3741
open_ai: {
3842
organization: :text,
3943
disable_native_tools: :checkbox,
44+
disable_temperature: :checkbox,
45+
disable_top_p: :checkbox,
4046
disable_streaming: :checkbox,
4147
reasoning_effort: {
4248
type: :enum,
@@ -69,6 +75,8 @@ def self.provider_params
6975
provider_order: :text,
7076
provider_quantizations: :text,
7177
disable_streaming: :checkbox,
78+
disable_temperature: :checkbox,
79+
disable_top_p: :checkbox,
7280
},
7381
}
7482
end

config/locales/client.en.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,8 @@ en:
488488
reasoning_effort: "Reasoning effort (only applicable to reasoning models)"
489489
enable_reasoning: "Enable reasoning (only applicable to Sonnet 3.7)"
490490
reasoning_tokens: "Number of tokens used for reasoning"
491+
disable_temperature: "Disable temperature (some thinking models don't support temperature)"
492+
disable_top_p: "Disable top P (some thinking models don't support top P)"
491493

492494
related_topics:
493495
title: "Related topics"

lib/completions/endpoints/anthropic.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ def self.can_contact?(model_provider)
1010

1111
def normalize_model_params(model_params)
1212
# max_tokens, temperature, stop_sequences are already supported
13+
model_params = model_params.dup
14+
model_params.delete(:top_p) if llm_model.lookup_custom_param("disable_top_p")
15+
model_params.delete(:temperature) if llm_model.lookup_custom_param("disable_temperature")
1316
model_params
1417
end
1518

lib/completions/endpoints/aws_bedrock.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ def normalize_model_params(model_params)
1616
model_params = model_params.dup
1717

1818
# max_tokens, temperature, stop_sequences, top_p are already supported
19+
#
20+
model_params.delete(:top_p) if llm_model.lookup_custom_param("disable_top_p")
21+
model_params.delete(:temperature) if llm_model.lookup_custom_param("disable_temperature")
1922

2023
model_params
2124
end

lib/completions/endpoints/open_ai.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ def normalize_model_params(model_params)
2424
model_params[:stop] = model_params.delete(:stop_sequences)
2525
end
2626

27+
model_params.delete(:top_p) if llm_model.lookup_custom_param("disable_top_p")
28+
model_params.delete(:temperature) if llm_model.lookup_custom_param("disable_temperature")
29+
2730
model_params
2831
end
2932

lib/completions/endpoints/open_router.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ def normalize_model_params(model_params)
1616
model_params[:stop] = model_params.delete(:stop_sequences)
1717
end
1818

19+
model_params.delete(:top_p) if llm_model.lookup_custom_param("disable_top_p")
20+
model_params.delete(:temperature) if llm_model.lookup_custom_param("disable_temperature")
21+
1922
model_params
2023
end
2124

spec/lib/completions/endpoints/anthropic_spec.rb

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -664,4 +664,54 @@
664664
expect(log.feature_name).to eq("testing")
665665
expect(log.response_tokens).to eq(30)
666666
end
667+
668+
describe "parameter disabling" do
669+
it "excludes disabled parameters from the request" do
670+
model.update!(provider_params: { disable_top_p: true, disable_temperature: true })
671+
672+
parsed_body = nil
673+
stub_request(:post, url).with(
674+
body:
675+
proc do |req_body|
676+
parsed_body = JSON.parse(req_body, symbolize_names: true)
677+
true
678+
end,
679+
headers: {
680+
"Content-Type" => "application/json",
681+
"X-Api-Key" => "123",
682+
"Anthropic-Version" => "2023-06-01",
683+
},
684+
).to_return(
685+
status: 200,
686+
body: {
687+
id: "msg_123",
688+
type: "message",
689+
role: "assistant",
690+
content: [{ type: "text", text: "test response" }],
691+
model: "claude-3-opus-20240229",
692+
usage: {
693+
input_tokens: 10,
694+
output_tokens: 5,
695+
},
696+
}.to_json,
697+
)
698+
699+
# Request with parameters that should be ignored
700+
llm.generate(
701+
prompt,
702+
user: Discourse.system_user,
703+
top_p: 0.9,
704+
temperature: 0.8,
705+
max_tokens: 500,
706+
)
707+
708+
# Verify disabled parameters aren't included
709+
expect(parsed_body).not_to have_key(:top_p)
710+
expect(parsed_body).not_to have_key(:temperature)
711+
712+
# Verify other parameters still work
713+
expect(parsed_body).to have_key(:max_tokens)
714+
expect(parsed_body[:max_tokens]).to eq(500)
715+
end
716+
end
667717
end

spec/lib/completions/endpoints/aws_bedrock_spec.rb

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,4 +436,52 @@ def encode_message(message)
436436
end
437437
end
438438
end
439+
440+
describe "parameter disabling" do
441+
it "excludes disabled parameters from the request" do
442+
model.update!(
443+
provider_params: {
444+
access_key_id: "123",
445+
region: "us-east-1",
446+
disable_top_p: true,
447+
disable_temperature: true,
448+
},
449+
)
450+
451+
proxy = DiscourseAi::Completions::Llm.proxy("custom:#{model.id}")
452+
request = nil
453+
454+
content = {
455+
content: [text: "test response"],
456+
usage: {
457+
input_tokens: 10,
458+
output_tokens: 5,
459+
},
460+
}.to_json
461+
462+
stub_request(
463+
:post,
464+
"https://bedrock-runtime.us-east-1.amazonaws.com/model/anthropic.claude-3-sonnet-20240229-v1:0/invoke",
465+
)
466+
.with do |inner_request|
467+
request = inner_request
468+
true
469+
end
470+
.to_return(status: 200, body: content)
471+
472+
# Request with parameters that should be ignored
473+
proxy.generate("test prompt", user: user, top_p: 0.9, temperature: 0.8, max_tokens: 500)
474+
475+
# Parse the request body
476+
request_body = JSON.parse(request.body)
477+
478+
# Verify disabled parameters aren't included
479+
expect(request_body).not_to have_key("top_p")
480+
expect(request_body).not_to have_key("temperature")
481+
482+
# Verify other parameters still work
483+
expect(request_body).to have_key("max_tokens")
484+
expect(request_body["max_tokens"]).to eq(500)
485+
end
486+
end
439487
end

spec/lib/completions/endpoints/open_ai_spec.rb

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,37 @@ def request_body(prompt, stream: false, tool_call: false)
395395
end
396396
end
397397

398+
describe "parameter disabling" do
399+
it "excludes disabled parameters from the request" do
400+
model.update!(provider_params: { disable_top_p: true, disable_temperature: true })
401+
402+
parsed_body = nil
403+
stub_request(:post, "https://api.openai.com/v1/chat/completions").with(
404+
body:
405+
proc do |req_body|
406+
parsed_body = JSON.parse(req_body, symbolize_names: true)
407+
true
408+
end,
409+
).to_return(
410+
status: 200,
411+
body: { choices: [{ message: { content: "test response" } }] }.to_json,
412+
)
413+
414+
dialect = compliance.dialect(prompt: compliance.generic_prompt)
415+
416+
# Request with parameters that should be ignored
417+
endpoint.perform_completion!(dialect, user, { top_p: 0.9, temperature: 0.8, max_tokens: 100 })
418+
419+
# Verify disabled parameters aren't included
420+
expect(parsed_body).not_to have_key(:top_p)
421+
expect(parsed_body).not_to have_key(:temperature)
422+
423+
# Verify other parameters still work
424+
expect(parsed_body).to have_key(:max_tokens)
425+
expect(parsed_body[:max_tokens]).to eq(100)
426+
end
427+
end
428+
398429
describe "image support" do
399430
it "can handle images" do
400431
model = Fabricate(:llm_model, vision_enabled: true)

spec/lib/completions/endpoints/open_router_spec.rb

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,35 @@
4444

4545
expect(parsed_body).to eq(expected)
4646
end
47+
48+
it "excludes disabled parameters from the request" do
49+
open_router_model.update!(provider_params: { disable_top_p: true, disable_temperature: true })
50+
51+
parsed_body = nil
52+
stub_request(:post, open_router_model.url).with(
53+
body: proc { |body| parsed_body = JSON.parse(body, symbolize_names: true) },
54+
headers: {
55+
"Content-Type" => "application/json",
56+
"X-Title" => "Discourse AI",
57+
"HTTP-Referer" => "https://www.discourse.org/ai",
58+
"Authorization" => "Bearer 123",
59+
},
60+
).to_return(
61+
status: 200,
62+
body: { "choices" => [message: { role: "assistant", content: "test response" }] }.to_json,
63+
)
64+
65+
proxy = DiscourseAi::Completions::Llm.proxy("custom:#{open_router_model.id}")
66+
67+
# Request with parameters that should be ignored
68+
proxy.generate("test", user: user, top_p: 0.9, temperature: 0.8, max_tokens: 500)
69+
70+
# Verify disabled parameters aren't included
71+
expect(parsed_body).not_to have_key(:top_p)
72+
expect(parsed_body).not_to have_key(:temperature)
73+
74+
# Verify other parameters still work
75+
expect(parsed_body).to have_key(:max_tokens)
76+
expect(parsed_body[:max_tokens]).to eq(500)
77+
end
4778
end

0 commit comments

Comments
 (0)