added optional request params and context limit from GOOSE_PREDEFINED_MODELS (#6489)
This commit is contained in:
@@ -444,6 +444,7 @@ mod tests {
|
||||
toolshim: false,
|
||||
toolshim_model: None,
|
||||
fast_model: None,
|
||||
request_params: None,
|
||||
},
|
||||
max_tool_responses: None,
|
||||
}
|
||||
|
||||
@@ -1,10 +1,39 @@
|
||||
use once_cell::sync::Lazy;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
use std::collections::HashMap;
|
||||
use thiserror::Error;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
const DEFAULT_CONTEXT_LIMIT: usize = 128_000;
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
struct PredefinedModel {
|
||||
name: String,
|
||||
#[serde(default)]
|
||||
context_limit: Option<usize>,
|
||||
#[serde(default)]
|
||||
request_params: Option<HashMap<String, Value>>,
|
||||
}
|
||||
|
||||
fn get_predefined_models() -> Vec<PredefinedModel> {
|
||||
static PREDEFINED_MODELS: Lazy<Vec<PredefinedModel>> =
|
||||
Lazy::new(|| match std::env::var("GOOSE_PREDEFINED_MODELS") {
|
||||
Ok(json_str) => serde_json::from_str(&json_str).unwrap_or_else(|e| {
|
||||
tracing::warn!("Failed to parse GOOSE_PREDEFINED_MODELS: {}", e);
|
||||
Vec::new()
|
||||
}),
|
||||
Err(_) => Vec::new(),
|
||||
});
|
||||
PREDEFINED_MODELS.clone()
|
||||
}
|
||||
|
||||
fn find_predefined_model(model_name: &str) -> Option<PredefinedModel> {
|
||||
get_predefined_models()
|
||||
.into_iter()
|
||||
.find(|m| m.name == model_name)
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum ConfigError {
|
||||
#[error("Environment variable '{0}' not found")]
|
||||
@@ -80,6 +109,9 @@ pub struct ModelConfig {
|
||||
pub toolshim: bool,
|
||||
pub toolshim_model: Option<String>,
|
||||
pub fast_model: Option<String>,
|
||||
/// Provider-specific request parameters (e.g., anthropic_beta headers)
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub request_params: Option<HashMap<String, Value>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
@@ -97,7 +129,26 @@ impl ModelConfig {
|
||||
model_name: String,
|
||||
context_env_var: Option<&str>,
|
||||
) -> Result<Self, ConfigError> {
|
||||
let context_limit = Self::parse_context_limit(&model_name, None, context_env_var)?;
|
||||
let predefined = find_predefined_model(&model_name);
|
||||
|
||||
let context_limit = if let Some(ref pm) = predefined {
|
||||
if let Some(env_var) = context_env_var {
|
||||
if let Ok(val) = std::env::var(env_var) {
|
||||
Some(Self::validate_context_limit(&val, env_var)?)
|
||||
} else {
|
||||
pm.context_limit
|
||||
}
|
||||
} else if let Ok(val) = std::env::var("GOOSE_CONTEXT_LIMIT") {
|
||||
Some(Self::validate_context_limit(&val, "GOOSE_CONTEXT_LIMIT")?)
|
||||
} else {
|
||||
pm.context_limit
|
||||
}
|
||||
} else {
|
||||
Self::parse_context_limit(&model_name, None, context_env_var)?
|
||||
};
|
||||
|
||||
let request_params = predefined.and_then(|pm| pm.request_params);
|
||||
|
||||
let temperature = Self::parse_temperature()?;
|
||||
let max_tokens = Self::parse_max_tokens()?;
|
||||
let toolshim = Self::parse_toolshim()?;
|
||||
@@ -111,6 +162,7 @@ impl ModelConfig {
|
||||
toolshim,
|
||||
toolshim_model,
|
||||
fast_model: None,
|
||||
request_params,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -285,6 +337,11 @@ impl ModelConfig {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_request_params(mut self, params: Option<HashMap<String, Value>>) -> Self {
|
||||
self.request_params = params;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn use_fast_model(&self) -> Self {
|
||||
if let Some(fast_model) = &self.fast_model {
|
||||
let mut config = self.clone();
|
||||
|
||||
@@ -642,6 +642,15 @@ pub fn create_request(
|
||||
apply_cache_control_for_claude(&mut payload);
|
||||
}
|
||||
|
||||
// Add request_params to the payload (e.g., anthropic_beta for extended context)
|
||||
if let Some(params) = &model_config.request_params {
|
||||
if let Some(obj) = payload.as_object_mut() {
|
||||
for (key, value) in params {
|
||||
obj.insert(key.clone(), value.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(payload)
|
||||
}
|
||||
|
||||
@@ -1013,6 +1022,7 @@ mod tests {
|
||||
toolshim: false,
|
||||
toolshim_model: None,
|
||||
fast_model: None,
|
||||
request_params: None,
|
||||
};
|
||||
let request = create_request(&model_config, "system", &[], &[], &ImageFormat::OpenAi)?;
|
||||
let obj = request.as_object().unwrap();
|
||||
@@ -1044,6 +1054,7 @@ mod tests {
|
||||
toolshim: false,
|
||||
toolshim_model: None,
|
||||
fast_model: None,
|
||||
request_params: None,
|
||||
};
|
||||
let request = create_request(&model_config, "system", &[], &[], &ImageFormat::OpenAi)?;
|
||||
assert_eq!(request["reasoning_effort"], "high");
|
||||
@@ -1360,6 +1371,7 @@ mod tests {
|
||||
toolshim: false,
|
||||
toolshim_model: None,
|
||||
fast_model: None,
|
||||
request_params: None,
|
||||
};
|
||||
|
||||
let messages = vec![
|
||||
@@ -1411,6 +1423,7 @@ mod tests {
|
||||
toolshim: false,
|
||||
toolshim_model: None,
|
||||
fast_model: None,
|
||||
request_params: None,
|
||||
};
|
||||
|
||||
let messages = vec![Message::user().with_text("Hello")];
|
||||
|
||||
@@ -1295,6 +1295,7 @@ mod tests {
|
||||
toolshim: false,
|
||||
toolshim_model: None,
|
||||
fast_model: None,
|
||||
request_params: None,
|
||||
};
|
||||
let request = create_request(
|
||||
&model_config,
|
||||
@@ -1334,6 +1335,7 @@ mod tests {
|
||||
toolshim: false,
|
||||
toolshim_model: None,
|
||||
fast_model: None,
|
||||
request_params: None,
|
||||
};
|
||||
let request = create_request(
|
||||
&model_config,
|
||||
@@ -1374,6 +1376,7 @@ mod tests {
|
||||
toolshim: false,
|
||||
toolshim_model: None,
|
||||
fast_model: None,
|
||||
request_params: None,
|
||||
};
|
||||
let request = create_request(
|
||||
&model_config,
|
||||
|
||||
Reference in New Issue
Block a user