Claude 3.7 is out. we had some harcoded stuff (#6197)

Co-authored-by: Douwe Osinga <douwe@squareup.com>
This commit is contained in:
Douwe Osinga
2026-01-06 15:50:39 -05:00
committed by GitHub
parent 635131d7bf
commit 463eee3f76
6 changed files with 24 additions and 98 deletions
-4
View File
@@ -37,10 +37,6 @@ const ANTHROPIC_KNOWN_MODELS: &[&str] = &[
"claude-sonnet-4-20250514",
"claude-opus-4-0",
"claude-opus-4-20250514",
// Legacy Claude 3.x models
"claude-3-7-sonnet-latest",
"claude-3-7-sonnet-20250219",
"claude-3-opus-latest",
];
const ANTHROPIC_DOC_URL: &str = "https://docs.anthropic.com/en/docs/about-claude/models";
@@ -333,55 +333,23 @@ mod tests {
Some("anthropic/claude-3.5-sonnet".to_string())
);
// === Claude word-order swapping (3.x series) ===
// 3.x: {model}-{version} → {version}-{model}
assert_eq!(
map_to_canonical_model("databricks", "claude-haiku-3-5", r),
Some("anthropic/claude-3.5-haiku".to_string())
);
assert_eq!(
map_to_canonical_model("databricks", "claude-sonnet-3-7", r),
Some("anthropic/claude-3.7-sonnet".to_string())
);
assert_eq!(
map_to_canonical_model("databricks", "ng-tools-claude-haiku-3-5", r),
Some("anthropic/claude-3.5-haiku".to_string())
);
// === Claude word-order swapping (4.x series) ===
assert_eq!(
map_to_canonical_model("databricks", "claude-4-opus", r),
Some("anthropic/claude-opus-4".to_string())
);
// 4.x: {version}-{model} → {model}-{version}
assert_eq!(
map_to_canonical_model("databricks", "claude-4-sonnet", r),
Some("anthropic/claude-sonnet-4".to_string())
);
// 4.x with minor version + prefix stripping
assert_eq!(
map_to_canonical_model("databricks", "raml-claude-opus-4-5", r),
Some("anthropic/claude-opus-4.5".to_string())
);
assert_eq!(
map_to_canonical_model("databricks", "databricks-claude-sonnet-4-5", r),
Some("anthropic/claude-sonnet-4.5".to_string())
);
// === Claude with custom prefixes ===
assert_eq!(
map_to_canonical_model("databricks", "goose-claude-4-opus", r),
Some("anthropic/claude-opus-4".to_string())
);
assert_eq!(
map_to_canonical_model("databricks", "kgoose-claude-4-sonnet", r),
Some("anthropic/claude-sonnet-4".to_string())
);
assert_eq!(
map_to_canonical_model("databricks", "headless-goose-claude-4-sonnet", r),
Some("anthropic/claude-sonnet-4".to_string())
);
assert_eq!(
map_to_canonical_model("databricks", "kgoose-cashapp-claude-4-sonnet", r),
Some("anthropic/claude-sonnet-4".to_string())
);
// === Claude with platform suffixes ===
assert_eq!(
+17 -51
View File
@@ -394,9 +394,18 @@ pub fn create_request(
return Err(anyhow!("No valid messages to send to Anthropic API"));
}
// https://docs.anthropic.com/en/docs/about-claude/models/all-models#model-comparison-table
// Claude 3.7 supports max output tokens up to 8192
let max_tokens = model_config.max_tokens.unwrap_or(8192);
// https://platform.claude.com/docs/en/about-claude/models/overview
// 64k output tokens works for most claude models, but not old opus:
let max_tokens = model_config.max_tokens.unwrap_or_else(|| {
let name = &model_config.model_name;
if name.contains("claude-3-haiku") {
4096
} else if name.contains("claude-opus-4-0") || name.contains("claude-opus-4-1") {
32000
} else {
64000
}
});
let mut payload = json!({
"model": model_config.model_name,
"messages": anthropic_messages,
@@ -421,18 +430,15 @@ pub fn create_request(
// Add temperature if specified and not using extended thinking model
if let Some(temp) = model_config.temperature {
// Claude 3.7 models with thinking enabled don't support temperature
if !model_config.model_name.starts_with("claude-3-7-sonnet-") {
payload
.as_object_mut()
.unwrap()
.insert("temperature".to_string(), json!(temp));
}
payload
.as_object_mut()
.unwrap()
.insert("temperature".to_string(), json!(temp));
}
// Add thinking parameters for claude-3-7-sonnet model
let is_thinking_enabled = std::env::var("CLAUDE_THINKING_ENABLED").is_ok();
if model_config.model_name.starts_with("claude-3-7-sonnet-") && is_thinking_enabled {
if is_thinking_enabled {
// Minimum budget_tokens is 1024
let budget_tokens = std::env::var("CLAUDE_THINKING_BUDGET")
.unwrap_or_else(|_| "16000".to_string())
@@ -452,7 +458,6 @@ pub fn create_request(
}),
);
}
Ok(payload)
}
@@ -931,45 +936,6 @@ mod tests {
assert!(spec_array[0].get("cache_control").is_some());
}
#[test]
fn test_create_request_with_thinking() -> Result<()> {
let original_value = std::env::var("CLAUDE_THINKING_ENABLED").ok();
std::env::set_var("CLAUDE_THINKING_ENABLED", "true");
let result = (|| {
let model_config = ModelConfig::new_or_fail("claude-3-7-sonnet-20250219");
let system = "You are a helpful assistant.";
let messages = vec![Message::user().with_text("Hello")];
let tools = vec![];
let payload = create_request(&model_config, system, &messages, &tools)?;
// Verify basic structure
assert_eq!(payload["model"], "claude-3-7-sonnet-20250219");
assert_eq!(payload["messages"][0]["role"], "user");
assert_eq!(payload["messages"][0]["content"][0]["text"], "Hello");
// Verify thinking parameters
assert!(payload.get("thinking").is_some());
assert_eq!(payload["thinking"]["type"], "enabled");
assert!(payload["thinking"]["budget_tokens"].as_i64().unwrap() >= 1024);
// Temperature should not be present for 3.7 models with thinking
assert!(payload.get("temperature").is_none());
Ok(())
})();
// Restore the original env var state
match original_value {
Some(val) => std::env::set_var("CLAUDE_THINKING_ENABLED", val),
None => std::env::remove_var("CLAUDE_THINKING_ENABLED"),
}
// Return the test result
result
}
#[test]
fn test_cache_pricing_calculation() -> Result<()> {
// Test realistic cache scenario: small fresh input, large cached content
@@ -583,7 +583,6 @@ pub fn create_request(
.insert("tools".to_string(), json!(tools_spec));
}
// Add thinking parameters for Claude 3.7 Sonnet model when requested
let is_thinking_enabled = std::env::var("CLAUDE_THINKING_ENABLED").is_ok();
if is_claude_sonnet && is_thinking_enabled {
// Minimum budget_tokens is 1024
@@ -608,7 +607,6 @@ pub fn create_request(
}),
);
// Temperature is fixed to 2 when using claude 3.7 thinking with Databricks
payload
.as_object_mut()
.unwrap()
+1 -3
View File
@@ -462,9 +462,7 @@ impl Provider for GcpVertexAIProvider {
"gcp_vertex_ai",
"GCP Vertex AI",
"Access variety of AI models such as Claude, Gemini through Vertex AI",
GcpVertexAIModel::Gemini(GeminiVersion::Flash25)
.to_string()
.as_str(),
"gemini-2.5-flash",
known_models,
GCP_VERTEX_AI_DOC_URL,
vec![
+2 -2
View File
@@ -17,16 +17,16 @@ use crate::providers::formats::openai::{create_request, get_usage, response_to_m
use rmcp::model::Tool;
pub const OPENROUTER_DEFAULT_MODEL: &str = "anthropic/claude-sonnet-4";
pub const OPENROUTER_DEFAULT_FAST_MODEL: &str = "google/gemini-flash-2.5";
pub const OPENROUTER_DEFAULT_FAST_MODEL: &str = "google/gemini-2.5-flash";
pub const OPENROUTER_MODEL_PREFIX_ANTHROPIC: &str = "anthropic";
// OpenRouter can run many models, we suggest the default
pub const OPENROUTER_KNOWN_MODELS: &[&str] = &[
"x-ai/grok-code-fast-1",
"anthropic/claude-sonnet-4.5",
"anthropic/claude-sonnet-4",
"anthropic/claude-opus-4.1",
"anthropic/claude-opus-4",
"anthropic/claude-3.7-sonnet",
"google/gemini-2.5-pro",
"google/gemini-2.5-flash",
"deepseek/deepseek-r1-0528",