use rstructor::{GeminiClient, Instructor, LLMClient, MediaFile};
use serde::{Deserialize, Serialize};
use std::env;
#[derive(Instructor, Serialize, Deserialize, Debug)]
#[llm(description = "Structured analysis of an image")]
struct ImageAnalysis {
#[llm(
description = "The main subject depicted in the image",
example = "Rust logo"
)]
subject: String,
#[llm(description = "The dominant color in the image", example = "orange")]
dominant_color: String,
#[llm(description = "Colors visible in the image", example = ["orange", "black", "white"])]
colors: Vec<String>,
#[llm(description = "Whether the image is a logo or icon")]
is_logo: bool,
#[llm(description = "A detailed description of what the image depicts")]
description: String,
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let api_key =
env::var("GEMINI_API_KEY").expect("Please set GEMINI_API_KEY environment variable");
println!("Downloading Rust logo...");
let image_url = "https://www.rust-lang.org/logos/rust-logo-512x512.png";
let image_bytes = reqwest::get(image_url).await?.bytes().await?;
println!("Downloaded {} bytes", image_bytes.len());
let media = MediaFile::from_bytes(&image_bytes, "image/png");
println!("Analyzing image with Gemini...\n");
let client = GeminiClient::new(api_key)?.temperature(0.0);
let analysis: ImageAnalysis = client
.materialize_with_media(
"Analyze this image and describe what you see in detail.",
&[media],
)
.await?;
println!("===== Image Analysis =====");
println!("Subject: {}", analysis.subject);
println!("Dominant color: {}", analysis.dominant_color);
println!("Colors: {}", analysis.colors.join(", "));
println!("Is logo: {}", analysis.is_logo);
println!("\nDescription:");
println!("{}", analysis.description);
Ok(())
}