use super::ask::BASE_URL;
use super::error::GeminiResponseError;
use super::types::embedding::*;
use super::types::request::Part;
use reqwest::Client;
#[derive(Clone, Debug)]
pub struct GeminiEmbedding {
client: Client,
api_key: String,
model: String,
config: Option<EmbedContentConfig>,
}
impl GeminiEmbedding {
pub fn new(api_key: impl Into<String>, model: impl Into<String>) -> Self {
Self {
client: Client::default(),
api_key: api_key.into(),
model: model.into(),
config: None,
}
}
pub fn new_with_client(
api_key: impl Into<String>,
model: impl Into<String>,
client: Client,
) -> Self {
Self {
client,
api_key: api_key.into(),
model: model.into(),
config: None,
}
}
pub fn set_task_type(mut self, task_type: TaskType) -> Self {
let output_dimensionality = self
.config
.as_ref()
.and_then(|c| c.output_dimensionality().clone());
self.config = Some(EmbedContentConfig::new(
Some(task_type),
output_dimensionality,
));
self
}
pub fn set_output_dimensionality(mut self, output_dimensionality: u32) -> Self {
let task_type = self.config.as_ref().and_then(|c| c.task_type().clone());
self.config = Some(EmbedContentConfig::new(
task_type,
Some(output_dimensionality),
));
self
}
pub fn set_api_key(mut self, api_key: impl Into<String>) -> Self {
self.api_key = api_key.into();
self
}
pub fn set_model(mut self, model: impl Into<String>) -> Self {
self.model = model.into();
self
}
pub fn set_config(mut self, config: EmbedContentConfig) -> Self {
self.config = Some(config);
self
}
pub async fn embed(
&self,
content: Vec<Part>,
) -> Result<EmbedContentResponse, GeminiResponseError> {
let req_url = format!(
"{BASE_URL}/{}:embedContent?key={}",
self.model, self.api_key
);
let request_body = EmbedContentRequest {
model: format!("models/{}", self.model),
content: Content::new(content),
task_type: self.config.as_ref().and_then(|c| c.task_type().clone()),
output_dimensionality: self
.config
.as_ref()
.and_then(|c| c.output_dimensionality().clone()),
};
let response = self
.client
.post(req_url)
.json(&request_body)
.send()
.await
.map_err(|e| GeminiResponseError::ReqwestError(e))?;
if !response.status().is_success() {
let error = response
.json()
.await
.map_err(|e| GeminiResponseError::ReqwestError(e))?;
return Err(GeminiResponseError::StatusNotOk(error));
}
let embed_response: EmbedContentResponse = response
.json()
.await
.map_err(|e| GeminiResponseError::ReqwestError(e))?;
Ok(embed_response)
}
pub async fn embed_text(
&self,
text: impl Into<String>,
) -> Result<EmbedContentResponse, GeminiResponseError> {
let part: Part = text.into().into();
self.embed(vec![part]).await
}
}