From 945f64247851cd17e80be9b09b1de9d3b6c10d23 Mon Sep 17 00:00:00 2001 From: Shardul Vaidya <31039336+5herlocked@users.noreply.github.com> Date: Thu, 19 Mar 2026 11:32:04 -0400 Subject: [PATCH] bedrock: Make thinking toggle toggle thinking (#50673) Release Notes: - Support for Native Thinking toggle instead of model variants --------- Co-authored-by: Ona Co-authored-by: Bennet Bo Fenner Co-authored-by: Marshall Bowers --- crates/bedrock/src/models.rs | 266 ++++++------------ .../language_models/src/provider/bedrock.rs | 55 +++- 2 files changed, 138 insertions(+), 183 deletions(-) diff --git a/crates/bedrock/src/models.rs b/crates/bedrock/src/models.rs index ee1909b57c1bff8eba092dc5410f6cca16975341..8b6113e4d5521fb3c7e27a7f2f6547c7a9db86ce 100644 --- a/crates/bedrock/src/models.rs +++ b/crates/bedrock/src/models.rs @@ -48,49 +48,49 @@ pub enum Model { // Anthropic Claude 4+ models #[serde(rename = "claude-haiku-4-5", alias = "claude-haiku-4-5-latest")] ClaudeHaiku4_5, - #[serde(rename = "claude-sonnet-4", alias = "claude-sonnet-4-latest")] - ClaudeSonnet4, #[serde( - rename = "claude-sonnet-4-thinking", + rename = "claude-sonnet-4", + alias = "claude-sonnet-4-latest", + alias = "claude-sonnet-4-thinking", alias = "claude-sonnet-4-thinking-latest" )] - ClaudeSonnet4Thinking, + ClaudeSonnet4, #[default] - #[serde(rename = "claude-sonnet-4-5", alias = "claude-sonnet-4-5-latest")] - ClaudeSonnet4_5, #[serde( - rename = "claude-sonnet-4-5-thinking", + rename = "claude-sonnet-4-5", + alias = "claude-sonnet-4-5-latest", + alias = "claude-sonnet-4-5-thinking", alias = "claude-sonnet-4-5-thinking-latest" )] - ClaudeSonnet4_5Thinking, - #[serde(rename = "claude-opus-4-1", alias = "claude-opus-4-1-latest")] - ClaudeOpus4_1, + ClaudeSonnet4_5, #[serde( - rename = "claude-opus-4-1-thinking", + rename = "claude-opus-4-1", + alias = "claude-opus-4-1-latest", + alias = "claude-opus-4-1-thinking", alias = "claude-opus-4-1-thinking-latest" )] - ClaudeOpus4_1Thinking, - #[serde(rename = "claude-opus-4-5", alias = "claude-opus-4-5-latest")] - ClaudeOpus4_5, + ClaudeOpus4_1, #[serde( - rename = "claude-opus-4-5-thinking", + rename = "claude-opus-4-5", + alias = "claude-opus-4-5-latest", + alias = "claude-opus-4-5-thinking", alias = "claude-opus-4-5-thinking-latest" )] - ClaudeOpus4_5Thinking, - #[serde(rename = "claude-opus-4-6", alias = "claude-opus-4-6-latest")] - ClaudeOpus4_6, + ClaudeOpus4_5, #[serde( - rename = "claude-opus-4-6-thinking", + rename = "claude-opus-4-6", + alias = "claude-opus-4-6-latest", + alias = "claude-opus-4-6-thinking", alias = "claude-opus-4-6-thinking-latest" )] - ClaudeOpus4_6Thinking, - #[serde(rename = "claude-sonnet-4-6", alias = "claude-sonnet-4-6-latest")] - ClaudeSonnet4_6, + ClaudeOpus4_6, #[serde( - rename = "claude-sonnet-4-6-thinking", + rename = "claude-sonnet-4-6", + alias = "claude-sonnet-4-6-latest", + alias = "claude-sonnet-4-6-thinking", alias = "claude-sonnet-4-6-thinking-latest" )] - ClaudeSonnet4_6Thinking, + ClaudeSonnet4_6, // Meta Llama 4 models #[serde(rename = "llama-4-scout-17b")] @@ -181,28 +181,16 @@ impl Model { } pub fn from_id(id: &str) -> anyhow::Result { - if id.starts_with("claude-opus-4-6-thinking") { - Ok(Self::ClaudeOpus4_6Thinking) - } else if id.starts_with("claude-opus-4-6") { + if id.starts_with("claude-opus-4-6") { Ok(Self::ClaudeOpus4_6) - } else if id.starts_with("claude-opus-4-5-thinking") { - Ok(Self::ClaudeOpus4_5Thinking) } else if id.starts_with("claude-opus-4-5") { Ok(Self::ClaudeOpus4_5) - } else if id.starts_with("claude-opus-4-1-thinking") { - Ok(Self::ClaudeOpus4_1Thinking) } else if id.starts_with("claude-opus-4-1") { Ok(Self::ClaudeOpus4_1) - } else if id.starts_with("claude-sonnet-4-6-thinking") { - Ok(Self::ClaudeSonnet4_6Thinking) } else if id.starts_with("claude-sonnet-4-6") { Ok(Self::ClaudeSonnet4_6) - } else if id.starts_with("claude-sonnet-4-5-thinking") { - Ok(Self::ClaudeSonnet4_5Thinking) } else if id.starts_with("claude-sonnet-4-5") { Ok(Self::ClaudeSonnet4_5) - } else if id.starts_with("claude-sonnet-4-thinking") { - Ok(Self::ClaudeSonnet4Thinking) } else if id.starts_with("claude-sonnet-4") { Ok(Self::ClaudeSonnet4) } else if id.starts_with("claude-haiku-4-5") { @@ -216,17 +204,11 @@ impl Model { match self { Self::ClaudeHaiku4_5 => "claude-haiku-4-5", Self::ClaudeSonnet4 => "claude-sonnet-4", - Self::ClaudeSonnet4Thinking => "claude-sonnet-4-thinking", Self::ClaudeSonnet4_5 => "claude-sonnet-4-5", - Self::ClaudeSonnet4_5Thinking => "claude-sonnet-4-5-thinking", Self::ClaudeOpus4_1 => "claude-opus-4-1", - Self::ClaudeOpus4_1Thinking => "claude-opus-4-1-thinking", Self::ClaudeOpus4_5 => "claude-opus-4-5", - Self::ClaudeOpus4_5Thinking => "claude-opus-4-5-thinking", Self::ClaudeOpus4_6 => "claude-opus-4-6", - Self::ClaudeOpus4_6Thinking => "claude-opus-4-6-thinking", Self::ClaudeSonnet4_6 => "claude-sonnet-4-6", - Self::ClaudeSonnet4_6Thinking => "claude-sonnet-4-6-thinking", Self::Llama4Scout17B => "llama-4-scout-17b", Self::Llama4Maverick17B => "llama-4-maverick-17b", Self::Gemma3_4B => "gemma-3-4b", @@ -261,20 +243,12 @@ impl Model { pub fn request_id(&self) -> &str { match self { Self::ClaudeHaiku4_5 => "anthropic.claude-haiku-4-5-20251001-v1:0", - Self::ClaudeSonnet4 | Self::ClaudeSonnet4Thinking => { - "anthropic.claude-sonnet-4-20250514-v1:0" - } - Self::ClaudeSonnet4_5 | Self::ClaudeSonnet4_5Thinking => { - "anthropic.claude-sonnet-4-5-20250929-v1:0" - } - Self::ClaudeOpus4_1 | Self::ClaudeOpus4_1Thinking => { - "anthropic.claude-opus-4-1-20250805-v1:0" - } - Self::ClaudeOpus4_5 | Self::ClaudeOpus4_5Thinking => { - "anthropic.claude-opus-4-5-20251101-v1:0" - } - Self::ClaudeOpus4_6 | Self::ClaudeOpus4_6Thinking => "anthropic.claude-opus-4-6-v1", - Self::ClaudeSonnet4_6 | Self::ClaudeSonnet4_6Thinking => "anthropic.claude-sonnet-4-6", + Self::ClaudeSonnet4 => "anthropic.claude-sonnet-4-20250514-v1:0", + Self::ClaudeSonnet4_5 => "anthropic.claude-sonnet-4-5-20250929-v1:0", + Self::ClaudeOpus4_1 => "anthropic.claude-opus-4-1-20250805-v1:0", + Self::ClaudeOpus4_5 => "anthropic.claude-opus-4-5-20251101-v1:0", + Self::ClaudeOpus4_6 => "anthropic.claude-opus-4-6-v1", + Self::ClaudeSonnet4_6 => "anthropic.claude-sonnet-4-6", Self::Llama4Scout17B => "meta.llama4-scout-17b-instruct-v1:0", Self::Llama4Maverick17B => "meta.llama4-maverick-17b-instruct-v1:0", Self::Gemma3_4B => "google.gemma-3-4b-it", @@ -310,17 +284,11 @@ impl Model { match self { Self::ClaudeHaiku4_5 => "Claude Haiku 4.5", Self::ClaudeSonnet4 => "Claude Sonnet 4", - Self::ClaudeSonnet4Thinking => "Claude Sonnet 4 Thinking", Self::ClaudeSonnet4_5 => "Claude Sonnet 4.5", - Self::ClaudeSonnet4_5Thinking => "Claude Sonnet 4.5 Thinking", Self::ClaudeOpus4_1 => "Claude Opus 4.1", - Self::ClaudeOpus4_1Thinking => "Claude Opus 4.1 Thinking", Self::ClaudeOpus4_5 => "Claude Opus 4.5", - Self::ClaudeOpus4_5Thinking => "Claude Opus 4.5 Thinking", Self::ClaudeOpus4_6 => "Claude Opus 4.6", - Self::ClaudeOpus4_6Thinking => "Claude Opus 4.6 Thinking", Self::ClaudeSonnet4_6 => "Claude Sonnet 4.6", - Self::ClaudeSonnet4_6Thinking => "Claude Sonnet 4.6 Thinking", Self::Llama4Scout17B => "Llama 4 Scout 17B", Self::Llama4Maverick17B => "Llama 4 Maverick 17B", Self::Gemma3_4B => "Gemma 3 4B", @@ -362,17 +330,11 @@ impl Model { match self { Self::ClaudeHaiku4_5 | Self::ClaudeSonnet4 - | Self::ClaudeSonnet4Thinking | Self::ClaudeSonnet4_5 - | Self::ClaudeSonnet4_5Thinking | Self::ClaudeOpus4_1 - | Self::ClaudeOpus4_1Thinking | Self::ClaudeOpus4_5 - | Self::ClaudeOpus4_5Thinking | Self::ClaudeOpus4_6 - | Self::ClaudeOpus4_6Thinking - | Self::ClaudeSonnet4_6 - | Self::ClaudeSonnet4_6Thinking => 200_000, + | Self::ClaudeSonnet4_6 => 200_000, Self::Llama4Scout17B | Self::Llama4Maverick17B => 128_000, Self::Gemma3_4B | Self::Gemma3_12B | Self::Gemma3_27B => 128_000, Self::MagistralSmall | Self::MistralLarge3 | Self::PixtralLarge => 128_000, @@ -397,15 +359,12 @@ impl Model { pub fn max_output_tokens(&self) -> u64 { match self { Self::ClaudeHaiku4_5 + | Self::ClaudeSonnet4 | Self::ClaudeSonnet4_5 - | Self::ClaudeSonnet4_5Thinking | Self::ClaudeOpus4_5 - | Self::ClaudeOpus4_5Thinking - | Self::ClaudeSonnet4_6 - | Self::ClaudeSonnet4_6Thinking => 64_000, - Self::ClaudeSonnet4 | Self::ClaudeSonnet4Thinking => 64_000, - Self::ClaudeOpus4_1 | Self::ClaudeOpus4_1Thinking => 32_000, - Self::ClaudeOpus4_6 | Self::ClaudeOpus4_6Thinking => 128_000, + | Self::ClaudeSonnet4_6 => 64_000, + Self::ClaudeOpus4_1 => 32_000, + Self::ClaudeOpus4_6 => 128_000, Self::Llama4Scout17B | Self::Llama4Maverick17B | Self::Gemma3_4B @@ -436,17 +395,11 @@ impl Model { match self { Self::ClaudeHaiku4_5 | Self::ClaudeSonnet4 - | Self::ClaudeSonnet4Thinking | Self::ClaudeSonnet4_5 - | Self::ClaudeSonnet4_5Thinking | Self::ClaudeOpus4_1 - | Self::ClaudeOpus4_1Thinking | Self::ClaudeOpus4_5 - | Self::ClaudeOpus4_5Thinking | Self::ClaudeOpus4_6 - | Self::ClaudeOpus4_6Thinking - | Self::ClaudeSonnet4_6 - | Self::ClaudeSonnet4_6Thinking => 1.0, + | Self::ClaudeSonnet4_6 => 1.0, Self::Custom { default_temperature, .. @@ -459,17 +412,11 @@ impl Model { match self { Self::ClaudeHaiku4_5 | Self::ClaudeSonnet4 - | Self::ClaudeSonnet4Thinking | Self::ClaudeSonnet4_5 - | Self::ClaudeSonnet4_5Thinking | Self::ClaudeOpus4_1 - | Self::ClaudeOpus4_1Thinking | Self::ClaudeOpus4_5 - | Self::ClaudeOpus4_5Thinking | Self::ClaudeOpus4_6 - | Self::ClaudeOpus4_6Thinking - | Self::ClaudeSonnet4_6 - | Self::ClaudeSonnet4_6Thinking => true, + | Self::ClaudeSonnet4_6 => true, Self::NovaLite | Self::NovaPro | Self::NovaPremier | Self::Nova2Lite => true, Self::MistralLarge3 | Self::PixtralLarge | Self::MagistralSmall => true, // Gemma accepts toolConfig without error but produces unreliable tool @@ -492,17 +439,11 @@ impl Model { match self { Self::ClaudeHaiku4_5 | Self::ClaudeSonnet4 - | Self::ClaudeSonnet4Thinking | Self::ClaudeSonnet4_5 - | Self::ClaudeSonnet4_5Thinking | Self::ClaudeOpus4_1 - | Self::ClaudeOpus4_1Thinking | Self::ClaudeOpus4_5 - | Self::ClaudeOpus4_5Thinking | Self::ClaudeOpus4_6 - | Self::ClaudeOpus4_6Thinking - | Self::ClaudeSonnet4_6 - | Self::ClaudeSonnet4_6Thinking => true, + | Self::ClaudeSonnet4_6 => true, Self::NovaLite | Self::NovaPro => true, Self::PixtralLarge => true, Self::Qwen3VL235B => true, @@ -515,15 +456,10 @@ impl Model { matches!( self, Self::ClaudeSonnet4 - | Self::ClaudeSonnet4Thinking | Self::ClaudeSonnet4_5 - | Self::ClaudeSonnet4_5Thinking | Self::ClaudeOpus4_5 - | Self::ClaudeOpus4_5Thinking | Self::ClaudeOpus4_6 - | Self::ClaudeOpus4_6Thinking | Self::ClaudeSonnet4_6 - | Self::ClaudeSonnet4_6Thinking ) } @@ -531,17 +467,11 @@ impl Model { match self { Self::ClaudeHaiku4_5 | Self::ClaudeSonnet4 - | Self::ClaudeSonnet4Thinking | Self::ClaudeSonnet4_5 - | Self::ClaudeSonnet4_5Thinking | Self::ClaudeOpus4_1 - | Self::ClaudeOpus4_1Thinking | Self::ClaudeOpus4_5 - | Self::ClaudeOpus4_5Thinking | Self::ClaudeOpus4_6 - | Self::ClaudeOpus4_6Thinking - | Self::ClaudeSonnet4_6 - | Self::ClaudeSonnet4_6Thinking => true, + | Self::ClaudeSonnet4_6 => true, Self::Custom { cache_configuration, .. @@ -553,17 +483,11 @@ impl Model { pub fn cache_configuration(&self) -> Option { match self { Self::ClaudeSonnet4 - | Self::ClaudeSonnet4Thinking | Self::ClaudeSonnet4_5 - | Self::ClaudeSonnet4_5Thinking | Self::ClaudeOpus4_1 - | Self::ClaudeOpus4_1Thinking | Self::ClaudeOpus4_5 - | Self::ClaudeOpus4_5Thinking | Self::ClaudeOpus4_6 - | Self::ClaudeOpus4_6Thinking - | Self::ClaudeSonnet4_6 - | Self::ClaudeSonnet4_6Thinking => Some(BedrockModelCacheConfiguration { + | Self::ClaudeSonnet4_6 => Some(BedrockModelCacheConfiguration { max_cache_anchors: 4, min_total_token: 1024, }), @@ -579,25 +503,34 @@ impl Model { } } - pub fn mode(&self) -> BedrockModelMode { - match self { - Self::ClaudeSonnet4Thinking | Self::ClaudeSonnet4_5Thinking => { - BedrockModelMode::Thinking { - budget_tokens: Some(4096), - } + pub fn supports_thinking(&self) -> bool { + matches!( + self, + Self::ClaudeHaiku4_5 + | Self::ClaudeSonnet4 + | Self::ClaudeSonnet4_5 + | Self::ClaudeOpus4_1 + | Self::ClaudeOpus4_5 + | Self::ClaudeOpus4_6 + | Self::ClaudeSonnet4_6 + ) + } + + pub fn supports_adaptive_thinking(&self) -> bool { + matches!(self, Self::ClaudeOpus4_6 | Self::ClaudeSonnet4_6) + } + + pub fn thinking_mode(&self) -> BedrockModelMode { + if self.supports_adaptive_thinking() { + BedrockModelMode::AdaptiveThinking { + effort: BedrockAdaptiveThinkingEffort::default(), } - Self::ClaudeOpus4_1Thinking | Self::ClaudeOpus4_5Thinking => { - BedrockModelMode::Thinking { - budget_tokens: Some(4096), - } + } else if self.supports_thinking() { + BedrockModelMode::Thinking { + budget_tokens: Some(4096), } - Self::ClaudeOpus4_6Thinking => BedrockModelMode::AdaptiveThinking { - effort: BedrockAdaptiveThinkingEffort::default(), - }, - Self::ClaudeSonnet4_6Thinking => BedrockModelMode::AdaptiveThinking { - effort: BedrockAdaptiveThinkingEffort::default(), - }, - _ => BedrockModelMode::Default, + } else { + BedrockModelMode::Default } } @@ -612,15 +545,10 @@ impl Model { self, Self::ClaudeHaiku4_5 | Self::ClaudeSonnet4 - | Self::ClaudeSonnet4Thinking | Self::ClaudeSonnet4_5 - | Self::ClaudeSonnet4_5Thinking | Self::ClaudeOpus4_5 - | Self::ClaudeOpus4_5Thinking | Self::ClaudeOpus4_6 - | Self::ClaudeOpus4_6Thinking | Self::ClaudeSonnet4_6 - | Self::ClaudeSonnet4_6Thinking | Self::Nova2Lite ); @@ -676,39 +604,26 @@ impl Model { ( Self::ClaudeHaiku4_5 | Self::ClaudeSonnet4 - | Self::ClaudeSonnet4Thinking | Self::ClaudeSonnet4_5 - | Self::ClaudeSonnet4_5Thinking | Self::ClaudeOpus4_5 - | Self::ClaudeOpus4_5Thinking | Self::ClaudeOpus4_6 - | Self::ClaudeOpus4_6Thinking | Self::ClaudeSonnet4_6 - | Self::ClaudeSonnet4_6Thinking | Self::Nova2Lite, "global", ) => Ok(format!("{}.{}", region_group, model_id)), // US Government region inference profiles - (Self::ClaudeSonnet4_5 | Self::ClaudeSonnet4_5Thinking, "us-gov") => { - Ok(format!("{}.{}", region_group, model_id)) - } + (Self::ClaudeSonnet4_5, "us-gov") => Ok(format!("{}.{}", region_group, model_id)), // US region inference profiles ( Self::ClaudeHaiku4_5 | Self::ClaudeSonnet4 - | Self::ClaudeSonnet4Thinking | Self::ClaudeSonnet4_5 - | Self::ClaudeSonnet4_5Thinking | Self::ClaudeOpus4_1 - | Self::ClaudeOpus4_1Thinking | Self::ClaudeOpus4_5 - | Self::ClaudeOpus4_5Thinking | Self::ClaudeOpus4_6 - | Self::ClaudeOpus4_6Thinking | Self::ClaudeSonnet4_6 - | Self::ClaudeSonnet4_6Thinking | Self::Llama4Scout17B | Self::Llama4Maverick17B | Self::NovaLite @@ -728,11 +643,8 @@ impl Model { Self::ClaudeHaiku4_5 | Self::ClaudeSonnet4 | Self::ClaudeSonnet4_5 - | Self::ClaudeSonnet4_5Thinking | Self::ClaudeOpus4_6 - | Self::ClaudeOpus4_6Thinking | Self::ClaudeSonnet4_6 - | Self::ClaudeSonnet4_6Thinking | Self::NovaLite | Self::NovaPro | Self::Nova2Lite, @@ -743,11 +655,8 @@ impl Model { ( Self::ClaudeHaiku4_5 | Self::ClaudeSonnet4_5 - | Self::ClaudeSonnet4_5Thinking | Self::ClaudeOpus4_6 - | Self::ClaudeOpus4_6Thinking - | Self::ClaudeSonnet4_6 - | Self::ClaudeSonnet4_6Thinking, + | Self::ClaudeSonnet4_6, "au", ) => Ok(format!("{}.{}", region_group, model_id)), @@ -755,9 +664,7 @@ impl Model { ( Self::ClaudeHaiku4_5 | Self::ClaudeSonnet4_5 - | Self::ClaudeSonnet4_5Thinking | Self::ClaudeSonnet4_6 - | Self::ClaudeSonnet4_6Thinking | Self::Nova2Lite, "jp", ) => Ok(format!("{}.{}", region_group, model_id)), @@ -767,7 +674,6 @@ impl Model { Self::ClaudeHaiku4_5 | Self::ClaudeSonnet4 | Self::ClaudeSonnet4_5 - | Self::ClaudeSonnet4_5Thinking | Self::NovaLite | Self::NovaPro | Self::Nova2Lite, @@ -889,7 +795,7 @@ mod tests { "us-gov.anthropic.claude-sonnet-4-5-20250929-v1:0" ); assert_eq!( - Model::ClaudeSonnet4_5Thinking.cross_region_inference_id("us-gov-west-1", false)?, + Model::ClaudeSonnet4_5.cross_region_inference_id("us-gov-west-1", false)?, "us-gov.anthropic.claude-sonnet-4-5-20250929-v1:0" ); Ok(()) @@ -996,33 +902,43 @@ mod tests { "meta.llama4-scout-17b-instruct-v1:0" ); - // Thinking models have different friendly IDs but same request IDs + // Thinking aliases deserialize to the same model assert_eq!(Model::ClaudeSonnet4.id(), "claude-sonnet-4"); assert_eq!( - Model::ClaudeSonnet4Thinking.id(), - "claude-sonnet-4-thinking" - ); - assert_eq!( - Model::ClaudeSonnet4.request_id(), - Model::ClaudeSonnet4Thinking.request_id() + Model::from_id("claude-sonnet-4-thinking").unwrap().id(), + "claude-sonnet-4" ); } #[test] - fn test_model_modes() { - assert_eq!(Model::ClaudeSonnet4.mode(), BedrockModelMode::Default); + fn test_thinking_modes() { + assert!(Model::ClaudeHaiku4_5.supports_thinking()); + assert!(Model::ClaudeSonnet4.supports_thinking()); + assert!(Model::ClaudeSonnet4_5.supports_thinking()); + assert!(Model::ClaudeOpus4_6.supports_thinking()); + + assert!(!Model::ClaudeSonnet4.supports_adaptive_thinking()); + assert!(Model::ClaudeOpus4_6.supports_adaptive_thinking()); + assert!(Model::ClaudeSonnet4_6.supports_adaptive_thinking()); + assert_eq!( - Model::ClaudeSonnet4Thinking.mode(), + Model::ClaudeSonnet4.thinking_mode(), BedrockModelMode::Thinking { budget_tokens: Some(4096) } ); assert_eq!( - Model::ClaudeOpus4_6Thinking.mode(), + Model::ClaudeOpus4_6.thinking_mode(), BedrockModelMode::AdaptiveThinking { effort: BedrockAdaptiveThinkingEffort::High } ); + assert_eq!( + Model::ClaudeHaiku4_5.thinking_mode(), + BedrockModelMode::Thinking { + budget_tokens: Some(4096) + } + ); } #[test] diff --git a/crates/language_models/src/provider/bedrock.rs b/crates/language_models/src/provider/bedrock.rs index 0df2f0856c36053367172dd3a0412a0cb6cf4e6f..b05e9159cee443662c82153f205c4600afe0de34 100644 --- a/crates/language_models/src/provider/bedrock.rs +++ b/crates/language_models/src/provider/bedrock.rs @@ -642,10 +642,36 @@ impl LanguageModel for BedrockModel { } fn supports_thinking(&self) -> bool { - matches!( - self.model.mode(), - BedrockModelMode::Thinking { .. } | BedrockModelMode::AdaptiveThinking { .. } - ) + self.model.supports_thinking() + } + + fn supported_effort_levels(&self) -> Vec { + if self.model.supports_adaptive_thinking() { + vec![ + language_model::LanguageModelEffortLevel { + name: "Low".into(), + value: "low".into(), + is_default: false, + }, + language_model::LanguageModelEffortLevel { + name: "Medium".into(), + value: "medium".into(), + is_default: false, + }, + language_model::LanguageModelEffortLevel { + name: "High".into(), + value: "high".into(), + is_default: true, + }, + language_model::LanguageModelEffortLevel { + name: "Max".into(), + value: "max".into(), + is_default: false, + }, + ] + } else { + Vec::new() + } } fn supports_tool_choice(&self, choice: LanguageModelToolChoice) -> bool { @@ -718,7 +744,7 @@ impl LanguageModel for BedrockModel { model_id, self.model.default_temperature(), self.model.max_output_tokens(), - self.model.mode(), + self.model.thinking_mode(), self.model.supports_caching(), self.model.supports_tool_use(), use_extended_context, @@ -811,7 +837,7 @@ pub fn into_bedrock( model: String, default_temperature: f32, max_output_tokens: u64, - mode: BedrockModelMode, + thinking_mode: BedrockModelMode, supports_caching: bool, supports_tool_use: bool, allow_extended_context: bool, @@ -1085,11 +1111,24 @@ pub fn into_bedrock( system: Some(system_message), tools: tool_config, thinking: if request.thinking_allowed { - match mode { + match thinking_mode { BedrockModelMode::Thinking { budget_tokens } => { Some(bedrock::Thinking::Enabled { budget_tokens }) } - BedrockModelMode::AdaptiveThinking { effort } => { + BedrockModelMode::AdaptiveThinking { + effort: default_effort, + } => { + let effort = request + .thinking_effort + .as_deref() + .and_then(|e| match e { + "low" => Some(bedrock::BedrockAdaptiveThinkingEffort::Low), + "medium" => Some(bedrock::BedrockAdaptiveThinkingEffort::Medium), + "high" => Some(bedrock::BedrockAdaptiveThinkingEffort::High), + "max" => Some(bedrock::BedrockAdaptiveThinkingEffort::Max), + _ => None, + }) + .unwrap_or(default_effort); Some(bedrock::Thinking::Adaptive { effort }) } BedrockModelMode::Default => None,