use embellama::{EmbeddingEngine, EngineConfig, Error};
use std::env;
use std::path::PathBuf;
fn main() {
tracing_subscriber::fmt()
.with_env_filter("embellama=debug")
.init();
if let Err(e) = run_examples() {
eprintln!("Example failed: {e}");
std::process::exit(1);
}
}
fn run_examples() -> Result<(), Box<dyn std::error::Error>> {
println!("Error Handling Examples");
println!("=======================\n");
handle_missing_model();
handle_invalid_config()?;
handle_embedding_errors()?;
handle_batch_errors()?;
Ok(())
}
fn handle_missing_model() {
println!("1. Handling Missing Model File:");
println!("-------------------------------");
let result = EngineConfig::builder()
.with_model_path("/non/existent/model.gguf")
.with_model_name("test")
.build();
match result {
Ok(_) => {
println!(" Unexpected: Config created with non-existent model");
}
Err(e) => {
println!(" Expected error caught: {e}");
if e.is_configuration_error() {
println!(" -> This is a configuration error (as expected)");
}
}
}
println!();
}
fn handle_invalid_config() -> Result<(), Box<dyn std::error::Error>> {
println!("2. Handling Invalid Configuration:");
println!("----------------------------------");
let temp_dir = tempfile::tempdir()?;
let model_path = temp_dir.path().join("test.gguf");
std::fs::write(&model_path, b"dummy model")?;
let invalid_configs = vec![
(
"Empty name",
EngineConfig::builder()
.with_model_path(&model_path)
.with_model_name("")
.build(),
),
(
"Zero threads",
EngineConfig::builder()
.with_model_path(&model_path)
.with_model_name("test")
.with_n_threads(0)
.build(),
),
(
"Zero context",
EngineConfig::builder()
.with_model_path(&model_path)
.with_model_name("test")
.with_context_size(0)
.build(),
),
];
for (desc, result) in invalid_configs {
match result {
Ok(_) => println!(" {desc}: Unexpected success"),
Err(e) => println!(" {desc}: Caught error - {e}"),
}
}
println!();
Ok(())
}
fn handle_embedding_errors() -> Result<(), Box<dyn std::error::Error>> {
println!("3. Handling Embedding Errors with Retry:");
println!("----------------------------------------");
let model_path = if let Ok(path) = env::var("EMBELLAMA_MODEL") {
PathBuf::from(path)
} else {
println!(" Skipping: Set EMBELLAMA_MODEL to run this example");
println!();
return Ok(());
};
let config = EngineConfig::builder()
.with_model_path(model_path)
.with_model_name("retry-example")
.build()?;
let engine = EmbeddingEngine::new(config)?;
let texts = vec![
"", "Valid text for embedding",
];
for text in texts {
println!(" Attempting to embed: \"{text}\"");
let mut retries = 3;
loop {
match engine.embed(None, text) {
Ok(embedding) => {
println!(" Success! Embedding size: {}", embedding.len());
break;
}
Err(e) => {
println!(" Error: {e}");
if e.is_retryable() && retries > 0 {
retries -= 1;
println!(" Retrying... ({retries} attempts left)");
std::thread::sleep(std::time::Duration::from_millis(100));
} else {
println!(" Failed permanently");
break;
}
}
}
}
}
println!();
Ok(())
}
fn handle_batch_errors() -> Result<(), Box<dyn std::error::Error>> {
println!("4. Handling Batch Processing Errors:");
println!("------------------------------------");
let model_path = if let Ok(path) = env::var("EMBELLAMA_MODEL") {
PathBuf::from(path)
} else {
println!(" Skipping: Set EMBELLAMA_MODEL to run this example");
println!();
return Ok(());
};
let config = EngineConfig::builder()
.with_model_path(model_path)
.with_model_name("batch-error-example")
.build()?;
let engine = EmbeddingEngine::new(config)?;
let texts = vec![
"Valid document 1",
"", "Valid document 2",
" ", "Valid document 3",
];
println!(
" Processing batch of {} texts (including invalid ones)...",
texts.len()
);
match engine.embed_batch(None, &texts) {
Ok(embeddings) => {
println!(
" Batch succeeded! Generated {} embeddings",
embeddings.len()
);
for (i, (text, emb)) in texts.iter().zip(embeddings.iter()).enumerate() {
println!(
" Text {}: \"{}\" -> {} dimensions",
i,
text.trim(),
emb.len()
);
}
}
Err(Error::BatchError {
message,
failed_indices,
}) => {
println!(" Batch error: {message}");
println!(" Failed indices: {failed_indices:?}");
let valid_texts: Vec<&str> = texts
.iter()
.enumerate()
.filter(|(i, _)| !failed_indices.contains(i))
.map(|(_, t)| &**t)
.collect();
if !valid_texts.is_empty() {
println!(" Retrying with only valid texts...");
match engine.embed_batch(None, &valid_texts) {
Ok(embeddings) => {
println!(
" Retry succeeded! Generated {} embeddings",
embeddings.len()
);
}
Err(e) => {
println!(" Retry failed: {e}");
}
}
}
}
Err(e) => {
println!(" Unexpected error: {e}");
match e {
Error::ModelNotFound { name } => {
println!(" -> Model '{name}' not found. Load it first.");
}
Error::InvalidInput { message } => {
println!(" -> Invalid input: {message}");
}
Error::Timeout { message } => {
println!(" -> Operation timed out: {message}");
println!(" -> This is retryable!");
}
_ => {
println!(" -> Error type: {e:?}");
}
}
}
}
println!();
println!("Error handling examples completed!");
Ok(())
}