use siumai::models;
use siumai::prelude::*;
use siumai::traits::EmbeddingCapability;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("๐ Unified Embedding Interface Demo");
println!("===================================\n");
let texts = vec![
"Hello, world!".to_string(),
"Rust is a systems programming language.".to_string(),
"Machine learning and AI are transforming technology.".to_string(),
];
if let Ok(api_key) = std::env::var("OPENAI_API_KEY") {
println!("1๏ธโฃ OpenAI Embeddings via Unified Interface");
println!("-------------------------------------------");
match demonstrate_openai_embeddings(&api_key, &texts).await {
Ok(_) => println!("โ
OpenAI embeddings completed successfully\n"),
Err(e) => println!("โ OpenAI embeddings failed: {e}\n"),
}
} else {
println!("โญ๏ธ Skipping OpenAI (OPENAI_API_KEY not set)\n");
}
println!("2๏ธโฃ Ollama Embeddings via Unified Interface");
println!("------------------------------------------");
match demonstrate_ollama_embeddings(&texts).await {
Ok(_) => println!("โ
Ollama embeddings completed successfully\n"),
Err(e) => println!("โ Ollama embeddings failed: {e}\n"),
}
println!("3๏ธโฃ Capability Detection and Error Handling");
println!("-------------------------------------------");
demonstrate_capability_detection().await?;
if let Ok(api_key) = std::env::var("OPENAI_API_KEY") {
println!("4๏ธโฃ Provider-Specific vs Unified Interface");
println!("------------------------------------------");
demonstrate_interface_comparison(&api_key, &texts).await?;
}
println!("๐ All embedding demos completed!");
Ok(())
}
async fn demonstrate_openai_embeddings(
api_key: &str,
texts: &[String],
) -> Result<(), Box<dyn std::error::Error>> {
let client = Siumai::builder()
.openai()
.api_key(api_key)
.model(models::openai::TEXT_EMBEDDING_3_SMALL) .build()
.await?;
println!(" ๐ Direct embedding call:");
let response = client.embed(texts.to_vec()).await?;
println!(" Got {} embeddings", response.embeddings.len());
println!(
" Embedding dimension: {}",
response.embeddings[0].len()
);
println!(" Model used: {}", response.model);
if let Some(usage) = &response.usage {
println!(" Tokens used: {}", usage.total_tokens);
}
println!(" ๐ง Through capability proxy:");
let embedding_proxy = client.embedding_capability();
if embedding_proxy.is_reported_as_supported() {
println!(" โ
Embedding capability is supported");
println!(
" Max tokens per request: {}",
embedding_proxy.max_tokens_per_embedding()
);
println!(
" Supported models: {:?}",
embedding_proxy.supported_embedding_models()
);
let response2 = embedding_proxy.embed(vec![texts[0].clone()]).await?;
println!(
" Single embedding dimension: {}",
response2.embeddings[0].len()
);
} else {
println!(" โ Embedding capability not reported as supported");
}
Ok(())
}
async fn demonstrate_ollama_embeddings(texts: &[String]) -> Result<(), Box<dyn std::error::Error>> {
let base_url =
std::env::var("OLLAMA_BASE_URL").unwrap_or_else(|_| "http://localhost:11434".to_string());
let client = Siumai::builder()
.ollama()
.base_url(&base_url)
.model("nomic-embed-text") .build()
.await?;
println!(" ๐ Ollama embedding call:");
let response = client.embed(texts.to_vec()).await?;
println!(" Got {} embeddings", response.embeddings.len());
println!(
" Embedding dimension: {}",
response.embeddings[0].len()
);
println!(" Model used: {}", response.model);
let embedding_proxy = client.embedding_capability();
println!(
" Capability supported: {}",
embedding_proxy.is_reported_as_supported()
);
println!(
" Default dimension: {}",
embedding_proxy.embedding_dimension()
);
Ok(())
}
async fn demonstrate_capability_detection() -> Result<(), Box<dyn std::error::Error>> {
if let Ok(api_key) = std::env::var("ANTHROPIC_API_KEY") {
println!(" ๐งช Testing Anthropic (unsupported provider):");
let client = Siumai::builder()
.anthropic()
.api_key(&api_key)
.model(models::anthropic::CLAUDE_HAIKU_3_5)
.build()
.await?;
let embedding_proxy = client.embedding_capability();
println!(" Provider: {}", embedding_proxy.provider_name());
println!(
" Reported as supported: {}",
embedding_proxy.is_reported_as_supported()
);
println!(" Status: {}", embedding_proxy.support_status_message());
match client.embed(vec!["test".to_string()]).await {
Ok(_) => println!(" โ
Unexpectedly succeeded!"),
Err(e) => println!(" โ Expected error: {e}"),
}
} else {
println!(" โญ๏ธ Skipping Anthropic test (ANTHROPIC_API_KEY not set)");
}
Ok(())
}
async fn demonstrate_interface_comparison(
api_key: &str,
texts: &[String],
) -> Result<(), Box<dyn std::error::Error>> {
println!(" ๐ Unified Interface:");
let unified_client = Siumai::builder().openai().api_key(api_key).build().await?;
let unified_response = unified_client.embed(texts.to_vec()).await?;
println!(
" Unified: {} embeddings, {} dimensions",
unified_response.embeddings.len(),
unified_response.embeddings[0].len()
);
println!(" โ๏ธ Provider-Specific Interface:");
let specific_client = Provider::openai().api_key(api_key).build().await?;
let specific_response = specific_client.embed(texts.to_vec()).await?;
println!(
" Provider-specific: {} embeddings, {} dimensions",
specific_response.embeddings.len(),
specific_response.embeddings[0].len()
);
println!(" ๐ Both interfaces produce identical results!");
Ok(())
}