embed_anything/embeddings/cloud/
gemini.rs1use reqwest::Client;
2use serde::Deserialize;
3use serde_json::json;
4
5use crate::embeddings::embed::EmbeddingResult;
6
7#[derive(Deserialize, Debug, Default)]
8pub struct GeminiEmbedResponse {
9 pub embeddings: Vec<GeminiEmbeddingData>,
10}
11
12#[derive(Deserialize, Debug, Default)]
13pub struct GeminiEmbeddingData {
14 pub embedding: Vec<f32>,
15}
16
17#[derive(Debug)]
19pub struct GeminiEmbedder {
20 url: String,
21 api_key: String,
22 client: Client,
23}
24
25impl Default for GeminiEmbedder {
26 fn default() -> Self {
27 Self::new(None)
28 }
29}
30
31impl GeminiEmbedder {
32 pub fn new(api_key: Option<String>) -> Self {
33 let api_key =
34 api_key.unwrap_or_else(|| std::env::var("GEMINI_API_KEY").expect("API Key not set"));
35
36 Self {
37 url: "https://generativelanguage.googleapis.com/v1beta/models/gemini-embedding-001:embedContent".to_string(),
38 api_key,
39 client: Client::new(),
40 }
41 }
42
43 pub async fn embed(&self, text_batch: &[&str]) -> Result<Vec<EmbeddingResult>, anyhow::Error> {
44 let contents: Vec<serde_json::Value> = text_batch
46 .iter()
47 .map(|text| {
48 json!({
49 "parts": [{"text": text}]
50 })
51 })
52 .collect();
53
54 let request_body = json!({
55 "contents": contents,
56 "embedding_config": {
57 "task_type": "SEMANTIC_SIMILARITY"
58 }
59 });
60
61 let response = self
62 .client
63 .post(&self.url)
64 .header("Content-Type", "application/json")
65 .header("x-goog-api-key", &self.api_key)
66 .json(&request_body)
67 .send()
68 .await?;
69
70 let data = response.json::<GeminiEmbedResponse>().await?;
71 let encodings = data
72 .embeddings
73 .iter()
74 .map(|data| EmbeddingResult::DenseVector(data.embedding.clone()))
75 .collect::<Vec<_>>();
76
77 Ok(encodings)
78 }
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84
85 #[tokio::test]
86 async fn test_gemini_embed() {
87 let gemini = GeminiEmbedder::default();
88 let contents: Vec<serde_json::Value> = vec!["Hello world"]
89 .iter()
90 .map(|text| {
91 json!({
92 "parts": [{"text": text}]
93 })
94 })
95 .collect();
96
97 let request_body = json!({
98 "contents": contents,
99 "embedding_config": {
100 "task_type": "SEMANTIC_SIMILARITY"
101 }
102 });
103
104 let response = gemini
105 .client
106 .post(&gemini.url)
107 .header("Content-Type", "application/json")
108 .header("x-goog-api-key", &gemini.api_key)
109 .json(&request_body)
110 .send()
111 .await
112 .unwrap();
113
114 let data = response.json::<GeminiEmbedResponse>().await.unwrap();
115 println!("{:?}", data);
116 }
117}