// PUBLIC DOMAIN - NO LICENSE, NO WARRANTY // Copyright 2025 TimeHexOn & foxhop & russell@unturf // https://www.permacomputer.com /// UncloseAI Rust Library - Usage Examples /// /// Demonstrates how to use the UncloseAI library for: /// - Model discovery /// - Non-streaming chat completions /// - Streaming chat completions /// - Text-to-speech generation use uncloseai::{UncloseAI, ChatMessage, ChatOptions, UncloseAIError}; use futures_util::StreamExt; use std::fs::File; use std::io::Write; /// Example: Discover available models async fn example_model_discovery() -> Result<(), Box> { println!("=== Model Discovery Example ===\n"); // Initialize client (auto-discovers from environment variables) let client = UncloseAI::new(Some(uncloseai::UncloseAIConfig { debug: true, ..Default::default() })).await?; // List discovered models let models = client.list_models(); println!("\nDiscovered {} model(s):", models.len()); for model in models { println!(" - {}", model.id); println!(" Endpoint: {}", model.endpoint); println!(" Max tokens: {}", model.max_tokens); } println!(); Ok(()) } /// Example: Non-streaming chat completion async fn example_chat() -> Result<(), Box> { println!("=== Non-Streaming Chat Example ===\n"); let client = UncloseAI::new(None).await?; let response = client.chat( "auto", // Use first available model vec![ ChatMessage::system("You are a helpful AI assistant."), ChatMessage::user("Explain quantum computing in one sentence."), ], Some(ChatOptions { max_tokens: Some(100), ..Default::default() }) ).await?; // Extract and print the response let content = &response.choices[0].message.content; println!("Assistant: {}\n", content); Ok(()) } /// Example: Streaming chat completion async fn example_chat_streaming() -> Result<(), Box> { println!("=== Streaming Chat Example ===\n"); let client = UncloseAI::new(None).await?; println!("User: Write a short haiku about programming.\n"); print!("Assistant: "); let mut stream = client.chat_stream( "auto", vec![ ChatMessage::system("You are a poetic AI that writes haikus."), ChatMessage::user("Write a short haiku about programming."), ], Some(ChatOptions { max_tokens: Some(100), ..Default::default() }) ).await?; // Stream and print chunks while let Some(chunk) = stream.next().await { match chunk { Ok(chunk) => { if let Some(choice) = chunk.choices.first() { if let Some(content) = &choice.delta.content { print!("{}", content); std::io::stdout().flush()?; } } } Err(e) => { println!("\nError: {}", e); break; } } } println!("\n"); Ok(()) } /// Example: Streaming chat with conversation context async fn example_chat_streaming_with_context() -> Result<(), Box> { println!("=== Streaming Chat with Context ===\n"); let client = UncloseAI::new(None).await?; // Simulated conversation let mut messages = vec![ ChatMessage::system("You are a helpful coding assistant."), ChatMessage::user("What is Rust used for?"), ]; println!("User: What is Rust used for?\n"); print!("Assistant: "); // First response let mut full_response = String::new(); let mut stream = client.chat_stream( "auto", messages.clone(), Some(ChatOptions { max_tokens: Some(150), ..Default::default() }) ).await?; while let Some(chunk) = stream.next().await { if let Ok(chunk) = chunk { if let Some(choice) = chunk.choices.first() { if let Some(content) = &choice.delta.content { full_response.push_str(content); print!("{}", content); std::io::stdout().flush()?; } } } } println!("\n"); // Add assistant response to context messages.push(ChatMessage::assistant(full_response)); messages.push(ChatMessage::user("Can you give me a simple example?")); println!("User: Can you give me a simple example?\n"); print!("Assistant: "); // Second response with context let mut stream = client.chat_stream( "auto", messages, Some(ChatOptions { max_tokens: Some(200), ..Default::default() }) ).await?; while let Some(chunk) = stream.next().await { if let Ok(chunk) = chunk { if let Some(choice) = chunk.choices.first() { if let Some(content) = &choice.delta.content { print!("{}", content); std::io::stdout().flush()?; } } } } println!("\n"); Ok(()) } /// Example: Text-to-speech generation async fn example_tts() -> Result<(), Box> { println!("=== Text-to-Speech Example ===\n"); let client = UncloseAI::new(None).await?; // Generate speech let audio_data = client.tts( "Hello from UncloseAI Rust library! This demonstrates text to speech generation.", "alloy", // Options: alloy, echo, fable, onyx, nova, shimmer "tts-1" ).await?; // Save to file let mut file = File::create("speech.mp3")?; file.write_all(&audio_data)?; println!("[OK] Speech generated: speech.mp3 ({} bytes)\n", audio_data.len()); Ok(()) } /// Example: Using different models for different tasks async fn example_multiple_models() -> Result<(), Box> { println!("=== Multiple Models Example ===\n"); let client = UncloseAI::new(None).await?; let models = client.list_models(); if models.len() < 2 { println!("Note: Only one model available, using it for both examples\n"); } // Use first model for general chat println!("Using first model for general question:"); let response1 = client.chat( &models[0].id, vec![ChatMessage::user("What is AI?")], Some(ChatOptions { max_tokens: Some(50), ..Default::default() }) ).await?; println!(" {}\n", response1.choices[0].message.content); // Use second model (or first if only one available) for coding let model_idx = if models.len() > 1 { 1 } else { 0 }; println!("Using {} model for coding question:", if model_idx == 1 { "second" } else { "first" }); let response2 = client.chat( &models[model_idx].id, vec![ ChatMessage::system("You are a coding expert."), ChatMessage::user("Write a Rust function to check if a number is prime"), ], Some(ChatOptions { max_tokens: Some(200), ..Default::default() }) ).await?; println!(" {}\n", response2.choices[0].message.content); Ok(()) } /// Example: Error handling async fn example_error_handling() -> Result<(), Box> { println!("=== Error Handling Example ===\n"); let client = UncloseAI::new(None).await?; // Try to use non-existent model match client.chat( "non-existent-model", vec![ChatMessage::user("Hello")], None ).await { Ok(_) => println!("Unexpected success"), Err(e) => println!("Caught error (expected): {}\n", e), } Ok(()) } #[tokio::main] async fn main() -> Result<(), Box> { println!("{}", "=".repeat(60)); println!("UncloseAI Rust Library - Examples"); println!("{}", "=".repeat(60)); println!(); // Run examples if let Err(e) = example_model_discovery().await { eprintln!("Model discovery failed: {}", e); eprintln!("\nMake sure environment variables are set:"); eprintln!(" MODEL_ENDPOINT_1=https://your-endpoint/v1"); eprintln!(" TTS_ENDPOINT_1=https://your-tts-endpoint/v1"); return Err(e); } example_chat().await?; example_chat_streaming().await?; example_chat_streaming_with_context().await?; example_multiple_models().await?; if let Err(e) = example_tts().await { println!("[ERROR] TTS Error: {}\n", e); } example_error_handling().await?; println!("{}", "=".repeat(60)); println!("All examples completed successfully!"); println!("{}", "=".repeat(60)); Ok(()) }