use futures::StreamExt;
use rai_sdk::{Capability, ClientBuilder, Model, provider::ProviderStreamEvent};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let base_url = std::env::var("RAI_EXAMPLE_BASE_URL")
.unwrap_or_else(|_| rai_sdk::config::OLLAMA_BASE_URL.to_string());
let model = std::env::var("RAI_EXAMPLE_MODEL").unwrap_or_else(|_| "llama3.1:8b".to_string());
println!("Using {model} at {base_url}\n");
let client = ClientBuilder::new()
.openai_compatible_base_url(&base_url)
.model(Model::openai_compatible(&model))
.build()?;
let response = client
.request()
.prompt("Explain the borrow checker in two sentences.")
.generate()
.await?;
println!("Response:\n{}\n", response.text());
print!("Streaming: ");
let mut stream = client
.request()
.prompt("Count from one to five.")
.stream()
.await?;
while let Some(event) = stream.next().await {
match event? {
ProviderStreamEvent::Text(text) => {
print!("{text}");
use std::io::Write;
std::io::stdout().flush()?;
}
ProviderStreamEvent::Done { .. } => println!(),
_ => {}
}
}
let weather = rai_sdk::Tool::new("get_weather")
.description("Look up the weather for a city")
.handler(|args: WeatherArgs, _ctx| async move {
Ok(serde_json::json!({ "city": args.city, "forecast": "sunny" }))
})?;
println!("\nAsking for a tool call...");
match client
.request()
.tool(weather)
.prompt("What is the weather in Paris?")
.generate()
.await
{
Ok(response) => println!("{}", response.text()),
Err(error) if error.unsupported_capability() == Some(Capability::ToolCalling) => {
println!("{model} cannot call tools; answering without them instead.");
let response = client
.request()
.no_tools()
.prompt("What is the weather usually like in Paris in spring?")
.generate()
.await?;
println!("{}", response.text());
}
Err(error) => return Err(error.into()),
}
Ok(())
}
#[derive(serde::Deserialize, rai_sdk::JsonSchema)]
struct WeatherArgs {
city: String,
}