use anthropic_sdk::{
Anthropic,
ModelListParams, ModelRequirements, ModelCapability, PricingTier, QualityLevel,
ModelObject, ModelComparison, CostEstimation,
};
use std::time::Duration;
use tokio::time::sleep;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("🚀 Phase 5.3: Models API Enhancement Demo");
println!("=========================================");
let _client = match Anthropic::from_env() {
Ok(client) => client,
Err(_) => {
println!("⚠️ ANTHROPIC_API_KEY not set. This is a demo of the Models API structure.");
simulate_models_api_operations().await?;
return Ok(());
}
};
println!("\n📋 Demo 1: Model Discovery and Listing");
println!("--------------------------------------");
demonstrate_model_discovery().await?;
println!("\n🔍 Demo 2: Model Information and Capabilities");
println!("---------------------------------------------");
demonstrate_model_capabilities().await?;
println!("\n🎯 Demo 3: Model Selection and Requirements");
println!("------------------------------------------");
demonstrate_model_selection().await?;
println!("\n⚖️ Demo 4: Model Comparison");
println!("-----------------------------");
demonstrate_model_comparison().await?;
println!("\n💰 Demo 5: Cost Estimation and Pricing");
println!("---------------------------------------");
demonstrate_cost_estimation().await?;
println!("\n📚 Demo 6: Usage Recommendations");
println!("--------------------------------");
demonstrate_usage_recommendations().await?;
println!("\n🎉 Phase 5.3 Models API Enhancement Demo Complete!");
println!("=================================================");
println!("✅ Model Discovery: List and filter available models");
println!("✅ Model Information: Capabilities, pricing, and metadata");
println!("✅ Model Selection: Find best models based on requirements");
println!("✅ Model Comparison: Side-by-side analysis and recommendations");
println!("✅ Cost Estimation: Accurate pricing calculations and breakdowns");
println!("✅ Usage Guidance: Recommendations and best practices by use case");
Ok(())
}
async fn simulate_models_api_operations() -> Result<(), Box<dyn std::error::Error>> {
println!("🔄 Simulating Models API operations...");
demonstrate_model_discovery().await?;
demonstrate_model_capabilities().await?;
demonstrate_model_selection().await?;
demonstrate_model_comparison().await?;
demonstrate_cost_estimation().await?;
demonstrate_usage_recommendations().await?;
println!("✅ Models API simulation complete!");
Ok(())
}
async fn demonstrate_model_discovery() -> Result<(), Box<dyn std::error::Error>> {
println!("🔍 Demonstrating model discovery and listing...");
let list_params = ModelListParams::new()
.limit(20);
println!(" 📋 List Parameters:");
println!(" - Limit: {:?}", list_params.limit);
println!(" - After ID: {:?}", list_params.after_id);
println!(" - Before ID: {:?}", list_params.before_id);
let mock_models = create_mock_model_list();
println!("\n 📊 Available Models:");
for (_i, model) in mock_models.iter().enumerate() {
let family_icon = match model.family().as_str() {
"claude-4" => "🌟",
"claude-3-7" => "🔥",
"claude-3-5" => "⚡",
"claude-3" => "💎",
_ => "🤖",
};
let size_info = model.model_size().unwrap_or("unknown".to_string());
let alias_indicator = if model.is_alias() { " (alias)" } else { "" };
println!(" {} {} - {} ({}){}",
family_icon,
model.id,
model.display_name,
size_info,
alias_indicator
);
}
println!("\n 🔍 Filtering by Model Family:");
let claude35_models = mock_models.iter()
.filter(|m| m.is_family("claude-3-5"))
.collect::<Vec<_>>();
println!(" Found {} Claude 3.5 models:", claude35_models.len());
for model in claude35_models {
println!(" ⚡ {} - {}", model.id, model.display_name);
}
println!("\n 🔗 Alias Resolution:");
for model in &mock_models {
if model.is_alias() {
println!(" 📌 {} → Resolves to specific model version", model.id);
}
}
Ok(())
}
async fn demonstrate_model_capabilities() -> Result<(), Box<dyn std::error::Error>> {
println!("🔍 Demonstrating model capabilities and information...");
let mock_models = create_mock_model_list();
for model in mock_models.iter().take(3) {
let capabilities = create_mock_capabilities(&model);
println!("\n 📋 {} Capabilities:", model.display_name);
println!(" 🧠 Max Context: {} tokens", capabilities.max_context_length);
println!(" 📝 Max Output: {} tokens", capabilities.max_output_tokens);
println!(" 👁️ Vision Support: {}", if capabilities.supports_vision { "✅" } else { "❌" });
println!(" 🛠️ Tool Support: {}", if capabilities.supports_tools { "✅" } else { "❌" });
println!(" 💬 System Messages: {}", if capabilities.supports_system_messages { "✅" } else { "❌" });
println!(" 🌊 Streaming: {}", if capabilities.supports_streaming { "✅" } else { "❌" });
println!(" 🎯 Key Capabilities:");
for capability in capabilities.capabilities.iter().take(5) {
let icon = match capability {
ModelCapability::Vision => "👁️",
ModelCapability::ToolUse => "🛠️",
ModelCapability::CodeGeneration => "💻",
ModelCapability::Creative => "🎨",
ModelCapability::Mathematical => "🔢",
ModelCapability::Analysis => "📊",
_ => "🔹",
};
println!(" {} {:?}", icon, capability);
}
println!(" 🌍 Supported Languages: {} languages", capabilities.supported_languages.len());
println!(" 📅 Family: {} (Generation {})", capabilities.family, capabilities.generation);
sleep(Duration::from_millis(500)).await;
}
Ok(())
}
async fn demonstrate_model_selection() -> Result<(), Box<dyn std::error::Error>> {
println!("🎯 Demonstrating intelligent model selection...");
let scenarios = vec![
(
"Vision + Code Generation",
ModelRequirements::new()
.require_vision()
.require_capability(ModelCapability::CodeGeneration)
.min_context_length(100000)
.max_input_cost_per_token(0.01),
),
(
"Cost-Effective Text Processing",
ModelRequirements::new()
.max_input_cost_per_token(0.003)
.max_output_cost_per_token(0.01)
.min_speed_score(8)
.capabilities(vec![ModelCapability::TextGeneration, ModelCapability::Summarization]),
),
(
"High-Quality Creative Writing",
ModelRequirements::new()
.require_capability(ModelCapability::Creative)
.min_quality_score(9)
.min_context_length(200000)
.preferred_family("claude-3".to_string()),
),
(
"Mathematical Analysis",
ModelRequirements::new()
.require_capability(ModelCapability::Mathematical)
.require_tools()
.min_quality_score(8),
),
];
for (scenario_name, requirements) in scenarios {
println!("\n 📋 Scenario: {}", scenario_name);
println!(" 🎯 Requirements:");
if let Some(max_input) = requirements.max_input_cost_per_token {
println!(" 💵 Max input cost: ${:.4}/token", max_input);
}
if let Some(max_output) = requirements.max_output_cost_per_token {
println!(" 💵 Max output cost: ${:.4}/token", max_output);
}
if let Some(min_context) = requirements.min_context_length {
println!(" 🧠 Min context: {} tokens", min_context);
}
if !requirements.required_capabilities.is_empty() {
println!(" 🎯 Required capabilities:");
for cap in &requirements.required_capabilities {
println!(" - {:?}", cap);
}
}
if let Some(vision) = requirements.requires_vision {
if vision {
println!(" 👁️ Vision required: Yes");
}
}
if let Some(tools) = requirements.requires_tools {
if tools {
println!(" 🛠️ Tools required: Yes");
}
}
if let Some(family) = &requirements.preferred_family {
println!(" 🏷️ Preferred family: {}", family);
}
let best_model = simulate_model_selection(&requirements);
println!(" 🏆 Recommended Model:");
println!(" 📋 {}", best_model.display_name);
println!(" 🆔 {}", best_model.id);
println!(" ⭐ Score: {:.1}/10", simulate_score(&requirements));
println!(" 📊 Match Reasons:");
let reasons = generate_match_reasons(&requirements, &best_model);
for reason in reasons {
println!(" ✓ {}", reason);
}
sleep(Duration::from_millis(300)).await;
}
Ok(())
}
async fn demonstrate_model_comparison() -> Result<(), Box<dyn std::error::Error>> {
println!("⚖️ Demonstrating comprehensive model comparison...");
let models_to_compare = vec![
"claude-3-5-sonnet-latest",
"claude-3-5-haiku-latest",
"claude-3-opus-latest",
];
println!("\n 📊 Comparing Models: {}", models_to_compare.join(", "));
let comparison = create_mock_comparison(&models_to_compare);
println!("\n 📋 Performance Comparison:");
println!(" ┌─────────────────────────────┬─────────┬─────────┬─────────────────┐");
println!(" │ Model │ Speed │ Quality │ Cost Efficiency │");
println!(" ├─────────────────────────────┼─────────┼─────────┼─────────────────┤");
for (model, perf) in comparison.models.iter().zip(comparison.performance.iter()) {
let name = if model.display_name.len() > 27 {
format!("{}...", &model.display_name[..24])
} else {
format!("{:<27}", model.display_name)
};
println!(" │ {} │ {:>7} │ {:>7} │ {:>15} │",
name,
format!("{}/10", perf.speed_score),
format!("{}/10", perf.quality_score),
format!("{}/10", perf.cost_efficiency_score)
);
}
println!(" └─────────────────────────────┴─────────┴─────────┴─────────────────┘");
println!("\n 💰 Pricing Comparison:");
println!(" ┌─────────────────────────────┬──────────────┬───────────────┬──────────────┐");
println!(" │ Model │ Input/1M │ Output/1M │ Tier │");
println!(" ├─────────────────────────────┼──────────────┼───────────────┼──────────────┤");
for (model, pricing) in comparison.models.iter().zip(comparison.pricing.iter()) {
let name = if model.display_name.len() > 27 {
format!("{}...", &model.display_name[..24])
} else {
format!("{:<27}", model.display_name)
};
let tier_display = match pricing.tier {
PricingTier::Premium => "Premium 🌟",
PricingTier::Standard => "Standard ⚡",
PricingTier::Fast => "Fast 🚀",
PricingTier::Legacy => "Legacy 📚",
};
println!(" │ {} │ {:>12} │ {:>13} │ {:>12} │",
name,
format!("${:.2}", pricing.input_price_per_million),
format!("${:.2}", pricing.output_price_per_million),
tier_display
);
}
println!(" └─────────────────────────────┴──────────────┴───────────────┴──────────────┘");
println!("\n 🏆 Summary Recommendations:");
println!(" 🚀 Fastest: {}", comparison.summary.fastest_model);
println!(" 🎯 Highest Quality: {}", comparison.summary.highest_quality_model);
println!(" 💰 Most Cost-Effective: {}", comparison.summary.most_cost_effective_model);
println!(" ⚖️ Best Overall: {}", comparison.summary.best_overall_model);
println!("\n 🔍 Key Differences:");
for difference in &comparison.summary.key_differences {
println!(" • {}", difference);
}
println!("\n 🎯 Use Case Recommendations:");
for (use_case, model) in &comparison.summary.use_case_recommendations {
let icon = match use_case.as_str() {
"speed" => "🚀",
"quality" => "🎯",
"cost" => "💰",
"balanced" => "⚖️",
_ => "🔹",
};
println!(" {} {}: {}", icon, use_case, model);
}
Ok(())
}
async fn demonstrate_cost_estimation() -> Result<(), Box<dyn std::error::Error>> {
println!("💰 Demonstrating cost estimation and pricing analysis...");
let usage_scenarios = vec![
("Small Chat", "claude-3-5-haiku-latest", 500, 200),
("Code Review", "claude-3-5-sonnet-latest", 2000, 1000),
("Document Analysis", "claude-3-5-sonnet-latest", 5000, 1500),
("Creative Writing", "claude-3-opus-latest", 1000, 3000),
("Batch Processing", "claude-3-5-haiku-latest", 50000, 20000),
];
for (scenario, model_id, input_tokens, output_tokens) in usage_scenarios {
println!("\n 📋 Scenario: {}", scenario);
println!(" 🤖 Model: {}", model_id);
println!(" 📥 Input tokens: {}", input_tokens);
println!(" 📤 Output tokens: {}", output_tokens);
let estimation = simulate_cost_estimation(model_id, input_tokens, output_tokens);
println!(" 💵 Cost Breakdown:");
println!(" Input cost: ${:.4}", estimation.input_cost_usd);
println!(" Output cost: ${:.4}", estimation.output_cost_usd);
if let Some(discount) = estimation.batch_discount_usd {
println!(" Batch discount: -${:.4}", discount);
}
if let Some(savings) = estimation.cache_savings_usd {
println!(" Cache savings: -${:.4}", savings);
}
println!(" ─────────────────────");
println!(" Total cost: ${:.4}", estimation.final_cost_usd);
println!(" 📊 Cost Metrics:");
println!(" Cost per 1K tokens: ${:.4}", estimation.cost_per_1k_tokens());
if estimation.savings_percentage() > 0.0 {
println!(" Savings: {:.1}%", estimation.savings_percentage());
}
println!(" 🔍 Cost Analysis:");
println!(" Per input token: ${:.8}", estimation.breakdown.cost_per_input_token_usd);
println!(" Per output token: ${:.8}", estimation.breakdown.cost_per_output_token_usd);
println!(" Effective rate: ${:.8}/token", estimation.breakdown.effective_cost_per_token_usd);
let efficiency_rating = if estimation.cost_per_1k_tokens() < 0.001 {
"🌟 Excellent"
} else if estimation.cost_per_1k_tokens() < 0.01 {
"⚡ Good"
} else if estimation.cost_per_1k_tokens() < 0.05 {
"📊 Moderate"
} else {
"💎 Premium"
};
println!(" Cost efficiency: {}", efficiency_rating);
sleep(Duration::from_millis(400)).await;
}
println!("\n 📅 Monthly Cost Projections:");
println!(" ┌─────────────────────────────┬──────────────┬──────────────┬──────────────┐");
println!(" │ Usage Level │ Light │ Moderate │ Heavy │");
println!(" ├─────────────────────────────┼──────────────┼──────────────┼──────────────┤");
println!(" │ Daily tokens (in/out) │ 10K/5K │ 50K/25K │ 200K/100K │");
println!(" │ Claude 3.5 Haiku │ ${:<10.2} │ ${:<10.2} │ ${:<10.2} │", 11.25, 56.25, 225.0);
println!(" │ Claude 3.5 Sonnet │ ${:<10.2} │ ${:<10.2} │ ${:<10.2} │", 90.0, 450.0, 1800.0);
println!(" │ Claude 3 Opus │ ${:<10.2} │ ${:<10.2} │ ${:<10.2} │", 450.0, 2250.0, 9000.0);
println!(" └─────────────────────────────┴──────────────┴──────────────┴──────────────┘");
Ok(())
}
async fn demonstrate_usage_recommendations() -> Result<(), Box<dyn std::error::Error>> {
println!("📚 Demonstrating usage recommendations and best practices...");
let use_cases = vec![
"code-generation",
"creative-writing",
"data-analysis",
"customer-support",
"content-moderation",
];
for use_case in use_cases {
let recommendations = create_mock_recommendations(use_case);
println!("\n 🎯 Use Case: {}", recommendations.use_case.replace('-', " ").to_uppercase());
println!(" 🤖 Recommended Models:");
for (i, rec) in recommendations.recommended_models.iter().enumerate() {
let rank_icon = match i {
0 => "🥇",
1 => "🥈",
2 => "🥉",
_ => "🔹",
};
println!(" {} {} (Confidence: {}/10)", rank_icon, rec.model_id, rec.confidence_score);
println!(" 💡 {}", rec.reason);
println!(" 💰 Typical cost: ${:.4}", rec.cost_range.typical_cost_usd);
if !rec.strengths.is_empty() {
println!(" ✅ Strengths:");
for strength in &rec.strengths {
println!(" • {}", strength);
}
}
if !rec.limitations.is_empty() {
println!(" ⚠️ Limitations:");
for limitation in &rec.limitations {
println!(" • {}", limitation);
}
}
}
println!(" 📋 Best Practices:");
for guideline in &recommendations.guidelines {
println!(" ✓ {}", guideline);
}
println!(" ⚙️ Recommended Parameters:");
let params = &recommendations.recommended_parameters;
println!(" 🌡️ Temperature: {:.1} - {:.1}", params.temperature_range.0, params.temperature_range.1);
println!(" 📝 Max tokens: {} - {}", params.max_tokens_range.0, params.max_tokens_range.1);
if let Some(top_p) = params.top_p_range {
println!(" 🎯 Top-p: {:.1} - {:.1}", top_p.0, top_p.1);
}
if let Some(streaming) = params.use_streaming {
println!(" 🌊 Streaming: {}", if streaming { "Recommended" } else { "Optional" });
}
let perf = &recommendations.expected_performance;
println!(" 📊 Expected Performance:");
println!(" ⏱️ Response time: {}ms - {}ms",
perf.response_time_range_ms.0, perf.response_time_range_ms.1);
println!(" 💰 Cost range: ${:.4} - ${:.4}",
perf.cost_range.min_cost_usd, perf.cost_range.max_cost_usd);
let quality_icon = match perf.quality_level {
QualityLevel::Excellent => "🌟",
QualityLevel::Good => "⚡",
QualityLevel::Acceptable => "📊",
QualityLevel::Basic => "🔹",
};
println!(" 🎯 Quality level: {} {:?}", quality_icon, perf.quality_level);
println!(" ✅ Success rate: {:.1}%", perf.success_rate_percentage);
if !recommendations.pitfalls.is_empty() {
println!(" ⚠️ Common Pitfalls to Avoid:");
for pitfall in &recommendations.pitfalls {
println!(" ❌ {}", pitfall);
}
}
sleep(Duration::from_millis(600)).await;
}
Ok(())
}
fn create_mock_model_list() -> Vec<ModelObject> {
use chrono::Utc;
vec![
ModelObject {
id: "claude-4-opus-latest".to_string(),
display_name: "Claude 4 Opus".to_string(),
created_at: Utc::now(),
object_type: "model".to_string(),
},
ModelObject {
id: "claude-4-sonnet-latest".to_string(),
display_name: "Claude 4 Sonnet".to_string(),
created_at: Utc::now(),
object_type: "model".to_string(),
},
ModelObject {
id: "claude-3-7-sonnet-latest".to_string(),
display_name: "Claude 3.7 Sonnet".to_string(),
created_at: Utc::now(),
object_type: "model".to_string(),
},
ModelObject {
id: "claude-3-5-sonnet-latest".to_string(),
display_name: "Claude 3.5 Sonnet".to_string(),
created_at: Utc::now(),
object_type: "model".to_string(),
},
ModelObject {
id: "claude-3-5-haiku-latest".to_string(),
display_name: "Claude 3.5 Haiku".to_string(),
created_at: Utc::now(),
object_type: "model".to_string(),
},
ModelObject {
id: "claude-3-opus-latest".to_string(),
display_name: "Claude 3 Opus".to_string(),
created_at: Utc::now(),
object_type: "model".to_string(),
},
ModelObject {
id: "claude-3-sonnet-20240229".to_string(),
display_name: "Claude 3 Sonnet".to_string(),
created_at: Utc::now(),
object_type: "model".to_string(),
},
ModelObject {
id: "claude-3-haiku-20240307".to_string(),
display_name: "Claude 3 Haiku".to_string(),
created_at: Utc::now(),
object_type: "model".to_string(),
},
]
}
fn create_mock_capabilities(model: &ModelObject) -> anthropic_sdk::ModelCapabilities {
use anthropic_sdk::ModelCapabilities;
use chrono::Utc;
let (max_context, max_output, supports_vision, supports_tools) =
if model.id.contains("claude-4") {
(500_000, 8_192, true, true)
} else if model.id.contains("claude-3-7") {
(200_000, 8_192, true, true)
} else if model.id.contains("claude-3-5") {
(200_000, 8_192, model.id.contains("sonnet"), true)
} else {
(200_000, 4_096, true, true)
};
let capabilities = if supports_vision && supports_tools {
vec![
ModelCapability::TextGeneration,
ModelCapability::Vision,
ModelCapability::ToolUse,
ModelCapability::CodeGeneration,
ModelCapability::Mathematical,
ModelCapability::Creative,
ModelCapability::Analysis,
ModelCapability::Summarization,
ModelCapability::Translation,
ModelCapability::LongContext,
]
} else {
vec![
ModelCapability::TextGeneration,
ModelCapability::CodeGeneration,
ModelCapability::Creative,
ModelCapability::Analysis,
ModelCapability::Summarization,
]
};
ModelCapabilities {
max_context_length: max_context,
max_output_tokens: max_output,
capabilities,
family: model.family(),
generation: if model.id.contains("claude-4") {
"4".to_string()
} else if model.id.contains("claude-3-7") {
"3.7".to_string()
} else if model.id.contains("claude-3-5") {
"3.5".to_string()
} else {
"3".to_string()
},
supports_vision,
supports_tools,
supports_system_messages: true,
supports_streaming: true,
supported_languages: vec![
"en".to_string(), "es".to_string(), "fr".to_string(), "de".to_string(),
"it".to_string(), "pt".to_string(), "ru".to_string(), "ja".to_string(),
],
training_cutoff: Some(Utc::now()),
}
}
fn simulate_model_selection(requirements: &ModelRequirements) -> ModelObject {
use chrono::Utc;
let model_id = if requirements.requires_vision == Some(true) &&
requirements.required_capabilities.contains(&ModelCapability::CodeGeneration) {
"claude-3-5-sonnet-latest"
} else if requirements.max_input_cost_per_token.unwrap_or(1.0) < 0.005 {
"claude-3-5-haiku-latest"
} else if requirements.min_quality_score.unwrap_or(0) >= 9 {
"claude-3-opus-latest"
} else if requirements.required_capabilities.contains(&ModelCapability::Mathematical) {
"claude-3-5-sonnet-latest"
} else {
"claude-3-5-sonnet-latest"
};
let display_name = match model_id {
"claude-3-5-sonnet-latest" => "Claude 3.5 Sonnet",
"claude-3-5-haiku-latest" => "Claude 3.5 Haiku",
"claude-3-opus-latest" => "Claude 3 Opus",
_ => "Claude 3.5 Sonnet",
};
ModelObject {
id: model_id.to_string(),
display_name: display_name.to_string(),
created_at: Utc::now(),
object_type: "model".to_string(),
}
}
fn simulate_score(requirements: &ModelRequirements) -> f64 {
let mut score: f64 = 7.5;
if requirements.requires_vision == Some(true) {
score += 0.8;
}
if requirements.requires_tools == Some(true) {
score += 0.7;
}
if !requirements.required_capabilities.is_empty() {
score += 0.5;
}
if requirements.max_input_cost_per_token.is_some() {
score += 0.6;
}
score.min(9.8)
}
fn generate_match_reasons(requirements: &ModelRequirements, model: &ModelObject) -> Vec<String> {
let mut reasons = Vec::new();
if requirements.requires_vision == Some(true) {
reasons.push("Supports advanced vision capabilities".to_string());
}
if requirements.requires_tools == Some(true) {
reasons.push("Excellent tool use and function calling".to_string());
}
if requirements.required_capabilities.contains(&ModelCapability::CodeGeneration) {
reasons.push("Strong code generation and analysis".to_string());
}
if requirements.required_capabilities.contains(&ModelCapability::Mathematical) {
reasons.push("Advanced mathematical reasoning".to_string());
}
if model.id.contains("sonnet") {
reasons.push("Balanced performance and cost efficiency".to_string());
} else if model.id.contains("haiku") {
reasons.push("Optimized for speed and cost-effectiveness".to_string());
} else if model.id.contains("opus") {
reasons.push("Premium quality for demanding tasks".to_string());
}
if requirements.min_context_length.unwrap_or(0) > 100000 {
reasons.push("Large context window for complex tasks".to_string());
}
if reasons.is_empty() {
reasons.push("General-purpose model suitable for most tasks".to_string());
}
reasons
}
fn create_mock_comparison(model_ids: &[&str]) -> ModelComparison {
use anthropic_sdk::{ModelComparison, ModelPerformance, ModelPricing, PricingTier, ComparisonSummary};
use chrono::Utc;
use std::collections::HashMap;
let models = model_ids.iter().map(|&id| {
let display_name = match id {
"claude-3-5-sonnet-latest" => "Claude 3.5 Sonnet",
"claude-3-5-haiku-latest" => "Claude 3.5 Haiku",
"claude-3-opus-latest" => "Claude 3 Opus",
_ => "Claude Model",
};
ModelObject {
id: id.to_string(),
display_name: display_name.to_string(),
created_at: Utc::now(),
object_type: "model".to_string(),
}
}).collect();
let capabilities = model_ids.iter().map(|&id| create_mock_capabilities(&ModelObject {
id: id.to_string(),
display_name: "Test".to_string(),
created_at: Utc::now(),
object_type: "model".to_string(),
})).collect();
let pricing = model_ids.iter().map(|&id| {
let (input_price, output_price, tier) = match id {
"claude-3-5-sonnet-latest" => (3.0, 15.0, PricingTier::Standard),
"claude-3-5-haiku-latest" => (0.25, 1.25, PricingTier::Fast),
"claude-3-opus-latest" => (15.0, 75.0, PricingTier::Premium),
_ => (3.0, 15.0, PricingTier::Standard),
};
ModelPricing {
model_id: id.to_string(),
input_price_per_million: input_price,
output_price_per_million: output_price,
batch_input_price_per_million: Some(input_price * 0.5),
batch_output_price_per_million: Some(output_price * 0.5),
cache_write_price_per_million: Some(input_price * 1.25),
cache_read_price_per_million: Some(input_price * 0.1),
tier,
currency: "USD".to_string(),
updated_at: Utc::now(),
}
}).collect();
let performance = model_ids.iter().map(|&id| {
let (speed, quality, cost_eff) = match id {
"claude-3-5-sonnet-latest" => (8, 9, 8),
"claude-3-5-haiku-latest" => (10, 7, 10),
"claude-3-opus-latest" => (6, 10, 5),
_ => (7, 8, 7),
};
ModelPerformance {
model_id: id.to_string(),
speed_score: speed,
quality_score: quality,
avg_response_time_ms: Some(match speed {
10 => 500,
8 => 1000,
6 => 2000,
_ => 1500,
}),
tokens_per_second: Some(match speed {
10 => 100.0,
8 => 60.0,
6 => 25.0,
_ => 50.0,
}),
cost_efficiency_score: cost_eff,
}
}).collect();
let mut use_case_recommendations = HashMap::new();
use_case_recommendations.insert("speed".to_string(), "claude-3-5-haiku-latest".to_string());
use_case_recommendations.insert("quality".to_string(), "claude-3-opus-latest".to_string());
use_case_recommendations.insert("cost".to_string(), "claude-3-5-haiku-latest".to_string());
use_case_recommendations.insert("balanced".to_string(), "claude-3-5-sonnet-latest".to_string());
let summary = ComparisonSummary {
fastest_model: "claude-3-5-haiku-latest".to_string(),
highest_quality_model: "claude-3-opus-latest".to_string(),
most_cost_effective_model: "claude-3-5-haiku-latest".to_string(),
best_overall_model: "claude-3-5-sonnet-latest".to_string(),
key_differences: vec![
"Haiku optimized for speed and cost efficiency".to_string(),
"Opus provides highest quality output".to_string(),
"Sonnet offers best balance of capabilities".to_string(),
],
use_case_recommendations,
};
ModelComparison {
models,
capabilities,
pricing,
performance,
summary,
}
}
fn simulate_cost_estimation(model_id: &str, input_tokens: u64, output_tokens: u64) -> CostEstimation {
use anthropic_sdk::{CostEstimation, CostBreakdown};
use std::collections::HashMap;
let (input_price_per_million, output_price_per_million) = match model_id {
"claude-3-5-haiku-latest" => (0.25, 1.25),
"claude-3-5-sonnet-latest" => (3.0, 15.0),
"claude-3-opus-latest" => (15.0, 75.0),
_ => (3.0, 15.0),
};
let input_cost_usd = (input_tokens as f64 / 1_000_000.0) * input_price_per_million;
let output_cost_usd = (output_tokens as f64 / 1_000_000.0) * output_price_per_million;
let total_cost_usd = input_cost_usd + output_cost_usd;
let batch_discount_usd = if input_tokens + output_tokens > 50_000 {
Some(total_cost_usd * 0.1)
} else {
None
};
let final_cost_usd = total_cost_usd - batch_discount_usd.unwrap_or(0.0);
let breakdown = CostBreakdown {
cost_per_input_token_usd: input_price_per_million / 1_000_000.0,
cost_per_output_token_usd: output_price_per_million / 1_000_000.0,
effective_cost_per_token_usd: final_cost_usd / (input_tokens + output_tokens) as f64,
cost_vs_alternatives: HashMap::new(),
};
CostEstimation {
model_id: model_id.to_string(),
input_tokens,
output_tokens,
input_cost_usd,
output_cost_usd,
total_cost_usd,
batch_discount_usd,
cache_savings_usd: None,
final_cost_usd,
breakdown,
}
}
fn create_mock_recommendations(use_case: &str) -> anthropic_sdk::ModelUsageRecommendations {
use anthropic_sdk::{
ModelUsageRecommendations, ModelRecommendation, RecommendedParameters,
PerformanceExpectations, CostRange, QualityLevel,
};
match use_case {
"code-generation" => ModelUsageRecommendations {
use_case: "Code Generation".to_string(),
recommended_models: vec![
ModelRecommendation {
model_id: "claude-3-5-sonnet-latest".to_string(),
reason: "Excellent code understanding and generation".to_string(),
confidence_score: 9,
cost_range: CostRange {
min_cost_usd: 0.003,
max_cost_usd: 0.015,
typical_cost_usd: 0.008,
},
strengths: vec![
"Strong programming language support".to_string(),
"Good debugging assistance".to_string(),
],
limitations: vec![
"May generate verbose explanations".to_string(),
],
},
],
guidelines: vec![
"Provide clear specifications".to_string(),
"Request code comments".to_string(),
],
recommended_parameters: RecommendedParameters {
temperature_range: (0.0, 0.3),
max_tokens_range: (1024, 4096),
top_p_range: Some((0.1, 0.5)),
use_streaming: Some(true),
system_message_patterns: vec![
"You are an expert programmer.".to_string(),
],
},
pitfalls: vec![
"Using inappropriate temperature settings".to_string(),
],
expected_performance: PerformanceExpectations {
response_time_range_ms: (1000, 5000),
cost_range: CostRange {
min_cost_usd: 0.003,
max_cost_usd: 0.015,
typical_cost_usd: 0.008,
},
quality_level: QualityLevel::Excellent,
success_rate_percentage: 90.0,
},
},
_ => ModelUsageRecommendations {
use_case: use_case.replace('-', " ").to_uppercase(),
recommended_models: vec![
ModelRecommendation {
model_id: "claude-3-5-sonnet-latest".to_string(),
reason: "Well-balanced model for general use".to_string(),
confidence_score: 8,
cost_range: CostRange {
min_cost_usd: 0.003,
max_cost_usd: 0.015,
typical_cost_usd: 0.008,
},
strengths: vec![
"Versatile capabilities".to_string(),
"Good performance".to_string(),
],
limitations: vec![
"May not be specialized".to_string(),
],
},
],
guidelines: vec![
"Start with moderate settings".to_string(),
"Adjust based on results".to_string(),
],
recommended_parameters: RecommendedParameters {
temperature_range: (0.3, 0.7),
max_tokens_range: (1024, 4096),
top_p_range: Some((0.5, 0.9)),
use_streaming: Some(false),
system_message_patterns: vec![
"You are a helpful assistant.".to_string(),
],
},
pitfalls: vec![
"Not providing enough context".to_string(),
],
expected_performance: PerformanceExpectations {
response_time_range_ms: (1000, 4000),
cost_range: CostRange {
min_cost_usd: 0.003,
max_cost_usd: 0.015,
typical_cost_usd: 0.008,
},
quality_level: QualityLevel::Good,
success_rate_percentage: 85.0,
},
},
}
}