gemini_bridge 0.1.14

Types and functions to interact with Gemini AI API
Documentation
use anyhow::Error;
use async_trait::async_trait;
use serde_json::json;

use super::{request::RequestBody, response::GenerateContentResponse};

fn build_generate_content_uri(api_key: String, model: String) -> String {
    let result = format!(
        "https://generativelanguage.googleapis.com/v1beta/models/{}:generateContent?key={}",
        model, api_key
    );
    return result;
}

// fn build_generate_stream_uri(api_key: String, model: String) -> String {
//     let result = format!(
//         "https://generativelanguage.googleapis.com/v1beta/models/{}:streamGenerateContent?alt=sse&key={}",
//         model, api_key
//     );
//     return result;
// }

#[async_trait]
pub trait TextGenerator: Send + Sync {
    async fn generate_content(&self, req: RequestBody) -> Result<GenerateContentResponse, Error>;
    // async fn generate_content_stream(
    //     &self,
    //     req: RequestBody,
    // ) -> Result<GenerateContentResponse, Error>;
}

pub(crate) struct TextGeneratorImpl {
    pub api_key: String,
    pub model: String,
}

#[async_trait]
impl TextGenerator for TextGeneratorImpl {
    async fn generate_content(&self, req: RequestBody) -> Result<GenerateContentResponse, Error> {
        let uri = &build_generate_content_uri(self.api_key.to_owned(), self.model.to_owned());

        let request_body = json!(req);

        let res = reqwest::Client::new()
            .post(uri)
            .json(&request_body)
            .send()
            .await;

        print!("uri: {}", uri);

        let response_body = match res {
            Ok(response) => {
                if response.status().is_success() {
                    response.text().await?
                } else {
                    return Err(Error::msg(format!(
                        "Request failed with status: {}",
                        response.status()
                    )));
                }
            }
            Err(e) => return Err(Error::new(e)),
        };

        let result: GenerateContentResponse = match serde_json::from_str(&response_body) {
            Ok(parsed) => parsed,
            Err(e) => return Err(Error::new(e)),
        };

        Ok(result)
    }

    // async fn generate_content_stream(
    //     &self,
    //     req: RequestBody,
    // ) -> Result<GenerateContentResponse, Error> {
    //     let uri = &build_generate_stream_uri(self.api_key.to_owned(), self.model.to_owned());

    //     let request_body = json!(req);

    //     let res = reqwest::Client::new()
    //         .post(uri)
    //         .json(&request_body)
    //         .send()
    //         .await;

    //     print!("uri: {}", uri);

    //     let response_body = match res {
    //         Ok(response) => {
    //             if response.status().is_success() {
    //                 response.text().await?
    //             } else {
    //                 return Err(Error::msg(format!(
    //                     "Request failed with status: {}",
    //                     response.status()
    //                 )));
    //             }
    //         }
    //         Err(e) => return Err(Error::new(e)),
    //     };

    //     let result: GenerateContentResponse = match serde_json::from_str(&response_body) {
    //         Ok(parsed) => parsed,
    //         Err(e) => return Err(Error::new(e)),
    //     };

    //     Ok(result)
    // }
}