diff --git a/.gitignore b/.gitignore index d1350d3..50b3c23 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,6 @@ Cargo.lock # Only here because this is a library, and I use main.rs for testing purposes. src/main.rs Testing/ + +examples/images/response.png +examples/images/response.json \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 78fae60..5b2bd64 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,9 +22,14 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" thiserror = "2.0" tokio = { version = "1.43", features = ["full"] } +base64 = { version = "0.21", optional = true } [dev-dependencies] tokio = { version = "1.43", default-features = false, features = [ "macros", "rt-multi-thread", ] } + +[features] +default = [] +use-base64 = ["base64"] \ No newline at end of file diff --git a/examples/generate_image.rs b/examples/generate_image.rs new file mode 100644 index 0000000..cf9988f --- /dev/null +++ b/examples/generate_image.rs @@ -0,0 +1,75 @@ +#[cfg(feature = "use-base64")] +use base64::Engine; +#[cfg(feature = "use-base64")] +use base64::engine::general_purpose; +use std::fs; +// function calling example +use gemini_rs::types::{InlineData, Part}; +use serde::{Deserialize, Serialize}; +/// Proposal : Image enum for processing in-line image data +/// [API Reference](https://ai.google.dev/gemini-api/docs/image-understanding#supported-formats) +#[derive(Debug, Serialize, Deserialize, Clone)] +pub enum InlineDataMimeTypeEnum { + #[serde(rename = "image/png")] + ImagePng, + #[serde(rename = "image/jpeg")] + ImageJpeg, + #[serde(rename = "image/webp")] + ImageWebp, + #[serde(rename = "image/heic")] + ImageHeic, + #[serde(rename = "image/heif")] + ImageHeif, +} +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = gemini_rs::Client::instance(); + + let mut chat_list = vec![]; + chat_list.push(Part::text("Remake Tree well")); + #[cfg(feature = "use-base64")] + { + chat_list.push(Part::inline_data( + "image/jpeg", + &general_purpose::STANDARD.encode(&fs::read("examples/images/tree.jpg")?), + )); + } + + let response = client + .chat("gemini-2.5-flash-image-preview") + .send_parted_messages(chat_list) + .await?; + let image = response.candidates[0] + .content + .parts + .iter() + .filter(|a| { + if let Part { + inline_data: + Some(InlineData { + mime_type: _, + data: _, + }), + .. + } = a + { + true + } else { + false + } + }) + .map(|img| img.inline_data.as_ref().unwrap().data.clone()); + + #[cfg(feature = "use-base64")] + { + let image_data = general_purpose::STANDARD.decode(image.collect::>()[0].as_str())?; + let _ = fs::write("examples/images/response.png", &image_data)?; + } + #[cfg(not(feature = "use-base64"))] + { + let collected = image.collect::>(); + let image_data = collected[0].as_str(); + let _ = fs::write("examples/images/response.json", image_data)?; + } + Ok(()) +} diff --git a/examples/images/tree.jpg b/examples/images/tree.jpg new file mode 100644 index 0000000..6f69653 Binary files /dev/null and b/examples/images/tree.jpg differ diff --git a/src/chat.rs b/src/chat.rs index be1b54b..cdcca55 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -89,6 +89,14 @@ impl Chat { parts: vec![types::Part::text(message)], }); + self.generate_content().await + } + pub async fn send_parted_messages(&mut self, parts: Vec) -> Result { + self.history.push(types::Content { + role: types::Role::User, + parts, + }); + self.generate_content().await } } diff --git a/src/types.rs b/src/types.rs index fafe583..795ba8e 100644 --- a/src/types.rs +++ b/src/types.rs @@ -217,6 +217,15 @@ impl Part { ..Default::default() } } + pub fn inline_data(mime_type: &str, data: &str) -> Self { + Self { + inline_data: Some(InlineData { + mime_type: mime_type.into(), + data: data.into(), + }), + ..Default::default() + } + } } /// Metadata for a video File @@ -254,6 +263,7 @@ pub struct FileData { /// /// [API Reference](https://ai.google.dev/api/caching#Blob) #[derive(Debug, Deserialize, Serialize, Clone)] +#[serde(rename_all = "camelCase")] pub struct InlineData { pub mime_type: String, pub data: String,