Skip to content

Commit 1f93c69

Browse files
authored
Merge pull request #4 from M97Chahboun/main
Adds GenerationConfig struct to enhance content generation options
2 parents 831efef + 9f94ac3 commit 1f93c69

5 files changed

Lines changed: 111 additions & 7 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "gemini_client_rs"
3-
version = "0.3.0"
3+
version = "0.4.0"
44
edition = "2021"
55
description = "A Rust client for Google Gemini API"
66
license = "MIT"

examples/generation_config.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
use dotenvy::dotenv;
2+
use gemini_client_rs::{
3+
types::{GenerateContentRequest, PartResponse},
4+
GeminiClient,
5+
};
6+
use serde_json::json;
7+
8+
#[tokio::main]
9+
async fn main() -> Result<(), Box<dyn std::error::Error>> {
10+
dotenv().ok();
11+
12+
let api_key = std::env::var("GEMINI_API_KEY").expect("GEMINI_API_KEY must be set");
13+
14+
let client = GeminiClient::new(api_key.to_string());
15+
let model_name = "gemini-1.5-flash";
16+
17+
let req_json = json!({
18+
"contents": [
19+
{
20+
"parts": [
21+
{
22+
"text": "Generate a happy greeting message"
23+
}
24+
],
25+
"role": "user"
26+
}
27+
],
28+
"generationConfig": {
29+
"responseMimeType": "application/json",
30+
"responseSchema": {
31+
"type": "object",
32+
"properties": {
33+
"emoji": {
34+
"type": "string",
35+
"description": "A single emoji representing the mood of the message"
36+
},
37+
"message": {
38+
"type": "string",
39+
"description": "A greeting message"
40+
}
41+
},
42+
"required": ["emoji", "message"]
43+
}
44+
}
45+
});
46+
47+
let request: GenerateContentRequest = serde_json::from_value(req_json)?;
48+
49+
let response = client.generate_content(model_name, &request).await?;
50+
51+
if let Some(candidates) = response.candidates {
52+
for candidate in &candidates {
53+
for part in &candidate.content.parts {
54+
match part {
55+
PartResponse::Text(text) => println!("Response: {}", text),
56+
_ => println!("Unexpected response type"),
57+
}
58+
}
59+
}
60+
}
61+
62+
Ok(())
63+
}

src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,4 +120,3 @@ impl GeminiClient {
120120
}
121121
}
122122
}
123-

src/types.rs

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ pub struct GenerateContentRequest {
1919
pub system_instruction: Option<Content>,
2020
pub contents: Vec<Content>,
2121
pub tools: Option<Vec<ToolConfig>>,
22+
#[serde(rename = "generationConfig")]
23+
pub generation_config: Option<GenerationConfig>,
2224
}
2325

2426
#[derive(Debug, Serialize, Deserialize)]
@@ -50,6 +52,49 @@ pub struct Content {
5052
pub role: Role,
5153
}
5254

55+
#[derive(Debug, Serialize, Deserialize)]
56+
pub struct GenerationConfig {
57+
#[serde(rename = "stopSequences", skip_serializing_if = "Option::is_none")]
58+
pub stop_sequences: Option<Vec<String>>,
59+
#[serde(rename = "responseMimeType", skip_serializing_if = "Option::is_none")]
60+
pub response_mime_type: Option<String>,
61+
#[serde(rename = "responseSchema", skip_serializing_if = "Option::is_none")]
62+
pub response_schema: Option<serde_json::Value>,
63+
#[serde(rename = "responseModalities", skip_serializing_if = "Option::is_none")]
64+
pub response_modalities: Option<Vec<String>>,
65+
#[serde(rename = "candidateCount", skip_serializing_if = "Option::is_none")]
66+
pub candidate_count: Option<i32>,
67+
#[serde(rename = "maxOutputTokens", skip_serializing_if = "Option::is_none")]
68+
pub max_output_tokens: Option<i32>,
69+
#[serde(rename = "temperature", skip_serializing_if = "Option::is_none")]
70+
pub temperature: Option<f64>,
71+
#[serde(rename = "topP", skip_serializing_if = "Option::is_none")]
72+
pub top_p: Option<f64>,
73+
#[serde(rename = "topK", skip_serializing_if = "Option::is_none")]
74+
pub top_k: Option<i32>,
75+
#[serde(rename = "seed", skip_serializing_if = "Option::is_none")]
76+
pub seed: Option<i64>,
77+
#[serde(rename = "presencePenalty", skip_serializing_if = "Option::is_none")]
78+
pub presence_penalty: Option<f64>,
79+
#[serde(rename = "frequencyPenalty", skip_serializing_if = "Option::is_none")]
80+
pub frequency_penalty: Option<f64>,
81+
#[serde(rename = "responseLogprobs", skip_serializing_if = "Option::is_none")]
82+
pub response_logprobs: Option<bool>,
83+
#[serde(rename = "logprobs", skip_serializing_if = "Option::is_none")]
84+
pub logprobs: Option<i32>,
85+
#[serde(
86+
rename = "enableEnhancedCivicAnswers",
87+
skip_serializing_if = "Option::is_none"
88+
)]
89+
pub enable_enhanced_civic_answers: Option<bool>,
90+
#[serde(rename = "speechConfig", skip_serializing_if = "Option::is_none")]
91+
pub speech_config: Option<serde_json::Value>,
92+
#[serde(rename = "thinkingConfig", skip_serializing_if = "Option::is_none")]
93+
pub thinking_config: Option<serde_json::Value>,
94+
#[serde(rename = "mediaResolution", skip_serializing_if = "Option::is_none")]
95+
pub media_resolution: Option<String>,
96+
}
97+
5398
#[derive(Debug, Serialize, Deserialize)]
5499
pub enum ContentPart {
55100
#[serde(rename = "text")]
@@ -68,9 +113,6 @@ pub enum ContentPart {
68113
CodeExecutionResult(Value),
69114
}
70115

71-
72-
73-
74116
#[derive(Debug, Serialize, Deserialize)]
75117
pub struct ToolConfigFunctionDeclaration {
76118
pub function_declarations: Vec<FunctionDeclaration>,
@@ -169,7 +211,7 @@ pub struct ExecutableCode {
169211
pub struct InlineData {
170212
#[serde(rename = "mimeType")]
171213
mime_type: String,
172-
data: String
214+
data: String,
173215
}
174216

175217
#[derive(Debug, Serialize, Deserialize)]

0 commit comments

Comments
 (0)