From 3c021d089041d5de0e38d18de514c2a4b304fd22 Mon Sep 17 00:00:00 2001 From: Umesh Yadav <23421535+imumesh18@users.noreply.github.com> Date: Thu, 4 Sep 2025 09:32:13 +0530 Subject: [PATCH] language_models: Fix beta_headers for Anthropic custom models (#37306) Closes #37289 The current implementation has a problem. The **`from_id` method** in the Anthropic crate works well for predefined models, but not for custom models that are defined in the settings. This is because it fallbacks to using default beta headers, which are incorrect for custom models. The issue is that the model instance for custom models lives within the `language_models` provider, so I've updated the **`stream_completion`** method to explicitly accept beta headers from its caller. Now, the beta headers are passed from the `language_models` provider all the way to `anthropic.stream_completion`, which resolves the issue. Release Notes: - Fixed a bug where extra_beta_headers defined in settings for Anthropic custom models were being ignored. --------- Signed-off-by: Umesh Yadav --- crates/anthropic/src/anthropic.rs | 12 +++++------- crates/language_models/src/provider/anthropic.rs | 11 +++++++++-- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/crates/anthropic/src/anthropic.rs b/crates/anthropic/src/anthropic.rs index 773bb557de1895e57bdeb5612e01e2839af3244b..7fd0fb4bc5abd983c57507522c2a37dffcbfa258 100644 --- a/crates/anthropic/src/anthropic.rs +++ b/crates/anthropic/src/anthropic.rs @@ -363,11 +363,9 @@ pub async fn complete( api_url: &str, api_key: &str, request: Request, + beta_headers: String, ) -> Result { let uri = format!("{api_url}/v1/messages"); - let beta_headers = Model::from_id(&request.model) - .map(|model| model.beta_headers()) - .unwrap_or_else(|_| Model::DEFAULT_BETA_HEADERS.join(",")); let request_builder = HttpRequest::builder() .method(Method::POST) .uri(uri) @@ -409,8 +407,9 @@ pub async fn stream_completion( api_url: &str, api_key: &str, request: Request, + beta_headers: String, ) -> Result>, AnthropicError> { - stream_completion_with_rate_limit_info(client, api_url, api_key, request) + stream_completion_with_rate_limit_info(client, api_url, api_key, request, beta_headers) .await .map(|output| output.0) } @@ -506,6 +505,7 @@ pub async fn stream_completion_with_rate_limit_info( api_url: &str, api_key: &str, request: Request, + beta_headers: String, ) -> Result< ( BoxStream<'static, Result>, @@ -518,9 +518,7 @@ pub async fn stream_completion_with_rate_limit_info( stream: true, }; let uri = format!("{api_url}/v1/messages"); - let beta_headers = Model::from_id(&request.base.model) - .map(|model| model.beta_headers()) - .unwrap_or_else(|_| Model::DEFAULT_BETA_HEADERS.join(",")); + let request_builder = HttpRequest::builder() .method(Method::POST) .uri(uri) diff --git a/crates/language_models/src/provider/anthropic.rs b/crates/language_models/src/provider/anthropic.rs index 6c003c4c3919a9f553024c6b1b56d03d410d984b..d246976cda4eb46a46c857f1e94757697ddf5f65 100644 --- a/crates/language_models/src/provider/anthropic.rs +++ b/crates/language_models/src/provider/anthropic.rs @@ -424,14 +424,21 @@ impl AnthropicModel { return futures::future::ready(Err(anyhow!("App state dropped").into())).boxed(); }; + let beta_headers = self.model.beta_headers(); + async move { let Some(api_key) = api_key else { return Err(LanguageModelCompletionError::NoApiKey { provider: PROVIDER_NAME, }); }; - let request = - anthropic::stream_completion(http_client.as_ref(), &api_url, &api_key, request); + let request = anthropic::stream_completion( + http_client.as_ref(), + &api_url, + &api_key, + request, + beta_headers, + ); request.await.map_err(Into::into) } .boxed()